refactor: new structure

This commit is contained in:
2026-04-21 19:49:08 +07:00
parent 99bc387244
commit ba676c2924
45 changed files with 12097 additions and 807 deletions
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env node
/**
* Apply editor JSON edits to space-route HTML.
* Usage: node src/scripts/apply-route-edits.mjs output/html/space-route-edits.json
*/
import { readFileSync, writeFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = join(__dirname, '..', '..');
const editsPath = process.argv[2] || join(ROOT, 'output', 'html', 'space-route-edits.json');
const edits = JSON.parse(readFileSync(editsPath, 'utf-8'));
const htmlPath = join(ROOT, 'output', 'html', edits.file);
let html = readFileSync(htmlPath, 'utf-8');
// Split HTML into pages
const pageRegex = /<div class="w-\[210mm\] h-\[297mm\][^>]*>/g;
const pageStarts = [];
let m;
while ((m = pageRegex.exec(html)) !== null) {
pageStarts.push(m.index);
}
pageStarts.push(html.length);
function getPageHtml(pageIndex) {
return html.slice(pageStarts[pageIndex], pageStarts[pageIndex + 1]);
}
function setPageHtml(pageIndex, newPageHtml) {
html = html.slice(0, pageStarts[pageIndex]) + newPageHtml + html.slice(pageStarts[pageIndex + 1]);
// Recalculate starts
const diff = newPageHtml.length - (pageStarts[pageIndex + 1] - pageStarts[pageIndex]);
for (let i = pageIndex + 1; i < pageStarts.length; i++) {
pageStarts[i] += diff;
}
}
for (const pageEdit of edits.pages) {
const pi = pageEdit.page - 1;
let pageHtml = getPageHtml(pi);
console.log(`Applying page ${pageEdit.page}...`);
// Apply object edits
if (pageEdit.objects) {
for (const obj of pageEdit.objects) {
// Find the img with matching data-node-id and data-type on this page
const nodeId = obj.nodeId;
const type = obj.type;
// Build transform string
let transform = '';
if (obj.rotate) transform += `rotate(${obj.rotate}deg)`;
if (obj.flipH) transform += ` scaleX(-1)`;
transform = transform.trim();
const transformAttr = transform ? `transform:${transform};` : '';
const w = parseFloat(obj.w);
const h = parseFloat(obj.h);
const left = parseFloat(obj.left);
const top = parseFloat(obj.top);
// Match the img element by data-node-id and data-type
const imgRegex = new RegExp(
`(<img[^>]*data-node-id="${nodeId}"[^>]*data-type="${type}"[^>]*style=")([^"]*)(")`,
'g'
);
const newStyle = `left:${left.toFixed(1)}mm;top:${top.toFixed(1)}mm;width:${w}mm;height:${h}mm;margin-left:-${w/2}mm;margin-top:-${h/2}mm;z-index:4;${transformAttr}`;
const before = pageHtml;
pageHtml = pageHtml.replace(imgRegex, `$1${newStyle}$3`);
if (pageHtml === before) {
// Try alternate order (data-type before data-node-id)
const imgRegex2 = new RegExp(
`(<img[^>]*data-type="${type}"[^>]*data-node-id="${nodeId}"[^>]*style=")([^"]*)(")`,
'g'
);
pageHtml = pageHtml.replace(imgRegex2, `$1${newStyle}$3`);
}
console.log(` obj node:${nodeId} type:${type} → ${left.toFixed(1)},${top.toFixed(1)} ${w}×${h}mm${obj.rotate ? ' rot:'+obj.rotate+'°' : ''}${obj.flipH ? ' FLIP' : ''}`);
}
}
// Apply node edits
if (pageEdit.nodes) {
for (const nd of pageEdit.nodes) {
const nodeId = nd.nodeId;
const left = parseFloat(nd.left);
const top = parseFloat(nd.top);
// Update node div position
const nodeRegex = new RegExp(
`(<div[^>]*data-node-id="${nodeId}"[^>]*style=")(left:[^;]*;top:[^;]*)`,
'g'
);
pageHtml = pageHtml.replace(nodeRegex, `$1left:${left.toFixed(1)}mm;top:${top.toFixed(1)}mm`);
// Update all edges connected to this node
// Edge format: data-edge="A-B" where A or B matches nodeId
// Update x1,y1 if nodeId is the first, x2,y2 if second
const edgeRegex1 = new RegExp(
`(<line data-edge="${nodeId}-\\d+"[^>]*)(x1="[^"]*")(\\s*)(y1="[^"]*")`,
'g'
);
pageHtml = pageHtml.replace(edgeRegex1, `$1x1="${left.toFixed(1)}mm"$3y1="${top.toFixed(1)}mm"`);
const edgeRegex2 = new RegExp(
`(<line data-edge="\\d+-${nodeId}"[^>]*)(x2="[^"]*")(\\s*)(y2="[^"]*")`,
'g'
);
pageHtml = pageHtml.replace(edgeRegex2, `$1x2="${left.toFixed(1)}mm"$3y2="${top.toFixed(1)}mm"`);
}
console.log(` ${pageEdit.nodes.length} nodes updated`);
}
setPageHtml(pi, pageHtml);
}
writeFileSync(htmlPath, html, 'utf-8');
console.log(`\nWritten to ${htmlPath}`);