R8.4: ElyMark typesets inline formulas; \( and \[ read as math
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
10 files changed
+64
-15
No files matched your search
Generated
+1
-1
@@ -1986,7 +1986,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ely-gpui-component"
|
||||
version = "0.1.1"
|
||||
source = "git+https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components?rev=7d704d97f40a9d47c08891c35d7dbe26a2220e55#7d704d97f40a9d47c08891c35d7dbe26a2220e55"
|
||||
source = "git+https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components?rev=de961eb164c1c88797ea35f0860aba9d18c95e4f#de961eb164c1c88797ea35f0860aba9d18c95e4f"
|
||||
dependencies = [
|
||||
"alacritty_terminal",
|
||||
"anyhow",
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ jiff = "0.2"
|
||||
anyhow = "1"
|
||||
directories = "6"
|
||||
dunce = "1"
|
||||
ely-gpui-component = { git = "https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components", rev = "7d704d97f40a9d47c08891c35d7dbe26a2220e55" }
|
||||
ely-gpui-component = { git = "https://git.zacharyzhang.com/ZacharyZhang-NY/Ely-GPUI-Components", rev = "de961eb164c1c88797ea35f0860aba9d18c95e4f" }
|
||||
env_logger = "0.11"
|
||||
gpui = { package = "gpui-pre", version = "=0.3.8", default-features = false, features = ["stacker"] }
|
||||
gpui_platform = { package = "gpui-pre-platform", version = "=0.3.8", features = ["font-kit", "wayland", "x11"] }
|
||||
|
||||
@@ -40,7 +40,7 @@ site/ 官网(Vite 8、pnpm、TypeScript,无框架;等轴 SVG 积木
|
||||
|
||||
## 组件映射
|
||||
|
||||
依赖 `ely-gpui-component`(pin 7d704d9,gpui 为 crates.io 的 `gpui-pre` =0.3.8)。名字取自 `reference/Ely-GPUI-Components/src`。gpui 用法规则见该仓库 `AGENTS.md`。`tests/scripts/agents_md.py` 核对下表每个名字都是组件库公开项。
|
||||
依赖 `ely-gpui-component`(pin de961eb,gpui 为 crates.io 的 `gpui-pre` =0.3.8)。名字取自 `reference/Ely-GPUI-Components/src`。gpui 用法规则见该仓库 `AGENTS.md`。`tests/scripts/agents_md.py` 核对下表每个名字都是组件库公开项。
|
||||
|
||||
| 需要 | 用 |
|
||||
| --- | --- |
|
||||
@@ -80,7 +80,7 @@ site/ 官网(Vite 8、pnpm、TypeScript,无框架;等轴 SVG 积木
|
||||
| 幻灯片缩略图条(`documents::PageThumbnailList` 只收图片路径,无隐藏标记、右键菜单与重排) | `apps/ely-show` 的 `slides.rs`,内核按页绘制到内存图 |
|
||||
| PDF 页面缩略图(同上,且一次铺全部页,不合 PERF-05) | `apps/ely-pdf` 的 `side.rs`,`uniform_list` 只画可见行,worker 按需渲染 |
|
||||
| 演示的参考线:LOK 不把参考线画进图块,也无参考线接口 | 补丁 0027 读写参考线;`apps/ely-show` 的 `guides.rs` 画在画布上,拖动移动,拖出幻灯片即删除 |
|
||||
| gpui 文本里不能嵌图片:行内公式无从排版 | 组件库的 `MarkdownRenderer` 把行内公式显示为 TeX 原文(着色),块公式才排版 |
|
||||
| gpui 文本里不能嵌图片:行内公式无从排版 | 组件库 `render/math_text.rs`:以不断行的空格占出公式的宽(整个公式作一个词折行),排好的公式画在其上,按下处读回公式的原文 |
|
||||
| `A11yChecker` 的 `audit` 与对照表是私有的;Omarchy 色板要照同一套规则 | `ely-ui` 的 `omarchy/palette.rs` 抄了对照表。上游待办:公开 `audit` |
|
||||
| 组件无 role/aria 语义:菜单、列表等控件在 AX 树仍不可见 | 上游已修核心控件(7380afb:Button、TextInput、Tabs、面板行、对话框等);其余上游待办。项目自绘控件已自带 |
|
||||
| gpui 无 aria-disabled API(`AriaProperties` 无 disabled 字段) | 组件 7380afb 起以本地化 aria_description 表达;上游待办:gpui 补 API |
|
||||
@@ -320,3 +320,4 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely
|
||||
- 2026-10-16(用户定):ElyMark 打开的块保持原样(R7.5)。组件库 bff7ebc 起,可视模式里按下的块以原文显示在它合上时的框里(同样的边距与透明边框),字号、行高与颜色同合上时:段落、列表、引用等为正文,标题按其级数的字号、1.3 倍行高、加粗(六级为次要色),照原文写出的块(链接定义等)为等宽次要色;不再加深色底板与另一套边距,按下前后不挪位置。代码块、块公式与 front matter 仍有自己的底板(代码与 front matter 为等宽小号,front matter 为次要色,同合上时)。输入框的着色(源码模式同用)给标题与粗体同一字重(原为半粗,压过所设的加粗),六级标题里的字照为次要色(行内代码照为正文色,2e65b05),front matter 照 front matter 读(原读成分隔线加标题,键名变亮变粗)(1ff993d、962964e)。表格单元格照旧。打字机模式的居中另按两端余量判定(原只按块高与视图高,打开前后同高时首块不再居中)。同批带入组件库 cdc5ce8(标题栏拖动区里的控件按下归控件,Windows)。Windows 真窗口核对(`.work/r75`):段落、三级标题、代码块打开前后位置相同。
|
||||
- 2026-10-18:Word 公式(R8.2,Gitea #9)。附件 math.docx 的六类公式逐类核对(本机无 Word,以文件所写为准):键盘输入、OMML(内核转为公式对象)、MathType(OLE,显示随带的 WMF 预览)、上下标、图片原本就对;差别在两处根因。其一,运行的 `w:position`(升降)原先只给文字,图片与 OLE 公式所在的运行失去它(25 张图片与一个 ½ 浮在行上):补丁 `0049-writer-inline-objects-move-with-their-run.patch` 把它作为固定升降写到对象的锚字符上(按锚字符自己的字号换算百分比,不扩展到其后的文字),版面让“作为字符”的对象随锚字符的固定升降移动(vertAlign 的自动上下标不动对象,同原样);各导出本就写出锚字符的升降,DOCX 往返仍为 `w:position`。其二,EQ 域原先只认 `\o`、`\s\do` 与注音,其余(如分数 `\f`)整个消失:补丁 `0050-writer-eq-field-parser.patch`(读法)与 `0051-writer-eq-fields-as-formulas.patch`(导入)把 EQ 域转为公式对象:`\f` 分数、`\r` 根式、`\s` 上下标、`\b` 括号、`\l` 列表、`\a` 阵列、`\i` 积分与求和求积;`\x` 与 `\o` 只留内容(无框、无叠印),`\d` 只前移,`\ai`、`\di` 只是行距(不升降),开关不分大小写;每个命令字符保留其运行的上下标(Word 照此画),同一段上下标里字样变了仍是一个上下标;斜体字母写成标识符(StarMath 与 OMML 都画成斜体,DOCX 往返不丢),斜体的数字与符号写成 `ital` 文字,存为 DOCX 后成正体(OMML 无此写法,已知限制);没有底的上下标以空文字为底(空的底在 OMML 里是占位符,重开成 `<?>`);公式取域的字号;读不通的命令以其域代码显示为文字,不消失。只有整个域是 `\s\do N(文字)` 时照原样成为下移的文字,其余都经读法(原先小写的 `\s\do` 读到第一个括号即止,其后丢失)。`client/tests/word.rs` 以 `tests/fixtures/office/word.docx`(由 `.work/r8/gen/eq.py` 生成,不入库)核对公式文本(含开头的空格、大写开关、读不通的域、字样变化的下标、`\ai`、`\di`、小写 `\s\do` 的尾部与嵌套)、DOCX 往返后的斜体、下标与无占位符、锚字符的升降与图块里图片低于文字(去掉版面的升降即失败)。审查三轮:第 3 轮的四处已修并以上述测试核对,未再审查(每条至多三轮)。仍与 Word 不同:编辑区里公式与图片四周有内核的辅助框线(`ShowBoundaries`,视图辅助,不印出);DOCX 另存后重开行距变宽,因内核导出改写文档默认字体与段距,与公式无关。
|
||||
- 2026-10-18:工作表过多时标签条(R8.3,Gitea #8)。组件库 `navigation::Tabs` 横排时可横向滚动(滚轮同样),标签可窄于自然宽度;所选标签在所选或标签条宽度变了时滚入视口,在绘制时以刚排好的宽度判定(原先只在首帧滚一次,其后右栏打开、标签条变窄,所选标签被挤出视口);手动滚动保留到二者之一再变;横排的标签至多与标签条同宽,名字过长以省略号结尾(组件库 e56a343、3a68d1b、7d704d9,同批带入上游列外壳拖动的四个提交)。ElyTable 的标签条随之收缩,添加按钮留在其旁;标签条的状态按工作簿各记一份(元素 id 带标签号),切到另一工作簿时其所选标签照样滚入。`navigation/tests/tabs.rs` 以 30 个标签核对:首帧滚到所选、滚轮回到第一个、新选的滚入、变窄后所选仍在末端(去掉按宽度判定即失败)、长名的所选标签整个在标签条内(去掉宽度上限即失败);ElyTable 的 `tests/strip.rs` 以 `sheets::strip` 画两个各有 30 张表、都选第 30 张的工作簿,滚回开头后来回切换,所选标签每次都在标签条内(两个工作簿共用一个 id 即失败)。Windows 真窗口(`.work/r8/strip3.png`):30 张表、第 30 张为当前,1100 宽时标签条末端为它。
|
||||
- 2026-10-18:ElyMark 公式(R8.4,用户定两项都做)。行内公式照块公式由 RaTeX 排版(原只显示着色的 TeX 原文):gpui 的文本里放不进图片,组件库 `render/math_text.rs` 把每个行内公式换成等宽的不断行空格(U+00A0,按字体量出个数),排好的公式居中画在其上,行高随最高的公式撑开;空格串与词一样整个折到下一行,画在其所在行(折行处的序号 gpui 读作上一行末);按下与右键所在的字节经换算读回公式的原文;排不出的公式照旧显示 TeX 原文,其后以危险色写出 RaTeX 给的原因与位置,记警告(不含公式)。`\(…\)` 读作行内公式,`\[…\]` 读作块公式(ChatGPT 等常写的分隔符;GitHub 不认,Typora 默认不认):解析前逐字节把成对的分隔符换成 `$`(长度不变,位置照旧对得上)。成对只在同一段落、标题或单元格里(跨列表项、CR 空行不成对);不跨代码、公式、HTML 标签、链接地址与引用标签、图片、脚注引用,`<code>`、`<kbd>` 之间(含嵌套;交叉闭合照可视的读法关闭与重开)的文字照原文;`\\(` 不换。公式里与段落里另有的 `$`(含 `\$`)解析时暂写成文本里没有的控制字节,解析后还原,不与换上的 `$` 配对;相邻的两个公式之间暂插一个空格,解析后去掉,仍是两个公式。公式节点的范围是整对分隔符,值是写下的 TeX 原文。独占一段的 `\[…\]` 为块公式(段首可有一至三个空格)。组件库公开 `documents::markdown_tree`,ElyMark 的 HTML、PDF、纯文本导出都经它解析(`markdown_options` 不再公开),纯文本里独占一段的公式照块公式写其 TeX。同时查出(组件库 e095f06):RaTeX 的 SVG 以 pt 定尺寸,usvg 按 px 量墨迹,两者差 4/3,每个公式的画面右侧与下方多出约四分之一的空白(块公式因此偏左)、导出的公式比正文大 4/3;现生成时即把根改为 px。`markdown/tex/tests.rs` 与 `tree/tests.rs` 核对分隔符的各种情形(相邻、`\$`、链接地址、`<code>`、跨块),`math_text.rs` 的窗口测试核对公式排进并读回原文、折到第二行的公式画在第二行首(改回按起点定位即失败)、排不出的公式写出原因(组件库 a20e712、5fba7b3、de961eb),`math/tests.rs` 核对画面与公式同宽(改回 pt 即失败),ElyMark 的 `visual.rs` 核对导出与纯文本。Windows 真窗口(`.work/r8/mark/visual2.png`):`$…$`、`\(…\)` 排在行内,`\[…\]` 居中成块,行内代码与转义的 `\\(` 照原文。
|
||||
@@ -10,7 +10,7 @@ mod tests;
|
||||
|
||||
use std::{io, path::Path};
|
||||
|
||||
use ely_gpui_component::documents::markdown_options;
|
||||
use ely_gpui_component::documents::markdown_tree;
|
||||
|
||||
pub use files::{Format, Target, write};
|
||||
pub use pictures::{Pictures, picture_file};
|
||||
@@ -43,8 +43,7 @@ pub fn body(text: &str, beside: Option<&Path>, pictures: &Pictures) -> io::Resul
|
||||
|
||||
/// `text`'s body; `placed` keeps what it copied.
|
||||
fn page_of(text: &str, placed: &mut pictures::Placed) -> io::Result<Page> {
|
||||
let tree = markdown::to_mdast(text, &markdown_options())
|
||||
.map_err(|error| io::Error::other(error.to_string()))?;
|
||||
let tree = markdown_tree(text);
|
||||
let mut page = Page::default();
|
||||
html::write(&tree, text, placed, &mut page)?;
|
||||
log::info!(
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
use std::io;
|
||||
|
||||
use ely_gpui_component::documents::{
|
||||
MarkdownBlock, MarkdownReader, alert, is_toc, markdown_options,
|
||||
MarkdownBlock, MarkdownReader, alert, is_toc, markdown_tree,
|
||||
};
|
||||
use markdown::mdast::Node;
|
||||
|
||||
/// `text` as plain text, a blank line between blocks.
|
||||
pub fn plain(text: &str) -> io::Result<String> {
|
||||
let tree = markdown::to_mdast(text, &markdown_options())
|
||||
.map_err(|error| io::Error::other(error.to_string()))?;
|
||||
let tree = markdown_tree(text);
|
||||
let reader = MarkdownReader::joined(text, &tree);
|
||||
let mut blocks = Vec::new();
|
||||
// Alerts and `[toc]` live only at the root.
|
||||
@@ -75,7 +74,15 @@ fn block(reader: &MarkdownReader, node: &Node, blocks: &mut Vec<String>) {
|
||||
block(reader, child, blocks);
|
||||
}
|
||||
}
|
||||
Node::Paragraph(_) | Node::Heading(_) => blocks.push(words(reader, node)),
|
||||
Node::Paragraph(_) => {
|
||||
let mut read = Vec::new();
|
||||
reader.block(node, &mut read);
|
||||
match read.as_slice() {
|
||||
[MarkdownBlock::Math(tex)] => blocks.push(tex.clone()),
|
||||
_ => blocks.push(words(reader, node)),
|
||||
}
|
||||
}
|
||||
Node::Heading(_) => blocks.push(words(reader, node)),
|
||||
Node::Html(_) => {
|
||||
let mut read = Vec::new();
|
||||
reader.block(node, &mut read);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Exports read the file as the visual mode does (R4.4).
|
||||
|
||||
use super::{Pictures, page, plain};
|
||||
use crate::output::{Page, html::write, markdown_options, pictures::Placed};
|
||||
use crate::output::{Page, html::write, markdown_tree, pictures::Placed};
|
||||
|
||||
fn html(text: &str) -> String {
|
||||
page(text, None, &Pictures::Inline).html
|
||||
@@ -160,7 +160,7 @@ fn notes_under_deep_marks_write_in_linear_time() {
|
||||
"<b>".repeat(count),
|
||||
"x[^n] ".repeat(count)
|
||||
);
|
||||
let tree = markdown::to_mdast(&source, &markdown_options()).expect("parsed");
|
||||
let tree = markdown_tree(&source);
|
||||
let mut placed = Placed::new(None, &Pictures::Inline);
|
||||
let start = std::time::Instant::now();
|
||||
write(&tree, &source, &mut placed, &mut Page::default()).expect("written");
|
||||
@@ -237,3 +237,17 @@ fn a_soft_break_joins_in_exports_as_typora_exports_it() {
|
||||
assert!(page.contains("<p>你好 测试<br>end</p>"), "{page}");
|
||||
assert_eq!(text("你好\n测试\n"), "你好 测试\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tex_delimiters_export_as_formulas() {
|
||||
let source = r"a \(x^2\) b
|
||||
|
||||
\[
|
||||
y+1
|
||||
\]
|
||||
";
|
||||
let page = page(source, None, &Pictures::Inline);
|
||||
assert_eq!(page.html.matches("<svg").count(), 2, "{}", page.html);
|
||||
assert!(page.formulas.is_empty(), "{:?}", page.formulas);
|
||||
assert_eq!(text(source), "a x^2 b\n\ny+1\n");
|
||||
}
|
||||
+3
-2
@@ -291,5 +291,6 @@
|
||||
- [x] R8.1 深色外观下内容照文件原色(§5,用户定,取代 2026-10-04 的“内容区随系统深浅色”):ElyPDF 页面不反相;ElyDoc 页面、ElyTable 单元格照文件的颜色(白底即白底),ElyShow 已是如此(`ely.xcd` 只留浅色方案,每个视图首帧发一次;MuPDF 不再反相;Windows 真窗口深色外观下四个应用都是白纸;测试以深色档案起内核、视图须把页面画白,去掉发送即失败 — 第 1 轮:`theme.sh` 仍要深色网格、测试的内核本就浅色;第 2 轮:两处注释超长;第 3 轮 PASS)
|
||||
- [x] R8.2 Gitea #9 公式不兼容(§7):附件 math.docx 的键盘公式、OMML、MathType(OLE)、EQ 域、上下标、图片公式逐类与 Word 对照,查明各类差异的根因并修;修不了的写明原因与证据(补丁 0049:运行的 `w:position` 随锚字符移动图片与 OLE;0050、0051:EQ 域转为公式对象,读不通的显示域代码;`word.rs` 三项测试;第 3 轮四处修后未再审查)
|
||||
- [x] R8.3 Gitea #8 工作表过多时标签条不滚动(§9):活动工作表变化时标签条滚动,使该标签完整可见;被裁到窗口外的工作表可经标签条到达(组件库 7d704d9:按所选与宽度滚入、长名有上限;ElyTable 标签条按工作簿各记状态;`tabs.rs` 与 `strip.rs` 测试 — 第 1 轮:共用 id、长名越宽;第 2 轮:每工作簿状态无测试;第 3 轮 PASS)
|
||||
- [ ] R8.4 ElyMark 公式(§14):行内公式排版(原只显示着色的 TeX 原文);`\(…\)` 读作行内公式,`\[…\]` 读作块公式
|
||||
- [ ] R8.5 答复 #8、#9,修好的关闭;`agents.md` 随之
|
||||
- [x] R8.4 ElyMark 公式(§14):行内公式排版(原只显示着色的 TeX 原文);`\(…\)` 读作行内公式,`\[…\]` 读作块公式(组件库 dceca9f、e095f06、a20e712、5fba7b3、de961eb;`tex/tests.rs`、`math_text.rs` 与 ElyMark `visual.rs` 测试 — 第 1 轮:折行处的公式画错行、相邻公式合并、链接地址与 `<code>` 被换、`\$` 被拒、跨块成对、行内错误不显示、注释超长;第 2 轮:段首空格的块公式、嵌套 `<code>`、注释超长;第 3 轮:交叉闭合的标签,修后以测试核对,不再审查)
|
||||
- [ ] R8.5 发布 0.1.8(用户 2026-10-18 定,要快):版本号,打标签由发布流程三端建包、签名公证、上传
|
||||
- [ ] R8.6 答复 #8、#9,写已修于 0.1.8,修好的关闭;`agents.md` 随之
|
||||
@@ -0,0 +1,17 @@
|
||||
FAIL
|
||||
|
||||
1. `../Ely-GPUI-Components/src/documents/render/math_text.rs:182`:U+00A0 占位不能保证公式整体换行;当前 GPUI 会在这些字符之间断行,图片却仍从占位起点整张绘制。160px 宽的段落显示 `aaaaaaaaaa $x^2+y^2=r^2$ tail` 时,探针测得同一公式占位从 `(105.6, 0)` 跨到 `(76.8, 26)`,公式越过右边界,下一行留下空位,点击位置也不再对应画面。不符合 R8.4 的行内排版,`agents.md` 的“不断行”说明亦不成立。修正方向:让公式宽度以不可拆分的单元参与换行,并测试公式接近行尾时的排版与命中。证据:`.work/r84-r1-probe-tests.log` 的 `formula_space_is_indivisible`;原有窗口测试未覆盖换行。
|
||||
|
||||
2. `../Ely-GPUI-Components/src/documents/markdown.rs:64`:把两端替换为 `$ ` 和 ` $` 会把相邻公式的边界拼成 `$$`。`\(x\)\(y\)` 实际变成 `$ x $$ y $`,只解析出一个内容为 `x $$ y` 的公式;`$x$\(y\)` 同样合并。可视模式与导出都失去原来的两条公式。修正方向:保留每对分隔符的独立公式节点,避免转换产生新的美元符号连续串,并覆盖两种分隔符相邻的组合。证据:`.work/r84-r1-probe-tests.log` 的 `adjacent_formulas_remain_distinct`、`.work/r84-r1-parser.log`。
|
||||
|
||||
3. `../Ely-GPUI-Components/src/documents/markdown.rs:40`:保护范围没有排除链接和图片的目标地址,整文件扫描会把地址里的转义括号当公式。合法的 `[go](https://e.test/\(x\))` 原本指向 `https://e.test/(x)`,现在变成正文碎片与指向 `https://e.test/$` 的错误链接;`.png)` 则不再是图片。违反 MARK-03,也影响使用同一解析入口的输出。修正方向:只在允许公式的正文范围转换,保留目标地址、标题和定义的语法;增加地址含转义括号的回归测试。证据:`.work/r84-r1-probe-tests.log` 的 `links_and_images_keep_their_addresses`、`.work/r84-r1-parser.log`。
|
||||
|
||||
4. `../Ely-GPUI-Components/src/documents/markdown.rs:62`:只要内容出现 `$` 就拒绝整对分隔符,连合法的 TeX 转义 `\$` 也拒绝。`\(\$5\)` 因此显示为普通文字 `($5)`,没有公式节点,而相同的 `\$5` 可由本项目的 RaTeX 正常排版。不符合 R8.4 的 `\(…\)` 支持。修正方向:按 TeX 的转义语义处理内容,不能用任意美元符号否决整对分隔符;覆盖含 `\$` 的行内与块公式。证据:`.work/r84-r1-probe-tests.log` 的 `escaped_dollar_is_valid_tex` 先确认排版成功,再在公式节点数量上失败。
|
||||
|
||||
5. `../Ely-GPUI-Components/src/documents/markdown.rs:56`:配对状态只在 LF 空行处清除,可以跨两个不同的 Markdown 块配对,且漏掉 CR 换行的空行。两项列表 `- \(a\n- b\)` 原本分别显示 `(a`、`b)`,现在分别显示 `$ a`、`b $`;`\(a\r\rb\)` 也会凭空出现美元符号。转换既未形成公式,又改变了普通文本。修正方向:按实际块边界限定配对范围,并使用 CommonMark 支持的 LF、CRLF、CR 换行规则;覆盖跨列表项和 CR 空行。证据:`.work/r84-r1-probe-tests.log` 的 `unrelated_blocks_do_not_acquire_dollars`、`.work/r84-r1-parser.log`。
|
||||
|
||||
6. `../Ely-GPUI-Components/src/documents/markdown.rs:44`:仅保护 `Html` 节点的标签字节,没有保护 HTML 代码标签的正文。`a <code>\(x\)</code> b` 中的代码内容被转换成公式节点,渲染时会排成公式,失去应展示的代码文字,与 `agents.md` 所称代码、HTML 中不转换不符。修正方向:识别并保留 HTML 代码内容的范围,使解析、可视显示与导出都保持代码语义;增加 `<code>` 内分隔符的回归测试。证据:`.work/r84-r1-probe-tests.log` 的 `html_code_stays_literal`。
|
||||
|
||||
7. `../Ely-GPUI-Components/src/documents/render/math_text.rs:187`:行内排版失败时直接丢弃 `MathError`,只记固定警告,界面保留着色 TeX 而没有错误原因或位置。例如 `$x^2^3$` 的错误本应是 `Double superscript at 3`,此分支不把它交给任何可见元素。违反 §14.2“语法错误显示原文与错误位置”,也违反不吞错的规则;块公式已有可见错误处理。修正方向:保留并展示行内公式的错误及位置,同时保留原文,并增加失败公式的可见错误断言;日志继续不含公式内容。
|
||||
|
||||
8. `../Ely-GPUI-Components/src/documents/tree/mod.rs:321`、`../Ely-GPUI-Components/src/typography/math.rs:196`:两条新增或改写的注释分别为 “Text split at its images; lone `$$` or `\[` math is block.” 和 “`svg`'s drawing under a root viewing `[left, top, w, h]` in px.”,按空白分词均为 12 个词,超过十词上限。修正方向:各缩至十词以内。
|
||||
@@ -0,0 +1,7 @@
|
||||
FAIL
|
||||
|
||||
1. `../Ely-GPUI-Components/src/documents/tree/mod.rs:326`:块公式的判定检查整个段落是否以分隔符开头,漏掉 CommonMark 允许的段首空格。独占一段的 ` \[x\]` 因而读成 `Paragraph` 内的行内公式,而同样内容去掉一个空格即读成 `Math`,违反 R8.4 的块公式要求。修正方向:从公式节点的原文范围识别分隔符,正确处理段首一至三个空格,并补回归测试。实测:`.work/r84-r2-review/component-probes.log` 的 `review_r84_display_math_accepts_prose_indentation` 失败。
|
||||
|
||||
2. `../Ely-GPUI-Components/src/documents/markdown/tex.rs:100`:HTML 代码保护只记一个标签,遇到同名内层标签的关闭即清掉保护,外层仍未关闭。`a <code><code>\(x\)</code> \(y\)</code> b` 中的 `\(y\)` 被转成公式;组件读出的文字由 `a (x) (y) b` 变成 `a (x) y b`,并给 `y` 加上 `Math` 样式。这仍会把代码内容排成公式,违反 MARK-04 与 `agents.md` 的代码保护说明;第 1 轮第 6 项只修好了非嵌套情形。修正方向:按现有 HTML 读者的嵌套与闭合规则维护保护范围,覆盖嵌套的 `code`、`kbd`。实测:`.work/r84-r2-review/component-probes.log` 的 `review_r84_nested_code_stays_literal`、`review_r84_nested_code_keeps_its_text_and_styles` 均失败。
|
||||
|
||||
3. `../Ely-GPUI-Components/src/typography/math.rs:196`、`../Ely-GPUI-Components/src/documents/markdown/tex.rs:244`:注释 “`svg` drawn in a px root viewing `[left, top, w, h]`.” 与 “Restores a text's dollars; drops a parting space at its ends.” 按空白分词均为 11 词,仍超过十词上限;前者是第 1 轮第 8 项未修完的问题,后者为本轮新增。修正方向:各缩至十词以内。证据:`.work/r84-r2-review/rules.log`。
|
||||
@@ -0,0 +1,3 @@
|
||||
FAIL
|
||||
|
||||
1. `../Ely-GPUI-Components/src/documents/markdown/tex.rs:109`:代码保护的新栈只删除同名标签,没有遵循 `Reader::end` 的闭合与重开规则。`a <code><kbd>x</code> \(y\) b` 中,读者在 `</code>` 处同时结束不会重开的 `kbd`,其后的文字已是普通正文;保护栈却仍保留 `kbd`,把正文保护到段末,导致 `\(y\)` 不被识别为公式。实测可视读法为 `a x (y) b`、没有 `Math` 样式,纯文本导出也多出括号;`a <b><kbd>x</b> \(y\) b` 同样失败。违反 R8.4 与 MARK-04/11。修正方向:让保护范围与现有 HTML 读者采用相同的标签闭合、内层清理和重开规则,并覆盖交叉闭合后恢复公式识别的情形。证据:`.work/r84-r3-review/probe-tests.log` 中三个失败探针;第 2 轮的段首缩进与正常嵌套探针均已通过。
|
||||
Reference in new issue
Block a user