| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- #!/usr/bin/env node
- // ==============================================================================
- // 从已生成的 HTML 报告中提取所有 slide section 的 HTML 内容
- // 用途:PowerShell GBK 编码损坏 chapter 文件后的快照式恢复
- // 输出:scripts/tools/voc-validation/_slides-snapshot.json
- // {
- // "method-1": { html: "...", tone: "green", slideNum: "03/42" },
- // ...
- // }
- // ==============================================================================
- const fs = require('fs');
- const path = require('path');
- const HTML_PATH = path.join('reports', 'jiangzhong-liver-voc-validation-report.html');
- const OUT_PATH = path.join('scripts', 'tools', 'voc-validation', '_slides-snapshot.json');
- function main() {
- const html = fs.readFileSync(HTML_PATH, 'utf8');
- // 用正则定位每个 <section class="report-section" id="..." ...>
- // 由于 section 里可能嵌套 section(eg. cover-hero 不是),但 report-section 不嵌套,
- // 采用首尾配对方式:从每个 <section class="report-section" 起点开始,寻找对应的 </section>
- const openRx = /<section\s+class="report-section"\s+id="([^"]+)"\s+data-tone="([^"]*)"\s+data-slide-num="([^"]+)"[^>]*>/g;
- const closeTag = '</section>';
- const starts = [];
- let m;
- while ((m = openRx.exec(html)) !== null) {
- starts.push({ id: m[1], tone: m[2], slideNum: m[3], start: m.index, headerEnd: m.index + m[0].length });
- }
- console.log(`Found ${starts.length} sections`);
- const snapshot = {};
- for (let i = 0; i < starts.length; i++) {
- const s = starts[i];
- // 找 section 的结束位置:从 headerEnd 开始,下一个 section 开始前最后一个 </section>
- const nextStart = i + 1 < starts.length ? starts[i + 1].start : html.length;
- const closeIdx = html.lastIndexOf(closeTag, nextStart);
- if (closeIdx < s.headerEnd) {
- console.warn(`[WARN] cannot find close for ${s.id}`);
- continue;
- }
- const fullHtml = html.slice(s.start, closeIdx + closeTag.length);
- snapshot[s.id] = {
- tone: s.tone,
- slideNum: s.slideNum,
- html: fullHtml,
- };
- console.log(` ${s.id.padEnd(18)} ${s.tone.padEnd(8)} ${s.slideNum} (${fullHtml.length} bytes)`);
- }
- fs.mkdirSync(path.dirname(OUT_PATH), { recursive: true });
- fs.writeFileSync(OUT_PATH, JSON.stringify(snapshot, null, 2), 'utf8');
- console.log(`\n✓ 写入 ${OUT_PATH} (${Object.keys(snapshot).length} sections)`);
- }
- main();
|