// usage: node split-css.mjs IN.css OUTDIR — extracts each distinct base64 data:image (png, svg+xml) url() into OUTDIR/img/. // and rewrites the CSS to url(img/.). Anything else with data: is an error. import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'; import { createHash } from 'node:crypto'; const [inFile, outDir] = process.argv.slice(2); const css = readFileSync(inFile, 'latin1'); mkdirSync(outDir + '/img', { recursive: true }); const ext = { png: 'png', 'svg+xml': 'svg' }; const seen = new Map(); const out = css.replace(/url\(\s*(["']?)data:image\/(png|svg\+xml);base64,([A-Za-z0-9+/=]*)\1\s*\)/g, (m, q, kind, data) => { const bytes = Buffer.from(data, 'base64'); const name = createHash('sha256').update(bytes).digest('hex').slice(0, 8) + '.' + ext[kind]; if (!seen.has(name)) { writeFileSync(`${outDir}/img/${name}`, bytes); seen.set(name, bytes.length); } return `url(img/${name})`; }); if (/data:/.test(out)) throw new Error('data: left in output'); writeFileSync(outDir + '/toastui-editor.css', out, 'latin1'); console.log('data URIs in', (css.match(/data:/g) || []).length, '-> files', seen.size, JSON.stringify([...seen])); console.log('css bytes in/out', css.length, out.length);