MindMap/docs/table-node-rendering.md

5.3 KiB
Raw Permalink Blame History

节点包含表格时的渲染逻辑MindMap 前端)

本文件汇总“当节点内容中有表格时”的数据流、渲染、样式、交互与导出路径,便于快速定位问题与修改。

一、总体流程

  • 输入来源
    • Markdown 表格GFM
    • 已有 HTML<table>
  • 转换阶段
    • Markdown → HTML解析后输出 <table class="markdown-table">(附基础样式)。
    • HTML → Markdown需要时优先用 Vditor 的 html2md;内置兜底逻辑会提取 <table> 为 GFM 格式。
  • 节点渲染
    • 优先使用 dangerouslySetInnerHTML 将 HTML 直接写入节点 DOM。
    • 若是纯文本则走普通 topic 文本渲染。
  • 样式覆盖
    • 统一为表格设置固定布局、边框、间距、white-space: normal 等,避免被思维导图默认排版影响。
  • 交互编辑
    • 双击含表格的节点 → 走“表格专用编辑”流程(弹出覆盖层,按 Markdown 表格编辑)。
  • 图片导出SVG
    • 发现 <table> 时,导出使用 foreignObject 渲染,并内联样式与添加背景矩形,确保版式一致。

二、数据来源与转换

  • Markdown → HTML保留为 <table>
    • 位置:frontend/src/components/MindMap.vue
    • 逻辑:将 GFM 表格替换为 <table class="markdown-table">,并生成 <thead>/<tbody> 与单元格基础内联样式。
  • 渲染后统一后处理
    • 位置:frontend/src/utils/markdownRenderer.js
    • 逻辑:把裸 <table> 补成 <table class="markdown-table">,并处理代码块语法高亮等。
  • HTML → Markdown用于回填编辑器/导出)
    • 位置:frontend/src/components/MindMap.vue
    • 逻辑:若缺少 Markdown 源,优先 Vditor.html2md;否则解析 DOM<table> 转回 GFM 表格(含表头/表体)。

示例 Markdown

| A | B |
|---|---|
| 1 | 2 |

渲染为:

<table class="markdown-table">...

三、节点渲染优先级与更新

  • 优先级dangerouslySetInnerHTML > markdown > topic 文本。
  • 直接写入 DOM:更新节点时,如果存在 dangerouslySetInnerHTML,直接 nodeElement.innerHTML = dangerouslySetInnerHTML
  • 回退渲染:当内容不是 Markdown 时,回退渲染会先清理重复符号;若检测到 <table>,不做列表转换,直接保留表格结构。

涉及位置:

  • frontend/src/components/MindMap.vue(保存与“直接设置 HTML”
  • frontend/src/lib/mind-elixir/src/utils/dom.ts(回退渲染与表格检测)

四、样式与布局(确保表格按网格显示)

  • 全局样式(保证在节点内渲染出的 <table> 有固定布局/合并边框/边框色):
    • frontend/src/App.vue 中对 .mind-elixir .map-container .topic table 的规则。
  • 组件内样式(覆盖思维导图的 white-spacedisplay
    • frontend/src/components/MindMap.vue.topic .topic-text.markdown-content tableth/td/tr 规则。
  • 统一 th/td 的内边距、边框与交互高亮,避免被默认 inline 布局破坏行列结构。

五、交互:双击进入表格编辑

  • 位置:
    • frontend/src/lib/mind-elixir/src/mouse.ts:双击节点时若 innerHTML<table>,走“表格编辑”。
    • frontend/src/lib/mind-elixir/src/nodeOperation.tsbeginEdit 内部判断表格后调用 editTableNode
  • 编辑方式:
    • editTableNode 弹出覆盖层,编辑 Markdown 表格源(包含 HTML↔Markdown 的转换工具)。

六、导出图片SVG中的表格渲染

  • 位置:frontend/src/lib/mind-elixir/src/plugin/exportImage.ts
  • 检测 dangerouslySetInnerHTML 中是否含 <table>
    • 含表格:使用 foreignObject 嵌入 HTML计算节点尺寸创建背景矩形并将所需样式内联化以确保导出与画布一致表格本身在 foreignObject 内按浏览器 HTML 布局渲染。
    • 非表格 HTML优先尝试原生 SVG 文本渲染;必要时退回 foreignObject

七、关键判断点一览

  • 是否包含表格:
    • 通过检测 '<table''<td>''<th>' 或 Markdown 中的 | 来作出路径选择(如走表格编辑、使用 foreignObject 导出等)。
  • 渲染选择:
    • dangerouslySetInnerHTML → 直接注入 HTML
    • 否则尝试 markdownmarked/自定义解析
    • 最后回退到纯文本 topic

八、常见问题与建议

  • 若表格在节点中“挤成一行”或“行列错乱”,优先检查是否有样式覆盖了:
    • display: table-*white-space: normal !importanttable-layout: fixedborder-collapse: collapse 是否生效。
  • 导出图片中表格错位:确认 foreignObject 是否被禁用、样式是否已内联、节点尺寸计算是否准确。
  • 需要统一风格时,优先改 .markdown-table.topic .topic-text.markdown-content table 相关样式。

相关文件清单(便于跳转)

  • frontend/src/components/MindMap.vue
  • frontend/src/utils/markdownRenderer.js
  • frontend/src/lib/mind-elixir/src/utils/dom.ts
  • frontend/src/lib/mind-elixir/src/mouse.ts
  • frontend/src/lib/mind-elixir/src/nodeOperation.ts
  • frontend/src/lib/mind-elixir/src/plugin/exportImage.ts
  • frontend/src/App.vue