diff --git a/PRD.md b/PRD.md index 2009a05..0cc5074 100644 --- a/PRD.md +++ b/PRD.md @@ -487,7 +487,7 @@ Git 托管、PR 审核平台、Issue 系统、CI 平台和远程开发环境不 | MARK-01 | 本地文件 | 新建、打开、保存、重命名和另存;支持直接打开文件或文件夹 | | MARK-02 | 编辑模式 | 可视化、源码和只读预览可切换;切换本身不修改文件内容 | | MARK-03 | Markdown | 支持 CommonMark 与 GFM 常用语法:标题、列表、任务、引用、链接、图片、表格和代码块 | -| MARK-04 | 扩展语法 | 支持脚注、数学公式、Mermaid 与 YAML front matter;照 Typora 默认显示 `:表情:`、行内与块级 HTML 的常用标签、GitHub 提示块与 `[toc]` 目录;`==`、`^`、单个 `~` 照 GFM,不作高亮、上下标;Typora 与 GitHub 读法不同处随 GitHub(表情名、标签与强调交叉);资源随包提供 | +| MARK-04 | 扩展语法 | 支持脚注、数学公式、Mermaid 与 YAML front matter;照 Typora 默认显示 `:表情:`、行内与块级 HTML 的常用标签、GitHub 提示块与 `[toc]` 目录;`==`、`^`、单个 `~` 照 GFM,不作高亮、上下标;Typora 与 GitHub 读法不同处随 GitHub(表情名与转义、标签与强调交叉);资源随包提供 | | MARK-05 | 导航 | 提供文件树、文档大纲、多标签、最近文件和按标题跳转 | | MARK-06 | 编辑工具 | 支持查找替换、源码正则搜索、缩进、列表续写、表格行列操作和代码高亮 | | MARK-07 | 附件 | 支持拖放和粘贴图片,默认复制到文档旁的资源目录并写入相对路径 | diff --git a/agents.md b/agents.md index 43ec41a..c04c986 100644 --- a/agents.md +++ b/agents.md @@ -286,4 +286,4 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely - 2026-10-11(用户定:ElyMark 不用 CEF,不用 Electron):ElyMark 改为原生。界面用组件库的 Markdown 组件(`documents::MarkdownEditor` 一族,缺的在组件库补并推到 Gitea),解析用 markdown-rs(`markdown` 1.0.0),公式用 RaTeX,Mermaid 用 mermaid-rs-renderer,PDF 用 MuPDF Story;CEF 随之删去,ElyMail 的正文也不用 CEF 与 Electron。进度在 `tasks/TASKS.md` 的 C14。组件库 fcad0ff 与 508cc55:`MarkdownRenderer`、`MarkdownEditor`、Markdown 着色、块范围与链接查找改读 markdown-rs 的语法树(GitHub 风格加公式),引用式链接与图片按定义解析,图片把所在段落分开,单行 `$$…$$` 为块公式,软换行(LF、CRLF、CR)读作空格,嵌套在引用与列表里的定义同样解析,强调与链接里的图片仍是图片(链接里的图片可按);`BlockEditor` 的导入导出不属 ElyMark,仍用 pulldown-cmark。markdown-rs 读嵌套图片时只留外层的说明。组件库 d5ecc5a:块公式经 `typography::Latex` 由 RaTeX 排出(字形为轮廓,按窗口缩放画),```` ```mermaid ```` 块经 `documents::Diagram` 由 mermaid-rs-renderer 画出(Mermaid 自己的深浅主题,底色与字色取 Ely 色板),都作为 gpui 资源在后台排版,RaTeX 或 Mermaid 对已解析的输入 panic 时显示为错误;`MarkdownRenderer::base` 给出文档所在文件夹,相对与 file 地址的图片从中读取并按自身大小、不超过栏宽显示,`data:` 地址解码,网络图片不载入(写明)。组件库 ab9a14c:每个公式、图与图片元素经 `primitives::held` 持有其资源,按资源计数持有者(8b9820b;画出的图存在共享的记录里,9036c92 起由最后离开的持有者释放,哪怕它自己还没收到图),最后一个持有者换了内容或离开窗口才从 gpui 资源缓存移除、在本帧之后从图集释放,共用同一内容的元素(含 gpui 缓存的视图)不受影响;公式按字形实际范围取画框,字形不被裁;公式失败显示原因、RaTeX 给的位置与原文,日志不含公式;`file:` 地址去掉查询与片段,`localhost` 为本机,Windows 上别的主机为共享路径,他处拒绝;Mermaid 的节点与饼图文字取 Ely 的前景色。组件库 2b6f551:`documents::MarkdownDocument` 是文件级的 Markdown 文档:全文与撤销在一个 `CodeEditor` 里(`CodeEditor::highlighter` 以 `markdown_highlights` 着色,无行号);可视以 gpui `list` 逐块画出文件的顶层块(链接定义、HTML、front matter 照原文显示,每个字节都在块里或块间),按下的块开成源码(`TextInput`),其键入即刻算作文档的文字,写回为一步撤销,上下键越过块边进入相邻块,Esc 写回;Cmd(他处 Ctrl)按下交给链接;预览只读;源码为编辑器本身;128 KiB 以内当场解析,更长的在后台解析,解析中按下块不打开(日志);新解析保留两端相同的块,滚动不跳。`CodeEditor` 的撤销历史最多留 64 MiB 文字,超出先丢最旧的步;`CodeEditor::reset` 换文字且撤销重新开始;`MarkdownMode` 加 `Preview`。组件库 fc181b4:一个插入点通用于各模式(编辑器的选区,写回的块移动它);`set_caret` 与 `set_top_line` 分别设插入点与视图,换模式保持顶行;按下的块在前一块写回后仍是所按的块(按偏移换算,结构变了即不开并记日志);块是 Tab 停靠点,Enter 或空格打开;预览不收按下、撤销与重做;撤销与重做每次记录、输入法组字、撤销、重做后都限在 64 MiB 内(先丢最旧的撤销,再丢最远的重做)。组件库 433c38f:只有对当下文字的解析才能打开块(解析的文字与编辑器相同),否则拒绝;要求的顶行在其文字解析后才落定:先到所在块,下一帧按块高的比例到块内位置,再有新的要求即接着放下一个;源码与列表之间切换保持顶行,可视与预览共用一个列表,切换不动滚动。组件库 abac8b4:顶行的要求带编号,迟到的帧回调只完成自己的那个;文字一换即按新文字重新放,放时按当下文字的行数夹住;`reveal` 是同样的要求(插入点设在该行,该行放到顶上),新文字解析后才落定。组件库 f59c9f7:文字超过读取上限(2 MiB)即丢掉旧的读取,大纲与块为空。ElyMark(C14.4):视图即一个 `MarkdownDocument`,文本即文件原文(BOM 与 CRLF 照 `text.rs` 存回),新建、打开、保存、另存、重命名经外壳照旧;视图在建成后的下一轮更新向外壳报一次载入(文档在 `new` 里当场解析,外壳此时还未订阅);文字超过 2 MiB 即只用源码并转去源码(随当前文字,不只看打开时);网页实现的查找替换、表格、附件、书写视图的应用、导出与打印删去,在 C14.9、C14.10、C14.12、C14.14 原生重做。C14.5 删去 CEF:`crates/ely-web-content`、`apps/ely-mark/web`、`scripts/fetch-cef.sh`、`scripts/build-mark-content.sh`、macOS 包里的辅助应用与其授权、Linux AppImage 的 `libcef` 安排、CEF 与网页依赖的许可、存储设置里的网页缓存、`webview.sh`、`hardened-macos.sh`、`linux-mark-idle.sh`、参考源码 cef、cef-rs、milkdown、codemirror-dev;`apps::open` 不再复原信号(只为 Chromium 屏蔽的 SIGTERM 而设)。旧 C14.1 至 C14.7、R2.13 与 ElyMark AppImage 的记录(CEF 实现)删去,在 git 历史;仍在的应用行为(外部变更与比较、会话、改名、Git 状态、最近与文件夹、`look.json`)在 C14.8 至 C14.16 逐条核对后重记。用户以前的 ElyMark 数据目录里可能留着 `web` 缓存文件夹,Ely 不再读写它。组件库 6f0401e:焦点进入空的可视文档即打开末尾的输入框,新文件可直接键入(原先键入无处落下);362a0fc:换回可视时同样打开(预览与可视共用焦点,无焦点事件),全文撤销后若文档成空,读完新文字再打开末尾的输入框;639521e:只有一份撤销历史,块的输入框自己的撤销与重做从不运行:在打开的块里撤销或重做,先把块写回为一步,再走全文的历史(块内逐键的撤销没有了,一次块编辑是一步),重做跨模式、跨多次撤销都在。ElyMark(C14.6):每个标签各记其模式,切换不改一个字节(编码写出与原文相同),撤销跨模式(全文一份撤销历史);视图在模式首次可键入时记一次 `mark: shown as "…"`(源码即刻,可视与预览在块读完后),PERF-07 计到这条。Windows 上实测(Ryzen 9 9950X3D)1 MB 文档 P50 341 毫秒、P95 560 毫秒(`docs/perf/2026-10-12-Ryzen9-9950X3D.md`);macOS、Linux 与树莓派未测。C14.7:语法由 markdown-rs 读(CommonMark 加 GFM 的表格、任务、删除线、自动链接,脚注,公式),front matter 不进可视,以原文块显示在最上(组件库 parse 测试核对各种块画成内容而非原文);链接照 M-05:预览单击、可视 Cmd(他处 Ctrl)按下交应用,可视普通按下编辑该块(组件库 bbb6071 的链接测试);应用只把 http、https、mailto 交系统打开,其余以提示拒绝(应用测试);链接地址与图片读不出的原因不进日志(地址与路径属文档内容)。文档旁图片按文件所在文件夹读(`MarkView` 在打开与改名时交给组件);组件库 4801555:表格单元格也是块,图片在格内照常画出(原只画替代文字),图片取自身宽度、以所在容器为上限(单元格可收缩,窄格里的图片按比例缩小,组件库 2e196a1)。gpui 的图片加载(`vendor/gpui-pre` 的 `img.rs`):GIF 与 WebP 的坏帧即结束加载并报错(`img.rs` 的加载器与 `platform.rs` 的 `Image::to_image_data`,后者给 `data:` 图片用)(原样跳过坏帧,解码器到文件尾仍不停地报错,加载永不结束、占满一个核),错误与日志不带图片路径(原样把路径写进错误,`AssetLogger` 照写进日志);应用测试以坏 GIF 核对两处加载都结束、错误里没有所在文件夹名。C14.8:左栏三页照旧(文件夹树、大纲、搜索);大纲在纵向滚动区里(标题再多也选得到,侧栏测试以 100 个标题滚到最后),取组件按 markdown-rs 读出的标题与行,选一项即 `reveal`(该行在视图里、插入点在其上;可视模式里键入仍须先按下块);多标签与最近列表经外壳与 `recent.json` 照旧。`desk::open_in` 收数据文件夹(`open` 照旧取本机的),应用的 gpui 测试以临时文件夹起整个窗口:打开文件即有标签、大纲行号、跳转落点与最近列表,键入的标题进大纲,两个文件两个标签各有大纲,打开文件夹只列 Markdown;文件监视在真线程上,测试以 `allow_parking` 允许。`ely_ui::install_no_launch_files`(`test-support`)给测试一个空的启动文件队列。随删去的网页页面一起的 `web.*` 文案(`i18n/web.rs`)删去。C14.9(组件库 ce4a1e9):回车照列表续写(无序、有序加一、任务为未勾),空项回车即结束列表,源码与打开的块都如此,只在 markdown-rs 读作列表项且不在代码或公式里时(围栏里的 `- a` 照常换行;长文读完前源码里回车只换行),新项照所在项的引用前缀、缩进(空格或 Tab)、标记后的空白与任务框写出,父项标记处换成空格(组件库 e162082);没写正文的任务框也算空项,回车即结束列表;Shift+Tab 按列退回一级:行首的空格与 Tab 混写时,Tab 补到下一个四格位,去掉合计四列(组件库 b39097c);在空白行(含只有空格的行)插入表格即以表格取代该行(上一行有字时先空一行),免成缩进代码(组件库 cd16b20);打开的块里 Tab、Shift+Tab 把所触的行缩进或退回四格(`MarkdownDocument > ElyInput` 键位,块外 Tab 照旧在块间移动),源码由编辑器自己缩进;`MarkdownDocument::edit_table` 按插入点所在表格增删行列,`insert_table` 在插入点所在行后放一个三列表格,都为一步撤销,表格按规范写法重写(引用与列表里的表格各行照留其前缀,前缀不一即拒绝;表头之外的多余单元格照留,在其上的列操作拒绝;拒绝的原因经 `TableRefusal` 交给应用提示),预览里一切修改(表格、替换)都拒绝;`show_match` 在源码选中、可视打开其所在块并选中、预览转到其行,`replace` 一步替换(自己的写入计入,已打开的块不被关掉);文字未读完时 `show_match` 先读,长文等读完在下一帧落定(记下所等的文字版本:其间文字一变即作废,新的请求取代等着的);围栏代码按其语言着色(`forms::syntax_fenced`,散文名不着色,无名照通用着色)。ElyMark:Cmd/Ctrl+F 与“编辑›查找和替换”打开查找框(组件库 `FindWidget`,`find_all` 的大小写、全词、正则;正则写错即框内显示原因),源码里标出全部匹配与当前一处;替换一处后转到替换文字之后的下一处(到尾即回到第一处),全部替换为一步撤销;“表格”菜单插入表格与增删行列,插入点不在表格里即提示。应用测试以整窗核对计数、替换与撤销、正则错误、跳到下一处、表格菜单。C14.10(组件库 d126a7e):拖到文档上的文件与剪贴板里只有图片(没有文字)时的粘贴,组件以 `Attachment` 事件交给属主(源码、打开的块与可视无块时都接 Cmd/Ctrl+V),`MarkdownDocument::insert` 在插入点写入文字(打开的块里照键入,预览拒绝)。ElyMark 的 `attach.rs`:只收图片(png、jpg、jpeg、gif、webp、svg、bmp,别的文件提示不收),在后台复制到文件旁的 `assets/`(拖入的保留原名、重名加序号,粘贴的名为 `pasted-毫秒.扩展名`;`ely_files::import_attachment` 与新的 `write_attachment` 同一套:以 `create_new` 占名,从不覆盖,写坏即删去),完成时文件仍在原文件夹才在插入点写 `![名](assets/名)`(名中的控制字符换成空格,方括号与反斜杠转义;地址除字母数字与 `-._~` 外逐字节百分号转义;文件名不是规范文字的图片在复制前即拒绝并说明,链接从不改写文件名),否则提示图片留在哪里;未保存过的文档与预览拒绝并说明。视图的文件夹只在外壳告知已存文件的位置时才有(`MarkView::moved`),图片的读取位置随之;未命名文档没有文件夹。`Opened` 去掉(只剩源),引擎直接载入 `Source`。C14.11(组件库 e89fb32):`MarkdownDocument::reset` 换文字时保留插入点与顶行(按新文字夹住,顶行等新文字读完后落定),干净的标签接过磁盘文字即停在原处,撤销不回到旧文字;外部变更、改名跟随、删除与读错照旧(`outside.rs`;`ely_files::Fingerprint` 加上文件身份,保留修改时间的原子替换也认作变更,各应用的冲突核对同受其益;每次读盘编号,只认最新一次,落定前再核对磁盘仍是所读的那份,否则重看),比较后的合并经 `view.adopt` 为一步撤销。应用测试以整窗核对:干净重载保位与撤销止于磁盘,删除后留着文字并标为已删,改名后标签跟到新名,路径变成文件夹即标为读不出,合并为一步撤销,保留时间的替换照样重载,过期的读取不落定。C14.12(组件库 508fee9):`MarkdownDocument::set_look(DocumentLook)` 是书写视图,只管怎么显示:`measure` 给正文栏的最大宽并居中(三种模式),`font` 给可视与预览的正文字体(代码照用等宽),`scale` 乘以正文与标题的字号(可视、预览经渲染的 `Draw`,打开的块同样,源码经 `CodeEditor::set_scale`),`focus` 让可视里读者所在块之外的块、源码里插入点所在行之外的行淡到 0.35(`CodeEditor::set_focus_line`),`typewriter` 让可视里读者所在块(打开的或插入点所在的)、源码里插入点所在行居中(块、文字、键入、块高或可视区一变即重新居中;两端各留半屏余量,首末块与首末行也能居中:可视放在第一块之上与末尾项之下,源码为列表首尾的空行(行数取正文区高度的一半,绘制、输入法与点按的坐标同一原点);模式切换的定位落定后重新居中;源码在渲染时以严格居中滚动,`CodeEditor::set_typewriter`;居中记录含视图与行高;组件库 f102ea0、cf9cc19、7ed4ea8)。ElyMark 的 `look.json` 照旧(专注、打字机、窄中宽 36/48/64rem、无衬线/衬线/等宽、字号 70% 至 200%),新标签首次报到即取用,菜单一改即作用于全部标签并存下(存不下即提示);衬线字体为 Georgia(Linux 为 DejaVu Serif,未在 Linux 上核对是否装有);专注模式另收起标签条、左栏与状态栏(照旧)。搜索(C14.13,MARK-10)照旧:本文件或所开文件夹,不分大小写逐行找,打开着的文件按当前文字;每条结果另记该行第一处命中的字符列(查询与原文都逐字去掉大小写,词尾 `ς` 同 `σ`,照 Unicode 的大小写折叠;逐字对应回原文,`İ` 等变长的字照样对得上),选中即打开或转到该文件,插入点落在该处。输出(C14.14,MARK-11):“文件›导出…”(⌘E)一个对话框选 HTML、HTML 与资源文件夹、PDF、纯文本,再选位置;HTML 由 ElyMark 按 markdown-rs 的语法树逐个节点写出(`output/html.rs`:GFM 加数学,front matter 不进输出,文档里的 HTML 一律转义成文字,链接按浏览器的读法(去掉首尾空白与控制字符、删去制表与换行)判定协议,只放行无协议、网页与邮件地址,脚注照 GFM 放在页末),公式换成 RaTeX 的轮廓 SVG(组件库 `formula_svg`,黑色;RaTeX 没有轮廓而写成文字的字,与图一样经 usvg 以系统字体变成路径,找不到字体即报错;先变路径再按墨迹定边框),Mermaid 图换成浅色 SVG,经 usvg 把箭头标记与文字都变成路径(组件库 `diagram_svg`,与公式共用 `flatten`;有标签或字找不到字体即报错,不让字悄悄消失),画不出的公式与图照原代码保留,按各自所在的行提示;图片:自包含的 HTML 内嵌为 data URL,资源文件夹版拷进新建的 `名称_files`(以 `create_new` 占名,由文件系统判同名,大小写不分的盘上也不互相覆盖;文件夹已在即拒绝,写坏只删本次自己建的(以建成与否为准,不先查是否存在)),网址与 `data:image` 原样保留,读不到的在 HTML 里照原地址、在 PDF 里写成方括号里的替代文字,并都提示;纯文本取自 mdast(块间空行,表格以制表符分格,公式写 TeX)。PDF:同一页面与图片写进标签暂存目录下每次各自的文件夹,`ely-pdf-worker` 的 `HTML_PDF` 以 MuPDF 的 story 排成 A4(边距 2 厘米),MuPDF 读不了的图(WebP、网址)事先列为缺图;story 或绘制有任何警告即整份失败、不写文件(同图片导出);暂存随即删去。打印(⌘P)先写同一份 PDF(每次打印各自的文件)再交系统面板(`ely_office::print_later`)。“编辑›复制为富文本”:所选的 Markdown(源码模式里编辑器的选区,或打开的块的选区,组件库 `MarkdownDocument::selected`;可视与预览没打开块时没有选区,即全文)以同一套生成 HTML(图片内嵌)放进剪贴板,纯文本为 Markdown 本身;缺图、画不出的公式与图同导出一样提示。会话恢复(C14.15,MARK-12)照旧(`restore.rs`:`session.json` 记标签的路径、名称、模式、插入点与滚动,`look.json` 记视图设置,崩溃后未保存的文字以未命名副本回来,原文件不动);恢复点或会话写不进时,窗口以提示写明(恢复点另写明该标签上次存下的时间,未曾存下写“尚无”),同一类错误(按 `io::ErrorKind`,不按含临时文件名的原话)只提示一次,每次计时照样重试;崩溃后恢复的标签以所载恢复点的时间为“上次存下”;所记的模式改为类型化的 `Mode`(serde 按小写名),认不出的模式与其他坏字段一样使会话读不出、启动报错,不再悄悄当作可视;原由已删的 CEF 窗口脚本覆盖的重启与崩溃恢复,改由同一进程里两个 gpui 测试上下文先后开同一数据目录核对。Git 配合(C14.16,MARK-13)照旧:状态栏的 Git 项(未改动、有改动、未跟踪、已忽略、有冲突)在保存(指纹变化)后重问,按下即以该文件开 ElyTree;单测核对各状态,窗口测试核对保存后由未改动变为有改动(测试的提交关掉签名,不受用户 `commit.gpgsign` 影响)。组件库 50a59d2 至 58227cd:图在屏上的尺寸与公式的边框改用带系统字体的 usvg 读取,选字照 gpui 的渲染器(字库为系统字体加组件库资源里 gpui 自带的 IBM Plex Sans,没有字体答应的通用族改指自带字体;指名的字体族找不到即取 sans-serif,再找不到取任一字体,单个字再按字回退),导出也照此(原先用无字体的默认选项量尺寸,每张图的每个标签都记一条“找不到字体”的警告,公式的边框也算不进回退字的墨迹)。验收(2026-10-12):Windows 与 Linux(WSL)的 `packaging/stage.sh ely-mark` 带出 `ely-mark`、`ely-pdf-worker`、Git 与许可,冒烟(`ELY_SMOKE=1`,打开含公式与图的文件)均正常退出、Windows 日志无警告;macOS 只能经发布 CI 构建,本次未验证。已知限制:markdown-rs 的解析时间随块数平方增长(release,本机:短段落 1 万段 0.12 秒、2 万 0.40 秒、4 万 1.44 秒、8 万 5.5 秒,纯 CommonMark 同样),所以短段落极多的大文件导出要数秒;PERF-07 的 1 MB 样本仍在 2 秒内。Linux 上 gpui 的 SVG 渲染器找不到其自带的 Lilex 字体(共用资源里没有),每次启动记一条警告,改用系统字体,不属 ElyMark。导出不写打开着的文件(`ely_files::export` 与外壳的持有者检查)。ElyMark 因此依赖 `ely-pdf-engine`,各端的包随带 `ely-pdf-worker` 与 MuPDF、OpenSSL、Great Vibes 的许可;OCR 语言数据只随 ElyPDF。 - 2026-10-12(用户报:Windows 上 ElyMark 的最近列表显示 `\\?\C:\…`):凡取真实路径一律 `dunce::canonicalize`(ely-files 的会话登记、ely-lok 的内核目录与配置目录、ElyMark 的文件夹、最近列表、会话与标签比对;ElyTree 原已如此):Windows 上能写成普通路径即普通路径,他处同 `std::fs::canonicalize`。只供读写的路径照旧保留 `\\?\`(`ely_files::save` 的落盘与同文件判定:在 250 字的文件夹里,普通写法的暂存文件名越过 260 而写不进),保存后交给会话与 `Saved` 的路径以 `dunce::simplified` 整体判定后为普通写法;ely-office 另存的目标先以完整路径求出,再以 `dunce::simplified` 整体判定能否写成普通路径(先简化文件夹再接文件名时,结尾带空格的名字会被 Windows 削成另一个已打开的文件)。`ely_files::recent` 读入时以 `dunce::simplified` 去掉旧版写下的 `\\?\` 并去重,下次写入即为普通路径。 - 2026-10-12(用户报:ElyTable 的网格上一直是文字指针):`LokView` 原把指针写死为文字指针。现不按键的鼠标移动也交内核(悬停,不算编辑、不加修订),内核以 `LOK_CALLBACK_MOUSE_POINTER` 回报 CSS 指针名(`vcl` 的 `gaLOKPointerMap`),随事件批次到视图,换成 gpui 的指针:单元格上为箭头,编辑单元格或文字时为文字指针,链接为手;未知的名字记警告并用箭头。 -- 2026-10-13(用户定):ElyMark 以 Typora 1.14.10 为对照(R4;安装包与解包放在 `TyporaRef`,不入库):可视模式仍是按下的块以原文编辑;语法照 Typora 默认(`:表情:`、行内与块级 HTML 的常用标签、GitHub 提示块、`[toc]`、front matter 框;`==`、`^`、单个 `~` 照 GFM);快捷键照 Typora(Ctrl+1–6 标题、Ctrl+0 段落、Ctrl+/ 源码、Ctrl+Shift+=/-/0 字号、F8 专注、F9 打字机);右键菜单照 Typora 的布局,剪贴板与格式为图标行(组件库 `Menu` 新增)。Typora 与 GitHub 读同一份文件不同时随 GitHub(GFM,§14.3):表情名取 GitHub 现行的 gemoji(`emojis` 库,`:cricket:` 为蟋蟀),HTML 标签与强调交叉时照浏览器修复 CommonMark 输出,`
` 照 HTML5 也是换行;Typora 只决定哪些扩展显示。审查改用 gpt-6-astra,effort max,fast。 +- 2026-10-13(用户定):ElyMark 以 Typora 1.14.10 为对照(R4;安装包与解包放在 `TyporaRef`,不入库):可视模式仍是按下的块以原文编辑;语法照 Typora 默认(`:表情:`、行内与块级 HTML 的常用标签、GitHub 提示块、`[toc]`、front matter 框;`==`、`^`、单个 `~` 照 GFM);快捷键照 Typora(Ctrl+1–6 标题、Ctrl+0 段落、Ctrl+/ 源码、Ctrl+Shift+=/-/0 字号、F8 专注、F9 打字机);右键菜单照 Typora 的布局,剪贴板与格式为图标行(组件库 `Menu` 新增)。Typora 与 GitHub 读同一份文件不同时随 GitHub(GFM,§14.3):表情名取 GitHub 现行的 gemoji(`emojis` 库,`:cricket:` 为蟋蟀),转义与字符引用之后照样是表情,自动链接与 `` 里不是,HTML 标签与强调交叉时照浏览器修复 CommonMark 输出,`
` 照 HTML5 也是换行;Typora 只决定哪些扩展显示。审查改用 gpt-6-astra,effort max,fast。 diff --git a/tasks/TASKS.md b/tasks/TASKS.md index e4cb5a4..391e1bf 100644 --- a/tasks/TASKS.md +++ b/tasks/TASKS.md @@ -233,7 +233,7 @@ - [x] R4.0 前置:`scripts/review.sh` 与本文件头改用 gpt-6-astra(effort max,fast);PRD §14 与 `agents.md` 记下四项决定与 Typora 对照的范围;`TyporaRef` 不入库 — R1 PASS - [~] R4.1 组件库:菜单的图标按钮行(`Menu` 一行若干图标按钮,各带名称与快捷键提示、可禁用);键盘可达;选中即运行并关菜单;画廊有例,有测试 — R1 FAIL 三项已修:所标按钮被禁用或移走时改选了别的按钮;带筛选框的菜单左右键被文本框吞掉;禁用按钮不说明不可用。R2 FAIL 两项已修:菜单关后的指针移动越界崩溃;移走中间按钮后右邻顶替被执行(标记认项不认位)。R3 FAIL 两项已修(三轮用尽,未再审):按钮无无障碍的点按动作;方向键所标按钮不进无障碍树(按钮报选中并作活动后代,面板为菜单角色);各有回归测试。组件库 1b8d678 已推送;`check.sh` 的 GPUI Kit 一步(Kit 0.7.3 要 gpui-pre 0.3.9)与五处未动文件的 raw px 早于本条 -- [ ] R4.2 组件库:行内扩展照 Typora 默认:`:shortcode:` 表情;行内 HTML 的 `u`、`b`/`strong`、`i`/`em`、`s`/`del`/`strike`、`code`、`kbd`、`mark`、`br`、`a` 按其义显示,其余标签只显示文字;脚注引用为上标数字;`~x~` 仍为删除线 +- [~] R4.2 组件库:行内扩展照 Typora 默认:`:shortcode:` 表情;行内 HTML 的 `u`、`b`/`strong`、`i`/`em`、`s`/`del`/`strike`、`code`、`kbd`、`mark`、`br`、`a` 按其义显示,其余标签只显示文字;脚注引用为上标数字;`~x~` 仍为删除线 — R1 FAIL 六项已修:表情吞掉转义与自动链接;连字符名当成已支持标签;属性值未解码字符引用;无引号值的斜杠被删;非 a 标签读 href;两条注释超长。R2 FAIL 六项已修:引用扫描为平方复杂度;属性值改照 HTML5 解码;表情名照 GitHub 现行 gemoji(用户定 GitHub 优先);关闭标签跨不出 Markdown 容器;无引号值只按 ASCII 空白分隔;`
` 照 HTML5 换行。R3 FAIL 五项已修(三轮用尽,未再审):Markdown 容器即 GitHub 写出的元素(em、strong、del、a),与标签同栈照 HTML5 修复:关闭标签结束同名元素并弹出其上各元素,只有格式元素重开,`mark`、`kbd`、`del` 止于浏览器止处,新的 `a` 先结束已开的 `a`;表情在解码后的正文里认(`\:smile:`、`:smile:` 照 GitHub 为表情,用户定 GitHub 优先,推翻 R1 第一项的转义部分),自动链接与 `` 里不认(GitHub Markdown API 实测);各有回归测试,旧代码上失败。组件库 9f39d32 已推送 - [ ] R4.3 组件库:块扩展照 Typora 默认:GitHub 提示块(NOTE、TIP、IMPORTANT、WARNING、CAUTION);独占一段的 `[toc]` 画成可按的标题目录;front matter 去掉 `---` 显示在框里;HTML 块按 R4.2 的标签显示,`script`、`style` 不显示;分隔线可见;嵌套无序列表的标记随层级变化 - [ ] R4.4 ElyMark:导出 HTML、纯文本与富文本复制随 R4.2、R4.3,与可视所见一致(表情、提示块、目录、行内 HTML 的同一组标签) - [ ] R4.5 组件库:可视模式按下块时插入点落在所按的字处;右键不开块,把插入点放到所点处,以事件告知属主所点的目标(块的种类、链接地址、图片地址、是否在表格或代码块里) diff --git a/tasks/reviews/R4.2-r3.md b/tasks/reviews/R4.2-r3.md new file mode 100644 index 0000000..9ede67c --- /dev/null +++ b/tasks/reviews/R4.2-r3.md @@ -0,0 +1,13 @@ +FAIL + +1. [P2] `../Ely-GPUI-Components/src/documents/tree/mod.rs:125` — HTML 关闭标签只匹配 `tag: Some(...)`,认不到 Markdown 生成的元素,仍不符合本轮明确采用的浏览器修复语义。`a *inside outside* end` 实测将 `inside outside` 全部设为斜体(`2..16`);CommonMark 输出经 HTML5 解析后只有 `inside` 是斜体(`2..8`)。`**inside outside**` 同样错误。应让原始关闭标签也能结束 Markdown 生成的同名元素,并正确处理随后到来的 Markdown 结束事件;补这两种交叉测试。失败断言在 `.work/R4.2-r3/confirmed-probes.log`,独立解析结果在 `html-oracle.log`;规则见 [HTML5 树构造](https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody)。 + +2. [P2] `../Ely-GPUI-Components/src/documents/tree/mod.rs:372` — 退出 Markdown 容器时无区别地保留全部 HTML 标签,把浏览器不会重建的 `mark`、`kbd`、`del` 也延续到了容器外。`a **bold marked** outside end` 实测连 `outside` 都被高亮;浏览器在 `` 处关闭 `mark`,`outside` 应无高亮。换成 `kbd` 或 `del`,代码底色或删除线也错误延伸。应区分 HTML5 的活动格式元素与普通元素,按实际关闭与重建规则计算范围;补不同类别标签的交叉测试。`mark`、`kbd` 的失败断言及 `del` 的独立对照见 `.work/R4.2-r3/confirmed-probes.log`、`html-oracle.log`;规则见 [HTML5 活动格式元素](https://html.spec.whatwg.org/multipage/parsing.html#the-list-of-active-formatting-elements)。 + +3. [P2] `../Ely-GPUI-Components/src/documents/tree/mod.rs:139` — 新的 `` 直接入栈,没有按 HTML5 结束已打开的锚点,产生重叠链接并让后文仍可点击。`[one two three](/outer)` 实测外链范围为 `0..13`,内链为 `4..7`;浏览器及 GitHub 实际输出仅让 `one ` 链到 `/outer`(`0..4`)、`two` 链到 `/inner`,` three` 不属于链接。应在新锚点开始时关闭已有锚点,包括 Markdown 链接,并断言完整链接范围与目标。失败及两套对照在 `.work/R4.2-r3/confirmed-probes.log`、`html-oracle.log`、`github-oracle.log`;规则见 [HTML5 锚点处理](https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody)。 + +4. [P2] `../Ely-GPUI-Components/src/documents/tree/mod.rs:310` — 表情替换只避开自动链接和 Markdown 代码节点,未避开 HTML `code` 内的文字。`a :smile: b` 实测显示 `a 😄 b`;GitHub 官方 Markdown API 的实际结果保留代码中的 `:smile:`。应根据当前 HTML `code` 上下文保留代码文字,覆盖代码内与代码外同一短码的测试;不能仅按共用的 `Style::Code` 判断,因为 `kbd` 内仍应转换。失败断言与 [GitHub Markdown API](https://docs.github.com/en/rest/markdown/markdown?apiVersion=2022-11-28) 的原始响应在 `.work/R4.2-r3/confirmed-probes.log`、`github-oracle.log`。 + +5. [P2] `../Ely-GPUI-Components/src/documents/tree/html.rs:215` — 仍用源码是否字面写出短码来决定转换,与最新「读法不同随 GitHub」决定冲突。`Show \:smile: now.`、`Show :smile: now.`、`Show :smile: now.` 在当前实现中保留 `:smile:`;GitHub 官方 Markdown API(`mode=gfm`)将三种写法都显示为 😄。现有转义测试反而固定了旧的 Typora 行为。应按当前决定对解码后的普通正文识别短码,保留代码等实际上下文的排除规则,并调整对应回归断言。失败及 [GitHub Markdown API](https://docs.github.com/en/rest/markdown/markdown?apiVersion=2022-11-28) 原始响应见 `.work/R4.2-r3/confirmed-probes.log`、`github-oracle.log`。 + +清理例外:自动审批审查拒绝了 PowerShell 删除暂存副本的命令,仅返回 `blocked by policy`。已用 Cargo 定向清理两个独立构建目录,共释放约 5.3 GiB;仍留有项目内 `.work/R4.2-r3/source/`、`parser/`、`html-oracle/`、`tmp/`、`source.tar`。完整库测试 1882 项、原生与 WebAssembly Clippy、格式及画廊元数据检查通过;上一轮六项的逐项核验与本轮证据在 `.work/R4.2-r3/validation.log`。