Files
boos e0a5f57793 feat(desktop): embed BoosAPI Desktop client as a subproject
Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
2026-06-22 11:32:57 +08:00

16 KiB
Raw Permalink Blame History

description
description
快速查阅 MarkdownRender、CodeBlockNode、MermaidBlockNode、ImageNode、LinkNode 等 markstream-vue 导出组件。

渲染器与节点组件

当你已经明确知道自己要找的是某个导出的组件,并且想快速确认它的 props、事件、CSS 要求,以及该去哪个页面继续往下看时,就从这页开始。

如果你还在判断应该改解析流程、作用域覆盖,还是组件替换,建议先看:

快速参考

组件 推荐场景 关键 props / 事件 额外 CSS / 同伴依赖 排障提示
MarkdownRender 渲染完整 AST(默认导出) Props:content / nodes、custom-id、final、parse-options、custom-html-tags、is-dark、code-block-props、mermaid-props、d2-props、infographic-props;事件:copy、handleArtifactClick、click、mouseover、mouseout 在 reset 之后引入 markstream-vue/index.css(CSS 已被限定在内部 .markstream-vue 容器中),并放入受控 layer 用 setCustomComponents(customId, mapping) + custom-id 限定覆盖范围;配合 CSS 排查清单
CodeBlockNode 基于 Monaco 的交互式代码块、流式 diff node、monacoOptions、stream、loading;事件:copy、previewCode;插槽 header-left / header-right;diff 悬浮操作配置放在 monacoOptions(diffHunkActionsOnHover、diffHunkHoverHideDelayMs、onDiffHunkAction) 安装 stream-monaco(peer)并打包 Monaco workers SSR 首包会先给 <pre><code> fallback;编辑器空白时优先检查 worker 打包和客户端增强链路
MarkdownCodeBlockNode 轻量级高亮(Shiki) node、stream、loading;插槽 header-left / header-right 同伴依赖 stream-markdown SSR/低体积场景优先使用
MermaidBlockNode 渐进式 Mermaid 图 node、isDark、isStrict、maxHeight、estimatedPreviewHeightPx;事件 copy、export、openModal、toggleMode mermaid >= 11;无需额外 CSS SSR 首包先给可读 fallback;异步渲染问题详见 /zh/guide/mermaid
D2BlockNode 渐进式 D2 图 node、isDark、maxHeight、progressiveRender、progressiveIntervalMs;工具栏开关 @terrastruct/d2;无需额外 CSS SSR 首包先给 fallback / 源码;缺少依赖时保持 fallback;详见 /zh/guide/d2
MathBlockNode / MathInlineNode KaTeX 公式 node 安装 katex 并引入 katex/dist/katex.min.css 注册同步 KaTeX loader 后可直接 SSR 出 HTML;否则稳定回退为原文
ImageNode 自定义图片预览 / 懒加载 Props:fallback-src、show-caption、lazy、svg-min-height、use-placeholder;事件:click / load / error 无额外 CSS 通过 setCustomComponents 包装,实现 lightbox
LinkNode 下划线动画、颜色自定义 color、underlineHeight、showTooltip 无 浏览器默认 a 样式可通过 reset 解决
VmrContainerNode 自定义 ::: 容器 node(name、attrs、loading、children) 极简基础 CSS;通过 setCustomComponents 覆盖 JSON attrs 会规范到 node.attrs(去掉 data- 前缀);无效/不完整 JSON 存到 attrs.attrs;name 后面的 args 存到 attrs.args

TypeScript 类型导出

markstream-vue 同步导出渲染器与组件 props 类型:

import type { CodeBlockNodeProps } from 'markstream-vue'
import MarkdownRender from 'markstream-vue'

type MarkdownRenderProps = InstanceType<typeof MarkdownRender>['$props']
type MarkdownRenderCodeBlockProps = NonNullable<MarkdownRenderProps['codeBlockProps']>

declare const markdownRenderProps: MarkdownRenderProps
declare const markdownRenderCodeBlockProps: MarkdownRenderCodeBlockProps
declare const codeBlockProps: CodeBlockNodeProps

// 更推荐 hover 每一行点号后面的字段名。
markdownRenderProps.content
markdownRenderProps.customId
markdownRenderProps.isDark
markdownRenderProps.codeBlockProps?.showHeader
markdownRenderProps.codeBlockProps?.showTooltips
markdownRenderProps.codeBlockMonacoOptions
markdownRenderProps.codeBlockMonacoOptions?.theme
markdownRenderProps.codeBlockMonacoOptions?.languages
markdownRenderProps.codeBlockMonacoOptions?.diffHunkActionsOnHover
markdownRenderProps.themes

markdownRenderCodeBlockProps.showFontSizeButtons
markdownRenderCodeBlockProps.showCollapseButton

codeBlockProps.monacoOptions
codeBlockProps.monacoOptions?.MAX_HEIGHT
codeBlockProps.theme

说明:

  • InstanceType<typeof MarkdownRender>['$props'] 是最直接的组件 props 查看入口。
  • NodeRendererProps 是同一套公开 props 结构的命名类型导出。
  • codeBlockProps 现在会跟随公开的 CodeBlockNode props 结构(去掉 node),因此像 showHeader、showFontSizeButtons、showTooltips 这类字段也能直接获得 hover 与补全。
  • 新接入更推荐使用 codeBlockProps.theme;darkTheme / lightTheme 仍保留作兼容字段。
  • 更推荐 hover 上面每一行点号后面的字段名,而不是只 hover 导入的类型名。
  • 如果你主要想看组件 props 的 hover,优先看下面这段 MarkdownRender 示例。
  • 只有写成 ts twoslash / vue twoslash 的代码块才会在这个文档站里显示 hover 类型信息。

语言图标默认使用内置 material theme。进阶接入可以通过导出的 helper 查看或切换 icon theme:

import { getRegisteredThemes, registerIconTheme, setIconTheme } from 'markstream-vue'

console.log(getRegisteredThemes()) // ['material']
setIconTheme('material')

// registerIconTheme(...) 可用于先注册你自己的图标包,再切换过去。

先快速判断该用哪个组件

  • 大多数业务接入都应该先用 MarkdownRender。
  • 如果你要自己拼接底层节点渲染器,再考虑 CodeBlockNode、MermaidBlockNode、D2BlockNode、MathBlockNode。
  • 如果你只是想替换单个内置节点,通常看 ImageNode、LinkNode、VmrContainerNode 这一层就够了。
  • 如果你脱离 MarkdownRender 单独渲染节点组件,请记得包一层 <div class="markstream-vue">...</div>,否则库内变量和样式不会完整生效。

MarkdownRender

主入口:接受 Markdown 字符串或解析后的 AST,然后使用内置节点渲染器输出。

快速要点

  • 适用:Vite/Nuxt/VitePress 中渲染整篇 Markdown。
  • 关键 props:content / nodes、custom-id、final、parse-options、custom-html-tags
  • CSS 顺序:先引入 reset,再在 @layer components 中导入 markstream-vue/index.css。

CSS 作用域

markstream-vue 已把打包后的 CSS 限定在内部 .markstream-vue 容器中,用于降低全局样式冲突。

  • 使用 MarkdownRender 时一般无需处理:它默认渲染在容器内部。
  • 如果你独立使用节点组件(例如 CodeBlockNode、MathBlockNode),请外层包一层 <div class="markstream-vue">...</div>,这样库内样式与变量才会生效。

最适合先 hover 的目标

如果你只是想先看组件 props,先 hover 下面这段里的 :content、custom-id、:is-dark、:code-block-monaco-options:

<script setup lang="ts">
import MarkdownRender from 'markstream-vue'

type MarkdownRenderProps = InstanceType<typeof MarkdownRender>['$props']

const content: MarkdownRenderProps['content'] = '# Hello'
const customId: MarkdownRenderProps['customId'] = 'docs'
const isDark: MarkdownRenderProps['isDark'] = true
const monacoOptions: MarkdownRenderProps['codeBlockMonacoOptions'] = {
  theme: 'vitesse-dark',
  languages: ['typescript', 'vue'],
  MAX_HEIGHT: 520,
}
</script>

<template>
  <MarkdownRender
    :content="content"
    :custom-id="customId"
    :is-dark="isDark"
    :code-block-monaco-options="monacoOptions"
  />
</template>

使用阶梯

<script setup lang="ts">
import type { CodeBlockMonacoOptions } from 'markstream-vue'
import MarkdownRender from 'markstream-vue'

const md = '# 你好\n\n使用 custom-id 控制样式。'
const monacoOptions = {
  theme: 'vitesse-dark',
  themes: ['vitesse-dark', 'vitesse-light'],
  languages: ['typescript', 'vue'],
  MAX_HEIGHT: 520,
  diffHunkActionsOnHover: true,
} satisfies CodeBlockMonacoOptions
</script>

<template>
  <MarkdownRender
    custom-id="docs"
    :content="md"
    :code-block-monaco-options="monacoOptions"
  />
</template>
// 注册自定义节点
import { setCustomComponents } from 'markstream-vue'
import CustomImageNode from './CustomImageNode.vue'

setCustomComponents('docs', {
  image: CustomImageNode,
})
/* styles/main.css */
@import 'modern-css-reset';
@tailwind base;

@layer components {
  @import 'markstream-vue/index.css';
}

[data-custom-id='docs'] .prose {
  max-width: 720px;
}

性能相关 props

  • 批量渲染 —— batchRendering、initialRenderBatchSize、renderBatchSize、renderBatchDelay、renderBatchBudgetMs 控制每一帧有多少节点从占位骨架切换为真实组件。仅在关闭虚拟化(:max-live-nodes="0")时会启用增量骨架模式。
  • 延迟可见节点 —— deferNodesUntilVisible 与 viewportPriority 默认开启,让 Mermaid、D2、Monaco、KaTeX 等重型节点只有在接近视口时才加载。
  • 虚拟化窗口 —— maxLiveNodes 限制 DOM 中最多保留多少个已渲染节点,liveNodeBuffer 控制超前/超后范围。详见 性能指南。
  • 代码块降级 —— 通过 renderCodeBlocksAsPre 与 codeBlockStream 可将普通代码块切换为 <pre><code> 或关闭流式更新。

常见问题

  • 样式错乱:先检查 CSS 排查清单。
  • 工具类覆盖:传入 custom-id 并使用 [data-custom-id="docs"] 限定样式。
  • SSR 报错:渲染器本身已经 SSR-safe;只把你自己的浏览器专属页面逻辑,或手动初始化的 peer,放到 <ClientOnly> / onMounted 后面。

什么时候优先用它

  • 你想走“默认解析器 + 默认渲染器”的最短接入路径。
  • 你希望把流式渲染、虚拟化、批量渲染、自定义标签、作用域覆盖都集中在一个入口处理。
  • 你还不想自己拼装各个节点渲染器,只是要在 content 与 nodes 之间做选择。

最常见的组合方式

  • content + custom-id:静态页面或轻量定制页面。
  • nodes + final:流式输出、服务端预解析、增量渲染。
  • custom-html-tags + setCustomComponents(customId, mapping):像 thinking 这样的可信标签。
  • renderCodeBlocksAsPre:SSR 或受限环境里,把重型代码块降级成普通 <pre><code>。

CodeBlockNode

基于 Monaco 的代码块渲染器,支持流式 diff 和交互式工具栏。

  • 适合:代码审阅、diff 检查、补丁预览、悬浮操作
  • 关键 props:node、monacoOptions、stream、loading
  • 事件:copy、previewCode
  • 插槽:header-left、header-right
  • 同伴依赖:stream-monaco,以及 bundler 里的 Monaco worker 配置
  • 常见问题:编辑器空白时,优先检查 worker 打包和 SSR 边界

如果代码块本身就是产品体验的一部分,用它最合适;如果你只是想高亮代码,不需要 Monaco 的编辑能力,优先看 MarkdownCodeBlockNode。

深入页面: CodeBlockNode、Monaco

MarkdownCodeBlockNode

基于 Shiki 和 stream-markdown 的轻量代码块渲染器。

  • 适合:SSR 友好的文档站、博客页、更小的打包体积
  • 关键 props:node、stream、loading
  • 插槽:header-left、header-right
  • 同伴依赖:stream-markdown
  • 常见问题:一直没有高亮时,先确认 stream-markdown 已安装,并在实际渲染环境里可用

如果你不需要 Monaco 的编辑面板和 diff 交互,这个通常是更轻的选择。

MermaidBlockNode

渐进式 Mermaid 渲染器,带复制、导出、弹窗等交互能力。

  • 适合:大图、AI 生成图表、用户主动导出
  • 关键 props:node、isDark、isStrict、maxHeight、estimatedPreviewHeightPx
  • 事件:copy、export、openModal、toggleMode
  • 同伴依赖:mermaid >= 11
  • 常见问题:把 Mermaid 当成客户端增强能力看待;SSR 首包已经有 fallback,真正的 preview 仍然在客户端初始化

MarkdownRender 会在调用方未传入时为 Mermaid 围栏估算 estimatedPreviewHeightPx。只有在直接使用 MermaidBlockNode,或自定义 mermaid 渲染器已经知道首屏 preview 高度时,才需要手动传入。

深入页面: Mermaid、MermaidBlockNode

D2BlockNode

渐进式 D2 图表渲染器,适合结构化架构图和说明图。

  • 适合:D2 文档、自动生成的架构视图、渐进式渲染
  • 关键 props:node、isDark、maxHeight、progressiveRender、progressiveIntervalMs
  • 同伴依赖:@terrastruct/d2
  • 常见问题:缺少 peer 时会回退显示源码,而不是渲染好的图表

深入页面: D2 图表

MathBlockNode / MathInlineNode

基于 KaTeX 的块级 / 行内公式渲染器。

  • 适合:技术文档、公式说明、AI 数学输出
  • 关键 prop:node
  • 同伴依赖:katex
  • 必需 CSS:katex/dist/katex.min.css
  • 常见问题:公式空白通常是 KaTeX CSS 缺失,而不是解析失败

ImageNode

内置图片渲染器,提供 caption、fallback、lazy 等常用能力。

  • 适合:自定义预览、埋点、lightbox 集成
  • 关键 props:fallback-src、show-caption、lazy、svg-min-height、use-placeholder
  • 事件:click、load、error
  • 常见接法:先包一层自定义组件,再通过 setCustomComponents(customId, { image: CustomImageNode }) 注册

深入页面: ImageNode

LinkNode

带下划线动画和 tooltip 选项的链接渲染器。

  • 适合:文档站、聊天界面、需要和设计系统统一交互样式的链接
  • 关键 props:color、underlineHeight、showTooltip
  • 常见问题:浏览器默认样式或 reset 顺序不对时,看起来会像“组件失效”,先检查 CSS 顺序

VmrContainerNode

用来渲染 ::: 容器以及解析器归一化后的结构化块。

  • 适合:提示框、Notice、AI 特殊块、容器型自定义组件
  • 关键 prop:node,其中包含 name、attrs、loading、children
  • 归一化细节:JSON attrs 会整理到 node.attrs;无效或不完整 JSON 会保留在 attrs.attrs;容器名后面的参数会落到 attrs.args
  • 常见接法:和 custom-html-tags 或 parser hooks 配合,处理可信的结构化块

单独渲染节点组件时的检查清单

如果你绕过 MarkdownRender,直接挂载节点组件:

  • 外层包上 .markstream-vue 容器。
  • 引入和完整渲染器一致的 CSS。
  • 只安装并初始化当前节点真正需要的 peers。
  • 所有替换样式都用父级选择器或 data-custom-id 一类的方式做局部作用域。

如果你现在找的是别的层级

  • 查解析器工具、setCustomComponents、AST hooks:看 API 参考
  • 查完整渲染器配置:看 Props 与选项
  • 组件选对了但样式 / peers / SSR 还是不对:看 故障排除