mirror of
https://github.com/eternity4719/HowToLiveBetter.git
synced 2026-10-28 19:54:50 +08:00
上一个提交只改了 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
38 lines
2.1 KiB
JavaScript
38 lines
2.1 KiB
JavaScript
// 收益、备注、来源的拆分规则有两份: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);
|