--- words: 2026-08-25: 919 --- # 00index.canvas 自动生成原理说明 ## 一句话概括 `00index.canvas` **不是 Obsidian 插件生成的**,而是由你自建的守护脚本 **`/Users/ar/bin/tagfeed.py`** 持续重写的一个 Obsidian Canvas(JSON)文件;Obsidian 里的 **Cammvas 社区插件** 读取其中的 `mindmap: true`,把它渲染成「向右展开的目录脑图」。 ## 启动链路(谁把它跑起来) 1. **macOS 登录 / 开机自启**:`~/Library/LaunchAgents/com.ar.tagfeedwatch-login.plist`(Label `com.ar.tagfeedwatch-login`,`RunAtLoad=true`)执行 `/usr/bin/open -g /Users/ar/Applications/TagfeedWatch.app`。 2. **TagfeedWatch.app**(`/Users/ar/Applications/`):只是一个 ~60KB 的 Mach-O 外壳,内部用 `/usr/bin/python3` 调用真正的脚本。 3. **真正的生成器**:`/Users/ar/bin/tagfeed.py`,以 `tagfeed.py --watch` 常驻运行,默认 **每 3 秒**轮询一次 vault(检测到变化后还会等 1.5 秒防抖再处理)。 ## 生成逻辑(每次触发都重画) 核心函数:`generate_canvas_index(vault, rel_dir="00index", canvas_name="00index.canvas")`(tagfeed.py 约 1124–1291 行)。 1. **触发条件**:每轮用 `canvas_signature()` 计算 `00index` 目录的「结构指纹」——所有 `.md` 文件与子目录的相对路径集合。文件**改名**不改 mtime(普通内容指纹看不见),所以这个独立指纹专门捕捉「增 / 删 / 改名」。指纹变了才重画,否则跳过本轮。 2. **建树 `build()`**:递归遍历 `00index`,同层文件夹在前、`.md` 文件在后;跳过 `SKIP_DIRS`(如 `X.Attachment`、`.obsidian`)和 **`CANVAS_SKIP_DIRS={"0inbox"}`**(实时聚合草稿目录,不进脑图)。 3. **布局**:自底向上算子树高度、每层取最大宽度决定列间距,整体向右展开。 4. **放置 `place()`**:根节点 → 文件夹节点(📁)→ 文件节点。文件节点用**文字节点 + wikilink**(`[[路径|文件名]]`)而非 `file` 节点,避免渲染满屏「笔记属性」预览;点击可直接打开对应笔记。节点 id 由路径经 md5 确定性生成。 5. **颜色策略**:生成器**不再自动上任何颜色**(旧逻辑用 `CANVAS_COLORS` 给每个分支染红/绿/蓝,会覆盖你手动设的色,已停用)。改为「读取旧画布里已有的 `color`,按节点 id 匹配后保留」——所以你手动上的色在每次重画后都还在;新出现的节点默认无色,由你上色。 6. **写盘门控**:整张画布序列化为 JSON 后与磁盘现有内容比对,完全相同就**不写盘**,避免无谓改动触发 Obsidian 重载。 ## 渲染(怎么变成脑图) - 文件本身是标准 Obsidian Canvas JSON(`{nodes, edges}`)。 - 你装的 **Cammvas 插件**(社区插件)读取画布里的 `mindmap: true`,渲染成「向右展开的脑图」样式。 - 注意:Obsidian 直接打开 `.canvas` 默认是自由画布视图,要看到脑图需启用 Cammvas 的 mindmap 模式。 ## 涉及的文件 / 插件清单 | 角色 | 名称 | 位置 | |---|---|---| | 启动项 | LaunchAgent plist | `~/Library/LaunchAgents/com.ar.tagfeedwatch-login.plist` | | 外壳 App | TagfeedWatch.app | `/Users/ar/Applications/TagfeedWatch.app` | | 生成脚本 | **tagfeed.py** | `/Users/ar/bin/tagfeed.py` | | 生成函数 | `generate_canvas_index()` / `canvas_signature()` | tagfeed.py 内(约 1124–1291 行) | | 渲染插件 | Cammvas(社区插件,mindmap 模式) | Obsidian 设置 → 社区插件 | | 产物 | 00index.canvas | `/Users/ar/Downloads/Syn/Ob/Ob.temp/00index/00index.canvas` | ## 关于你刚挪动的 0inbox 你把 `00index/标签聚合/0inbox` 移到了 `00index/0inbox`: - **画布**:`CANVAS_SKIP_DIRS={"0inbox"}` 按目录名全局跳过,位置变化不影响排除 → 画布依旧不含 0inbox。 - **sync_0inbox.py**:其 `INBOX_DIR="0inbox"` 本就拼成 `00index/0inbox`,与你的新位置一致 → 无需改动脚本。 - 当前画布实测:**73 节点 / 72 连线 / 0 个 0inbox / 72 个带颜色**(即你手动上的色都被成功保留)✅