53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
|
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;
|
||
|
}
|