Refactor external svg handler

This commit is contained in:
Catalin Constantin Mititiuc 2024-05-31 10:27:01 -07:00
parent cf5e8a34fe
commit 414fd16298

View File

@ -121,51 +121,50 @@ const resolveImportedSvg = {
path: path.resolve('public', args.path),
};
});
}
}
const externalSvgToInternal = {
name: 'externalSvgToInternal',
setup(build) {
build.onLoad({ filter: /\.svg$/ }, async (args) => {
const document = (await JSDOM.fromFile(args.path)).window.document;
const externalResourceUseEls = Array.from(document.querySelectorAll('use[href*=".svg"'));
const externalResourceEls = Array.from(document.querySelectorAll('use[href*=".svg"'));
const files = [...new Set([...externalResourceUseEls.map(el =>
el.getAttributeNS(null, 'href').match(/.+\.svg/).at(0)
)])];
const readFiles = await Promise.all(
files.map(filename => JSDOM.fromFile(path.join(path.dirname(args.path), filename)))
).then(result => result.reduce((acc, dom, index) => {
acc[files[index]] = dom.window.document;
return acc;
}, {}));
const refs = {};
externalResourceUseEls.forEach(el => {
const refs = externalResourceEls.reduce((acc, el) => {
const href = el.getAttributeNS(null, 'href');
const [filename] = href.match(/.+\.svg/);
const fragId = href.split('.svg').pop();
const frag = readFiles[filename].querySelector(fragId);
const fragmentIdentifier = href.split('.svg').pop();
if (frag) {
frag.querySelectorAll('use').forEach(el =>
(refs[filename] ??= []).push(el.getAttributeNS(null, 'href'))
);
(acc[filename] ??= new Set()).add(fragmentIdentifier);
el.setAttributeNS(null, 'href', fragmentIdentifier);
(refs[filename] ??= []).push(fragId);
el.setAttributeNS(null, 'href', fragId);
}
return acc;
}, {});
await Promise.all(
Object.keys(refs).map(filename => JSDOM.fromFile(path.join(path.dirname(args.path), filename)))
).then(result => {
const defs = document.querySelector('defs');
Object.keys(refs).forEach((filename, index) => {
const external = result[index].window.document;
refs[filename].forEach(fragmentIdentifier => {
external
.querySelectorAll(`${fragmentIdentifier} use`)
.forEach(el => refs[filename].add(el.getAttributeNS(null, 'href')));
});
Object.keys(refs).forEach(filename => {
const refsQuery = [...new Set([...refs[filename]])].join(', ');
const refNodes = readFiles[filename].querySelectorAll(refsQuery);
const defs = document.querySelector('defs');
refNodes.forEach(n => defs.appendChild(n));
const refsQuery = [...refs[filename]].join(', ');
external.querySelectorAll(refsQuery).forEach(node => defs.appendChild(node));
});
});
return {
contents: `<?xml version="1.0" standalone="no"?>\n${document.querySelector('svg').outerHTML}`,
loader: 'file',
watchFiles: Object.keys(readFiles).map(filename => path.join(path.dirname(args.path), filename))
watchFiles: Object.keys(refs).map(filename => path.join(path.dirname(args.path), filename))
}
});
}
@ -175,7 +174,7 @@ const ctx = await esbuild.context({
entryPoints: ['src/index.js', 'src/soldier_record_block.js', 'src/map.js'],
bundle: true,
outdir: 'build',
plugins: [resolveImportedSvg],
plugins: [resolveImportedSvg, externalSvgToInternal],
loader: {
'.svg': 'file'
},