import * as posix from "node:path/posix"; import { Node, Element } from "antihtml"; function shallowCopyElement(element: Element) { const copy = new Element(element.name); copy.attributes = new Map(element.attributes); copy.childNodes = element.childNodes; return copy; } /** Resolves absolute href attributes in a and link elements the Node tree into relative references from the given directory. @param node Node tree to transform @param dir Absolute path to directory to resolve references from. @returns new node tree with href attributes transformed, or the original node if no transformations took place. */ export function resolveRefs(node: Node, dir: string) { if (!(node instanceof Element)) { return node; } let resolvedNode = node; const name = node.name; if ( (name === "link" || name === "a") && node.attributes.has("href") ) { const original = node.attributes.get("href")! /* node:coverage ignore next 3 */ if (!original.startsWith("/")) { console.log(`Warning: found relative href to ${original}`); } else { const ref = posix.relative(dir, original); resolvedNode = shallowCopyElement(node); resolvedNode.attributes.set("href", ref); } } const resolvedChildren: Node[] = []; let modifiedChildren = false; for (const child of resolvedNode.childNodes) { const resolvedChild = resolveRefs(child, dir); if (child !== resolvedChild) { modifiedChildren = true; } resolvedChildren.push(resolvedChild); } if (modifiedChildren) { resolvedNode = shallowCopyElement(node); resolvedNode.childNodes = resolvedChildren; } return resolvedNode; }