hornwitser.no/utils/resolve-refs.ts

53 lines
1.6 KiB
TypeScript
Raw Normal View History

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;
}