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.
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
---
|
||||
description: 快速查阅 MarkdownRender、CodeBlockNode、MermaidBlockNode、ImageNode、LinkNode 等 markstream-vue 导出组件。
|
||||
---
|
||||
|
||||
# 渲染器与节点组件
|
||||
|
||||
当你已经明确知道自己要找的是某个导出的组件,并且想快速确认它的 props、事件、CSS 要求,以及该去哪个页面继续往下看时,就从这页开始。
|
||||
|
||||
如果你还在判断应该改解析流程、作用域覆盖,还是组件替换,建议先看:
|
||||
|
||||
- 想查解析器工具、AST hooks 或 `setCustomComponents()` 的接入方式: [API 参考](/zh/guide/api)
|
||||
- 想有作用域地替换内置渲染器: [覆盖内置组件](/zh/guide/component-overrides)
|
||||
- 想支持 `thinking` 这类可信标签: [自定义标签与高级组件](/zh/guide/custom-components)
|
||||
- 想调配置、性能或工具栏: [Props 与选项](/zh/guide/props)
|
||||
|
||||
## 快速参考
|
||||
|
||||
| 组件 | 推荐场景 | 关键 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 排查清单](/zh/guide/troubleshooting#css-looks-wrong-start-here) |
|
||||
| `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 类型:
|
||||
|
||||
```ts twoslash
|
||||
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:
|
||||
|
||||
```ts
|
||||
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`:
|
||||
|
||||
```vue twoslash
|
||||
<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>
|
||||
```
|
||||
|
||||
### 使用阶梯
|
||||
|
||||
```vue twoslash
|
||||
<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>
|
||||
```
|
||||
|
||||
```ts
|
||||
// 注册自定义节点
|
||||
import { setCustomComponents } from 'markstream-vue'
|
||||
import CustomImageNode from './CustomImageNode.vue'
|
||||
|
||||
setCustomComponents('docs', {
|
||||
image: CustomImageNode,
|
||||
})
|
||||
```
|
||||
|
||||
```css
|
||||
/* 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` 控制超前/超后范围。详见 [性能指南](/zh/guide/performance)。
|
||||
- **代码块降级** —— 通过 `renderCodeBlocksAsPre` 与 `codeBlockStream` 可将普通代码块切换为 `<pre><code>` 或关闭流式更新。
|
||||
|
||||
### 常见问题
|
||||
|
||||
- **样式错乱**:先检查 [CSS 排查清单](/zh/guide/troubleshooting#css-looks-wrong-start-here)。
|
||||
- **工具类覆盖**:传入 `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](/zh/guide/code-block-node)、[Monaco](/zh/guide/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](/zh/guide/mermaid)、[MermaidBlockNode](/zh/guide/mermaid-block-node)
|
||||
|
||||
## D2BlockNode
|
||||
|
||||
> 渐进式 D2 图表渲染器,适合结构化架构图和说明图。
|
||||
|
||||
- **适合**:D2 文档、自动生成的架构视图、渐进式渲染
|
||||
- **关键 props**:`node`、`isDark`、`maxHeight`、`progressiveRender`、`progressiveIntervalMs`
|
||||
- **同伴依赖**:`@terrastruct/d2`
|
||||
- **常见问题**:缺少 peer 时会回退显示源码,而不是渲染好的图表
|
||||
|
||||
深入页面: [D2 图表](/zh/guide/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](/zh/guide/image-node)
|
||||
|
||||
## 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 参考](/zh/guide/api)
|
||||
- 查完整渲染器配置:看 [Props 与选项](/zh/guide/props)
|
||||
- 组件选对了但样式 / peers / SSR 还是不对:看 [故障排除](/zh/guide/troubleshooting)
|
||||
Reference in New Issue
Block a user