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