fix(wiki): 新增 remark-math-sanitize 插件净化 PDF 语料病态公式,消除构建期 KaTeX 告警与渲染缺陷 - #1117
Merged
Conversation
- 货币 \$ 误配对(数学体含 CJK)降级回正文文本,消除百余条 unicodeTextInMathMode 告警
- 未转义 % 补 \%,修复 TeX 注释符吞掉渲染内容(11.5%→15.0% 只显示 11.5)
- ‖/∥/• 归一为 \Vert/\parallel/\bullet,消除 unknownSymbol 与 tofu 渲染
- display 公式下标裸 CJK 包进 \text{},走文本模式渲染
- 关键路径:mdast-util-math 把公式值存两份(node.value + data.hChildren 内
hast text 副本,层级 inlineMath/display 不同),须递归同步才能到达 KaTeX
- 真实 135 篇内容构建复验:KaTeX 告警 164 → 0,产物 HTML 抽查四类修复全部正确
🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
依 KaTeX 0.16.47 源码与实机渲染探测,修正插件四处会造成公式丢失或渲染错误的判据:
1. CJK 区间下界字形混淆:`豈`(U+8C48 普通汉字) 误作 `豈`(U+F900 兼容表意文字),
致区间展开为 U+8C48–U+FAFF、误纳谚文音节与代理项码位 U+D800–U+DFFF。
改以转义码位书写并提取 CJK_CLASS 单一常量,消除两处字面量漂移。
2. `%` 转义误豁免文本模式:KaTeX 的 `%` 是 Lexer 构造期设定的 catcode 14,
与数学/文本模式无关,`\text{增长 50%}` 会注释掉闭合 `}` 直接抛 ParseError
(实测渲染 .katex-error)。转义改为作用于整串,不再走 replaceOutsideTextMacros。
3. `(?<!\\)%` 单字符回看漏判:`\\%`(换行符紧邻裸 `%`)被误判为已转义,
`%` 及其后内容仍被当注释吞掉。改按前导反斜杠奇偶判定,对已转义输入幂等。
4. 文本宏白名单漏项:遗漏 KaTeX 支持的 `\textrm`/`\textsf`/`\textnormal`/
`\textmd`/`\textup`/`\emph`,其内 CJK 逃过剥离后被货币误配对分支整条降级、
丢失公式渲染。按 src/functions/text.ts 的 names 补齐并提为单一常量复用。
验证:新增 4 项回归用例(文本模式 `%`、`\\%` 奇偶判定、`\%` 幂等、文本宏 CJK
不降级、非 CJK 下标不误包),wiki 全量 122 项测试通过;对四处修复逐一做变异
回退,确认各用例均能红灯、无恒真断言;next build 成功且 KaTeX 告警计数为 0。
🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
negentropy-ui 与 wiki 渲染同一份 PDF 提取语料(知识库文档详情页 / 静态站), 此前仅 wiki 挂载净化插件,两端行为不对称。本次同步挂载。 挂载范围经循证扩大至全局链 defaultRemarkPlugins(非仅文档渲染处):实测 「输入 $3/ 百万 token ,输出 $15/ 百万 token」在未净化链下正文被打乱重复 (`$15` 段渲染成 `$3` 段、中文空格被吞)并触发 5 次 KaTeX 告警——该缺陷源自 remark-math 对相邻货币符的通用误配对,非 PDF 语料专属,而 LLM 回复中报价文本 极常见,故 MessageBubble 等 5 个消费点均需覆盖。 实现要点: - 补 unified@^11.0.5 / unist-util-visit@^5.0.0 显式声明。二者是 remark-math 的 传递依赖,pnpm 严格隔离下未提升至 negentropy-ui,直接复制插件会 TS2307 + 运行时解析失败(同 @types/hast 未 hoist 之坑)。版本与 wiki 端对齐, lockfile 仅新增 2 条声明、复用既有解析,无新包引入。 - 插件采孪生副本而非提为共享包:agents-chat-core 是 AGUI 协议层专属包(tsup 构建), wiki 无 workspace 依赖且以 GitHub Pages 为出口,为单个插件引入构建链爆炸半径过大 (参照 rehype-notranslate 亦为单端持有)。两端文件头互加交叉标注约束单边漂移。 - 修正两端测试中 NBSP 归一化断言,改用显式 转义(字面空格与 NBSP 形近, 与 CJK 字形混淆同源)。 验证:ui 全量 1006 项(122 文件)通过、lint 与 typecheck/typecheck:test 零错误、 next build 成功且 KaTeX 告警计数为 0;wiki 全量 122 项通过无回归;摘除插件做变异 回退确认 4 项新用例(含 DocumentMarkdownRenderer 端到端护栏)均红灯;孪生副本 代码体经 diff 核对逐字节一致。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
remark-math-sanitize 因构建边界无法提为共享包,以逐字节副本形式在 wiki 与 ui 两处持有。副本的固有风险是单边漂移:改了一处忘了另一处,缺陷从此静默分叉。 此前仅靠文件头注释约束,本次补上机器执法。 实现(照仓库既有 version-sync-check 三件套范式): - scripts/check_twin_files.py:PEP723 内联依赖脚本,登记表显式列出每组副本 (不用 glob 或内容嗅探猜测),精确字节相等比对,漂移时打印统一 diff 指明 行号与同步方向。只读不自动同步——哪份权威取决于改动意图,机器不该代猜。 - 两端副本的交叉标注改写为对称形式(同时列出全部路径、文字一致),使两文件 逐字节相同。校验遂退化为精确相等,零启发式;连「注释说 A 代码做 B」这类 最危险的漂移也在射程内(启发式剥离注释会放过它)。 - pre-commit 钩子 + CI workflow 双侧执法(后者兜底 --no-verify 绕过的提交)。 - 脚本自检触发覆盖:登记路径若未出现在 pre-commit 的 files 正则与 CI 的 paths 里则报错。二者是独立于登记表的第二/三份清单,漏配会使执法对新增副本组静默 失效,此自检把该风险闭合在脚本内。 验证:四态实测——通过 exit 0;代码漂移 exit 1 并输出精确 diff;副本缺失 exit 1; 纯注释漂移亦被捕获。覆盖自检注入未登记副本组后 exit 1 且点名两份触发清单。 pre-commit 全量 18 钩子通过(含新增 Twin files consistency),逐条暂存验证钩子 Passed 而非 Skipped;wiki 122 项、ui 1006 项测试无回归。 注:曾试图顺带给 scripts/ 加 ruff 门,因该目录不在任何 app 的 [tool.ruff] 覆盖内 会吃默认行宽 88(仓库约定 120),且会对既有 sync_versions.py 提出 3 项无关改动, 已撤回以守最小干预;新脚本自身按 120 行宽通过 ruff lint 与 format。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
next build静态页生成期输出百余条 KaTeX 告警(unicodeTextInMathMode/commentAtEnd/unknownSymbol),且不只是噪音——PDF 提取语料存在三类实际渲染缺陷:$误配对:正文三轮调用总共 $0.022 ——看似很便宜…约为 $0.029的相邻货币符被 remark-math 误配成行内公式,中间整段中文以 math mode 渲染(错位不可读);$11.5%\to15.0%$中%是 TeX 注释符,渲染时吞掉其后内容(只显示11.5),属内容丢失;‖/∥/•无 KaTeX 字形度量,渲染为 tofu 方框。output: "export"静态产物不消费 NFT trace,next.config.ts 已有决策注释),本 PR 不处理。核心变更
apps/negentropy-wiki/src/components/markdown/remark-math-sanitize.tsremark 插件(挂 remark-math 之后、rehype-katex 之前):\text{}后)含 CJK → 判定货币误配对,还原为正文 text 节点(补回字面$);合法 display 公式不受影响;%转义:未转义的%→\%,修复注释吞内容;‖→\Vert、∥→\parallel、•→\bullet(Pandoc texmath 同款归一化思路);display 下标裸 CJK(_{常数 2})包进\text{}走文本模式。MarkdownRenderer.tsx注册插件(一行改动)。node.value+data.hChildren内 hast text 副本,层级 inlineMath/display 不同),remark-rehype 走后者——只改node.value不会到达 KaTeX,插件递归同步两份副本。风险与回滚
\text{}后再测 CJK」限定误配对场景;\text{中文}合法用法有回归用例保护);值变换仅限数学体片段,\text{}内字符保持原样。remarkPlugins数组移除remarkMathSanitize一项即整体失效,插件文件可独立删除,无其他耦合。验证证据
pnpm --filter negentropy-wiki test117/117 全绿(4s),新增 9 条用例覆盖四类病灶 + 「渲染零 KaTeX 告警」循证断言(spy console.warn);next build复验,KaTeX 告警 164 → 0(170/170 页全部生成),仅剩定性保留的 1 条 NFT 告警;$字面可见、15.0%完整渲染、‖字形正常、常数在<mtext>文本模式);影响范围
negentropy-wikiMarkdown 渲染管线(渲染层修复,对全部既有导出内容即时生效,无需重提取语料);Next Best Action
$做源级转义从源头消除误配对,涉及重提取策略建议另开任务评估;渲染层插件已兜底,无紧迫性。