前端富文本UI组件AI 应用【免费下载链接】BlockNoteA React Rich Text Editor thats block-based (Notion style) and extensible. Built on top of Prosemirror and Tiptap.项目地址https://gitcode.com/gh_mirrors/bl/BlockNote点击查看免费下载导读本文以 BlockNote 仓库中 Markdown 导出测试的快照文件tests/src/unit/core/formatConversion/export/__snapshots__/markdown/style/mixedInParagraph.md为切入点剖析 BlockNote 如何将同一段落内混合的加粗、斜体、行内代码、删除线等文本样式无损地序列化为标准 Markdown 语法。读者将理解blocksToMarkdownLossy的完整调用链、htmlToMarkdown行内样式的逐标签映射规则以及仓库测试如何用快照固化这一行为。快照内容一行精确的预期输出关联文档tests/src/unit/core/formatConversion/export/__snapshots__/markdown/style/mixedInParagraph.md全文仅一行Normal **bold** *italic* code ~~strike~~这一行并不是普通的 Markdown 文本而是仓库导出测试体系中的预期输出快照它对应一个由五个文本节点拼接而成的段落依次为普通文本、加粗、斜体、行内代码、删除线。快照文件由 exportTestExecutors.ts 中的testExportMarkdown执行器通过toMatchFileSnapshot自动比对生成任何导出逻辑的改动导致输出变化都会让该快照测试失败从而锁死序列化行为。快照背后的测试用例输入与输出一一对应style/mixedInParagraph测试用例定义在 exportTestInstances.ts其输入的 BlockNote 块结构如下{ type: paragraph, content: [ { type: text, text: Normal , styles: {} }, { type: text, text: bold , styles: { bold: true } }, { type: text, text: italic , styles: { italic: true } }, { type: text, text: code , styles: { code: true } }, { type: text, text: strike, styles: { strike: true } }, ], }对照快照输出可以得出 BlockNote 的样式映射约定输入样式Markdown 标记输出示例{}无样式原样输出Normal{ bold: true }**...****bold**{ italic: true }*...**italic*{ code: true }...code{ strike: true }~~...~~~~strike~~同目录快照的横向对照style/目录下的其他快照印证了映射规则的一致性与组合规则见 style 快照目录bold.md**Bold text**italic.md*Italic text*code.mdInline codestrike.md~~Strikethrough text~~combined.md***Bold and italic***bold italic 合并为***boldItalicStrike.md***~~All styles~~***三样式嵌套组合另外两个有代表性的不可导出样式也体现在快照中underline.md输出Underline text即下划线在 Markdown 中没有等价语法序列化时被剥掉标签、仅保留文本textColor.md 与 backgroundColor.md输出均为纯文本说明颜色类样式同样无法用 Markdown 表达导出时丢失。这正是blocksToMarkdownLossy中 Lossy有损一词的含义非 Markdown 原生样式在导出过程中被有意丢弃而加粗、斜体、行内代码、删除线这些有原生语法的样式则被完整保留。调用链从编辑器 API 到快照比对导出 Markdown 的完整调用链如下编辑器公开 APIblocksToMarkdownLossy定义于 BlockNoteEditor.ts将调用委托给内部管理器ExportManager.blocksToMarkdownLossy见 ExportManager.ts调用blocksToMarkdownmarkdownExporter.ts 的blocksToMarkdown先把块序列化为外部 HTML再调用cleanHTMLToMarkdowncleanHTMLToMarkdown去除空块占位符后调用htmlToMarkdown见 markdownExporter.tshtmlToMarkdown执行真正的 DOM 级序列化见 htmlToMarkdown.ts。在测试侧testExportMarkdown直接调用editor.blocksToMarkdownLossy(testCase.content)并把返回值与快照文件比对。由于exportTestInstancesMarkdown是由 BlockNote HTML 测试实例.map()派生而来见 exportTestInstances.ts同一组用例同时覆盖了 BlockNote HTML、外部 HTML、Markdown、TipTap 节点四种导出格式快照目录也因此一一对应blocknoteHTML/、html/、markdown/、nodes/。源码级序列化规则行内样式逐标签映射htmlToMarkdown的注释明确说明见 htmlToMarkdown.ts这是一个替换 unified/rehype-remark 管线的自研 DOM 实现输入是createExternalHTMLExporter产生的 HTML 字符串输出为 GFM 兼容的 Markdown。其行内内容序列化逻辑集中在serializeInlineContent见 [htmlToMarkdown.ts](https://link.gitcode.com/i/49a93729f0e8c5273cde7d606abfebd1#L741-L850核心映射如下case strong: case b: { const inner serializeInlineContent(childEl); const { content, trailing } extractTrailingWhitespace(inner); if (content) { result **${content}**${trailing}; } else { result trailing; // 纯空白节点不加强调标记 } break; } case em: case i: { // 同理输出 *content*末尾空白移到标记外 ... } case s: case del: result ~~${serializeInlineContent(childEl)}~~; break; case code: { // 根据反引号连续长度自适应围栏必要时补空格 ... } case u: // Markdown 无等价语法——剥离标签保留内容 result serializeInlineContent(childEl); break; case span: // 颜色 span 等——剥离标签保留内容 result serializeInlineContent(childEl); break;几个值得注意的实现细节尾部空白的处理extractTrailingWhitespace会把强调内容末尾的空格移到强调标记之外。例如strongbold /strong输出为**bold**而非**bold **见 htmlToMarkdown.ts 的注释。这正是混合段落中**bold**、*italic*等标记后空格不进入强调语法的原因行内代码围栏自适应code序列化会统计内容中最长的反引号连续长度用longestRun 1个反引号作为围栏并在内容以反引号开头或结尾时补充空格避免代码内容与围栏冲突见 htmlToMarkdown.ts空强调节点的降级当strong内全是空白时不加**标记直接输出空白避免产生****这类无意义语法见 htmlToMarkdown.ts。同时serializeParagraph见 htmlToMarkdown.ts通过trimHardBreaks去掉段落首尾的br硬换行再以\n\n结束段落保证多段落混合文档的 Markdown 排版正确。测试如何驱动并验证该行为该快照属于tests/src/unit/core/formatConversion/export/runTests.test.ts中 Export tests (Markdown) 测试组见 runTests.test.ts。每个测试用例通过createTestEditor(testSchema)创建真实编辑器实例再执行导出并做快照比对。在 exportTestExecutors.ts 中可以看到比对前的两个细节(window as any).__TEST_OPTIONS.mockID 0重置 mock ID保证块 ID 等输出确定性addIdsToBlocks(testCase.content)为测试内容补上 ID模拟真实文档结构。结合同目录的 HTML 快照如blocknoteHTML/style/boldItalicStrike.html可以推断导出流程是块 → 外部 HTML → Markdown的两段式外部 HTML 序列化器先把样式表达为strong、em、del、code等标准标签htmlToMarkdown再将标签翻译成 Markdown 标记。两段职责分离也让快照测试可以分别锁定各自的行为。实战应用在项目中使用 Markdown 导出在实际业务中可直接使用编辑器实例的公开 API 获得与快照一致的 Markdown 输出import { BlockNoteEditor } from blocknote/core; const editor new BlockNoteEditor({ /* 你的 schema 配置 */ }); // 导出整个文档为 Markdown有损 const markdown editor.blocksToMarkdownLossy(); // 或导出指定块列表 const subset editor.blocksToMarkdownLossy([/* PartialBlock 数组 */]);使用注意事项blocksToMarkdownLossy是有损导出下划线、文字颜色、背景色等非 Markdown 原生样式会被丢弃见 ExportManager.ts 的注释说明如需保留完整样式信息应改用blocksToFullHTML或blocksToHTMLLossy非列表项的嵌套子块在输出中会被解嵌套这是 Markdown 表达能力限制下的既有行为反向操作可使用tryParseMarkdownToBlocks见 ExportManager.ts与导出 API 组成完整的 Markdown 往返链路。小结mixedInParagraph.md虽只有一行却完整记录了 BlockNote Markdown 导出的核心行为加粗**、斜体*、行内代码、删除线~~四种原生样式被正确映射空白被优雅地移出强调标记而无 Markdown 语法的样式则被显式丢弃。结合 htmlToMarkdown.ts 的逐标签实现与 exportTestInstances.ts 的用例定义开发者可以准确预判blocksToMarkdownLossy的输出行为并以此为基础设计自己的导出与迁移管线。赞分享前端富文本UI组件AI 应用【免费下载链接】BlockNoteA React Rich Text Editor thats block-based (Notion style) and extensible. Built on top of Prosemirror and Tiptap.项目地址https://gitcode.com/gh_mirrors/bl/BlockNote点击查看免费下载相关推荐BlockNote 多引用块 Markdown 导出全解析从快照用例到序列化源码BlockNote 多引用块 Markdown 导出全解析从快照用例到序列化源码 导读 本文聚焦 BlockNote 中多个 相邻引用块blockquote前端富文本UI组件AI 应用从快照测试看 BlockNote 的 Markdown 导出复杂块如何做有损序列化从快照测试看 BlockNote 的 Markdown 导出复杂块如何做有损序列化 本篇技术指南以 BlockNote 仓库中一个真实的导出快照文件 misc前端富文本UI组件AI 应用AMD显卡怎么练AI绘画模型kohya_ss的ROCm完整上手指南AMD显卡怎么练AI绘画模型kohya_ss的ROCm完整上手指南 想在AMD显卡上训练Stable Diffusion风格的AI绘画模型可以用开源项目 k前端富文本UI组件AI 应用上一篇Windows驱动清理终极指南使用Driver Store Explorer快速释放C盘空间下一篇如何快速掌握XXMI-Launcher6款热门游戏模组管理器完整使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考