eaa705ab by Adam Heath

Add support for attribute decoding, via a proxy(this should really be

fixed upstream).
1 parent 9b920fd6
1 import nodeUtil from 'util' 1 import nodeUtil from 'util'
2 import TTLCache from '@isaacs/ttlcache' 2 import TTLCache from '@isaacs/ttlcache'
3 import { decode } from 'html-entities'
3 4
4 import type { NodeType } from 'ultrahtml' 5 import type { NodeType } from 'ultrahtml'
5 import { 6 import {
...@@ -306,12 +307,42 @@ export const createMatcher = (selector: string): Matcher => { ...@@ -306,12 +307,42 @@ export const createMatcher = (selector: string): Matcher => {
306 return newMatcherCreater() 307 return newMatcherCreater()
307 } 308 }
308 309
310 const nodeProxyHandler = {
311 get(target, prop, receiver) {
312 const { _proxy } = target
313 if (prop in _proxy) return _proxy[ prop ]
314 const { [ prop ]: origValue } = target
315 if (!origValue) return origValue
316 switch (prop) {
317 case 'attributes':
318 return _proxy[ prop ] = (origValue ? Object.fromEntries(Object.entries(origValue).map(([ key, value ]) => {
319 return [ key, decode(value) ]
320 })) : origValue)
321 return newValue
322 case 'parent':
323 return _proxy[ prop ] = proxyNode(origValue)
324 case 'children':
325 return _proxy[ prop ] = origValue.map((child) => proxyNode(child))
326 default:
327 return origValue
328 }
329 }
330 }
331
332 const proxyNode = (node) => {
333 const { _proxy: { proxy } = {} } = node
334 if (proxy) return proxy
335 const newProxy = new Proxy(node, nodeProxyHandler)
336 node._proxy = { proxy: newProxy }
337 return newProxy
338 }
339
309 export const parseHtml = (html: string): NodeType => { 340 export const parseHtml = (html: string): NodeType => {
310 const cached = parsedHtmlCache.get(html) 341 const cached = parsedHtmlCache.get(html)
311 if (cached) return cached 342 if (cached) return proxyNode(cached)
312 const doc = ultraParse(html) 343 const doc = ultraParse(html)
313 parsedHtmlCache.set(html, doc) 344 parsedHtmlCache.set(html, doc)
314 return doc 345 return proxyNode(doc)
315 } 346 }
316 347
317 export const findNode = (doc: NodeType, selector: string): NodeType => { 348 export const findNode = (doc: NodeType, selector: string): NodeType => {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
8 "dependencies": { 8 "dependencies": {
9 "@isaacs/ttlcache": "^1.4.1", 9 "@isaacs/ttlcache": "^1.4.1",
10 "@reduxjs/toolkit": "^2.2.5", 10 "@reduxjs/toolkit": "^2.2.5",
11 "html-entities": "^2.5.2",
11 "parsel-js": "^1.1.2", 12 "parsel-js": "^1.1.2",
12 "ultrahtml": "^1.5.3" 13 "ultrahtml": "^1.5.3"
13 }, 14 },
...@@ -3200,6 +3201,21 @@ ...@@ -3200,6 +3201,21 @@
3200 "url": "https://opencollective.com/unified" 3201 "url": "https://opencollective.com/unified"
3201 } 3202 }
3202 }, 3203 },
3204 "node_modules/html-entities": {
3205 "version": "2.5.2",
3206 "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
3207 "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==",
3208 "funding": [
3209 {
3210 "type": "github",
3211 "url": "https://github.com/sponsors/mdevils"
3212 },
3213 {
3214 "type": "patreon",
3215 "url": "https://patreon.com/mdevils"
3216 }
3217 ]
3218 },
3203 "node_modules/html-escaper": { 3219 "node_modules/html-escaper": {
3204 "version": "3.0.3", 3220 "version": "3.0.3",
3205 "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", 3221 "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
12 "dependencies": { 12 "dependencies": {
13 "@isaacs/ttlcache": "^1.4.1", 13 "@isaacs/ttlcache": "^1.4.1",
14 "@reduxjs/toolkit": "^2.2.5", 14 "@reduxjs/toolkit": "^2.2.5",
15 "html-entities": "^2.5.2",
15 "parsel-js": "^1.1.2", 16 "parsel-js": "^1.1.2",
16 "ultrahtml": "^1.5.3" 17 "ultrahtml": "^1.5.3"
17 }, 18 },
......