mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-10-01 09:19:34 +05:30
Before this commit, src/renderer/flowchart-bundle.js was a 1700+
line hand-maintained file with ~1100 lines of inlined copies of the
pure modules (shapes, mermaid, mermaid-parse, store, canvas,
clipboard, align). Every change to a pure module required a manual
re-sync, and the C17 multi-select commit had to be applied in two
places — drift between source and bundle was a real risk.
This refactor introduces scripts/build-flowchart-bundle.js that
reads each pure module from src/flowchart/ and concatenates them
into the final src/renderer/flowchart-bundle.js that the standalone
window loads as a single <script> tag.
Architecture:
- src/renderer/flowchart-bundle.js — now auto-generated, gitignored
only conceptually (still tracked so the standalone window works
without running a build step in dev).
- src/renderer/flowchart-bundle-tail.js — the unique code that
was previously buried in the middle of the hand-maintained bundle:
IIFE open, defensive checks, pure-module destructure, controller
bootstrap, modal helpers, node-list panel, closing IIFE, and
DOMContentLoaded bootstrap trigger.
- scripts/build-flowchart-bundle.js — the generator. Reads 8 pure
modules in dependency order (vsdx-export excluded — main-process
only), wraps each in its own IIFE for scope isolation, rewrites
canvas's CommonJS require() lines to use window globals, and
rewrites bare 'module.exports = X' to 'window.FlowchartX = X'
for modules without UMD guards.
Tests: 1386/1386 passing (no regressions). The pre-existing per-node
fill color test that was passing before now passes for the right
reason — the canvas source was updated to pass node.color through
to shapeSvg, which it always should have. The hand-maintained bundle
had been silently carrying a patched version that passed color but
was never backported to src/.
Amit Haridas
161 lines
5.8 KiB
JavaScript
161 lines
5.8 KiB
JavaScript
#!/usr/bin/env node
|
|
// v4.13.1 — Flowchart bundle generator.
|
|
//
|
|
// Reads the pure modules from src/flowchart/ and the unique "tail"
|
|
// (controller bootstrap + modal helpers + node-list panel) from
|
|
// src/renderer/flowchart-bundle-tail.js, then concatenates them into
|
|
// the final src/renderer/flowchart-bundle.js that the standalone
|
|
// BrowserWindow loads as a single <script> tag.
|
|
//
|
|
// Why this exists: before this script, the bundle manually inlined
|
|
// ~1100 lines of pure modules at the top. Every change to a pure
|
|
// module required a manual re-sync, which led to drift (the C17
|
|
// multi-select change had to be applied in two places, and a missed
|
|
// sync would silently break the standalone window).
|
|
//
|
|
// Usage: npm run build:bundle
|
|
// Output: src/renderer/flowchart-bundle.js
|
|
//
|
|
// @module build-flowchart-bundle
|
|
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const ROOT = path.join(__dirname, '..');
|
|
const SRC = path.join(ROOT, 'src');
|
|
const FLOWCHART_DIR = path.join(SRC, 'flowchart');
|
|
const TAIL_PATH = path.join(SRC, 'renderer', 'flowchart-bundle-tail.js');
|
|
const OUTPUT_PATH = path.join(SRC, 'renderer', 'flowchart-bundle.js');
|
|
|
|
// Pure modules in load order. flowchart-vsdx-export is intentionally
|
|
// excluded — it runs in the main process only (consumed by the IPC
|
|
// handler), never by the renderer. The remaining modules are
|
|
// collision-free at the top level (each declares its own unique
|
|
// constants) so they can be concatenated without IIFE wrapping.
|
|
const PURE_MODULES = [
|
|
'flowchart-shapes.js',
|
|
'flowchart-viewport.js',
|
|
'flowchart-mermaid.js',
|
|
'flowchart-mermaid-parse.js',
|
|
'flowchart-clipboard.js',
|
|
'flowchart-store.js',
|
|
'flowchart-canvas.js',
|
|
'flowchart-align.js',
|
|
];
|
|
|
|
function readModule(filename) {
|
|
const filePath = path.join(FLOWCHART_DIR, filename);
|
|
if (!fs.existsSync(filePath)) {
|
|
throw new Error('build-flowchart-bundle: missing pure module ' + filePath);
|
|
}
|
|
let source = fs.readFileSync(filePath, 'utf-8');
|
|
const basename = filename.replace(/\.js$/, '');
|
|
// Camel-case the basename for the window global: flowchart-mermaid-parse
|
|
// -> FlowchartMermaidParse, flowchart-clipboard -> FlowchartClipboard.
|
|
const windowName = 'window.Flowchart' + basename
|
|
.replace(/^flowchart-/, '')
|
|
.split('-')
|
|
.map((p) => p.charAt(0).toUpperCase() + p.slice(1))
|
|
.join('');
|
|
|
|
// v4.13.1 — strip CommonJS-isms before concatenating into the bundle.
|
|
// The bundle is a browser-only script (no Node `module` / `require`),
|
|
// so we have to:
|
|
// 1. Replace `const shapesModule = (typeof window !== 'undefined'
|
|
// && window.FlowchartShapes) || require('./flowchart-shapes')`
|
|
// with the pure browser form so canvas can still pick up
|
|
// SHAPE_KINDS / DEFAULT_WIDTH / etc. from the shapes module
|
|
// that was inlined just above.
|
|
// 2. Replace any top-level `module.exports = ...` lines that some
|
|
// modules (mermaid-parse, vsdx-export) have without a UMD
|
|
// guard with an equivalent `window.X = ...` assignment so the
|
|
// bundle's tail can still find the module's exports.
|
|
// The CommonJS paths stay intact for tests + the sidebar panel.
|
|
if (filename === 'flowchart-canvas.js') {
|
|
source = source.replace(
|
|
/const shapesModule =\s*\n?\s*\(typeof window[\s\S]*?require\('\.\/flowchart-shapes'\);/,
|
|
'const shapesModule = window.FlowchartShapes;'
|
|
);
|
|
source = source.replace(
|
|
/const viewportModule =\s*\n?\s*\(typeof window[\s\S]*?require\('\.\/flowchart-viewport'\);/,
|
|
'const viewportModule = window.FlowchartViewport;'
|
|
);
|
|
}
|
|
// Replace bare `module.exports = X;` with `window.X = X;` so the
|
|
// tail can pick up the module's exports from window globals.
|
|
source = source.replace(
|
|
/^module\.exports\s*=\s*([^\n;]+);?\s*$/gm,
|
|
windowName + ' = $1;'
|
|
);
|
|
source = source.replace(/\n{3,}/g, '\n\n');
|
|
|
|
return source;
|
|
}
|
|
|
|
function buildHeader() {
|
|
const parts = [
|
|
'// v4.13.1 — AUTO-GENERATED FILE. DO NOT EDIT.',
|
|
'//',
|
|
'// This file is the concatenation of every pure module in',
|
|
'// src/flowchart/ plus the unique tail from',
|
|
'// src/renderer/flowchart-bundle-tail.js. Regenerate it by running',
|
|
"// `npm run build:bundle` whenever a pure module changes.",
|
|
'//',
|
|
'// Each pure module is wrapped in its own IIFE so top-level',
|
|
'// `const` declarations (DEFAULT_WIDTH, DEFAULT_HEIGHT, SHAPE_KINDS,',
|
|
'// etc.) stay local to that module and do not collide with',
|
|
'// identically-named declarations in other modules. The UMD',
|
|
'// wrappers inside each module continue to expose the public API',
|
|
'// as window.FlowchartXxx, which the tail consumes.',
|
|
];
|
|
for (const filename of PURE_MODULES) {
|
|
const basename = filename.replace(/\.js$/, '');
|
|
parts.push('');
|
|
parts.push(' // ========== ' + basename + ' (inlined by build script) ==========');
|
|
// Wrap each module in its own IIFE for scope isolation. The UMD
|
|
// wrapper inside still runs and assigns to window.FlowchartXxx
|
|
// on the outer window object.
|
|
parts.push('(function () {');
|
|
parts.push(readModule(filename));
|
|
parts.push('})();');
|
|
}
|
|
return parts.join('\n');
|
|
}
|
|
|
|
function buildTail() {
|
|
if (!fs.existsSync(TAIL_PATH)) {
|
|
throw new Error('build-flowchart-bundle: missing tail ' + TAIL_PATH);
|
|
}
|
|
return fs.readFileSync(TAIL_PATH, 'utf-8');
|
|
}
|
|
|
|
function main() {
|
|
const header = buildHeader();
|
|
const tail = buildTail();
|
|
const output = header + '\n' + tail;
|
|
fs.writeFileSync(OUTPUT_PATH, output);
|
|
const stat = fs.statSync(OUTPUT_PATH);
|
|
console.log(
|
|
'build-flowchart-bundle: wrote ' +
|
|
path.relative(ROOT, OUTPUT_PATH) +
|
|
' (' +
|
|
stat.size +
|
|
' bytes, ' +
|
|
PURE_MODULES.length +
|
|
' pure modules + tail)'
|
|
);
|
|
}
|
|
|
|
if (require.main === module) {
|
|
try {
|
|
main();
|
|
} catch (err) {
|
|
console.error(err.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
module.exports = { main, PURE_MODULES };
|