Files
Zhao ChenandClaude Opus 5.5 14bbb39fde 检索网页、离线版、PDF 也拆超长收益、备注和来源,四个出口同一套规则
上一个提交只改了 EPUB,网页、离线单文件、PDF 上同一条收益仍是一整块。这次四个出口都拆,
正文 md 仍不动(index.html 按行解析、sync-stats 按「- 来源:」行数链接都依赖一个字段一行)。

- tools/lib/split-items.mjs:导出 splitGain / splitSrc。来源栏改用 index.html 原有 splitSrc
  的规则(括号外的「;」一条一行),四个出口的来源拆法从此一致。
- index.html:在原有 splitSrc 旁边加同一份 splitGain,收益、备注拆开时渲染成一块一行的列表,
  两份规则用 // <split-rules> 标出来。离线单文件用的是同一个 index.html,自动跟上。
- tools/pdf/build.mjs:read 之后同样套 splitLongItems。
- tools/check-split.mjs:从 index.html 抽出 <split-rules> 那段,和 split-items.mjs 在全书
  2013 个收益/备注/来源字段上逐条比对;也查拆完能否逐字拼回原文、** 有没有被拆开。
  CI 新增「拆分规则一致性检查」job,和交叉引用检查一样不挡发布。
- 换话题规则排除「该 / 本 / 此 / 这 / 同 / 上述」开头:「该办法第五条」是接着上文讲的,不另起。
- CLAUDE.md 电子版那段记一笔:规则两份要同步。

验证:check-split 0 处问题(拆开 554 个字段);check-plain、check-refs --check、
sync-stats --check 全过;epubcheck 5.4.0 0 errors / 0 warnings;pandoc 3.11 + typst 0.15.1
出 PDF 正常;本地起服务器和 file:// 打开离线单文件,第 31 节第 1 条的收益都拆成 11 行,控制台无报错。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X6s254TjQjvF9YgR8uK1LE
2026-10-08 11:48:59 +08:00

38 lines
2.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 收益、备注、来源的拆分规则有两份:tools/lib/split-items.mjs(EPUB、PDF)和 index.html 里
// <split-rules> 那一段(检索网页、离线单文件)。这个脚本拿全书每一条比对两边拆出来的结果,
// 顺带查拆完能不能逐字拼回原文、加粗的 ** 有没有被拆到两块里。
// 用法:node tools/check-split.mjs 有问题退出码 1
import { readdirSync } from 'node:fs';
import vm from 'node:vm';
import { read, readBook } from './lib/book.mjs';
import { splitGain, splitSrc } from './lib/split-items.mjs';
const html = read('index.html');
const m = html.match(/\/\/ <split-rules>[\s\S]*?\/\/ <\/split-rules>/);
if (!m) { console.error('index.html 里找不到 // <split-rules> … // </split-rules> 这一段'); process.exit(1); }
const ctx = {};
vm.runInNewContext(`${m[0]}\nthis.splitGain = splitGain; this.splitSrc = splitSrc;`, ctx);
const { docFiles } = readBook();
const files = [...readdirSync(new URL('../book/', import.meta.url)).filter(f => f.endsWith('.md')).map(f => `book/${f}`), ...docFiles];
const problems = [];
let total = 0, split = 0;
for (const f of files) {
read(f).split('\n').forEach((line, i) => {
const mm = line.match(/^\s*- (收益|备注|来源):(.*)$/);
if (!mm) return;
const [, label, body] = mm;
const at = `${f}:${i + 1}(${label})`;
const lib = label === '来源' ? splitSrc(body) : splitGain(body);
const web = label === '来源' ? ctx.splitSrc(body) : ctx.splitGain(body);
total++;
if (lib.length > 1) split++;
if (JSON.stringify(lib) !== JSON.stringify(web)) problems.push(`${at}:split-items.mjs 拆成 ${lib.length} 块,index.html 拆成 ${web.length} 块`);
if (label !== '来源' && lib.join('') !== body) problems.push(`${at}:拆完拼不回原文`);
if (lib.length > 1 && lib.some(c => (c.match(/\*\*/g) || []).length % 2)) problems.push(`${at}:有一块里的 ** 不成对,加粗被拆开了`);
});
}
for (const p of problems) console.log(p);
console.log(`${files.length} 个文件,${total} 个收益/备注/来源字段,拆开 ${split} 个,问题 ${problems.length} 处`);
process.exit(problems.length ? 1 : 0);