关于 markstream-vue
面向普通 Vue 3(通常基于 Vite、非 Nuxt)项目的 Markstream Vue 使用技能,供构建 Markdown 和 AI 聊天界面的开发者参考。内容涵盖流式渲染模式、代码块与长消息虚拟滚动的选择。
主要功能
- 01选择聊天、文档或轻量渲染模式
- 02配置 Markdown 流式输出节奏
- 03使用内置代码块渲染
- 04为长聊天记录配置虚拟滚动
- 05注册自定义组件并验证
适用场景
- 01构建 AI 聊天消息界面
- 02渲染富文本 Markdown 文档
- 03处理长对话消息列表
- 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 时,使用此技能。
工作流
- 确认仓库使用 Vue 3,而不是 Nuxt。
- 安装
markstream-vue,以及仅限所需功能必需的可选 peer 依赖。 - 在重置样式之后导入
markstream-vue/index.css。- 在 Tailwind 或 UnoCSS 项目中,使用
@import 'markstream-vue/index.css' layer(components);。 - 根 JS 导入不会注入样式;请显式使用
markstream-vue/index.css或markstream-vue/index.px.css。
- 在 Tailwind 或 UnoCSS 项目中,使用
- 从
content开始,并根据使用场景选择渲染器模式。- 对 AI 聊天或 SSE 输出使用
mode="chat"。它采用轻量批次、fade=false和max-live-nodes=0;smooth-streaming="auto"会为可见输出控制节奏。 - 对丰富文档场景使用
mode="docs"。这是默认模式,会启用更大的批次、工具提示和淡入效果。 - 当场景较轻量但不属于聊天时,使用
mode="minimal"。 - 常规围栏代码使用内置的
CodeBlockNode;安装可选 peerstream-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 严格模式。
- 对 AI 聊天或 SSE 输出使用
- 对于较长的 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 锚点。
- 如果应用尚未自行管理时间线虚拟化,优先使用
- 对本地覆盖使用
custom-id和作用域内的setCustomComponents(...);如果仓库已有应用级插件入口,则从markstream-vue导入{ VueRendererMarkdown }并安装。 - 使用最小且有用的开发、构建或类型检查命令进行验证。
默认决策
- 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/diffsWorkerPoolManager,以将 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.mddocs/guide/installation.mddocs/guide/usage.mddocs/guide/ai-chat-streaming.mddocs/guide/performance.mddocs/guide/component-overrides.mddocs/guide/code-block-runtime.md
评论
支持 Markdown