Repository navigation
feat(desktop): Markdown 文件的结构窗口显示标题大纲 - #1920
Merged
Merged
Conversation
结构窗口原来只认语言服务器的 documentSymbols,Markdown 没有语言服务器, 只能显示“没有语言服务器为此文件提供结构”。现在 Markdown 文件向 Core markdown.outline 要标题树(与预览浮动目录同一方言),按层级嵌套显示, 筛选、排序、折叠、跟随光标照常可用。 - core: 新增 Client.MarkdownOutline,并按 Core 契约 fixture 校验 - workbench: 新增 outlineMarkdown 路径,后台请求、300ms 节流、丢弃过期结果; 超过预览上限不请求并说明过大;没有标题时单独说明;失败可重试 - workbench: 仅预览模式下点击标题滚动预览页面 - i18n: 新增 desktop.outline.noHeadings、desktop.outline.tooLarge - 固定 Core 到 Lithe-core-rust#41 的 b0e19d5(尚未合入) - 功能矩阵 outline-symbols 补充 Markdown 证据与验证
xiaoyumuxi
marked this pull request as ready for review
November 14, 2026 11:38
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.
关联 Issue / Linked issue
markdown.outline命令,尚未合入;本 PR 临时固定在该分支的 commit,见下方“插件契约”)。PR 类型 / Type
改动说明 / What changes
背景 / Why
打开
AGENTS.md这类 Markdown 文件时,结构(Structure)工具窗口只显示“没有语言服务器为此文件提供结构。”,而同一文件的预览浮动目录明明能列出一级、二级标题。结构窗口原来只认语言服务器的 documentSymbols,Markdown 没有语言服务器,所以永远是空的。做法:Rust Core 新增
markdown.outline,用预览同一套 Markdown 方言解析标题,输出与语言服务器 documentSymbols 归一化后相同的符号树;桌面端对 Markdown 文件直接向 Core 要这棵树,不再依赖任何语言服务器或插件。结构窗口原有的筛选、排序、全部折叠/展开、跟随光标都直接可用。改动 / Changes
Core 接入(
desktop/internal/core/)markdown.go:新增Client.MarkdownOutline(ctx, source),调用 Coremarkdown.outline,返回[]DocumentSymbol(一级标题是根,下级标题挂到前面最近的更高级标题下;selectionRange 是标题行,range 是到下一个同级或更高级标题前的整节)。markdown_test.go:新增TestMarkdownOutlineSharedFixture,逐例比对 Core 契约 fixtureeditor/markdown-outline-v1.json(经contractfixture从正在链接的 Core 检出读取,不复制到本仓库)。结构窗口(
desktop/internal/workbench/outline.go、outline_view.go)outlineMarkdown:Markdown 文件(与预览同一判定isMarkdownDocument)优先走 Core,即使装了提供 Markdown 语言服务器的插件也用 Core 的大纲,保证和预览目录一致。outlineMarkdownSync:与语言服务器路径相同的节流——窗口打开时请求一次,之后文本变化等outlineDelay(300ms)后再请求;在后台任务里调用 Core,不占窗口线程;按请求令牌丢弃切换文件或重复请求后迟到的旧结果。markdownPreviewMaxBytes(1 MiB)时不发给 Core,结构窗口说明“此文件过大,无法显示结构。”。outlineGo:Markdown 处于“仅预览”模式时编辑器是隐藏的,点击标题除了移动源码光标,还会把预览页面滚到该标题。预览(
desktop/internal/workbench/markdown_preview.go)markdownPreviewState.showLine(d, line):web view 预览发送已有的scroll消息,原生预览用已有的scrollTo,供结构窗口跳转使用。文案(
shared/i18n/)desktop.outline.noHeadings(“此文件没有标题。” / “This file has no headings.”)和desktop.outline.tooLarge(“此文件过大,无法显示结构。” / “This file is too large to show its structure.”),已运行node scripts/i18n/generate-i18n.mjs并提交生成的desktop/internal/i18n/shared.generated.go。Core 固定版本(
scripts/desktop/build-desktop-core.sh)PINNED_CORE_REVISION升到b0e19d5(Lithe-core-rust#41 分支上唯一的 commit,基于 Core mainc1df34b,没有带入其他改动)。feat(windows): 完善 W1 文档安全与多文件编辑 #41 合入 main 后需要把固定版本改成 squash 后的 commit。功能矩阵(
shared/platform-feature-matrix/features/outline-symbols.json)core/markdown.go、core/markdown_test.go、workbench/markdown_preview.go、workbench/outline_markdown_test.go;验证动作补充 Markdown 回归覆盖与命令;notes 记录 2026-11-14 的 Markdown 结构行为。验证状态保持pending。测试(
desktop/internal/workbench/outline_markdown_test.go,新文件)TestMarkdownOutlineShowsHeadingsWithoutServer:无语言服务器时按层级显示标题,光标所在节选中对应标题,跳转把光标放到标题行。TestMarkdownOutlineFollowsEditsAfterTheDelay:编辑后延迟未到不重复请求,延迟过后刷新出新标题。TestMarkdownOutlineSaysWhenThereAreNoHeadings:只有段落和代码块里的#时显示“没有标题”。TestMarkdownOutlineSkipsTooLargeFile:超过 1 MiB 不请求 Core 并显示“过大”。TestMarkdownOutlineFailureOffersRetry:失败显示重试、不自动重复请求,点重试后成功加载。TestMarkdownOutlineDropsTheAnswerForAnotherFile:a.md 的请求被挂起时切到 b.md,放行后只显示 b.md 的结果。TestMarkdownOutlineMovesThePageShownAlone:仅预览模式下跳到 Part 12,页面顶部是该标题所在行。t.Cleanup中必定放行。不在本 PR 范围内 / Out of scope
类型专属:feat
多平台对齐
Viva 桌面端 macOS 与 Windows 共用同一份 Go 代码,解析逻辑在 Rust Core;Windows 实机尚未验收(见“验证”)。
范围检查 / Scope checks
功能矩阵 / Feature matrix
shared/platform-feature-matrix/features/outline-symbols.json:两端的实现状态和验证状态、证据路径、owner、验证动作都如实填写;没有运行验证的保持pending./scripts/platform-feature-matrix/verify-platform-feature-matrix.sh;改了平台实现路径的,还运行了./scripts/platform-feature-matrix/verify-platform-feature-matrix-change.sh origin/preview HEAD.artifacts/下生成的矩阵视图插件归属 / Plugin ownership
develop-lithe第三节“插件归属与宿主零依赖”的自查命令,结果为空shared/i18n/;插件的构建步骤、资源路径和补丁没有写进scripts/resources/、docs/ci-builds.md、Agent Note 或 Skill统一日志系统 / Structured logging
app.notification.operation_failed,operation为markdown_outline;没有NSLog、os_log/Logger、直接写 stderr、print或手写事件 IDerror类型界面文案 / i18n
shared/i18n/补齐中英词条,运行node scripts/i18n/generate-i18n.mjs并提交生成结果,没有手改生成文件;Viva 代码通过desktop/internal/i18n/的接口读取node scripts/i18n/verify-app-language-localization.mjs和node scripts/i18n/generate-i18n.mjs --check,没有放宽脚本或扩大豁免名单逻辑归属 / Logic placement
editor/markdown-outline-v1.json随 Core PR 提交;桌面端只做请求、节流和呈现isMarkdownDocument)性能与内存 / Performance and memory
desktop/internal/editor/**、editorview/**),不涉及启动、输入、滚动路径设置 / Settings
N/A:没有新增或修改设置。
插件契约 / Plugin contract
markdown.outline是宿主调用的 Core 命令,fixture 在 Core 的rust/fixtures/随 Lithe-core-rust#41 提交scripts/desktop/build-desktop-core.sh的PINNED_CORE_REVISION已升到包含该命令的 Core commitb0e19d5(feat(windows): 完善 W1 文档安全与多文件编辑 #41 尚未合入,合入后改为 main 上的 commit),桌面端测试经scripts/desktop/desktop-go.sh读到的就是这份 fixture发行包与资源 / Bundle and resources
./scripts/desktop/verify/verify-runtime-bundle-immutability.sh无用代码与重构 / Dead code and refactoring
验证 / Verification
cargo test -p lithe-project、cargo test -p lithe-core、fmt、clippy、注释检查(Core #41 分支)scripts/desktop/desktop-go.sh test ./internal/core -run 'TestMarkdownOutlineSharedFixture|TestRenderMarkdownSharedFixture' -count=1scripts/desktop/desktop-go.sh test ./internal/workbench -run 'TestOutline|TestMarkdownOutline|TestMarkdown' -count=3scripts/desktop/desktop-go.sh test ./internal/workbench -run 'TestMarkdownOutline' -count=20scripts/desktop/desktop-go.sh test ./... -count=1.agents/skills/write-stable-tests/scripts/test-stability-macos.sh --package ./internal/workbench --filter 'TestMarkdownOutline'verify-test-stability.sh通过node scripts/i18n/verify-app-language-localization.mjs、node scripts/i18n/generate-i18n.mjs --check./scripts/platform-feature-matrix/verify-platform-feature-matrix.sh、verify-platform-feature-matrix-change.sh origin/preview HEAD./scripts/desktop/verify/verify-runtime-bundle-immutability.shgofmt -l改动文件未能执行的检查和原因:
pending。提交前确认 / Final checks
preview创建;目标分支:preview.build/、target/、dist/、.artifacts/等产物,没有凭据、个人路径和未脱敏的日志或截图