Skip to content

Releases: WinterMosquito/Obsidian-Mindmap-Studio

0.1.3

Choose a tag to compare

@github-actions github-actions released this 21 Sep 04:45

中文 | English

0.1.3 是一次性能与验证基建版本:修复「多节点导图打开时卡顿严重、加载很久」(打开时的默认视口居中不再把整棵树临时装配进 DOM),并收敛三处重复付出的高频成本(打开含图笔记不再为解析一个图片地址构建全库索引、文件重命名/删除的引用预检与拖拽落点识别的每帧/整树开销下降)。同时把 verify:visual 的四个固定延时型探针改为「渲染事件 + 轮询」的就绪判定,消除负载机器上的探针假失败。无破坏性变更(.mindmap.md 格式、命令 ID、设置项均未变;最低支持版本仍为 Obsidian 1.13.0)。

性能

  • 打开大图不再为「整体居中」把整棵树临时装配进 DOM(用户实测反馈「多节点打开卡顿严重、加载很久」):性能模式下视口外节点会被引擎回收出 DOM,而打开时的「100% + 整体内容居中」需要全图包围盒——旧实现先把整棵树同步装配进 DOM 再测量,且该动作在打开窗口内被重复触发多轮(首帧渲染结束、其自身事件重入、150ms 兜底、图片尺寸回灌后的补居中),节点越多每轮越重。现改为直接遍历渲染树的布局几何求包围盒(与引擎裁剪判定同源,零 DOM 装配、纯计算),并在「比例已是 100% 且内容已居中」时整体跳过(不再触发多余重绘)——「适应画布」仍是引擎的全量通道,行为不变
  • 解析一个图片地址不再构建全库索引:打开含图笔记时,首个 app://… 地址的解析此前会在惰性索引未建时同步构建全库索引(10 万文件库实测 300ms+ 的同步阻塞);现优先「从地址提取路径 → 直查文件 → 校验地址全等」(实测 ~2µs),未命中才回退索引——历史形态的兜底行为不变
  • 库事件与高频查询的成本收敛create 事件由「整体失效 + 下次全量重建」改为增量补建(批量导入 / 外部同步风暴期不再反复付全库成本);索引未命中自愈的数量比对加时间窗节流;同名冲突查询走共享索引计数(新建文档链接不再逐次全库扫描);拖拽辅助线每帧不再为全树节点分配临时坐标对象(先做平方距离预筛);文件重命名 / 删除的引用预检不再为每个节点拼接比对串(2000 节点实测 0.68ms → 0.51ms,「空 needle」也不再恒命中);纯文本行的解析少一次数组分配

工程

  • 测试:全量 48 文件 / 1567 例(三轮新增 / 改写覆盖索引增量与校验节流、资源地址直解与异常兜底、引用预检零拷贝、拖拽几何一致性、数据层包围盒与幂等短路等契约);npm run verify:visual 现有 16 个断言探针(新增 perf-box:大图居中不装配全量 DOM + 数据层盒与 DOM 盒口径一致)
  • 验证基建加固verify:visual 的四个固定延时型探针(perf / image / count / layout)改为「node_tree_render_end 事件 + 轮询」的就绪判定(读 DOM 结构 / 计数的探针用严格模式),并修复构建器计数器被邻图渲染污染的问题——负载机器上的稳定假失败(探针读到 renderer.root 为 null 的中间态)就此消除

兼容性说明

  • 与 0.1.2 一致:需要 Obsidian 1.13.0+仅桌面端isDesktopOnly: true
  • .mindmap.md 格式、既有命令 ID、设置项与快捷键均未变更;本版为纯性能 / 稳定性改动,无需任何迁移

Performance

  • Opening a large map no longer attaches the whole tree to the DOM just to centre it (user feedback: "opening a multi-node map stutters badly and takes a long time"): in performance mode off-viewport nodes are reclaimed out of the DOM, while the opening "100% + centre all content" needs the full-map bounding box — the old implementation first attached the entire tree to the DOM synchronously to measure it, and that step was repeated several times during the opening window (first frame, its own event re-entry, the 150 ms fallback, and the re-centring after image-size corrections); the more nodes, the heavier each round. The box is now computed directly from the render tree's layout geometry (the same source the engine's culling check uses — zero DOM attachment, pure computation), and the whole step is skipped when the view is already at "100% and centred" (no redundant redraw triggers). "Fit canvas" still uses the engine's full-load path, unchanged
  • Resolving one image address no longer builds the whole-vault index: opening a note with images used to synchronously build the lazy whole-vault index for the first app://… address (measured 300 ms+ on a 100k-file vault); it now tries "extract the path → look the file up → verify the address matches" first (~2 µs) and falls back to the index only on a miss — historical-format fallback behaviour is unchanged
  • Lower cost for vault events and hot lookups: create events now incrementally add their entries instead of invalidating the whole index (bulk imports / external sync no longer pay the full-vault cost over and over); the self-healing count comparison on an index miss is throttled by a time window; the same-name conflict check reads shared index counts (creating a document link no longer scans the whole vault per call); drag guides no longer allocate a temporary coordinate object per node per frame (squared-distance pre-filter first); rename / delete reference pre-checks no longer concatenate a comparison string per node (2000 nodes: 0.68 ms → 0.51 ms, and an empty needle no longer matches everything); plain-text Markdown lines skip one array allocation

Engineering

  • Tests: the full suite is 48 files / 1567 cases (new / rewritten across the rounds: index increment and validation throttling, resource-address direct resolution and exception paths, zero-copy reference pre-checks, drag geometry parity, the data-layer bounding box and idempotent centring); verify:visual now has 16 assertion probes (the new perf-box probe: centring a large map attaches no whole-tree DOM, and the data-layer box matches the DOM box)
  • Verification hardening: the four fixed-delay probes (perf / image / count / layout) now use an "engine render event + polling" readiness check (strict mode for probes that read DOM structure or counts), and the builder counter is no longer installed on the shared options object (neighbouring maps' first frames used to leak calls into its idle-render window) — the stable false failures on loaded machines (probes reading renderer.root while it was still null) are gone

Compatibility notes

  • Unchanged from 0.1.2: requires Obsidian 1.13.0+, desktop only (isDesktopOnly: true)
  • No changes to the .mindmap.md format, command IDs, settings or hotkeys; this release is performance / stability-only and needs no migration

0.1.2

Choose a tag to compare

@github-actions github-actions released this 17 Sep 13:20

中文 | English

0.1.2 是一次「节点内富文本 + 结构整理 + 图片增强 + 回写保真 + 逐条对齐 Obsidian 官方交互口径」的版本:新增节点内富文本(方案 B)——节点里的链接渲染为可点文本(多链接各自可点、URL 恢复为可点地址、悬停预览跟指针)、轻标记(粗体 / 斜体 / 行内代码 / 删除线)、超长节点截断展示多 token 编辑后原位保真;新增混排双链拆分(选中节点命令、编辑后自动、全文批量三种入口),段落(文本)节点支持首行图片渲染;图片链路做了成体系的修复与性能优化(加载期尺寸不回写、调宽写入合并、缓存 LRU / 跨会话);回写层集中修复了一批编辑后数据降级问题(一行多图的嵌入语法、一行多链接 / 多 URL 的非首个 token、链接引用定义行),并再次调整「纯双链化」写入语义。同时修复了打开导图时的视口偏差与**「先亮根节点居中、再跳成整体居中」的可见跳变**(首帧几何三坑,见「修复」),设置面板调整改为原地生效、不再重建引擎(性能阈值 / 主题不再重置视图,见「性能」)。底层 Markdown 无损往返、三类链接图标、官方尺寸语法、PNG 导出、搜索、性能模式均保持兼容。本版另含一轮对照官方指南与 API 的合规审计(修复发布阻断、许可声明分发、视图与引擎的生命周期泄漏,收回 ESLint 配置层的三处静默放宽,并补上 CSS 检查与发布元数据门禁——见「工程」)。

新增

  • 混排双链拆分:与描述文字混排的文档 / 附件双链(如 关于 [[冬天]] 和 [[秋天]] 的相关问题)可抽离为子节点——父节点保留描述文字(链接处替换为可见名),每条链接一个子节点(各自拥有图标 / 悬停 / 点击)。三种入口:① 命令「拆分节点内双链为子节点」;② 编辑此类节点后自动拆分(设置项「自动拆分混排双链」,默认开启,可关闭;检查对象为编辑期捕获的节点,编辑提交后即使快速切换选中节点也不会漏拆);③ 命令「拆分文档内全部混排双链」批量处理整篇(含未编辑的存量节点)。图片与外链不拆分、链接引用定义行不拆分、同一目标去重、重复执行幂等
  • 段落节点首行图片:段落(文本)节点首行的 ![[图.png]] 现在会渲染为节点图片(可更换 / 移除);段落中的链接语法仍按原文逐字保真
  • 节点内富文本(方案 B):节点里的链接渲染为可点文本(点击跳转、Ctrl/Command+点击在新标签打开)——一行多枚链接各自可点(此前只有第一枚生效)、悬停预览两级制(悬停某枚链接文字 → 预览那一枚;悬停节点其它位置 → 预览该节点承载的链接);URL 与其它内容混排时恢复为可点地址(此前一律仅图标);轻标记 **粗体** / *斜体* / `行内代码` / ~~删除线~~ 在节点内直接呈现(无链接的节点同样生效),文件原文逐字保真;段落(多行)节点里的链接同样可点。含链接 / 轻标记 / 超长文本的节点改由插件文本弹窗编辑(双击 / 右键「编辑文本」/ F2 三入口共用,弹窗里是全文),自绘内容样式随导出 SVG 内联带出(PNG 导出保真)
  • 超长节点截断展示:超过 2000 字的节点只渲染开头 + (悬停有说明),完整内容仍在文件中、双击可查看 / 编辑全文
  • 节点编辑弹窗:原文模式(编辑入口按节点类型分流):纯链接节点仍是「改别名」(原语义不变);其余富节点(混排链接 / URL / 轻标记 / 超长)改为编辑文件里的那一行——[[双链]]、URL、**粗体** 语法全部可见可改,弹窗内实时显示「节点将显示为」预览,保存后逐字写回该行(重解析 → 行内字段整体重建 ⇒ 未编辑态)。此前这类节点编辑的是显示文本:双链只剩剥壳名、外链(icon-only)连影子都没有(用户实测反馈)
  • 多 token 编辑后「原位」保真:一行内多枚链接 / URL / 图在编辑节点后按原文位置写回(此前一律挪到行尾);无法定位时才回落到行尾追加
  • 交互对齐 Obsidian 官方口径(逐条对照官方帮助库):① 打开链接的落点补齐两档——Ctrl/Command+Alt+点击=新标签组,再加 Shift新窗口(此前只有「新标签」);② 未解析链接弱化——指向尚不存在目标的链接显示为弱化配色(同阅读视图),且悬停不再弹预览;③ 行内语法扩至官方清单——新增 ==高亮==__粗体__ / _斜体_***粗斜***、双反引号代码跨度,并正确处理反斜杠转义(\*a\* 显示 *a*,此前会被误渲染成斜体)与 %%注释%%(节点内隐藏,文件里保留),与阅读视图一致;④ 拖入系统文件支持任意类型(此前有类型白名单),可嵌入的附件默认写嵌入语法 ![[报告.pdf]],按住 Ctrl(Win/Linux)/Option(mac)拖入则不复制、改插入指向原位置的绝对链接 [文件名](<file:///…>)(点击交系统默认应用)——与 Obsidian 的拖放一致

修复

  • 回写保真:一行多张库内图片![[a.png]] 与 ![[b.png]] 此前任何保存都会把第二张图的嵌入语法降级为纯文件名文本(被误判为「残留链接」);现按目标类型区分,图片类嵌入完整保留
  • 回写保真:一行多链接 / 多 URL / 多图:编辑此类节点后,非首个 token 此前会降级为文本(多裸 URL 连内容都会整体丢失);现按原文完整保留——内容与语法不丢,为保持行结构稳定,额外 token 统一附于行尾,所在位置可能与原文不同(本版后续已改为原位写回,见「新增」最后一条)
  • 回写保真:链接引用定义行(参考式 [ref]: … / 脚注 [^1]: …):此前编辑含裸 URL 的定义行会把 URL 挪到行尾、[ref] 引用全部失效;现定义行整体按纯文本保真,拆分命令同样跳过定义行
  • frontmatter 写盘取磁盘现值(数据安全):写盘前重读文件,文件头以磁盘当前内容为准——视图打开期间在属性面板 / 其它窗格 / 其它设备(同步)改动的属性,不再被加载时的旧快照覆盖(此前偶有「笔记属性丢失」)
  • frontmatter 解析边界对齐 Obsidian:空属性块(------ 相邻、属性被删光)不再被并进正文;YAML 块标量(| / >)内部的 --- 不再截断属性;开头 BOM 计入文件头原样保留(此前会导致首个标题降级为段落、首个列表项多出假缩进)
  • 图片:加载期自动尺寸不再回写:按原始比例自动算出的显示尺寸(非用户意图)不再写出 |宽度——此前从未编辑过的行可能在保存后凭空多出尺寸参数
  • 图片:右键「移除图片」后不再复活:此前在列表 / 标题节点移除图片,下一次保存会把原图写回(图片回写元数据被清理后,「图片已移除」判定失效、整行被逐字写回);现判定不再依赖字段残留——image 为空且行内仍有图片语法(行内 ![[…]] / ![…](…))即按移除处理,与段落节点同口径
  • 拆分:运行期资源地址不再污染笔记:此前图片节点的混排拆分会把运行期资源地址(app://…#图.png?时间戳)当作附件抽成子节点、URL 编码片段被写进父文本;现与序列化同入口携带 app,行内出现 app:// 一律放弃拆分
  • 删除笔记导致链接被静默降级为纯文本(数据安全,用户实测反馈):此前删除笔记(或移入 .trash)时,插件会把导图节点上的链接引用清空——但节点文本与行内台账不动,于是下一次保存把 [[笔记A]] 写成了纯文本 笔记A(同一行里其它链接因台账仍在而保留语法,表现为「首个链接降级」),不可逆。现改为:链接只改不删——删除/回收站场景保留为「未解析链接」(与 Obsidian 一致,同名笔记重建即恢复),重命名仍照旧改写;附件整条删除——引用与节点内的可见文字一起去掉(只清引用会留下「报告.pdf」这样的纯文本残留),因此变成空的叶子节点连节点一并摘除,带子节点的节点则退化为保留引用(不连带删子树);内嵌图片仍按删除即清除(目标缺失会在节点上留下坏死图块)
  • 超长节点导致白屏 / 卡死后关闭:根因在引擎默认 SVG 文本路径——其换行逐字符迭代、每加一字重新拼接整行并重新测量一次,单行开销随字数二次增长(无头 Chrome 同机实测:20k 字单行 ≈ +2.8 秒 / 节点,整轮 1.1s → 3.9s),而原「超长文本回落引擎」策略恰好把最长的行送进该通道。现改为长文本一律自绘接管 + 截断展示:同负载整轮回到 1.1 秒(与无长文本基线持平)
  • 轻标记在无链接节点不生效**粗体** 此前只有在含链接的节点里才渲染,否则原样显示标记符;现「含链接轻标记」都接管
  • 导出 PNG 掉样式:自绘内容的布局 / 排版 / 配色 / 轻标记样式改为全部内联在元素上(引擎导出只注入自身 CSS,不加载插件 styles.css;此前依赖类规则会让导出图尺寸与排版错乱)
  • 富节点双击无响应:引擎的节点编辑框对自绘节点静默失效;现双击 / 右键「编辑文本」/ F2 统一走插件文本弹窗(弹窗内为全文)
  • 打开导图首次渲染就偏移(用户实测反馈):打开 .mindmap.md / 文档模式导图时内容整体偏向一侧、点「适应画布」能立刻拉回(故一直像「偶发」)。根因是首帧居中用陈旧几何——引擎只在创建与 resize() 时缓存容器矩形(elRect / width / height),而首帧后工作区布局 settle、文档模式工具栏重建都会改容器尺寸与位置且不触发 view.onResize,缩放锚点与内容包围盒换算便同时按旧画布算。现取视口前先按实时容器同步引擎几何再换算(getLiveCanvasRect / syncCanvasGeometry),内容包围盒也改以实时容器为原点
  • 保存视口可能把内容推出画布:保存的视口按「当时的容器与内容布局」记录,容器尺寸大改或内容变化后恢复它可能让画面停在画布外(打开即空白)。现恢复后做落界校验:明确判定不可见则放弃恢复、回退默认居中;无法判定(性能模式、引擎中间态)时保持原状,不误伤用户自己的视口
  • 打开时先亮「根节点居中」再跳成「整体居中」(可见跳变):引擎默认 initRootNodePosition = [center, center],首次布局把根节点摆在画布中心,而插件的视口设置发生在 150ms 兜底定时器里 ⇒ 中间态被绘制、随后跳变。现在在首次布局落地的事件回调里同帧应用视口node_tree_render_end,属布局任务内提交,浏览器不会绘制中间态),并为「布局后内容还会变」的窗口留 2 次重算预算(resize 触发的再布局、图片尺寸回灌都会改包围盒),用尽即停手,不抢用户之后的视口
  • 含图笔记的居中在图片尺寸落定后才准:图片尺寸探测改为不挡首帧后,真实尺寸回灌会改节点尺寸与包围盒;现在回灌后(仅当当前视口仍是打开时自动设置的那个)补一次居中——用户已平移 / 缩放则完全不打扰

性能

  • 图片调宽写入合并:拖拽按最小步长(8px)合并写入、松手补写最终尺寸——整树重排开销降一个量级;陈旧帧按会话所属引擎校验,不写进新引擎
  • 图片尺寸缓存真 LRU:命中提升,热点图不再被冷图挤出后重复解码
  • 跨会话尺寸缓存:经官方 App#saveLocalStorage 按库隔离——第二次打开同一库的图片尺寸零解码探测(外链与探测失败不落盘、数据损坏静默降级)
  • 图片弹窗:预览按解析结果去重,输入中间态不再逐键重建 DOM
  • 节点渲染成本封顶:自绘路径的每节点上界 = 2000 字(与文本总长无关,超长节点不再随字数变慢);行内段序列按原文内容寻址缓存,拖拽 / 缩放期间同一行不再重复解析
  • 设置面板调整「即时生效、不重建引擎」:此前应用设置对每个打开的视图一律重建(整树深拷贝 + 销毁重建引擎 + 全量重渲染 + 工具栏重建),而性能阈值是 step 100 的滑块、拖一次即几十轮。现按按键差集分流——主题setThemeConfig)与性能模式 / 阈值updateConfig,引擎显式支持运行时开关)原地生效默认布局 / 默认连线样式对已打开的图本就不生效,直接跳过;只有拖拽开关语言仍需重建(引擎侧只有创建期通道:拖拽由创建期注册的 Drag 插件承担,语言在创建期被闭包捕获)
  • 渲染经济:一次动作至多一次布局落地:审计插件侧全部 render() 调用点,查出并修掉一处冗余(关闭性能模式时与引擎自带的一次重复 ⇒ 白白多一轮全树渲染);verify:visual 新增 render-eco 探针,把 8 条代表性动作的布局落地次数钉成回归闸门
  • 大图撤销深度的内存预算:命令历史逐条保存「整树 JSON 快照」,单条 ≈ 节点数 × 0.4KB,原先的固定条数上限让单视图历史常驻内存随图规模失控(旧策略 500 节点图 ≈ 91MB/视图,反重于 2000 节点图 ≈ 70MB)。现按 30MB/视图的内存预算反推条数上限:500 节点 → 163 条、2000 节点 → 40 条、超大图保底 30 条(预算宽裕的小图仍是引擎默认 500 条)——单视图历史内存钉在预算内,撤销深度仍远超日常所需

行为变化提示

  • 链接写入语义再修订(0.1.1「无条件覆盖」→ 本版仅「完全空白」节点覆盖):把链接(文档 / 附件 / URL)挂到节点时——已有任何内容的节点(文字 / 原链接 / 图片 / 行内额外 token)一律建为子节点,节点原内容完全不动(行内多链接不再被覆盖牵动);只有完全空白节点才覆盖为链接节点。URL 单独成节点时仍是「仅图标」(节点文本为空;与其它内容混排时显示为可点地址)。注意:「一键改链」入口随之取消——改链请先「清除链接」再添加,或直接编辑节点文本
  • 节点内链接现在是可点文本(此前只有第一枚可点、URL 仅图标);含链接 / 轻标记 / 超长文本的节点不再有引擎原位编辑框,双击弹出插件弹窗
  • 编辑弹窗分两种模式(同上「新增」条目):纯链接节点 = 改别名(不变);其余富节点 = 编辑原文行(此前编辑的是显示文本,链接语法与外链都看不见)。原文模式下取消或未改动不写盘
  • 节点宽度(拖左右边框):只有自绘节点能拖——含链接 / 轻标记 / 超长文本(>2000 字)的节点自绘渲染,拖宽生效且高度随换行跟随;纯文本与含图节点不显示该手柄(引擎的 SVG 文本路径不支持按节点改换行宽度,此前手柄可拖但毫无反应)。拖宽仅当前会话有效(正文保持纯 Markdown,宽度不落文件),重开回落 500px 折行上限
  • 超过 2000 字的节点只显示开头 标示,悬停有说明);文件内容与 data.text 不受影响,双击可查看 / 编辑全文
  • 含图节点不受这些渲染变化影响:图片仍由引擎图片通道渲染(图片节点的混排文本不再叠加文档页图标);含图 + 超长文本的节点仍由引擎换行承担(无法接管),建议把该节点拆短
  • F2 对齐官方未选中节点时 F2 交回 Obsidian=重命名当前文件(官方语义);选中节点时仍是编辑该节点(中心节点被选中时同理——中心节点文本即文件名)。此前无条件吞键,等于在导图视图里用不了官方 F2
  • 新增设置「自动更新链接」(对应官方「自动更新内部链接」,默认开启):关闭后重命名不再改写链接(变未解析)、删除不再清理引用与附件,与官方关掉该设置的表现一致
  • 链接语法跟随官方 Wikilink 设置:官方「使用 [[Wikilinks]]」开启(官方默认)行为完全不变(恒写 [[双链]]、保留自绘文档页图标);用户关闭该设置时,新文档链接写 md 形态 [显示名](路径.md)(走 hyperlink 通道),重命名改写同样支持该形态(此前只认 [[…]],md 形态链接改名后会失效)
  • 拖入类型白名单取消:库内文件、系统文件、链接弹窗三处的「附件」判定统一为解析侧口径(非文档扩展名即附件,无扩展名视为文档)——手写 [[说明.txt]] 能显示、拖入 .txt 也同样能挂上(此前拖入会被拒、手写却可以,属两侧口径不一致)。随之删除三份失效白名单与两条失效文案
  • 不可渲染的库内文件点击改为交系统默认应用(此前只有音视频外跳,其余弹「无法预览」)——白名单取消后任意扩展名都可能入库,弹提示等于「链了打不开」
  • 大图上的撤销步数减少:历史上限改为按内存预算反推(见「性能」)——可回退步数随图规模收敛(500 节点 163 步 / 2000 节点 40 步 / 保底 30 步),换来单视图历史内存不超过 30MB

工程

  • 测试(全量 42 个文件 / 1327 例):新增 tests/view-split-links.test.ts(自动拆分:设置开关 / 未编辑 / 编辑中与候选集语义)、tests/agents-md-sync.test.ts文档-代码同步契约src/**tests/** 每个文件必须登记在 AGENTS.md,漏登记即红灯);tests/links-split.test.ts 扩为全规则矩阵(含链接引用定义行跳过、拆分后多 token 重建);tests/md-roundtrip.test.ts 补回写保真用例组(一行多图、多链接 / 多 URL / 多图编辑后保真、定义行 4 形态 + 不误伤对照);frontmatter(CRLF / 空块 / 块标量 / BOM)、图片尺寸与缓存、自动拆分候选、引擎事件转发契约等回归补强
  • 文档:AGENTS.md 重构为 K 编号分组体系(K1–K49 稳定引用 ID + 「新增功能检查清单」+ 「本文件维护规则」);标准文档同步(拆分规则、回写保真与已知降级表);README 修正链接写入语义
  • 校验:类型检查 0 错误、eslint 0 警告、全量测试全绿
  • 测试(本轮新增):全量 44 文件 / 1401 例;新增 tests/node-inline-content.test.ts(段序列、接管判定、轻标记、超长截断、内联样式契约)、tests/md-line-write.test.ts(原文写入:行内字段整体重建、逐字往返锁、多行、未闭合语法)、tests/view-wikilink.test.ts 锚点级悬停 6 例、tests/view-hotkeys.test.ts 编辑入口两种模式分流;tests/md-inline.test.ts 补台账登记边界;npm run verify:visual 扩为 9 个场景 + 6 个探针(自绘装配、测宽同源、合成点击命中锚点、导出内联样式、30 富节点规模、超长截断、段落可点)
  • 单一台账:额外 token 的 mdExtraTokens 并入 mdSegmentsfirst 区分首 token / 额外 token),解析、拆分重建、清除链接三处各只有一处实现
  • 修复(撤销失效)拆分文档内全部混排双链(以及重命名/删除文件的引用更新)此前用引擎 setData 落数据——它内部 clearHistory() 会把历史清成「只剩新状态一条」,之后 Ctrl/Command+Z 永远无事发生(用户实测)。现统一走 engine/mindmap.replaceMindMapDataupdateData + CLEAR_ACTIVE_NODE):只追加一条历史,一次撤销即回到操作前;契约由 vendor-contract(引擎必须保留 updateData/CLEAR_ACTIVE_NODE)与拆分、引用更新三处回归锁定
  • 测试(对齐轮):全量 44 文件 / 1437 例tests/node-inline-content.test.ts 补轻标记扩展 / 转义字符集 / 注释 / 未解析标记,tests/view-wikilink.test.ts 补修饰键矩阵、中键(auxclick)与悬停预览两级制用例(锚点优先含「首链为外链时的行内库内 md 链接」实测场景、节点级兜底、锚点为外链时回落);2026-09-16 定稿:曾一度只留锚点级(常规悬停静默无反应)或只留节点级(首链为外链时行内库内链接无法预览),且「未解析不预览」的解析预检与核心职责重复——现为锚点优先 + 节点级兜底、均不做解析预检;tests/view-dnd.test.ts 重写为「任意类型可导入 / Ctrl 绝对链接 / 无扩展名走文档通道」,tests/url.test.tsfile:/// 绝对链接三形态往返,tests/view-node-actions.test.tsapplyExternalLinkmdEmbednpm run verify:visual 扩为 10 个场景 + 6 个探针(新增 syntax 场景:<mark> / __粗__ / 转义 / 注释 / is-unresolved,并含两条负向自检:解析桩恒真、注释不隐藏,均实测报红)
  • 修复(拖边框改宽后节点高度不跟随):自绘(富)节点「选中后拖动左右边框改宽」时宽度变、高度不变。根因在引擎分工:引擎只对自绘节点给出 ew-resize 边框手柄,拖拽中每帧只把宽度写进节点字段 node.customTextWidthreRender([]) 不重建自绘内容),松手也不重建(整树 render() / needLayout 均无效,无头实测元素 inline width 为空),而自绘节点的宽高全部来自内容元素的离屏测宽。现两处配合:自绘内容读 `customText...
Read more

0.1.1

Choose a tag to compare

@github-actions github-actions released this 11 Sep 07:05

中文 | English

0.1.1 是一次「体验增强 + 链路修正」的版本:新增连线样式切换(工具栏 + 设置,按文件持久化)、右键菜单重置缩放维基链接悬停预览扩展到三类节点,并修正了悬停预览的链路判定与「干净双链化」语义。底层 Markdown 无损往返、三类链接图标、图片与嵌入语法保真、PNG 导出、搜索、性能模式均保持兼容,且行为口径更清晰。

新增

  • 连线样式切换(工具栏 + 设置):工具栏新增「连线」下拉,可在 自动 / 曲线 / 直连 / 折线 间切换,偏好按文件持久化到视图状态存储(不写入正文)。设置面板新增「默认连线样式」。目录组织图 / 时间轴 / 鱼骨图 为布局类原生直线、不可切换,控件只显示「自动」
  • 右键菜单「重置缩放」:右键菜单新增「重置缩放」项(rotate-ccw 图标),将视口恢复为 100%
  • 维基链接悬停预览扩展到三类节点:文档双链 / 文档嵌入(mdWikiLinkpath)、双链附件 / 嵌入附件 / 拖入的库内附件(attachmentUrl 回形针通道)现均可悬停触发 Obsidian 原生页面预览 / 附件预览;外链节点不触发(core 只服务库内目标);拖拽节点 / 框选 / 平移时按住鼠标键不弹预览(避免噪声)
  • 根节点连线起点改在节点右缘rootLineStartPositionKeepSameInCurve):与子层级一致、从右缘水平出发,消除此前「斜戳出来」的观感

修复

  • 维基链接悬停预览链路修正:节点承载的链接读取顺序与图标分流同源——文档双链 / 嵌入走 mdWikiLinkpath、附件走 attachmentUrl(并以 mdAttachmentLinkpath 为门控,避免已「移除引用」的残留字段让附件继续可悬停 / 可打开);hyperlink 仅双链形态有效,裸 URL / 协议地址 / 畸形串一律不预览,与 Obsidian 阅读视图一致

行为变化提示

  • 「纯双链化」:把文档 / 附件链接挂到节点时,节点文字无条件覆盖为链接显示名(别名优先),不再保留用户已有的手写正文;底层 md 行也只剩 [[目标|显示名]]。如果你此前依赖「正文节点只附加链接、保留手写正文」,请注意此行为变化
  • 移除引擎自带 Ctrl+L 快捷键(仅 RESET_LAYOUT,不含「适应画布」、无提示):自动整理统一走 mindmap-arrange 命令——你把它绑到 Ctrl+L 时同样以「适应画布」收尾,口径统一

工程

  • 新增 scripts/verify-visual.mjs 可视化校验脚本(202 行),配合 CI 归档诊断日志(verify-visual-logs/,不入库)
  • 测试补强:新增 tests/mindmap-theme.test.ts,并对工具栏、维基链接、视图状态、保存管线、设置、节点操作、视口等大量用例扩充
  • 对齐官方校验:obsidian-api(1.13.2 类型校验 0 错误)、eslint-plugin-obsidianmd(0.4.2,0 警告)
  • 文档同步:README / AGENTS.md / 双语说明更新连线样式、「纯双链化」口径、悬停预览语义

兼容性说明

  • 与 0.1.0 一致:需要 Obsidian 1.13.0+仅桌面端isDesktopOnly: true
  • 视图状态存储新增 lineStyle 字段(按文件持久化连线偏好);旧版 data.json 无该字段时回落全局默认,向后兼容
  • .mindmap.md 文件格式与命令 ID 均未变更;无破坏性格式变更

Added

  • Connector style switching (toolbar + settings): the toolbar gains a "Line style" dropdown with Auto / Curve / Direct / Elbow; the preference is persisted per file in the view-state store (never written into the note body). Settings adds "Default line style". Catalog / Timeline / Fishbone are natively straight layouts and cannot switch, so the control shows only "Auto"
  • Right-click menu "Reset zoom": a new "Reset zoom" item (rotate-ccw icon) restores the viewport to 100%
  • Wikilink hover preview extended to three node kinds: document wikilinks / embeds (mdWikiLinkpath) and dual-link / embedded / dragged vault attachments (attachmentUrl paperclip channel) now trigger Obsidian's native page / attachment preview on hover; external-link nodes do not (core only serves vault targets); holding the mouse button during drag / box-select / pan suppresses the preview (avoids noise)
  • Root node connector now starts at the node's right edge (rootLineStartPositionKeepSameInCurve): consistent with child levels and emits horizontally, removing the previous "skewed out" look

Fixed

  • Wikilink hover-preview link resolution corrected: the node's link is now read in the same order as icon routing — document wikilink / embed via mdWikiLinkpath, attachment via attachmentUrl (gated on mdAttachmentLinkpath so a "removed reference"'s leftover field can't keep the attachment hoverable / openable); hyperlink is only valid as a wikilink shape — bare URLs / protocol addresses / malformed strings never preview, matching Obsidian's reading view

Behaviour changes

  • Pure-wikilink conversion: when a document / attachment link is attached to a node, the node text is unconditionally overwritten with the link's display name (alias first); user-authored body text is no longer preserved, and the underlying md line becomes only [[target|display]]. If you previously relied on "body nodes only append a link and keep the hand-written text", note this change
  • Removed the engine's built-in Ctrl+L shortcut (only RESET_LAYOUT, no "fit canvas", no notice): auto-arrange now goes solely through the mindmap-arrange command — binding it to Ctrl+L still ends with "fit canvas", keeping one consistent behavior

Engineering

  • New scripts/verify-visual.mjs visual-verification script (202 lines), with CI archiving its diagnostic logs (verify-visual-logs/, excluded from the repo)
  • Test hardening: added tests/mindmap-theme.test.ts and expanded coverage for the toolbar, wikilinks, view state, save pipeline, settings, node actions and viewport
  • Aligned with official checks: obsidian-api (1.13.2 type-check, 0 errors), eslint-plugin-obsidianmd (0.4.2, 0 warnings)
  • Docs synced: README / AGENTS.md / bilingual notes updated for line style, pure-wikilink semantics and hover-preview behavior

Compatibility notes

  • Unchanged from 0.1.0: requires Obsidian 1.13.0+, desktop only (isDesktopOnly: true)
  • The view-state store gains a lineStyle field (per-file connector preference); older data.json without it falls back to the global default, so it is backward compatible
  • The .mindmap.md format and command IDs are unchanged; no breaking format changes

0.1.0

Choose a tag to compare

@github-actions github-actions released this 10 Sep 12:21

中文 | English

0.1.0 是一次「先审计、后修复」的版本:先对照官方帮助与官方 API 类型定义做了 [[]] / ![[]] 支持度审计(结论与四项决策已登记),再逐条修复清扫中发现的七处静默数据损坏 / 保真缺陷,并把 Canvas / Bases 正式纳入文档类。核心能力(Markdown 无损往返、三类链接图标、图片与嵌入语法保真、PNG 导出、搜索、性能模式)保持兼容,且保真度整体提高

新增

  • Canvas / Bases 归为文档类![[画布.canvas]] / ![[表格.base#视图]] 与文档双链走同一通道——显示自绘文档页图标、可悬停预览、点图标打开;从文件浏览器拖入 canvas/base 同样按文档处理(.md 用去扩展名写法,非 Markdown 文档必须带扩展名)。指向 .base 的链接此前会提示「无法预览」,现在可正常在标签页打开
  • 非图片嵌入的管道位原文保留![[报告.pdf|300]] 在编辑节点后不再丢 |300。官方未定义该位语义(PDF 用 #height= / #page=、音频无尺寸语法),故插件不解释、只原样保存并回写

修复

  • 换文件时的保存排空可能写错文件(最严重):一次写盘的目标文件与其内容必须同源——排空期间切换文件(核心不等待 onUnloadFile)时,树快照与 frontmatter 一律按该次写盘的文件取,不同文件不再并入同一批次。此前可复现「新文件的正文写进旧文件」或「旧文件的 YAML frontmatter 被丢掉」
  • 「清除链接」对嵌入无效、链接会复活![[笔记]] / ![[报告.pdf|300]] 在字段被清空后仍整行回写。现在只有指向本节点图片的嵌入才在检测中排除,文档 / 附件嵌入按链接形态处理,清除后一并剥离
  • 外链 md 图片被改写成非法 wikilink![截图|300](https://…) 在拖拽调宽或编辑文本后会写成 ![[https://…|300]](wikilink 目标不能是 URL → 图失效、alt 丢失)。现在外链判定先于「image 等于解析期目标」分支,恒写 ![alt|尺寸](url)
  • 未编辑也会改动原文的两类字符:plain 行的行首缩进行尾空格此前被 trim —— 4 空格缩进的代码块退化为普通段落,「行尾两空格 = 硬换行」被抹掉。现在 mdRaw 保存未 trim 原文,节点显示文本仍 trim(行首缩进不进节点文本)
  • 跨文件夹移动后链接悬空[[folder/笔记]] + folder/笔记.mdother/笔记2.md 此前改写为 [[folder/笔记2]](目标不存在)。现在链接形态跟用户走(有前缀继续写路径)但路径取新位置;裸名链接保持裸名;canvas/base 的文件名保留扩展名
  • --- 分两种身份:整行丢弃的规则会连 CommonMark 的 setext H2 下划线一起吞掉(标题\n--- 是二级标题 → 被降级为段落),而 ===== 却保留,两者不对称。现在空行之后的短横线行仍是结构分隔线(丢弃,行为不变),紧跟非空行之后的按 setext 下划线保留

行为变化提示(保真度提高)

  • plain 行现在逐字保真:行首缩进与行尾空格不再被吃掉。若你此前依赖「保存即归一缩进」,请注意行为变化(文件内容会更接近原文,这正是「无损往返」的承诺)
  • 列表 / 标题之后的 --- 现在保留为独立分隔线,序列化器会补一个空行(此前整行消失)
  • 列表续行的行首缩进仍按树深度归一为 2 空格(内容不丢),只有行尾空格改为保真

工程

  • 测试 1174 → 1200(38 个文件),新增 tests/constants.test.ts(33 例,锁定扩展名清单这类「漏登记即误判」的常量契约)
  • 每处修复都做负向对照:把修复退回旧实现,新用例必须变红(实测 3 / 3 / 4 / 6 / 2 / 3 条红),随后按 SHA256 校验复原
  • 把 4 条「把旧缺陷当预期锁死」的用例改写为「已修复」(外链图片「已知降级」、plain 行 trim 归一、空列表项、续行 handle)
  • 文档同步:AGENTS.mddocs/markdown-mindmap-standard.md 登记写盘归属不变式、--- 两种身份、行级保真规则、清除链接口径,以及 [[]] / ![[]] 支持度审计结论与四项决策(均「保持现状」并写明复查触发条件)

兼容性说明

  • 与 0.0.x 一致:需要 Obsidian 1.13.0+仅桌面端isDesktopOnly: true
  • .mindmap.md 文件格式与命令 ID 均未变更;无破坏性变更。本版的行为差异只有「保真度提高」与「--- 不再丢行」两类

Added

  • Canvas / Bases are now document-class targets: ![[Board.canvas]] / ![[Table.base#View]] share the document-wikilink channel — the hand-drawn document icon, hover preview and click-to-open all behave like note links; dragging a canvas/base file in from the file explorer also treats it as a document (.md drops the extension, non-Markdown documents must keep it). Links to .base files used to report "cannot preview"; they now open in a tab
  • Pipe content of non-image embeds is preserved verbatim: editing a node no longer drops |300 from ![[report.pdf|300]]. The official docs never define that slot (PDFs use #height= / #page=, audio has no sizing syntax), so the plugin stores it as-is and writes it back unchanged

Fixed

  • The save drain could write to the wrong file when switching files (most serious): a write's target file and its content must belong to the same file — during the drain, snapshots and frontmatter are now taken for the file being written and different files never share a drain batch (core does not await onUnloadFile). It was reproducible that the new file's body was written into the old file, or the old file's YAML frontmatter was dropped
  • "Clear link" did nothing for embeds, so links came back: ![[note]] / ![[report.pdf|300]] were still written verbatim after the link fields were cleared. Only embeds of the node's own image are excluded from the check now; document/attachment embeds are treated as links and stripped
  • External markdown images were rewritten into invalid wikilinks: after resizing or editing text, ![shot|300](https://…) became ![[https://…|300]] — a wikilink cannot point at a URL, so the image broke and the alt text was lost. The remote-URL check now runs before the "image equals its parsed target" branch, always writing ![alt|size](url)
  • Two kinds of characters were changed even without editing: leading indentation and trailing spaces of plain lines were trimmed — a 4-space indented code block degraded into a paragraph, and the "two trailing spaces = hard line break" was erased. mdRaw now keeps the untrimmed source while the node's display text stays trimmed
  • Links went stale after moving a file across folders: [[folder/note]] with folder/note.mdother/note2.md was rewritten to [[folder/note2]] (a dangling link). The link now keeps the user's shape (path stays a path) but takes the new location; bare links stay bare, and canvas/base names keep their extension
  • --- has two identities: the drop-the-whole-line rule also swallowed CommonMark setext H2 underlines (title\n--- is an H2 heading and was downgraded to a paragraph) while ===== survived — an asymmetry. A dash line after a blank line is still a structural separator (dropped, unchanged); one directly after a non-blank line is now kept as a setext underline

Behaviour changes (higher fidelity)

  • Plain lines are now verbatim: leading indentation and trailing spaces are no longer eaten. If you relied on "save normalises indentation", note the change — file content now stays closer to the source, which is what lossless round-trip promises
  • A --- after a list or heading is now kept as a standalone separator (the serializer inserts a blank line); previously the whole line disappeared
  • Continuation lines inside list items still normalise their leading indentation to 2 spaces per tree depth (nothing is lost); only trailing spaces became verbatim

Engineering

  • Tests 1174 → 1200 (38 files), including a new tests/constants.test.ts (33 cases) locking down constant contracts such as the openable-extension list, where a missing entry means a wrong "cannot preview"
  • Every fix carries a negative control: reverting the fix to the old implementation must turn the new cases red (measured 3 / 3 / 4 / 6 / 2 / 3 failures), then the file is restored and verified by SHA256
  • Four tests that had locked in old defects as expected behaviour were rewritten as "fixed" (external-image "known degradation", plain-line trimming, empty list item, continuation handling)
  • Documentation: AGENTS.md and docs/markdown-mindmap-standard.md now record the write-ownership invariant, the two identities of ---, the plain-line fidelity rules, the clear-link semantics, and the [[]] / ![[]] support audit with its four "keep as-is" decisions and their recheck triggers

Compatibility notes

  • Unchanged from 0.0.x: requires Obsidian 1.13.0+, desktop only (isDesktopOnly: true)
  • The .mindmap.md format and command IDs are unchanged; nothing is breaking. The only behaviour differences are higher fidelity and --- no longer disappearing

0.0.5

Choose a tag to compare

@github-actions github-actions released this 09 Sep 14:46

中文 | English

0.0.5 是一次以「代码检查 + 实测复现」驱动的修复版本:五路并行审查(官方 API 类型定义、官方 eslint 规则、源码正确性、发布/工作流一致性、测试缺陷检测力)后,逐条修复了三处 Markdown 往返数据丢失、悬停预览弹窗定位、改名断链、多窗口(popout)兼容与若干生命周期问题,并删除了 28.8 KB 无用 CSS。核心能力(Markdown 无损往返、三类链接图标、图片、PNG 导出、搜索、性能模式)保持兼容。

新增

  • F2 编辑当前节点:与双击等效;输入框内让位给输入,已在编辑时忽略,无激活节点时仍吞键(避免触发核心「重命名文件」)。引擎自带的 F2 因要求「事件目标为 document.body 且指针在画布内」而时常失效,现由视图 scope 统一接管
  • 「重置缩放(100%)」按钮(位于「适应画布」左侧):以画布中心为锚点回到 100%,屏幕可见内容保持原位;自动整理后同样重置缩放(不再把大图压到文字不可读)
  • 打开时的默认视口:100% 缩放 + 整体内容包围盒居中(不再 fit 压小,也不再只居中根节点导致偏心树偏到一侧)

修复

  • Markdown 往返不再丢内容(实测复现后修复,新增 8 例回归用例)
    • 图文混合 / 「图 + 链接」节点只要编辑过文本,图片引用会被静默丢弃(合成路径此前只输出一枚 token);给已有链接的节点插入图片、给已有图片的节点插入链接同样丢图 —— 现按原文顺序写出全部 token
    • 移除图片后旧图会复活rawOkimage 为空时跳过图片检查,而「链接已清除」检测又排除嵌入语法)—— 现判定「image 空但 md 图片字段仍在 → 已变更」,并同步清理 mdImageTarget/mdImageWidth/mdImageHeight/mdImageAlt
    • 节点文本恰好含同名串时,新插入的图片/链接不会写入文件(特征用裸子串判断)—— 现按嵌入/双链语法边界匹配
    • ![[图.png|说明]] 的说明文本在编辑节点后丢失 —— 现解析与回写均保留
  • 悬停预览弹窗现在会翻转到节点下方:官方 HoverPopover.position() 的锚定矩形是混合取值(宽高走 targetEl.offsetWidth/offsetHeight、位置走 getBoundingClientRect()),SVG 节点没有前两个属性 → bottom/rightNaN,官方定位函数「下方放得下就放下方」的分支恒假,且上方放不下时 top 被写成 "NaNpx"(表现为完全没有预览)。现触发前补齐只读几何,恢复「下方优先、下方不足翻上方、两侧都不足则限高滚动」
  • 编辑中心节点改名不再断链:改用 FileManager.renameFileVault.rename 只改文件系统、不更新库内其他笔记中指向本文件的链接/反链)
  • 多窗口(popout)兼容:拖拽换父、图片拖拽调宽会话与窗口级粘贴兜底的监听改挂画布所属窗口(此前在 popout 里图片调宽完全失效、会话悬挂到视图关闭)
  • 生命周期与竞态:引擎初始化的 rAF 可取消(关闭视图后不再建出无人销毁的引擎实例)、视图关闭后不再应用过期加载结果、首帧视口恢复定时器随销毁取消、跨 await 校验引擎代际(弹窗/保存图片期间换文件不再静默丢失编辑)
  • 文件名清理对齐 Obsidian 约束:补 # ^ [ ](含这些字符的名字无法被双链正确引用)、结尾点/空格与 CON/PRN/… 保留名(此前会直接失败或写出无法引用的文件名)
  • 文档纠错:README 曾写「编辑节点文本 = 双击或按 Enter」——Enter 实际是「添加同级节点」(按下去会新建节点),现改为 F2 并补上「重置缩放」;同时修正若干过期注释

工程

  • 删除无用代码 −28.8 KBstyles.css 的 vendor 段 100% 是 Quill 富文本样式(240 条 .ql-* 选择器),而本插件从不注册 RichText 插件、引擎样式由 bundle 运行时注入 document.head —— 删除该段及 vendor/simple-mind-map.cssscripts/sync-vendor-css.mjs 与对应 npm 脚本;实测删除前后渲染契约与节点测宽逐字节相同
  • 测试 430 → 472(35 个文件):新增默认视口真实几何(此前只断言 mock 被调用)、快捷键注册接线、popout 窗口监听归属、文件名清理、保存「卸载兜底快照」等用例;变异检验确认新用例能抓住旧缺陷
  • CI 增加 verify:visual --require-chrome(浏览器缺失即失败,不再静默跳过);发布工作流的 tag 版本校验前移到构建之前(fail-fast)
  • 收敛重复实现:「插入承载节点」4 处手写收敛为单一入口 insertChildNodeWithData;三处裸 getData 改走防腐收口 getNodeDataString

兼容性说明

  • 与 0.0.1–0.0.4 一致:需要 Obsidian 1.13.0+仅桌面端isDesktopOnly: true
  • 本版无破坏性变更;.mindmap.md 文件格式与既有文件的解析/回写行为保持兼容

Added

  • F2 edits the active node (same as double-click): text inputs keep F2, an in-progress edit is left alone, and the key is still swallowed with no active node (so core's "Rename file" never fires). The engine's own F2 only fires when the event target is document.body and the pointer is inside the canvas, which is rarely true — the view scope now owns it
  • Reset zoom (100%) button (left of Fit to canvas): returns to 100% anchored at the canvas centre so the visible content stays put; auto-arrange resets zoom too instead of fitting the whole map down to unreadable text
  • Default viewport on open: 100% zoom with the whole content bounding box centred (no more fit-to-canvas shrink, and no more root-only centring that pushed lopsided maps to one side)

Fixed

  • Markdown round-trip no longer loses content (reproduced, then fixed, with 8 new regression cases):
    • editing the text of a node that has both an image and a link silently dropped the image (the compose path emitted a single token); adding an image to a linked node or a link to an image node lost the image the same way — all tokens are now written in source order
    • removing an image brought it back on the next save (rawOk skipped the image check when image was empty while the "link cleared" check excluded embeds) — a removed image is now detected, and removeNodeImage clears the md image fields
    • a newly inserted image/link was not written when the node text happened to contain the same string (bare-substring feature match) — matching is now embed/wikilink-boundary aware
    • the caption in ![[img.png|note]] was lost after editing — now preserved on parse and write-back
  • Hover previews now flip below the node: the official anchor rect mixes sources (targetEl.offsetWidth/offsetHeight for width/height, getBoundingClientRect() for position); SVG nodes lack the former, so bottom/right became NaN, the "place below when there is room" branch never applied, and with no room above top was set to "NaNpx" (no preview at all). The geometry is now supplied before the preview is requested
  • Renaming the central node no longer breaks links: uses FileManager.renameFile (Vault.rename renames on disk only and leaves links/backlinks pointing at the old name)
  • Popout window support: drag-reparent, image-resize sessions and the window paste fallback now listen on the canvas's own window (image resizing used to fail outright in a popout and the session hung until the view closed)
  • Lifecycle and races: the engine-init rAF is cancellable (no orphan engine instance after the view closes), stale load results are never applied, the first-frame viewport timer is cancelled on destroy, and engine identity is re-checked across await (switching files mid-dialog no longer drops edits)
  • File-name sanitising matches Obsidian's rules: # ^ [ ], trailing dots/spaces and reserved names (CON/PRN/…) are handled — previously they either failed outright or produced names that cannot be linked to correctly
  • Docs: the READMEs claimed "double-click or press Enter" to edit a node — Enter actually inserts a sibling node. They now say F2 and also list Reset zoom

Engineering

  • 28.8 KB of dead code removed: the styles.css vendor block was 100% Quill rich-text CSS (240 .ql-* selectors) while the plugin never registers the RichText plugin and the engine injects its own styles at runtime — the block, vendor/simple-mind-map.css, scripts/sync-vendor-css.mjs and its npm script are gone; rendering metrics are byte-identical before and after
  • Tests 430 → 472 (35 files), including real geometry for the default viewport (the only previous "coverage" asserted that a mock was called), hotkey wiring, popout listener ownership, file-name sanitising and the save-time fallback snapshot; mutation checks confirm the new cases fail against the old code
  • CI runs verify:visual --require-chrome (a missing browser now fails instead of silently skipping); the release workflow verifies the tag against manifest.json before building
  • Duplicate owners collapsed: four hand-written INSERT_CHILD_NODE call sites became insertChildNodeWithData, and three raw getData reads now go through the getNodeDataString facade

Compatibility notes

  • Unchanged from 0.0.1–0.0.4: requires Obsidian 1.13.0+, desktop only (isDesktopOnly: true)
  • No breaking changes; .mindmap.md files and their parsing/write-back behaviour remain compatible

0.0.4

Choose a tag to compare

@github-actions github-actions released this 08 Sep 15:06

中文 | English

0.0.4 是一次以「外部权威源严格检测」驱动的质量版本:用官方 API 类型定义(1.13.2)、官方 eslint-plugin-obsidianmd(0.4.2)规则、官方插件模板与社区目录校验工作流、官方帮助文档与 style guide 五路对照,逐项修复了 API 合规、Markdown 回写保真度、交互收尾、错误可见性、文案规范等问题,并把回归测试从 251 条扩到 430 条、新增无头渲染契约验证脚本。核心能力(Markdown 无损往返、三类链接图标、图片、PNG 导出、搜索、性能模式)保持兼容。

变更

  • Markdown 回写保真度:编辑节点后合成回写不再丢信息——![[图.png|300x150]] 保留显式高度(源行仅有宽度时仍写 |宽度)、外链图片保留 alt(![说明|300](url))、带显示文本的链接保留 [文本](url) 形态(不再被降级为 文本 <url>)、附件双链保留别名([[报告.pdf|说明]]
  • 多图拖入不再丢图:外部拖入多张图片时,首张挂到所选节点(与单图行为一致),其余各新建一个子节点承载;单张失败不再中断其余(失败经 Notice 汇总上报)
  • 搜索修复:命中为 0 时「没有匹配的节点」提示现在可达(此前依赖引擎回调,而引擎在空结果集上不回调,计数会残留上一次结果);防抖窗口内按 Enter 先让未决搜索落地,不再作用于上一次关键词的陈旧结果集
  • 弹窗修复:新建名称弹窗空白输入时「创建」按钮置灰(不再是点了没反应的死按钮);弹窗关闭兜底改用官方 Modal.setCloseCallback(不再覆写 modal.onClose);链接弹窗手输 [[笔记|别名]] 会解析出别名并同步到节点文本
  • 语言切换即时生效:切换语言后命令面板命令名、丝带图标提示、状态栏与搜索栏文案立即刷新(此前需重载);状态栏按单复数显示(1 node / 3 nodes);弹窗按钮按动作区分「创建」/「应用」
  • API 合规(对照官方 1.13.2 类型定义):库内文件查询改用官方推荐的 getFileByPath / getFolderByPath(并清掉全部源码级 eslint 抑制);深色主题判定改用 App.isDarkMode()(不再读未文档化的 body.theme-dark);文件浏览器菜单注入标记改用 WeakMap(不再往核心视图对象写自有属性);启动恢复定时器随组件注销清理;核心视图类型字符串与悬停预览事件名集中为常量;obsidian 开发依赖固定为 ^1.13.1
  • 交互与错误处理:拖拽换父 / 图片调宽的临时窗口监听在视图关闭时显式收尾(不再泄漏);工具栏/右键菜单的异步动作自兜错误(转成用户可见提示,不产生未处理拒绝);拖入失败由纯 console 改为 Notice;三处静默吞错降级为 console.warn(批量探测按次数汇总一次)
  • 文案规范(对照官方 style guide):英文词典全面改为句子式大小写;术语统一(「主题」仅表示配色主题,节点概念统一为「节点」「中心节点」「子节点」;「库」→「仓库」;「插入」→「添加」;「文字」→「文本」);快捷键写法规范化并补 macOS 变体;误导性提示修正(外部拖入仅支持图片、不再声称「音视频/PDF 无法写回」);未识别文件时不再把原始拖拽数据打印给用户
  • 工程:新增 npm run verify:visual 无头 Chrome 渲染契约验证(三类链接图标分流、图标尺寸、画布铺满、节点测宽;已做反向验证);npm run lint 收紧为 --max-warnings 0;源码零 eslint-disable;发布工作流新增 tag 与 manifest.json 版本一致性校验,并自动以 docs/release-notes-<tag>.md 作为 Release 说明;新增 vendor/THIRD-PARTY-NOTICES.md 声明打包内含的第三方依赖许可

其他变更

  • **测试:**回归测试 251 → 430(31 个文件,全绿);新增 view-/modal- 与交互收尾、语言刷新等用例;覆盖率 statements 43.6% → 60.9%,branches 86.0% → 86.6%tsc -noEmit、eslint(--max-warnings 0)、vitest、verify:visual 全通过
  • **版本:**0.0.3 → 0.0.4,manifest.json / versions.json / package.json / package-lock.json 同步

兼容性说明

  • 与 0.0.1–0.0.3 一致:需要 Obsidian 1.13.0+(声明式设置 API),仅桌面端isDesktopOnly: true
  • 本版无破坏性变更:.mindmap.md 视图、无损往返、三类链接图标、图片与拖拽、搜索、导出、性能模式等行为保持兼容;既有文件中已存在的 [文本](路径.md) 形态仍按原样解析与回写

已知限制

  • 沿用既往:图片独占节点(无文本)不参与节点文本搜索;每节点至多一条链接;非图片嵌入(如 ![[报告.pdf]])显示为可点击的附件图标而非内嵌渲染;行内标记随文本原样保留,导图内不做富文本渲染
  • **有意偏离(本版明确文档化):**新增链接与图片恒写 [[双链]] / ![[路径]],不跟随 Obsidian 的「使用 Wiki 链接」/「新链接格式」设置——这是为保住「文档双链 = 专属文档页图标」的视觉方案,详见 AGENTS.mddocs/markdown-mindmap-standard.md

Changes

  • Markdown write-back fidelity: synthesised write-back no longer loses information — explicit image heights are preserved (![[img.png|300x150]]; width-only sources still write |300), external image alt text is preserved (![caption|300](url)), links with display text keep the [text](url) form (no longer downgraded to text <url>), and attachment wikilink aliases survive ([[report.pdf|label]])
  • Multi-image drop no longer loses images: the first image goes on the selected node (unchanged single-image behaviour) and the rest become new child nodes; one failed import no longer aborts the others (failures are reported in a summary notice)
  • Search fixes: the "no matches" state is now reachable (the engine does not invoke the callback on an empty result set, which previously left a stale count); pressing Enter inside the debounce window flushes the pending search instead of acting on the previous keyword's results
  • Dialog fixes: the create-name dialog disables its confirm button while the name is blank (no more dead button); the close fallback now uses the official Modal.setCloseCallback instead of overwriting modal.onClose; typing [[note|alias]] in the link dialog resolves the alias and syncs it to the node text
  • Language switching takes effect immediately: command palette names, ribbon tooltip, status bar and search-bar labels refresh on switch (previously needed a reload); the status bar pluralises (1 node / 3 nodes); dialog buttons are action-specific (Create / Apply)
  • API compliance (audited against the official 1.13.2 typings): vault lookups now use the recommended getFileByPath / getFolderByPath (all source-level eslint suppressions removed); dark-mode detection uses App.isDarkMode() instead of the undocumented body.theme-dark; the file-explorer menu injection marker moved to a WeakMap (no more writing custom properties on core view objects); startup-restore timers are cleaned up with the component; core view-type strings and the hover-preview event name are centralised constants; the obsidian dev dependency is pinned to ^1.13.1
  • Interaction and error handling: temporary window listeners for drag-reparent and image-resize are torn down when the view closes; async toolbar/context-menu actions handle their own errors (user-visible notices, no unhandled rejections); drop failures notify instead of logging to console; three silent catches were downgraded to console.warn (batch probes summarised once)
  • Copy standards (per the official style guide): the English dictionary is sentence case throughout; terminology unified (theme vs node, "vault", "add" vs "insert", "text"); keyboard shortcuts formatted with macOS variants; misleading notices corrected; raw drag payloads are no longer shown to users
  • Engineering: new npm run verify:visual headless-Chrome rendering contract check (link-icon routing, icon size, canvas fill, node measuring; reverse-verified); npm run lint tightened to --max-warnings 0; zero eslint-disable in source; the release workflow now verifies the tag against manifest.json and attaches docs/release-notes-<tag>.md as the release body; new vendor/THIRD-PARTY-NOTICES.md documents bundled third-party licences

Other changes

  • Tests: regression grew from 251 to 430 across 31 files, all green; coverage 43.6% → 60.9% statements, 86.0% → 86.6% branches; tsc --noEmit, eslint (--max-warnings 0), vitest and verify:visual all pass
  • Version: 0.0.3 → 0.0.4, synced across manifest.json / versions.json / package.json / package-lock.json

Compatibility notes

  • Unchanged from 0.0.1–0.0.3: requires Obsidian 1.13.0+ (declarative settings API), desktop only (isDesktopOnly: true)
  • No breaking changes: the .mindmap.md view, lossless round-trip, the three link-icon channels, images and drag-and-drop, search, export and performance mode all remain compatible; existing [text](path.md) links keep parsing and writing back as before

Known limitations

  • Carried over: image-exclusive nodes (no text) are not searchable; one link per node; non-image embeds such as ![[report.pdf]] show a clickable attachment icon instead of rendering inline; inline marks are preserved as plain text — no rich-text rendering inside nodes
  • Intentional deviation (documented in this version): new links and images are always written as [[wikilinks]] / ![[path]], ignoring Obsidian's "Use Wikilinks" / "New link format" settings, in order to keep the dedicated document-page icon; see AGENTS.md and docs/markdown-mindmap-standard.md

0.0.3

Choose a tag to compare

@github-actions github-actions released this 07 Sep 13:32

中文 | English

作为 mindmap-studio 的第三个发布版本,0.0.3 合并了 0.0.2 以来的一处主动精简:移除 Markdown 代码块 渲染路径,统一以 .mindmap.md 作为唯一入口;同时清理了 0.0.2 期间的代码质量审计一次性产物。核心能力(Markdown 无损往返、双链与图片、PNG 导出、搜索、性能模式)保持不变,回归测试维持 21 个文件、251 条全绿。

变更

  • 移除 ```mindmap 代码块渲染src/codeblock.ts(95 行)及其在 mainregisterMarkdownCodeBlockProcessor / CODE_BLOCK_LANGUAGE)、constants、设置面板(codeBlockDefaultLayout「代码块默认布局」下拉)与主题 / 图片尺寸归一(mindmap-theme.tsimages-path.tsnormalizeImageSizes)中的代码块分支一并删除;今后思维导图统一以 .mindmap.md 文件打开(文件右键 / 命令面板 / 文件浏览器「新建」菜单),普通笔记中的 ```mindmap 代码块不再渲染为导图
  • 文档清理:移除已过期的代码质量 / eslint 一次性审计报告(docs/code-quality-report.htmldocs/eslint-audit-report.html)与审计指南(docs/code-quality-audit-guide.md),同步删除 AGENTS.md 中对被删报告的过期引用,并移除 gitignore 的可再生 coverage/ 产物;权威标准 docs/markdown-mindmap-standard.md 保留

其他变更

  • **测试:**回归测试 252 → 251(21 个文件,全绿;随 normalizeImageSizescodeBlockDefaultLayout 下线的用例移除);tsc -noEmit、eslint、vitest 全通过
  • **版本:**0.0.2 → 0.0.3,manifest.json / versions.json / package.json / package-lock.json 同步

兼容性说明

  • 与 0.0.1 / 0.0.2 一致:需要 Obsidian 1.13.0+(声明式设置 API),仅桌面端isDesktopOnly: true
  • 本版移除的多为一次性 / 只读路径(代码块渲染与「代码块默认布局」设置);.mindmap.md 视图、无损往返、图片 / 链接 / 搜索 / 导出 / 性能模式等核心能力不变

已知限制

  • **新增:**移除 ```mindmap 代码块后,普通笔记不再能以代码块形式呈现导图;如需导图请使用 .mindmap.md 文件
  • 沿用 0.0.2:图片独占节点(无文本)不参与节点文本搜索;每节点至多一条超链接;![[笔记]] 嵌入以 [[链接]] 形式承载不渲染嵌套内容;行内标记随文本原样保留,导图内不做富文本渲染

Changes

  • Removed ```mindmap code-block rendering: src/codeblock.ts (95 lines) plus its code-block branches in main (registerMarkdownCodeBlockProcessor / CODE_BLOCK_LANGUAGE), constants, the settings panel (codeBlockDefaultLayout dropdown), and theme / image-size normalization (mindmap-theme.ts, images-path.ts normalizeImageSizes) are removed. Mind maps now open exclusively from .mindmap.md files (context menu / command palette / file-explorer "New" menu); ```mindmap code blocks in ordinary notes no longer render as a map
  • Docs cleanup: removed the superseded one-time code-quality/eslint audit reports (docs/code-quality-report.html, docs/eslint-audit-report.html) and the audit guide (docs/code-quality-audit-guide.md), dropped the stale AGENTS.md reference, and removed the gitignored regenerable coverage/ output; the authoritative docs/markdown-mindmap-standard.md stays

Other changes

  • Tests: regression grew down from 252 to 251 across 21 files, all green (the cases for normalizeImageSizes and codeBlockDefaultLayout were removed with the feature); tsc --noEmit, eslint, and vitest all pass
  • Version: 0.0.2 → 0.0.3, synced across manifest.json / versions.json / package.json / package-lock.json

Compatibility notes

  • Unchanged from 0.0.1/0.0.2: requires Obsidian 1.13.0+ (declarative settings API), desktop only (isDesktopOnly: true)
  • What was removed this version is one-time/read-only paths (code-block rendering and the "code block default layout" setting); the .mindmap.md view, lossless round-trip, images/links/search/export, and performance-mode capabilities are unchanged

Known limitations

  • New: after dropping ```mindmap code blocks, ordinary notes can no longer present a map as a code block; use a .mindmap.md file instead
  • Carried over from 0.0.2: image-exclusive nodes (no text) are not searchable via node text search; one hyperlink per node; ![[note]] embeds are carried as [[links]] without rendering nested content; inline marks are preserved as plain text — no rich-text rendering inside nodes

0.0.2

Choose a tag to compare

@github-actions github-actions released this 07 Sep 08:59

中文 | English

作为 mindmap-studio 的第二个发布版本,0.0.2 汇总自 0.0.1 以来的主要用户与开发者相关变更:三类节点级新交互(拖拽换父辅助、节点图片拖宽、图片独占节点),一组可感知的性能与写盘优化,一个画布右键菜单的 bug 修复,以及工程底座扩充——回归测试由 75 条增至 252 条。

新增功能

  • 拖拽换父辅助:引擎原生判定要求指针精确落在目标节点矩形内;现拖到节点中心附近(与节点大小无关的均匀圆域)即挂为其子节点,拖到相邻兄弟间隙即插入该位置;两类候选统一按指针距离最近仲裁,拖拽期间实时高亮目标,松手仍走引擎原生命令(MOVE_NODE_TO / INSERT_AFTER),引擎精确命中时辅助让位
  • 节点图片拖宽:悬停图片右下角出现手柄,拖拽等比调宽(宽高联动钳制,防止比例破坏);松手后以 Obsidian 官方嵌入尺寸语法写回 Markdown——![[图.png|300]] 仅宽等比、![[图.png|300x150]] 指定宽高、![alt|300](url) 外链图尺寸在标签尾部;持久化进笔记本体而非 data.json
  • 图片独占节点:纯图行(- ![[x.png]])解析为无文本节点,不回退文件名占位;右键「移除文字」或双击清空文字后,节点即被图片独占,Markdown 往返保持

体验优化

  • **性能:**保存热路径的库内文件解析改为索引缓存快命中(原先每次保存对每图片节点全量扫描文件列表,现 O(1) 命中,新鲜度由库事件失效保证);拖拽期间的 mousemoverequestAnimationFrame 合帧;图片拖宽在相同取整尺寸下跳过引擎全量重渲染
  • **性能:**引擎初始化的画布零尺寸等待由 200ms 轮询改为 ResizeObserver 事件驱动;外部图片比例探测限流有界并发(上限 6),超大图打开不再触发解码风暴
  • **写盘:**设置面板变更 400ms 防抖合并落盘(滑块连续拖动由逐档重写合并为一次),写盘载荷不再携带视图状态全量快照(由写前重读合并保证 viewState 不丢失)
  • 库内文件解析收敛到统一入口 resolvePathToFile:远程地址拒绝 / obsidian:// / 资源地址 / 路径直查 / file://(官方 getFirstLinkpathDest)/ 索引兜底按形态路由,并以 eslint 规则机械禁止绕行

问题修复

  • 修复画布右键菜单在部分节点上恒为空白的问题:引擎不在节点 DOM 写入 uid,旧实现读取 data-uid 属性恒为 null;改为按「节点渲染 group 包含目标元素」做身份匹配,并以 vendor 契约测试锁定

其他变更

  • **测试与 CI:**回归测试 75 → 252(21 个文件,全绿;新增 engine-controller / event-binder / persistence / file-lookup / links-resolve / images-path / vendor 契约冒烟等);v8 覆盖率语句 43.21% / 分支 86.71%;CI 矩阵移除已 EOL 的 Node 20.x(保留 22.x / 24.x),actions/upload-artifact 升至 v7(Node 24 运行时)
  • Lint:manifest.jsonLICENSE 显式纳入 eslint(官方 recommended 配置不会自动拾取这两类文件;validate-license 所需的行级 parser 内置于 scripts/plain-text-parser.mjs);manifest.json 描述文案微调以符合提交规范
  • **文档:**新增代码质量审计报告与审计指南(docs/

兼容性说明

  • 与 0.0.1 一致:需要 Obsidian 1.13.0+(声明式设置 API),仅桌面端isDesktopOnly: true
  • 视图状态与打开偏好仍存于插件 data.json(按文件路径),节点图片尺寸改存笔记本体的官方嵌入语法,不含敏感内容

已知限制

  • 新增:图片独占节点(无文本)不参与节点文本搜索
  • 其余沿用 0.0.1:每节点至多一条超链接;![[笔记]] 嵌入以 [[链接]] 形式承载不渲染嵌套内容;行内标记随文本原样保留,导图内不做富文本渲染

New Features

  • Assisted drag reparenting: the engine's native hit test requires the pointer to land exactly inside the target node's rectangle; now dropping near a node's center (a uniform circular zone, size-independent) attaches the node as its child, and dropping in a sibling gap inserts between the two neighbors. Candidates are arbitrated by pointer distance with live highlighting; release still goes through native engine commands (MOVE_NODE_TO / INSERT_AFTER), and the assist yields whenever the engine gets an exact hit
  • Node image resizing: a handle appears at the hovered image's bottom-right corner; dragging resizes width with the aspect ratio preserved (width/height linked clamping). On release the size is written back in Obsidian's official embed sizing syntax — ![[img.png|300]] width-only, ![[img.png|300x150]] explicit width & height, ![alt|300](url) external images sized at the label tail — persisted into the note body, not data.json
  • Image-exclusive nodes: pure image lines (- ![[x.png]]) parse as textless nodes instead of falling back to a filename placeholder; after "Remove text" from the context menu (or clearing text by double-click) the node becomes image-exclusive and survives Markdown round-trips

Improvements

  • Performance: vault file lookups on the save hot path now hit an index cache (previously a full file-list scan per image node per save, now O(1) with freshness maintained by vault events); drag-time mousemove is coalesced with requestAnimationFrame; image resizing skips full engine re-renders when the rounded size is unchanged
  • Performance: the engine's zero-size canvas wait replaced 200 ms polling with an event-driven ResizeObserver; external image aspect probing runs under bounded concurrency (max 6), avoiding decode storms on oversized images
  • Disk writes: settings changes are debounced into a single write (400 ms) instead of per-step rewrites while dragging sliders; the write payload no longer carries a full viewState snapshot (write-before-read merging keeps viewState intact)
  • Vault file resolution is funneled through the single entry resolvePathToFile — remote rejection / obsidian:// / app-resource URLs / plain paths / file:// (official getFirstLinkpathDest) / index fallback are routed by form, with an eslint rule mechanically blocking bypasses

Bug Fixes

  • Fixed the canvas context menu appearing empty on some nodes: the engine never writes node uids into the DOM, so the old data-uid lookup always resolved to null; matching now uses "target element contained by the node's rendered group", locked in by a vendor contract test

Other changes

  • Tests & CI: regression tests grew from 75 to 252 (21 files, all green; new suites for engine-controller / event-binder / persistence / file-lookup / links-resolve / images-path / vendor contract smoke); v8 coverage: 43.21% statements / 86.71% branches; CI matrix drops the EOL Node 20.x (keeps 22.x / 24.x) and bumps actions/upload-artifact to v7 (Node 24 runtime)
  • Lint: manifest.json and LICENSE are now explicitly linted (the official recommended config never picks them up; the line-level parser required by validate-license lives in scripts/plain-text-parser.mjs); the manifest.json description was reworded to satisfy submission guidelines
  • Docs: added code-quality audit reports and the audit guide under docs/

Compatibility notes

  • Unchanged from 0.0.1: requires Obsidian 1.13.0+ (declarative settings API), desktop only (isDesktopOnly: true)
  • View state and open-as preferences still live in the plugin data.json (keyed by file path); node image sizes now live in the note body as official embed syntax — no sensitive content either way

Known limitations

  • New: image-exclusive nodes (no text) are not searchable via node text search
  • Carried over from 0.0.1: one hyperlink per node; ![[note]] embeds are carried as [[links]] without rendering nested content; inline marks are preserved as plain text — no rich-text rendering inside nodes

0.0.1

Choose a tag to compare

@github-actions github-actions released this 06 Sep 14:36

中文 | English

作为 mindmap-studio 的首个公开发布版本,本版本交付完整的核心能力闭环:把 .mindmap.md 当作思维导图编辑、以 100% 标准 Markdown 存储、无损往返;同时完成 API 合规(对照 obsidian.d.ts 1.13.2)、lint 基线(eslint-plugin-obsidianmd 0.4.2)与 75 条回归测试的工程底座。

新增功能

  • Markdown 渲染层.mindmap.md 是 100% 标准 Markdown(frontmatter + 标题 + 列表),无任何专有格式;解析为导图编辑后无损回写,未编辑的行(含 [[双链]]![[图片]]、行内标记、代码围栏)逐字保留
  • Obsidian 原生集成:双链(含 #区块|别名)、图片/附件嵌入、悬停页面预览、Ctrl/Cmd+点击新标签打开、附件粘贴与拖入遵循系统「附件存放位置」设置
  • 视图与编辑.mindmap.md 以导图视图打开(文件右键 / 命令面板 / 文件浏览器「新建」菜单),可随时切回 Markdown 编辑并自动记忆打开方式偏好(重启后恢复)
  • 节点操作:添加子级/同级、删除(uid 异常兜底)、复制/粘贴、编辑链接与图片、全屏查看图片;工具栏与右键菜单双入口
  • 链接与附件:插入链接弹窗联想库内笔记与附件(官方 AbstractInputSuggest),同名笔记自动按路径消歧;插入图片支持本地选择 / 剪贴板粘贴 / 外部 URL
  • 布局与外观:逻辑结构图 / 思维导图 / 组织结构图 / 目录组织图 / 时间轴 / 鱼骨图六种布局;主题跟随 Obsidian 亮暗色,可强制亮色或暗色
  • 搜索与导出:节点搜索(Mod+F,带计数与上下跳转);PNG 导出(倍率 1–4 可调,超大画布自动按轴适配不裁切)
  • ```mindmap 代码块:任意笔记中渲染只读思维导图(主题与布局可配置)
  • 性能模式:节点数超过阈值(默认 500,可调 100–2000)自动启用虚拟渲染,仅渲染可视区域;超大导图自动压缩命令历史,控制内存
  • 状态栏:实时节点计数(当前视图关闭后自动让位其他导图视图)

体验优化

  • 编辑快捷键对齐官方约定:Mod+Z 撤销、Mod+Shift+Z / Mod+Y 重做(视图内生效);Mod+F 搜索;Esc 关闭搜索
  • 设置面板采用 Obsidian 1.13+ 声明式设置,支持设置搜索;界面语言中文 / English 可切换
  • 新建文件默认名「思维导图 + 日期」,重名自动追加序号(序号插在 .mindmap.md 之前);粘贴图片按 Obsidian 核心约定命名 Pasted image YYYYMMDDHHMMSS,外部拖入保留原名并按比例设置节点图
  • 库内文件重命名 / 删除 / 移入回收站时,打开中的导图同步更新树内图片与 [[链接]] 引用
  • 视图状态(布局 / 视口 / 打开偏好)按文件路径持久化到插件 data.json,不写入笔记正文

其他变更

  • **工程底座:**对照官方 obsidian.d.ts 1.13.2 审计,仅存 3 处无官方等价私有 API 触点(均防御式实现并文档化),零废弃 API;lint 基线采用 eslint-plugin-obsidianmd 0.4.2
  • **测试与 CI:**75 条回归测试(Markdown 往返 / domain / 并发原语 / URL 谓词 / 保存管线 / 视图状态 / 设置校验),CI 在 build 后、lint 前执行;tsc -noEmit 同时校验 src/tests/
  • **引擎 vendor:**simple-mind-map 0.14.0-fix.3(思绪思维导图发布的第三方修订版,fork 自 wanglin2/mind-map 0.14.0),按需 tree-shake 重打包,修订清单与升级流程见 vendor/BUILD.md

兼容性说明

  • 需要 Obsidian 1.13.0+:设置面板使用 1.13 引入的声明式设置 API
  • 仅桌面端isDesktopOnly: true):系统默认应用打开附件、部分拖拽能力依赖桌面环境

已知限制

  • 每个节点至多承载一条超链接(引擎单链语义);需要多条链接时可拆分为子节点
  • 对 Markdown 笔记的嵌入(![[笔记]])以 [[链接]] 形式承载,不渲染嵌套笔记内容;图片 / 音视频 / PDF 等附件嵌入行为正常(图片渲染为节点图,其余以链接打开)
  • 布局 / 视口 / 打开偏好存于插件 data.json(按文件路径),不含敏感内容,不写入笔记正文
  • 节点内行内代码、粗体等轻标记随文本原样保留,导图内不做富文本渲染

New Features

  • Markdown rendering layer: a .mindmap.md file is 100% standard Markdown (frontmatter + headings + lists) with no proprietary format; edited as a mind map and written back losslessly — untouched lines (including [[wikilinks]], ![[embeds]], inline marks, and code fences) are preserved verbatim
  • Native Obsidian integration: wikilinks (with #blocks and |aliases), image/attachment embeds, hover page preview, Ctrl/Cmd+click to open in a new tab, and attachment pasting/dragging that follows the system "Attachment folder location" setting
  • View & editing: open a .mindmap.md in the mind map view (file context menu / command palette / file-explorer "New" menu), switch back to Markdown editing at any time; the open-as preference is remembered and restored across restarts
  • Node operations: insert child/sibling nodes, delete (with uid-anomaly fallback), copy/paste, edit link & image, fullscreen image preview; available from both the toolbar and context menus
  • Links & attachments: the link modal suggests vault notes and attachments (official AbstractInputSuggest) with automatic path disambiguation for same-name notes; insert images from local files / clipboard paste / external URLs
  • Layouts & appearance: six layouts — logical structure / mind map / organization chart / catalog organization / timeline / fishbone; theme follows Obsidian light/dark with forced options
  • Search & export: node search (Mod+F, with match counter and prev/next navigation); PNG export (scale 1–4, oversized canvases are per-axis scaled instead of clipped)
  • ```mindmap code block: render read-only mind maps inside any note (configurable theme and layout)
  • Performance mode: automatically enables virtual rendering above a node threshold (default 500, adjustable 100–2000); large maps compress command history to bound memory
  • Status bar: live node count, handed off between open mind map views

Experience improvements

  • Editing shortcuts aligned with official conventions: Mod+Z undo, Mod+Shift+Z / Mod+Y redo (inside the view); Mod+F search; Esc closes search
  • Declarative settings (Obsidian 1.13+) with settings-search support; UI language switches between 中文 and English
  • New files default to "思维导图 + date" with automatic ordinal suffixes for duplicates (inserted before the .mindmap.md suffix); pasted images follow the Obsidian core naming convention Pasted image YYYYMMDDHHMMSS, dropped images keep their original names and are sized by aspect ratio
  • Renaming / deleting / trashing vault files updates image and [[link]] references inside open mind maps
  • Per-file layout / viewport / open-as are persisted to the plugin data.json, never into note bodies

Other changes

  • Engineering baseline: audited against official obsidian.d.ts 1.13.2 — only 3 private API touchpoints with no official equivalent (all defensive and documented), zero deprecated API usage; lint baseline uses eslint-plugin-obsidianmd 0.4.2
  • Tests & CI: 75 regression tests (Markdown round-trip / domain / concurrency / URL predicates / save pipeline / view state / settings), run in CI after build and before lint; tsc --noEmit checks both src/ and tests/
  • Engine vendor: simple-mind-map 0.14.0-fix.3 (a third-party patched distribution, forked from wanglin2/mind-map 0.14.0), re-bundled with tree-shaking; the fix list and upgrade workflow are documented in vendor/BUILD.md

Compatibility notes

  • Requires Obsidian 1.13.0+: the settings panel uses the declarative settings API introduced in 1.13
  • Desktop only (isDesktopOnly: true): opening attachments with system apps and some drag capabilities rely on desktop features

Known limitations

  • Each node carries at most one hyperlink (engine single-link semantics); split multiple links into child nodes
  • Markdown-note embeds (![[note]]) are carried as [[links]] and do not render nested note content; image/audio/video/PDF embeds behave normally (images render as node images, others open as links)
  • Layout / viewport / open-as preferences live in the plugin data.json (keyed by file path) — no sensitive content, never written into note bodies
  • Inline marks (code, bold, etc.) are preserved as plain text inside nodes; the map does not render rich text