# Plugins 插件层指引 本文件适用于 src/plugins/ 下的插件代码。 ## 插件层职责 - 承接 Milkdown/ProseMirror 与业务逻辑之间的粘合层。 - 负责 AI 补全 ghost text、文档块节点、Mermaid 预览等编辑器级行为。 - 这里的代码状态性很强,误改后通常会出现“看起来还能编译,但交互细节坏掉”的问题。 ## 文件分工 - copilotPlugin.ts:AI 补全主逻辑,包含 ghost text、请求调度、取消、语言识别、隐藏上下文注入和大小限制。 - docBlockPlugin.ts:文档块节点、remark 适配和视图逻辑。 - mermaidPlugin.ts:Mermaid 代码块预览和渲染。 - index.ts:导出入口。 - types.ts:公共类型。 ## copilotPlugin 的真实职责 - 维护 ghost suggestion 的 plugin state。 - 用 mark + decoration 表示 ghost text,而不是简单的纯字符串缓存。 - 为每个 EditorView 维护 runtime: - enabled - debounceTimer - abortController - ctx - requestSeq - docVersion - 推断当前光标语言,处理 fenced code、latex、mermaid 等上下文。 - 提取 OCR 缓存和文档块内容,拼到隐藏上下文里。 - 控制请求失效和中止,避免旧请求把新文档状态覆盖掉。 - 在结果插入后恢复合理的光标位置和选择状态。 ## 先看哪些函数 - getCursorLanguageId:判断当前上下文语言 - extractDocBlocksFromMarkdown:从文档块生成隐藏上下文 - doFetchSuggestion:真正发起补全请求 - clearRuntimeRequests:中止定时器和请求 - insertGhostText / insertPlainText:把建议插回编辑器 ## 编辑规则 - 不要把隐藏 OCR 上下文或文档块上下文直接变成最终可见文本,除非需求明确要求。 - 不要破坏 requestSeq 和 AbortController 这套旧请求失效机制。 - 不要随意改 ghost text 的 mark/decorations 表示方式;这会影响显示、接受、拒绝和同步。 - parserCtx 和 serializerCtx 是和 Milkdown 集成的关键上下文,改解析插入逻辑时要一起考虑。 - 插件行为并不完全自洽,很多配置和启停逻辑是在 components/MilkdownEditor.vue 里接上的;不要只在插件内部脑补整体行为。 ## 容易踩坑的点 - 大小限制既有插件常量,也有编辑器 UI 层联动。 - 图片节点类型不止一种名字,代码已经兼容 image、image-block、imageBlock。 - 上下文语言识别会影响 Prompt 行为,改错以后通常不是“报错”,而是补全质量或补全边界变差。 - Mermaid、LaTeX、文档块这几类上下文都和“是否允许补全、是否允许上传”相关。 - 这是状态机式代码;局部改动后要优先验证交互,而不是只看类型通过。 ## 调试顺序 - 如果是“为什么没有发请求”,先查 enabled、size limit、cursor context、debounce 和 abort。 - 如果是“为什么结果插错位置”,先查 ghost range、mapping、selection 恢复。 - 如果是“为什么上下文不对”,先查 OCR 缓存、文档块摘录和语言识别。 - 如果是“为什么改了插件没生效”,再回看 MilkdownEditor.vue 里的 use/config/watch 是否也要一起改。 ## 改动建议 - 先做最小改动。 - 先验证单个交互问题,不要一口气同时改 ghost 插入、语言识别和请求时机。 - 当改动影响请求 payload 时,再考虑是否需要同步后端 Prompt 测试。 - 只有在确认插件本身是控制点时,才在这里改;很多行为实际上是在上层组件里决定的。