37 lines
991 B
JavaScript
37 lines
991 B
JavaScript
export const visitSkip = Symbol();
|
|
|
|
/**
|
|
* @param {import('../types.js').XastNode} node
|
|
* @param {import('../types.js').Visitor} visitor
|
|
* @param {any=} parentNode
|
|
*/
|
|
export const visit = (node, visitor, parentNode) => {
|
|
const callbacks = visitor[node.type];
|
|
if (callbacks?.enter) {
|
|
// @ts-expect-error hard to infer
|
|
const symbol = callbacks.enter(node, parentNode);
|
|
if (symbol === visitSkip) {
|
|
return;
|
|
}
|
|
}
|
|
// visit root children
|
|
if (node.type === 'root') {
|
|
// copy children array to not lose cursor when children is spliced
|
|
for (const child of node.children) {
|
|
visit(child, visitor, node);
|
|
}
|
|
}
|
|
// visit element children if still attached to parent
|
|
if (node.type === 'element') {
|
|
if (parentNode.children.includes(node)) {
|
|
for (const child of node.children) {
|
|
visit(child, visitor, node);
|
|
}
|
|
}
|
|
}
|
|
if (callbacks?.exit) {
|
|
// @ts-expect-error hard to infer
|
|
callbacks.exit(node, parentNode);
|
|
}
|
|
};
|