ReviewOS

also looking at this

stacks/ts-web-scraper

fix: support structured DOM selectors

#847
Merged chris wants to merge codex/transfermarkt-dom into main
6 files +225 -57
test/index.test.tsmodified+24-0
Changes to test/index.test.ts
@@ -117,6 +117,30 @@ describe('Web Scraper - Static HTML Parsing', () => {
117117 expect(doc.querySelector('ytd-display-ad-renderer')?.textContent).toContain('Ad')
118118 expect(doc.querySelector('[data-ad-slot]')?.tagName).toBe('ytd-display-ad-renderer')
119119 })
120
121 it('should follow descendant and child combinators for table rows', () => {
122 const doc = parseHTML(`
123 <table class="items">
124 <tbody>
125 <tr class="odd"><td><a href="/club/startseite/verein/31">Club</a></td></tr>
126 <tr class="even"><td><a href="/club/startseite/verein/42">Other</a></td></tr>
127 </tbody>
128 </table>
129 `)
130
131 expect(doc.querySelectorAll('table.items > tbody > tr')).toHaveLength(2)
132 expect(doc.querySelectorAll('table.items a[href*="/verein/"]')).toHaveLength(2)
133 expect(doc.querySelector('tr.odd > td > a')?.getAttribute('href')).toContain('/verein/31')
134 })
135
136 it('should decode entities in text and attributes', () => {
137 const doc = parseHTML('<a title="Brighton &amp; Hove Albion">Brighton &amp; Hove&nbsp;Albion &#x20AC;1.2bn</a>')
138 const link = doc.querySelector('a')
139
140 expect(link?.getAttribute('title')).toBe('Brighton & Hove Albion')
141 expect(link?.textContent).toBe('Brighton & Hove\u00A0Albion €1.2bn')
142 expect(extractText('<span>one</span><span>two</span>')).toBe('one two')
143 })
120144})
121145
122146describe('Client-Side Scraper - Detection', () => {