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
---
import Match from './match.astro'
const { props: { parent, children, debug = 0, replacers, slotHandler } } = Astro
const { props: { parent, children, debug = 0, replacers, slotHandler, adjuster } } = Astro
//console.log('Children:render', { parent, children, replacers })
if (debug) {
......@@ -11,7 +11,7 @@ const nextDebug = debug ? debug - 1 : 0
---
{
Array.isArray(children) ?
children.map((child, index) => <Match parent={parent} node={child} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>)
children.map((child, index) => <Match parent={parent} node={child} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>)
: !children ? ''
: <Match parent={parent} node={children} index={0} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>
: <Match parent={parent} node={children} index={0} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
}
......
......@@ -2,7 +2,7 @@
import Children from './children.astro'
const { props: { wrap = false, wrapAttributes = {}, node, replacers, slotHandler } } = Astro
const { props: { wrap = false, wrapAttributes = {}, node, replacers, slotHandler, adjuster } } = Astro
const { name: Name, attributes, children } = node
const CustomName = `custom-${Name}`
......@@ -15,14 +15,14 @@ const CustomName = `custom-${Name}`
{
node.isSelfClosingTag ? <Name {...attributes}/>
: <Name {...attributes}>
<Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler}/>
<Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
</Name>
}
</CustomName>
) : (
node.isSelfClosingTag ? <CustomName {...attributes}/>
: <CustomName {...attributes}>
<Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler}/>
<Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
</CustomName>
)
}
......
......@@ -2,16 +2,17 @@
import { ELEMENT_NODE, TEXT_NODE } from 'ultrahtml'
import Node from './node.astro'
const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler } } = Astro
const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler, adjuster } } = Astro
const { name: Name, attributes } = node
const fixedNode = adjuster(node, parent, index)
if (debug) {
console.log('trying to match against', {node})
console.log('trying to match against', {fixedNode})
}
let slotName
for (const [ matcher, handler ] of replacers) {
if (debug) console.log('attempting matcher', matcher.toString())
if (matcher(node, parent, index, false)) {
if (matcher(fixedNode, parent, index, false)) {
if (debug) console.log('matched')
slotName = handler
}
......@@ -20,6 +21,6 @@ for (const [ matcher, handler ] of replacers) {
const nextDebug = debug ? debug - 1 : 0
---
{
slotName ? slotHandler(slotName, node)
: <Node parent={parent} node={node} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>
slotName ? slotHandler(slotName, fixedNode)
: <Node parent={parent} node={fixedNode} index={index} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
}
......
......@@ -16,7 +16,7 @@ interface Props {
}
const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler } } = Astro
const { props: { parent = null, node, index = 0, debug = 0, replacers, slotHandler, adjuster } } = Astro
const { name: Name, attributes } = node
if (debug) {
......@@ -29,9 +29,9 @@ const nextDebug = debug ? debug - 1 : 0
: node.type === ELEMENT_NODE ? (
node.isSelfClosingTag ? <Name {...attributes}/>
: <Name {...attributes}>
<Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>
<Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
</Name>
) : (
<Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>
<Children parent={node} children={node.children} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
)
}
......
......@@ -10,18 +10,29 @@ interface Props {
debug?: number,
xpath?: string,
replacements?: Replacements,
adjustments?: any,
}
const { props } = Astro
const { html, debug = 0, xpath, replacements = {} } = props
const { html, debug = 0, xpath, replacements = {}, adjustments = {} } = props
const doc = props.node ? props.node : parseHtml(props.html)
const node = xpath ? findNode(doc, xpath) : doc
const replacers = Object.entries(replacements).map(([ selector, handler ]) => [ createMatcher(selector), handler ])
const adjustmentsCompiled = Object.entries(adjustments).map(([ selector, handler ]) => [ createMatcher(selector), handler ])
const adjuster = (node, parent, index) => {
for (const [ matcher, handler ] of adjustmentsCompiled) {
if (matcher(node, parent, index, false)) {
node = handler(node)
}
}
return node
}
const slotHandler: SlotHandler = (slotName, node) => {
return Astro.slots.render(slotName, [ node, { slotHandler, replacers } ] )
return Astro.slots.render(slotName, [ node, { slotHandler, replacers, adjuster } ] )
}
const nextDebug = debug ? debug - 1 : 0
---
<Match node={node} debug={nextDebug} replacers={replacers} slotHandler={slotHandler}/>
<Match node={node} debug={nextDebug} replacers={replacers} slotHandler={slotHandler} adjuster={adjuster}/>
......