markdown/.trae/documents/实现 Typora 风格的自动显隐与代码块样式.md

3.2 KiB
Raw Blame History

目标效果

  1. 自动显隐 Markdown 标记:光标不在当前行/当前元素时,自动隐藏 #***> ``` 等语法标记,只显示渲染后的文本;光标移入时恢复显示以便编辑。
  2. 代码块所见即所得代码块Fenced Code Block显示为灰色背景的卡片块优化字体和间距不再只是裸露的文本。
  3. 柔和样式优化调整行高、字号、颜色、段落间距使其视觉上更接近渲染后的文档Typora 风格)。

技术方案

1. 核心逻辑重构:从 StateField 转向 ViewPlugin

目前的 liveMarkdownDecorations.js 基于正则匹配行,无法精准处理嵌套语法(如加粗内的斜体)和光标交互。将改用 ViewPlugin 结合 syntaxTree(语法树):

  • 语法树解析:利用 @codemirror/language 提供的 syntaxTree 遍历文档节点,精准识别 HeaderMark(标题#)、EmphasisMark*)、CodeMark)、FencedCode`(代码块)等节点。
  • 光标感知:在 ViewPluginupdate 钩子中监听 docChangedselectionSet
  • 动态装饰
    • 隐藏逻辑:如果节点的范围 不包含 当前光标选区,则对该节点的语法标记部分应用 Decoration.replace({})(完全隐藏)或 Decoration.mark({ class: 'cm-md-hidden' })
    • 代码块逻辑:识别 FencedCode 节点,对整个范围应用 Decoration.line({ class: 'cm-md-fenced-code' }) 添加背景色;对首尾的 CodeMark```)在非聚焦时进行隐藏或弱化处理。

2. 样式实现细节

  • 隐藏类 (.cm-md-hidden):设置为 display: nonefont-size: 0
  • 代码块样式 (.cm-md-fenced-code)
    • 背景色:var(--app-background) 或微调的灰色。
    • 圆角与内边距:让代码块看起来像一个独立的容器。
    • 字体:使用等宽字体 (monospace)。
  • 柔和排版
    • 增加 line-height (如 1.8)。
    • 增加段落间距 (margin-bottom 效果)。
    • 调整标题 (Header) 的 font-weightborder-bottom,使其更像预览模式。

实施步骤

  1. 废弃旧逻辑:清空或重写 src/codemirror/liveMarkdownDecorations.js
  2. 实现 ViewPlugin
    • 引入 syntaxTree
    • 编写遍历逻辑,识别 Markdown 节点。
    • 实现光标包含判断逻辑。
    • 生成 Decoration.replace (隐藏) 和 Decoration.line (样式)。
  3. 完善 CSS:在 LivePreviewEditor.vue 中补充对应的 CSS 规则(.cm-md-hidden, .cm-md-header, .cm-md-fenced-code 等)。
  4. 验证:测试标题、加粗、代码块在光标移入/移出时的显隐效果。

预期节点类型 (基于 @lezer/markdown)

  • ATXHeading: 包含 HeaderMark (#) 和内容。
  • Emphasis / StrongEmphasis: 包含 EmphasisMark (*, _)。
  • FencedCode: 包含 CodeMark (```), CodeInfo (语言), CodeText (内容)。
  • Blockquote: 包含 QuoteMark (>)。

风险点

  • 性能:频繁遍历语法树可能在长文档中导致卡顿。需要利用 RangeSetBuilder 高效构建 Decoration并尽量复用。
  • 光标边界:光标恰好在标记边缘时的显隐判定需要精细调整(通常光标接触即显示)。