Files

38 lines
1.2 KiB
JavaScript

import { parse, parseFragment } from 'parse5';
import { SaxesParser } from 'saxes';
function visit(node, callback, insideSvg = false) {
callback(node, insideSvg);
const childInsideSvg = insideSvg || node.tagName === 'svg';
for (const child of node.childNodes || []) visit(child, callback, childInsideSvg);
if (node.content) visit(node.content, callback, childInsideSvg);
}
export function parseXml(source) {
return new SaxesParser({ xmlns: true }).write(source).close();
}
export function extractSvgs(markup, fragment = false) {
const document = fragment
? parseFragment(markup, { sourceCodeLocationInfo: true })
: parse(markup, { sourceCodeLocationInfo: true });
const direct = [];
const srcdocs = [];
visit(document, (node, insideSvg) => {
if (node.tagName === 'svg' && !insideSvg && node.sourceCodeLocation) {
direct.push(markup.slice(node.sourceCodeLocation.startOffset, node.sourceCodeLocation.endOffset));
}
const srcdoc = node.attrs?.find((attribute) => attribute.name === 'srcdoc');
if (srcdoc) srcdocs.push(srcdoc.value);
});
return {
direct,
embedded: srcdocs.flatMap((srcdoc) => {
const nested = extractSvgs(srcdoc, true);
return [...nested.direct, ...nested.embedded];
}),
};
}