/** * Inline every module into one self-contained HTML file, so the whole tool is a * single document that opens straight from the desktop with no install, no * server and no internet. */ import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; const here = dirname(fileURLToPath(import.meta.url)); const root = join(here, '..'); // Dependency order, leaves first. const MODULES = [ 'src/fonts.js', 'src/codec/bitfont.mjs', 'src/codec/td5.mjs', 'src/codec/tp5.mjs', 'src/codec/sheet.mjs', 'app/main.mjs', ]; function strip(src, name) { const out = src // drop the import lines; every symbol ends up in one shared scope .replace(/^\s*import\s+[^;]*?from\s*['"][^'"]+['"];?\s*$/gm, '') // `export const X` -> `const X`, `export function f` -> `function f` .replace(/^export\s+(const|let|var|function|class|async)\b/gm, '$1') // bare re-export statements, if any ever appear .replace(/^export\s*\{[^}]*\};?\s*$/gm, ''); if (/^\s*(import|export)\b/m.test(out)) { throw new Error(`${name}: an import/export slipped through the bundler`); } return `\n// ===== ${name} =====\n${out.trim()}\n`; } const code = MODULES.map((m) => strip(readFileSync(join(root, m), 'utf8'), m)).join('\n'); const html = readFileSync(join(root, 'app/index.html'), 'utf8'); if (!html.includes('')) { throw new Error('index.html no longer has the expected script tag'); } const banner = ` `; const bundled = banner + html.replace( '', `` ); mkdirSync(join(root, 'dist'), { recursive: true }); const outPath = join(root, 'dist/DestoGod.html'); writeFileSync(outPath, bundled); console.log(`wrote dist/DestoGod.html (${(bundled.length / 1024).toFixed(0)} KB, ${MODULES.length} modules inlined)`);