2626a712 by Adam Heath

Add feature to 'adjust' nodes before matching against them. This can be

used to change values of attributes, as an example.
1 parent a08f00fa
1 --- 1 ---
2 import Match from './match.astro' 2 import Match from './match.astro'
3 3
4 const { props: { parent, children, debug = 0, replacers, slotHandler } } = Astro 4 const { props: { parent, children, debug = 0, replacers, slotHandler, adjuster } } = Astro
5 5
6 //console.log('Children:render', { parent, children, replacers }) 6 //console.log('Children:render', { parent, children, replacers })
7 if (debug) { 7 if (debug) {
...@@ -11,7 +11,7 @@ const nextDebug = debug ? debug - 1 : 0 ...@@ -11,7 +11,7 @@ const nextDebug = debug ? debug - 1 : 0
11 --- 11 ---
12 { 12 {
13 Array.isArray(children) ? 13 Array.isArray(children) ?
14 children.map((child, index) => <Match parent={parent} node={child} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>) 14 children.map((child, index) => <Match parent={parent} node={child} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>)
15 : !children ? '' 15 : !children ? ''
16 : <Match parent={parent} node={children} index={0} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/> 16 : <Match parent={parent} node={children} index={0} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
17 } 17 }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 import Children from './children.astro' 3 import Children from './children.astro'
4 4
5 const { props: { wrap = false, wrapAttributes = {}, node, replacers, slotHandler } } = Astro 5 const { props: { wrap = false, wrapAttributes = {}, node, replacers, slotHandler, adjuster } } = Astro
6 const { name: Name, attributes, children } = node 6 const { name: Name, attributes, children } = node
7 7
8 const CustomName = `custom-${Name}` 8 const CustomName = `custom-${Name}`
...@@ -15,14 +15,14 @@ const CustomName = `custom-${Name}` ...@@ -15,14 +15,14 @@ const CustomName = `custom-${Name}`
15 { 15 {
16 node.isSelfClosingTag ? <Name {...attributes}/> 16 node.isSelfClosingTag ? <Name {...attributes}/>
17 : <Name {...attributes}> 17 : <Name {...attributes}>
18 <Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler}/> 18 <Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
19 </Name> 19 </Name>
20 } 20 }
21 </CustomName> 21 </CustomName>
22 ) : ( 22 ) : (
23 node.isSelfClosingTag ? <CustomName {...attributes}/> 23 node.isSelfClosingTag ? <CustomName {...attributes}/>
24 : <CustomName {...attributes}> 24 : <CustomName {...attributes}>
25 <Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler}/> 25 <Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
26 </CustomName> 26 </CustomName>
27 ) 27 )
28 } 28 }
......
...@@ -2,16 +2,17 @@ ...@@ -2,16 +2,17 @@
2 import { ELEMENT_NODE, TEXT_NODE } from 'ultrahtml' 2 import { ELEMENT_NODE, TEXT_NODE } from 'ultrahtml'
3 import Node from './node.astro' 3 import Node from './node.astro'
4 4
5 const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler } } = Astro 5 const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler, adjuster } } = Astro
6 const { name: Name, attributes } = node 6 const { name: Name, attributes } = node
7 7
8 const fixedNode = adjuster(node, parent, index)
8 if (debug) { 9 if (debug) {
9 console.log('trying to match against', {node}) 10 console.log('trying to match against', {fixedNode})
10 } 11 }
11 let slotName 12 let slotName
12 for (const [ matcher, handler ] of replacers) { 13 for (const [ matcher, handler ] of replacers) {
13 if (debug) console.log('attempting matcher', matcher.toString()) 14 if (debug) console.log('attempting matcher', matcher.toString())
14 if (matcher(node, parent, index, false)) { 15 if (matcher(fixedNode, parent, index, false)) {
15 if (debug) console.log('matched') 16 if (debug) console.log('matched')
16 slotName = handler 17 slotName = handler
17 } 18 }
...@@ -20,6 +21,6 @@ for (const [ matcher, handler ] of replacers) { ...@@ -20,6 +21,6 @@ for (const [ matcher, handler ] of replacers) {
20 const nextDebug = debug ? debug - 1 : 0 21 const nextDebug = debug ? debug - 1 : 0
21 --- 22 ---
22 { 23 {
23 slotName ? slotHandler(slotName, node) 24 slotName ? slotHandler(slotName, fixedNode)
24 : <Node parent={parent} node={node} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/> 25 : <Node parent={parent} node={fixedNode} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
25 } 26 }
......
...@@ -16,7 +16,7 @@ interface Props { ...@@ -16,7 +16,7 @@ interface Props {
16 } 16 }
17 17
18 18
19 const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler } } = Astro 19 const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler, adjuster } } = Astro
20 const { name: Name, attributes } = node 20 const { name: Name, attributes } = node
21 21
22 if (debug) { 22 if (debug) {
...@@ -29,9 +29,9 @@ const nextDebug = debug ? debug - 1 : 0 ...@@ -29,9 +29,9 @@ const nextDebug = debug ? debug - 1 : 0
29 : node.type === ELEMENT_NODE ? ( 29 : node.type === ELEMENT_NODE ? (
30 node.isSelfClosingTag ? <Name {...attributes}/> 30 node.isSelfClosingTag ? <Name {...attributes}/>
31 : <Name {...attributes}> 31 : <Name {...attributes}>
32 <Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/> 32 <Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
33 </Name> 33 </Name>
34 ) : ( 34 ) : (
35 <Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/> 35 <Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
36 ) 36 )
37 } 37 }
......
...@@ -10,18 +10,29 @@ interface Props { ...@@ -10,18 +10,29 @@ interface Props {
10 debug?: number, 10 debug?: number,
11 xpath?: string, 11 xpath?: string,
12 replacements?: Replacements, 12 replacements?: Replacements,
13 adjustments?: any,
13 } 14 }
14 15
15 const { props } = Astro 16 const { props } = Astro
16 const { html, debug = 0, xpath, replacements = {} } = props 17 const { html, debug = 0, xpath, replacements = {}, adjustments = {} } = props
17 const doc = props.node ? props.node : parseHtml(props.html) 18 const doc = props.node ? props.node : parseHtml(props.html)
18 19
19 const node = xpath ? findNode(doc, xpath) : doc 20 const node = xpath ? findNode(doc, xpath) : doc
20 const replacers = Object.entries(replacements).map(([ selector, handler ]) => [ createMatcher(selector), handler ]) 21 const replacers = Object.entries(replacements).map(([ selector, handler ]) => [ createMatcher(selector), handler ])
21 22
23 const adjustmentsCompiled = Object.entries(adjustments).map(([ selector, handler ]) => [ createMatcher(selector), handler ])
24 const adjuster = (node, parent, index) => {
25 for (const [ matcher, handler ] of adjustmentsCompiled) {
26 if (matcher(node, parent, index, false)) {
27 node = handler(node)
28 }
29 }
30 return node
31 }
32
22 const slotHandler: SlotHandler = (slotName, node) => { 33 const slotHandler: SlotHandler = (slotName, node) => {
23 return Astro.slots.render(slotName, [ node, { slotHandler, replacers } ] ) 34 return Astro.slots.render(slotName, [ node, { slotHandler, replacers, adjuster } ] )
24 } 35 }
25 const nextDebug = debug ? debug - 1 : 0 36 const nextDebug = debug ? debug - 1 : 0
26 --- 37 ---
27 <Match node={node} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/> 38 <Match node={node} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
......