内容格式转换(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/open-webui/open-webui/9.2-content-format-conversion
翻译时间:2026-06-09T16:09:52.142Z
翻译模型:deepseek-chat
原文字符数:10432
项目:Open WebUI (open-webui)
---
内容格式转换
相关源文件
以下文件为本 wiki 页面的生成提供了上下文:
src/lib/components/icons/AdjustmentsHorizontalOutline.sveltesrc/lib/components/icons/ArrowUpLeft.sveltesrc/lib/components/icons/PagePlus.sveltesrc/lib/components/notes/NoteEditor.sveltesrc/lib/components/notes/NoteEditor/Chat.sveltesrc/lib/components/notes/NoteEditor/Chat/Message.sveltesrc/lib/components/notes/NoteEditor/Chat/Messages.sveltesrc/lib/components/notes/NoteEditor/Controls.sveltesrc/lib/components/notes/NotePanel.sveltesrc/lib/components/notes/utils.tssrc/routes/(app)/admin/+layout.svelte/admin/+layout.svelte)src/routes/(app)/admin/+page.svelte/admin/+page.svelte)src/routes/(app)/home/+layout.svelte/home/+layout.svelte)src/routes/(app)/notes/+page.svelte/notes/+page.svelte)- [src/routes/(app)/notes/[id]/+page.svelte](src/routes/(app)/notes/[id]/+page.svelte)
src/routes/(app)/notes/new/+page.svelte/notes/new/+page.svelte)src/routes/(app)/playground/+layout.svelte/playground/+layout.svelte)src/routes/(app)/workspace/+layout.svelte/workspace/+layout.svelte)
本文档阐述了双向内容格式转换系统,该系统在 Markdown、HTML 和 Tiptap JSON 格式之间维护同步表示。转换管道允许用户使用 Markdown 语法,而 Tiptap 编辑器在内部操作 HTML/ProseMirror 结构,同时所有格式都会被存储,用于版本控制、AI 处理和导出。
有关 Tiptap 编辑器整体架构和扩展的信息,请参阅 9.1 TipTap 编辑器架构。有关使用 Yjs CRDT 的协作编辑功能,请参阅 9.3 协作编辑。
目的与范围
内容格式转换系统提供以下功能:
- Markdown → HTML 转换:在初始化编辑器内容时使用
marked库src/lib/components/notes/NoteEditor.svelte:168-170。 - HTML → Markdown 转换:在提取用户输入用于 AI 上下文或存储时使用
TurndownService。 - JSON → HTML 转换:通过 ProseMirror schema 恢复编辑器状态
src/lib/components/notes/NoteEditor.svelte:248-251。 - 自定义渲染规则:针对任务列表、表格和代码块,确保 AI 的 Markdown 响应与编辑器视觉状态之间的一致性
src/lib/components/notes/NoteEditor/Chat.svelte:7-31。 - 多格式存储:支持版本控制、导出和跨平台兼容性
src/lib/components/notes/NoteEditor.svelte:108-122。
该系统在编辑器事务期间透明运行,同时维护三种格式的表示。笔记将所有格式持久化到数据库结构中:note.data.content.json、note.data.content.html 和 note.data.content.md src/lib/components/notes/NoteEditor.svelte:108-115。
来源: src/lib/components/notes/NoteEditor.svelte:108-122、src/lib/components/notes/NoteEditor/Chat.svelte:7-31
转换管道架构
三向格式转换流程
graph TB
subgraph "外部接口"
MDInput["Markdown 输入<br/>(AI 响应 / 初始加载)"]
MDOutput["Markdown 输出<br/>(AI 上下文 / 导出)"]
end
subgraph "存储层"
NoteStorage["note.data.content<br/>{json, html, md}"]
end
subgraph "转换层"
MarkedParser["marked.use()<br/>Markdown -> HTML"]
TurndownService["TurndownService<br/>HTML -> Markdown"]
end
subgraph "编辑器核心"
TiptapEditor["Tiptap 编辑器<br/>(ProseMirror)"]
HTMLState["editor.getHTML()"]
JSONState["editor.getJSON()"]
end
MDInput --> MarkedParser
MarkedParser --> TiptapEditor
TiptapEditor --> HTMLState
TiptapEditor --> JSONState
HTMLState --> TurndownService
TurndownService --> MDOutput
HTMLState --> NoteStorage
JSONState --> NoteStorage
MDOutput --> NoteStorage
NoteStorage -.->|恢复版本| TiptapEditor
来源: src/lib/components/notes/NoteEditor.svelte:108-115、src/lib/components/notes/NoteEditor.svelte:168-170、src/lib/components/notes/NoteEditor.svelte:233-246
转换发生在关键事务节点:
- 初始化:加载笔记时,系统检查是否存在 HTML。如果缺失,则回退到通过
marked.parse()解析 Markdown 来填充编辑器src/lib/components/notes/NoteEditor.svelte:168-170。 - AI 集成:当 AI 模型生成内容时,通常提供 Markdown。
Chat.svelte组件处理此流并触发编辑器更新src/lib/components/notes/NoteEditor/Chat.svelte:204-241。 - 版本存储:
NoteEditor.svelte中的insertNoteVersion()函数为版本历史数组存储所有三种格式(JSON、HTML、MD)的快照src/lib/components/notes/NoteEditor.svelte:233-246。 - 手动编辑:当编辑器内容发生变化时,状态会更新并在各格式之间同步,以确保
md表示可用于标题生成src/lib/components/notes/NoteEditor.svelte:253-255。
来源: src/lib/components/notes/NoteEditor.svelte:168-170、src/lib/components/notes/NoteEditor.svelte:233-246、src/lib/components/notes/NoteEditor/Chat.svelte:204-241
Markdown 到 HTML 转换(marked.js)
marked 库被广泛用于将 AI 生成的 Markdown 转换为与 Tiptap 编辑器 schema 兼容的 HTML。自定义渲染器处理特定的 GFM(GitHub Flavored Markdown)扩展。
自定义列表和任务渲染
在笔记系统中,列表需要特定的 HTML 属性才能被 Tiptap 的 TaskList 和 TaskItem 扩展识别 src/lib/components/notes/NoteEditor/Chat.svelte:10-30:
- 列表渲染器:检测列表是否包含任务项(已勾选/未勾选)。如果是,则将内容包裹在
<ul data-type="taskList">中,而不是标准的<ul>src/lib/components/notes/NoteEditor/Chat.svelte:11-21。 - 列表项渲染器:将 Markdown 任务语法(
- [ ]或- [x])转换为带有data-type="taskItem"和布尔属性data-checked的列表项src/lib/components/notes/NoteEditor/Chat.svelte:23-29。
graph LR
subgraph "Marked 自定义渲染器"
MD["Markdown: - [x] 任务"] --> List["list() 函数"]
List --> Detect["检查 'data-checked='"]
Detect --> HTML["HTML: <li data-type='taskItem' data-checked='true'>"]
end
来源: src/lib/components/notes/NoteEditor/Chat.svelte:7-31
与 AI 工作流的集成
转换系统对于笔记中的 AI 集成至关重要。AI 充当“专家文档编辑器”,接收当前内容的 Markdown 格式,并返回增强后的相同格式版本。
AI 上下文准备
在向 LLM 发送请求之前,系统将数据聚合到基于 Markdown 的提示中 src/lib/components/notes/NoteEditor/Chat.svelte:160-171:
- 现有笔记:使用
note.data.content.md包裹在<notes>XML 标签中src/lib/components/notes/NoteEditor/Chat.svelte:166。 - 文件上下文:附加文件中提取的内容被追加
src/lib/components/notes/NoteEditor/Chat.svelte:167-169。 - 选中内容:如果用户高亮了文本,则将其包裹在
<selection>标签中src/lib/components/notes/NoteEditor/Chat.svelte:170。
AI 响应处理
当 AI 流式输出 Markdown 时,Chat.svelte 组件管理状态。AI 完成后,生成的 Markdown 用于更新编辑器内容 src/lib/components/notes/NoteEditor/Chat.svelte:219-224。
来源: src/lib/components/notes/NoteEditor/Chat.svelte:160-171、src/lib/components/notes/NoteEditor/Chat.svelte:219-241
笔记存储结构
笔记在 data.content 对象中以三种同步格式持久化内容 src/lib/components/notes/NoteEditor.svelte:108-115:
| 格式 | 属性 | 用途 |
|---|---|---|
| JSON | json | 主要的 Tiptap/ProseMirror 状态;用于精确的文档结构保存 src/lib/components/notes/NoteEditor.svelte:112。 |
| HTML | html | 用于编辑器中的即时渲染和基于 Web 的预览 src/lib/components/notes/NoteEditor.svelte:113。 |
| Markdown | md | 用于 AI 上下文、标题生成和导出到外部工具 src/lib/components/notes/NoteEditor.svelte:114。 |
版本控制集成
insertNoteVersion() 函数捕获所有三种格式的快照 src/lib/components/notes/NoteEditor.svelte:233-246。在保存新版本之前,它使用 areContentsEqual()(通过 fast-deep-equal)验证内容是否实际发生变化,以防止重复的历史记录 src/lib/components/notes/NoteEditor.svelte:229-231。
来源: src/lib/components/notes/NoteEditor.svelte:108-115、src/lib/components/notes/NoteEditor.svelte:229-246
格式支持矩阵
| Markdown 结构 | HTML 表示 | Tiptap 节点/属性 |
|---|---|---|
- [ ] 任务项 | <li data-type="taskItem" data-checked="false"> | taskItem 扩展 src/lib/components/notes/NoteEditor/Chat.svelte:26 |
- [x] 已勾选任务 | <li data-type="taskItem" data-checked="true"> | taskItem 扩展 src/lib/components/notes/NoteEditor/Chat.svelte:26 |
| GFM 表格 | <table>...</table> | Table 扩展 |
| 硬换行 | <br /> | HardBreak 扩展 src/lib/components/notes/NoteEditor/Chat.svelte:8 |
来源: src/lib/components/notes/NoteEditor/Chat.svelte:7-31