mcpField
M
markstream-vue

markstream-vue

github.com/simon-he95开发3.0k227 次安装2 天前更新
代码仓库

关于 markstream-vue

面向普通 Vue 3(通常基于 Vite、非 Nuxt)项目的 Markstream Vue 使用技能,供构建 Markdown 和 AI 聊天界面的开发者参考。内容涵盖流式渲染模式、代码块与长消息虚拟滚动的选择。

主要功能

  1. 01选择聊天、文档或轻量渲染模式
  2. 02配置 Markdown 流式输出节奏
  3. 03使用内置代码块渲染
  4. 04为长聊天记录配置虚拟滚动
  5. 05注册自定义组件并验证

适用场景

  1. 01构建 AI 聊天消息界面
  2. 02渲染富文本 Markdown 文档
  3. 03处理长对话消息列表
  4. 04按需自定义节点或代码块

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/simon-he95/markstream-vue --skill markstream-vue

安装后在 Claude Code 中输入/markstream-vue确认已加载。

附带文件agents/openai.yaml

详细介绍

Markstream Vue 3

当宿主应用是纯 Vue 3(通常基于 Vite)且不是 Nuxt 时,使用此技能。

工作流

  1. 确认仓库使用 Vue 3,而不是 Nuxt。
  2. 安装 markstream-vue,以及仅限所需功能必需的可选 peer 依赖。
  3. 在重置样式之后导入 markstream-vue/index.css。
    • 在 Tailwind 或 UnoCSS 项目中,使用 @import 'markstream-vue/index.css' layer(components);。
    • 根 JS 导入不会注入样式;请显式使用 markstream-vue/index.css 或 markstream-vue/index.px.css。
  4. 从 content 开始,并根据使用场景选择渲染器模式。
    • 对 AI 聊天或 SSE 输出使用 mode="chat"。它采用轻量批次、fade=false 和 max-live-nodes=0;smooth-streaming="auto" 会为可见输出控制节奏。
    • 对丰富文档场景使用 mode="docs"。这是默认模式,会启用更大的批次、工具提示和淡入效果。
    • 当场景较轻量但不属于聊天时,使用 mode="minimal"。
    • 常规围栏代码使用内置的 CodeBlockNode;安装可选 peer stream-diffs 后会增强此功能,否则回退到 <pre><code>。设置 render-code-blocks-as-pre=true 可强制使用纯文本路径;如果应用自行管理渲染器,则通过作用域内的 setCustomComponents(...) 替换 code_block。
    • 仅当场景也能禁用依赖包装器的功能(如淡入、批处理、延迟、虚拟化、打字机效果和自定义组件)时,才使用 dom-mode="minimal";否则会回退到完整 DOM。
    • typewriter 仅控制闪烁光标,默认值为 false。高频聊天优先使用 typewriter="simple";复杂的行内光标定位则使用精确模式。
    • 设置 :smooth-streaming="false" 可保留原始分块节奏;设置 :smooth-streaming="true" 可强制平滑控制节奏,即使内容位于首屏也如此(可能导致 SSR 水合不匹配)。
    • 在 Vue 3(包括 Nuxt)中,smooth-streaming 控制输出节奏,fade 控制不透明度;两者可以同时启用。mode="chat" 默认将 fade=false,以保持轻量。若需要逐渐显示文本,请添加 fade;若更重视动画开销,则保持关闭。Vue 3 的追加内容淡入使用稳定批次(200 ms、50 ms 合并窗口,每个文本节点最多四个批次);后续追加不会重启先前的批次。
    • 流式输出与恢复历史记录:聊天 UI 中,同一个 MarkdownRender 会先开始流式输出,之后在 final=true 时切换为历史记录。
      • 流式输出:从 mode="chat" 和 final 开始;若需要文本显示效果,则添加 fade;仅在需要光标时添加 typewriter。
      • 恢复已完成的聊天历史:在同一聊天行上保持 mode="chat",以免在 final=true 时切换布局策略;使用 :smooth-streaming="false"、typewriter=false,并独立选择 fade,以实现所需的进入/显示效果。除非这是有意的视觉策略,否则不要将其绑定为流式状态的反值。
      • 对轻量级的非聊天恢复内容使用 mode="minimal";仅对丰富文档场景使用 mode="docs",不要用它来结束现有聊天消息。
    • 仅当应用需要自定义 AST 控制、在 worker 中预解析或超出节奏控制范围的结构更新时,才切换到 nodes 加 final。
    • 请注意,html-policy 现在默认值为 safe,并且通过 mermaid-props 默认启用 Mermaid 严格模式。
  5. 对于较长的 AI 对话记录或已有的消息虚拟化器,请选择虚拟滚动方案。
    • 如果应用尚未自行管理时间线虚拟化,优先使用 MarkstreamVirtualTimeline。
    • 如果应用已经使用 vue-virtual-scroller 的 DynamicScroller,请使用 useMarkstreamVirtualAdapter(),并将 adapter.markdownProps(item, index) 绑定到 Markdown 项目。
    • 将 adapter.measureItem(item, index, el) 放在外层时间线行上,以便将行框架一并计入项目高度。
    • 请使用 Markstream 报告的逻辑高度(通过适配器/虚拟化器获取 metrics.totalHeight),不要使用渲染器元素当前的 offsetHeight,因为 Markdown 节点虚拟化可能只挂载可见窗口。
    • 切换线程时,将 adapter.captureThreadState() 与滚动器缓存一同保存;恢复时,先恢复滚动器缓存,再恢复 Markstream 锚点。
  6. 对本地覆盖使用 custom-id 和作用域内的 setCustomComponents(...);如果仓库已有应用级插件入口,则从 markstream-vue 导入 { VueRendererMarkdown } 并安装。
  7. 使用最小且有用的开发、构建或类型检查命令进行验证。

默认决策

  • Vue 3 应用默认使用 content;在微调较低层级的渲染属性之前,先选择 mode。
  • 只有在界面应采用丰富文档默认设置时,才省略 mode。
  • 当启用 typewriter 或 max-live-nodes <= 0 时,默认开启平滑流式传输(smooth-streaming="auto")。它只会控制 content 路径的节奏;nodes 模式不受影响。
  • 若要在 nodes 模式下手动控制节奏,请直接使用 useSmoothMarkdownStream:通过 enqueue() 添加文本块,完成后调用 finish(),从 visible 渲染,并在最终解析前等待 caughtUp。
  • 对于需要跟随流式输出的非虚拟化聊天滚动容器,请从 markstream-vue/utils 导入 useStickToBottom,并在 Vue 提交新内容后调用 scheduleScrollToBottom()。它会合并写入操作并保留手动滚动位置;不要为每个词元都运行 scrollIntoView({ behavior: 'smooth' })。对于较长的混合时间线,请改用 MarkstreamVirtualTimeline,并设置 stick-to-bottom="auto"。
  • 流式传输与恢复历史记录:同一聊天行应保持相同的渲染器模式;已完成的历史记录可以禁用节奏控制和光标;淡出效果是独立的视觉选项,在流式传输和完成后都可以保持启用。只有在将内容移至单独的丰富文档界面时,才切换到 mode="docs"。完整示例请参见 docs/guide/ai-chat-streaming.md。
  • 除非代码库已有共享插件入口,否则优先采用本地组件注册。
  • 如果 Vue 3 应用已对消息进行虚拟化,请继续由外层虚拟化器负责,仅对较大的 Markdown 消息启用 virtual-scroll。
  • 对于 vue-virtual-scroller,应让 sessionKey 与内容标识(thread:item:revision)绑定,并让 measurementKey 与宽度、主题、字体和密度等布局标识绑定。
  • 当增强型代码块需要应用级预加载时,请使用 preloadCodeBlockRuntime。若有意使用底层控制器,请直接从 stream-diffs 导入高级 API;不要依赖 markstream-vue 提供的原始运行时 getter。
  • Vue 3 增强型代码界面只使用 stream-diffs;不要安装 stream-monaco。
  • 对于较大的代码块(数万行)在 Vue 3 中的显示,请通过从 markstream-vue 调用 setStreamDiffsWorkerPool(...),注入上游 @pierre/diffs WorkerPoolManager,以将 Shiki 词元化工作交给 Web Worker。宿主使用自己的打包器(@pierre/diffs/worker/worker.js?worker)构建线程池,并将 @pierre/diffs 添加为直接依赖;markstream-vue 会将其转发为运行时选项 workerManager,并在每次变化时将当前的 isDark/theme/themes 主题同步到线程池。若未注入,或线程池报告自身不可用,高亮处理将继续在主线程上进行(行为不变)。不要在库内部打包或启动 Worker。
  • 通过顶层 code-block-options 或直接设置 CodeBlockNode.codeBlockOptions 来配置内置界面。将标题栏/工具栏属性放在 code-block-props 中;Markstream 保留对主题、代码/语言、流式生命周期、标题栏、挂载/显示时机以及释放操作的所有权。
  • 除非任务明确要求保留可信的旧版行为,否则请保持 html-policy="safe" 和 Mermaid 严格模式。
  • 如果可信界面需要采用加固前的行为,请在本地通过 html-policy="trusted" 和 :mermaid-props="{ isStrict: false }" 选择退出,并在最终交接中说明信任边界。
  • 如果宿主实际上是 Nuxt,请将 SSR 专属设置交由 markstream-nuxt 处理。

实用文档

  • docs/guide/quick-start.md
  • docs/guide/installation.md
  • docs/guide/usage.md
  • docs/guide/ai-chat-streaming.md
  • docs/guide/performance.md
  • docs/guide/component-overrides.md
  • docs/guide/code-block-runtime.md

评论

支持 Markdown