# Nestboard **A nested whiteboard plugin for Obsidian.** Every board is a plain-text `.nboard` file (JSON, human-readable) that lives inside your vault — local-only, Git-friendly, and linked to your notes. - **Plugin ID:** `nestboard` · **Display name:** Nestboard - **File extension:** `.nboard` (JSON, human-readable) - **Platform:** desktop only (`isDesktopOnly: true`). Tested on desktop; mobile is **not** verified yet. - **Network:** **no background network activity.** Only two features ever make a request, and both only when you click: _fetch link preview_ (on by default) and _map card static image_ (off by default). Rendering, exporting and opening boards issue zero requests. - **Data:** everything stays inside your vault. No cloud, no account, no telemetry. ## Features - **Infinite canvas** with pan / zoom and a remembered viewport. - **Cards:** sticky note · synced note · note reference (can show a single _section_) · image · map · file · board card · link (with site name / favicon / final URL) · to-do · swatch · ink drawing · comment · title · gallery · video · audio. - **Connections:** straight or dashed, smart routing that avoids cards, adjustable curve (drag the midpoint), labels, arrowheads, free endpoints. Either end can be a card **or** a column. - **Columns:** split / collect / collapse / drag into; convert a whole column into a group; columns work as connection endpoints too. - **Nested boards:** breadcrumbs, go-to-parent, back / forward, and four preview modes on a board card (thumbnail / mini / live window / off). - **Drawing:** pen, highlighter, and a temporary annotation layer (`⌘⇧A`, `Esc` to clear, never written to disk). - **Organize:** undo / redo, marquee select, align, z-order, duplicate, lock, rotate cards. - **Search** inside a board (`⌘F`) and filter by type / color / tag. - **Version snapshots** with history rollback. - **Export** a whole board to Markdown / PNG / PDF / SVG / ZIP / Canvas. - **Presentation mode** with a scripted path, per-card camera focus, and `→` / `←` stepping. - **Template library:** four built-in templates plus your own. - **Board URI:** `obsidian://nestboard?file=…&card=…` — usable from notes, daily notes or other apps. - **Home board & inbox:** a default landing spot when you don't want to decide where to put something first. - **Board list sidebar:** folder tree / recently opened / by tag, with filters. - **Thumbnail navigator:** click or drag to navigate. - **Drag & drop:** drop files in, paste images, or use _Add to board_ from a note's context menu. Not implemented yet: the OBS live-streaming set (local read-only HTTP output, transparent background, copy-browser-source URL, fixed frame and safe area, per-card _hide while live_, pointer highlight, OBS WebSocket control). Presentation mode itself already works with full-screen or window capture. ## Installation Not yet available in the Obsidian community plugin directory (submitted for review). Install manually: 1. Download `main.js`, `manifest.json` and `styles.css` from the [latest release](https://github.com/yisinever/nestBoard/releases/latest). 2. Create the folder `/.obsidian/plugins/nestboard/`. 3. Put the three files into it. 4. Obsidian → Settings → Community plugins → turn off _Restricted mode_ → enable **Nestboard**. ### Build from source ```bash npm install npm run build # production build -> main.js ``` Other scripts: `npm run dev` (watch), `npm run typecheck`, `npm run lint`, `npm test`. ## Getting started 1. Create a board from the command palette or the ribbon (_Create new board_). 2. Add cards from the left toolbar, by dragging files in, or from the canvas context menu. 3. Right-click a card or a column for its menu; select a single card to get the quick action bar (bold / italic / underline / text color / background). 4. Drop a board card onto another board to go one level deeper — the breadcrumb brings you back. ## Privacy Nestboard has no account, no telemetry and no background requests. The only two networking features are per-click: _fetch link preview_ (on by default, can be disabled in settings) and _map card static image_ (off by default; you choose a tile provider and may need your own API key). Everything else — rendering, exporting, switching boards — is fully local. ## License [MIT](LICENSE) --- ## 中文文档 > 把无限画布搬进你的 Vault:一块白板就是一个纯文本 `.nboard` 文件,纯本地、可 Git、可与笔记双链互通。 - 插件 ID:`nestboard` · 显示名:**Nestboard** - 文件扩展名:`.nboard`(JSON,人类可读) - 平台:**仅桌面端**(`isDesktopOnly: true`,手机 / 平板装不了);桌面端已实测,移动端未验证,见「已知限制」第 4 条 - 网络:**没有后台网络活动** —— 会联网的只有「抓取链接预览」与「地图卡静态图服务」两处,且**两处都只在你点那一下才发请求**(渲染、导出、翻板都是零请求)。「抓取链接预览」默认**开启**(`O20`,不想要就在设置里关掉),「地图卡静态图服务」默认是「不出图」。见「网络访问披露」 - 数据:全部在 Vault 内,不依赖任何云端 --- ## 当前状态 **v2.1.1**(**仅桌面端**;已提交 Obsidian 社区插件目录审核)。已经能用的部分: | 能力 | 状态 | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | | 新建 / 打开 `.nboard`、无限画布、平移缩放、记住视口 | ✅ | | 卡片:便签 · 同步便签 · 引用卡(指向 `.md`,可只显示**某一段**)· 图片 · 地图 · 文件 · 白板卡 · 链接卡(抓取后可显示**站点名 / 站点图标 / 最终网址**,`O20`)· 待办卡 · 色板卡 · 手绘 · 评论卡 | ✅ | | 便签卡可切**深色**(`O06`);色板卡**第一格就是整张卡的底色**(`O19`),其余色格退成卡角的 `+N`;色板卡也可放**渐变色格**(`O07`,粘贴一句 `linear-gradient(...)` 即可,导出照旧) | ✅ | | 地图卡**新建时就直接要链接**(`O17`:剪贴板里有就粘上,没有才弹框,取消则撤掉空卡),可**粘贴地图分享链接**(`O08`):认出经纬度存进卡片,配了静态图服务就顺带取一张图;没配置 / 取不到时卡上是坐标 + 链接 + 打开按钮 | ✅ | | 连线:虚线与实线 · **智能走线**(自动绕开卡片)· **曲线弧度**(拖中点)· **标签** · 箭头 · 自由端;两端都可以是**卡片或分栏**(`O21`:卡 → 栏、栏 → 卡、栏 → 栏都行) | ✅ | | 分栏:拆分 / 收集 / 折叠(折叠后**栏内卡片全部隐去**,`O16`)/ 拖入;**整栏转编组**、栏空了不留空壳、相邻栏自动合拢(`O04`);**栏本身也能当连线端点**、删栏时连着它的线一并删掉(`O21`) | ✅ | | 嵌套白板:面包屑、回到父级、后退 / 前进、白板卡卡面四档预览(缩略图 / 迷你 / 实时小窗 / 关闭;**迷你**是不预览内容的**固定正方形**,`O18`) | ✅ | | 拖入文件、粘贴图片、右键「添加到白板」 | ✅ | | 撤销 / 重做、框选、对齐、层级、复制、锁定、**卡片旋转**(`T7.06`) | ✅ | | 手绘:画笔 · **荧光笔**(半透明高亮)· **临时标注**(不落盘,`⌘⇧A`,`Esc` 清空) | ✅ | | 便签「提升为笔记」;整块白板导出为 Markdown / PNG / PDF / SVG / ZIP / Canvas | ✅ | | 白板内搜索(`⌘F`)、按类型 / 颜色 / 标签过滤 | ✅ | | 版本快照与历史回滚(`T4.01` / `T4.02`) | ✅ | | 重命名 / 移动白板(链接自动跟随) | ✅ | | 白板级只读 / 归档锁定(`settings.readOnly`,跟着文件走) | ✅ | | 跨 Vault 迁移后按文件名重连断链引用(逐个确认,可撤销) | ✅ | | 演示模式:演示路径编排、逐卡片相机聚焦、`→`/`←` 翻步、`O` 总览 | ✅ | | 模板库:4 个内置模板 + 自己的模板(从模板新建 / 另存为模板) | ✅ | | 白板 URI:`obsidian://nestboard?file=…&card=…`(可写进笔记 / 日程 / 库外 App) | ✅ | | Home 白板与收件箱:一个"不用先想放哪块板"的默认落点 | ✅ | | 白板列表侧栏:目录树 / 最近打开 / 按标签 + 筛选 | ✅ | | 缩略图导航器:可点击 / 可拖动定位,`×` 收起(`T5.09`) | ✅ | | 设置面板(新板目录 / 模板目录 / Home 路径 / 附件 / 自动保存 / 卡片外观 / 隐私) | ✅ | 尚未实现(不要期待):**OBS 直播那一套** —— 本地 HTTP 只读输出、透明背景、一键复制浏览器源 URL、固定画幅与安全区、卡片级"直播时隐藏"与一键遮罩敏感层、指针高亮、OBS WebSocket 控制。 (**手绘的临时标注层本身已经有了** —— `⌘⇧A` 开关、`Esc` 清空、不落盘;缺的只是"把白板直接喂给 OBS 浏览器源"那条通路。)演示模式本身已经能用(全屏或窗口捕获都能讲), 缺的是"把白板直接喂给 OBS 浏览器源"的那条通路,方案见 `docs/06-本地化与OBS集成方案.md`。 其余能力的实际进度以 `04-开发任务清单.md` 的勾选状态为准 (那份清单里未勾的条目分两类:还没做的,和"代码好了但只能在 Obsidian 里人工验"的)。 --- ## 安装 ### 手动安装(推荐,当前版本未上架社区目录) 1. 下载或自行构建,得到 `main.js`、`manifest.json`、`styles.css` 2. 在你的 Vault 里创建目录 `<你的Vault>/.obsidian/plugins/nestboard/` 3. 把上面三个文件放进去 4. Obsidian → 设置 → 第三方插件 → 关闭「安全模式」→ 启用 **Nestboard** ### 从源码构建 ```bash git clone cd nestboard npm install npm run build # 产出 main.js ``` 开发时用 `npm run dev`(监听改动并重建)。构建产物 `main.js` 会被压缩,但**不混淆** —— `src/` 全部公开可审查。 --- ## 用法 ### 1. 建一块白板 命令面板(`⌘P`)→ **Nestboard: 新建白板**(默认 `⌘⇧N`)。 文件落在设置里的「新白板目录」(默认 `Boards/`)。`.nboard` 已绑定到白板视图,所以之后**双击文件浏览器里的 `.nboard`**,或在笔记里写 `[[项目A.nboard]]` 再点它,都会直接进白板。 不想从空白板开始?见 [第 8 节 · 模板](#8-模板)。 ### 2. 往画布上放东西 | 想放什么 | 怎么做 | | ----------- | -------------------------------------------- | | 便签 | **右键画布空白** → 新建便签(`⌘⇧E` 也行) | | 同步便签 | 工具栏 / **右键画布空白** → 新建同步便签 | | 引用卡 | 从文件浏览器把 `.md` **拖到画布上** | | 图片 / 文件 | 把系统里的文件**拖进画布**,或直接 `⌘V` 粘贴 | | 已有笔记 | 在笔记上**右键** → 添加到白板 | > **引用卡 vs 便签卡**:便签的内容存在 `.nboard` 里;引用卡指向一个真实 `.md` 文件。 > 只有引用卡能让 `[[双链]]`、标签、反链、图谱、重命名同步**原生生效** —— > Obsidian 不会解析 `.nboard` 内部的链接,这一点无法绕过。 > 便签可以随时用 **提升为笔记** 抽成 `.md` 并原地变成引用卡(命令在面板里搜得到;它原本的默认键 > `⌘⇧P` 已让给演示模式,想常用可以自己去设置里绑一个)。 **转动卡片**:单选一张卡时,卡片上缘中间会探出一个**旋转手柄**(圆点)。拖着它转,卡片就跟着 转;按住 `⇧` 吸附到 15° 的整数倍 —— 摆正、摆 45° 斜排不用靠手感凑。旋转**不改卡片的尺寸和位置**, 只是换了个姿态:转过 90° 的卡片,八个缩放手柄仍然贴着手柄走,卡片也不会因为转了一下就"长胖"或 "占错地方"(框选、适应内容、缩略图按它**转过之后**占的那块算)。想回正:右键 →「重置旋转」 (和别的操作一样可以 `⌘Z` 撤销;没转过的卡片不会出现这一项)。转过的卡片连同**它上面连线的锚点** 一起进导出(PNG / SVG / PDF);导出 `.canvas` 时 JSON Canvas 没有"角度"这个概念,转过的卡在对面 会是正的 —— 导出前的损失清单里会**明说**这一项。 ### 3. 分栏 选中若干卡片后,在命令面板里用 **拆分为分栏** 把每张卡变成一栏,或用 **收集进分栏** 把它们塞进同一栏。 卡片也可以直接拖进 / 拖出分栏。这两条命令**没有默认热键**(避免和编辑器的常用键打架),想常用的可以去设置里自己绑。 **分栏也能当连线的端点**(`O21`):把鼠标移到栏上,四条边中点同样会浮出锚点 —— 从栏拉到卡片(或另一个栏) 就是一条普通连线(自动选边、点选、改样式、跟着栏一起动,都照旧)。删除分栏时,**连着这一栏的连线会一起删掉** (不然它们就指向了一个不存在的端点),这一步同样可以 `⌘Z` 撤销。 ### 4. 嵌套白板 在一张白板里放一张**白板卡**(把另一个 `.nboard` 拖进来即可)就形成嵌套。 - 面包屑在画布左上角,点任意一级直接跳过去 - **回到父级白板**(`⌘U`) - **后退 / 前进**(`⌘[` / `⌘]`):按访问顺序,不是按层级 **白板卡的卡面有四档**(右键 →「卡面预览」):**缩略图**(默认)/ **迷你** / **实时小窗** / **关闭**。 - **迷你**(`O18`)是一个**固定正方形**的方格子:卡面上**不预览那块板的任何内容** —— 正中只放这张卡的 emoji 图标(没设图标就是主题色小方块),**板名画在方格子正下方、居中**;名字行与「N 张卡片」**都不存在**。 尺寸由这一档定死(便签默认宽的 1/3,约 87px),选中时**没有缩放的八个手柄**、拖不动边 (**旋转**不受影响)。切到这一档会当场把卡钉成正方形、切走时还回默认尺寸(280×180)—— 这是唯一会改卡片尺寸的档位,一步 `⌘Z` 可撤销。 一屏摆十几张当目录扫的时候最合用:一枚记号回答"是哪一类",方块下面那行字回答"是哪一块"。 - **实时小窗**把整块子板按卡片**当下的大小**重新画一遍 —— 一扇窗,不是一张贴图。卡拖大内容跟着重排; 宽高比不合时保证**整块板都在**、多出来的边由板自己的背景填满;**子板一保存,这扇窗就更新**。 - 小窗**只读**(它不写那块钱);想动手就**双击进入**那块板。档位写进 `.nboard`,`⌘Z` 可撤销。 **笔记里也能嵌一块"活的"板**:写一个代码块,第二行给高度 —— 宽度跟着笔记栏宽,子板保存即重画: ````markdown ```nestboard file: Boards/项目A.nboard height: 480 ``` ```` 不给 `height:` 就是一张静态缩略图(高度随宽度);行内 `![[项目A.nboard]]` 也只取路径、高度随内容。 ### 5. 快捷键 macOS 用 `⌘`,Windows / Linux 用 `Ctrl`。全部可以在 设置 → 热键 里改。 | 键 | 动作 | | ------------- | --------------------------------------------------- | | `⌘⇧N` | 新建白板 | | `⌘⇧B` | 打开白板列表(见 [第 10 节](#10-白板列表三种看法)) | | `⌘=` / `⌘-` | 放大 / 缩小 | | `⌘1` / `⌘0` | 实际大小 / 适应内容 | | `⌘⇧E` | 新建便签 | | `⌘A` | 全选(正在编辑卡片时让路给"全选文字") | | `⌘C` / `⌘X` | 复制 / 剪切卡片(可贴到**别的白板**) | | `⌘V` | 粘贴卡片(或图片 / 网址 / 库内文件) | | `⌘D` | 原地复制选中 | | `⌘⇧L` | 锁定 / 解锁选中 | | `⌘⇧↑` / `⌘⇧↓` | 置于顶层 / 置于底层 | | `⌘Z` / `⌘⇧Z` | 撤销 / 重做 | | `⌘U` | 回到父级白板 | | `⌘[` / `⌘]` | 后退 / 前进 | **演示模式**(进去以后才生效,见 [第 7 节](#7-演示模式)): | 键 | 动作 | | ------------------------------------- | ----------------- | | `⌘⇧P` | 进入 / 退出演示 | | `→` / `←`(或 `Space` / `Backspace`) | 下一步 / 上一步 | | `1`~`9` | 跳到第 N 步 | | `O` | 总览整块白板 | | `Home` / `End` | 第一张 / 最后一张 | | `Esc` | 退出演示 | **没有默认热键**(在命令面板里可用,或在设置里自己绑): 编辑选中 · 删除选中 · 切换标题显示 · 拆分为分栏 · 收集进分栏 · 切换分栏折叠 · **切换缩略图导航器** · **导出为 Markdown** · **导出为 PNG** · **导出为 PDF** · **导出为 SVG** · **导出为 ZIP(白板 + 附件)** · **导出为 Canvas 文件** · **从 Canvas 文件导入白板** · **从模板新建白板** · **另存为模板** · **重命名白板** · **锁定白板(只读)** · **解锁白板** · **整理未使用附件** · **修复引用** · **提升为笔记**(默认键 `⌘⇧P` 已让给演示模式) · **开始 / 退出演示** · **演示:下一步 / 上一步** · **加入 / 移出演示路径** · **清空演示路径** · **打开 Home 白板** · **把当前文件放进收件箱**。 (**从 Canvas 文件导入白板**、**从模板新建白板**、**打开 Home 白板**、**把当前文件放进收件箱**都是全局命令 —— 前两者要解决的恰恰是"我现在没在看白板,但库里有一张别人给的 `.canvas` / 我想从模板起一块";后两者要解决的恰恰是"我现在哪儿都不是,只想回到手边那块板"和"我站在一篇笔记上,还不确定它属于哪块板"。) ### 6. 导出、导入与改名 - **导出为 Markdown**:把整块白板按「分栏顺序 + 栏内位置」线性化成一篇 `.md`,导出的文件里带一行指纹注释,所以**反复导出只会覆盖自己那份**,不会碰你手写的同名笔记。 - **导出为 PNG**:整块白板(含分栏与连线)渲染成一张图。导出前会告诉你画布会多大、有没有图片没加载出来。 - **导出为 PDF**:整块白板切成**真实的多页 A4**(每页一块 tile,翻页 / 打印 / 发给别人都能用),纸张可选纵向 / 横向,清晰度三档(每页**长边** 2048 / 3072 / 4096 px;只影响印刷清晰度与体积,**页数不变**),页码与白板名印在每页页脚。**PDF 里的文字是位图** —— 选不中、搜不到(要可复制的文字请用「导出为 Markdown」)。 - **导出为 SVG**:整块白板导出成一个**矢量**文件,放大多少倍都不糊,适合放进 PPT / 打印 / 交给设计。选项只有两个——**范围**(整板 / 当前视图 / 仅选中)与**背景透明**;矢量没有倍率、也没有分页。**图片卡与手绘卡在 SVG 里只保留文字**(不内嵌位图),导出前的对话框会明说"有几张图片卡只留了文字"。 - **导出为 ZIP**:把这块板连同它引用的**图片 / 文件附件**打成一个包,发给别人或在别处重建时不会满屏断链。归档**保留库内相对路径**(`assets/pic.png` 就叫 `assets/pic.png`),解压到对方库根即可开板。**不压缩(原样存储)**,所以包会比理论值大一些;只打包附件,**引用的笔记与子白板不进包**(它们留在 `.nboard` 里仍是链接)。库里找不到的附件会在导出前**单独列出**;打包过程中读不出来的文件会被跳过并在提示里说明。 - **导出为 Canvas 文件**:另存为一份 **JSON Canvas 1.0**(`.canvas`)—— Obsidian 自带画布、别的插件、别的工具都认识的格式。导出**不改动白板本身**,也不会覆盖同名文件(自动顺延成 `xxx 1.canvas`)。`.canvas` 表达不了的东西会在导出前**列给你看**(待办 / 色板 / 白板卡 / 手绘这四种卡只能降级成文本节点、悬空连线会丢),你可以就此取消。 - **从 Canvas 文件导入白板**:把一张 `.canvas` 变成一块真正的 `.nboard`,落在**那张画布旁边**、同名(重名顺延,绝不覆盖;原 `.canvas` 一个字节不动)。在文件浏览器里右键 `.canvas` 也能直接导入 —— 这一项排在「添加到白板」之前,因为对着一张画布,你多半是想把它打开成白板。 - **重命名白板**:走 Obsidian 自己的重命名流程,所以你其他笔记里的 `[[这块白板]]` 会跟着改。已经有别的文件占了目标名字时,插件不会覆盖。 ### 7. 演示模式 边讲边翻卡片用的(`J-06` / `J-07`)。**画布空白处右键 →「开始演示」**,或命令面板搜「开始演示」(`⌘⇧P`)。 底部会出现一条步骤条:上一个 / 第几步共几步 / 下一个 / 总览 / 退出。相机是**平滑飞过去**的,不是瞬移 ——飞行途中按一下鼠标就立刻停在原地,不会跟你的手动平移抢画面。 **讲哪些卡片**: - 排过顺序的:只讲你排进「演示路径」的那几张,顺序就是你排的顺序; - **一张都没排过**:按阅读顺序讲全部卡片—— **按块从上到下、从左到右**,**一个分栏算一块** (走进去就把那栏讲完,再走下一栏;栏内按栏内顺序)。压在分栏上方的标题卡会先讲。 零配置也能直接开讲;想穿插着讲(讲完左栏第 1 张跳去右栏)就用「加入演示路径」排一遍。 **编排顺序**:选中卡片 → 右键 →「加入演示路径」(可多选,按选中顺序接在末尾);右键 →「在演示中 前移 / 后移一步」调整次序;右键 →「移出演示路径」摘出去;「清空演示路径」一次清空。顺序写进 `.nboard` (跟着文件与 Git 走,并且**可以 `⌘Z` 撤销**)。 **演示时不能编辑**:这是一条硬约束,防的是讲课 / 直播时的误操作。拖动、双击编辑、空白双击新建、 卡片右键菜单、`Delete`、`⌘D`、`D`(画笔)以及命令面板里的编辑类命令**全部失效**;画布**仍可平移缩放** (`Space` + 拖动 / 滚轮 / 触控板),临时想凑近看某处没问题。系统开了「减少动态效果」时,切步是直接跳过去。 ### 8. 模板 两个入口都在命令面板里(没有默认热键): - **从模板新建白板** —— 挑一个模板,立刻得到一块**已经摆好**的新板并打开它。 - **另存为模板** —— 把**眼前这块板**复制一份进模板目录(同名自动顺延成 `xxx 2`,**绝不覆盖**)。 **有哪些模板**:4 个内置模板(桌面研究 / 每周排期 / 情绪板 / 长文骨架,每个都带一张说明卡), 外加**你自己的模板** —— 「模板目录」(设置里可改,默认 `Templates/`)下的 `.nboard`。 模板目录**认子目录**,所以 `Templates/研究/访谈.nboard` 这样按主题分文件夹是支持的。 **模板就是一份普通的 `.nboard`**:可以用别的编辑器打开改、可以进 Git、可以直接发给同事, 也可以用插件打开当一块普通白板来编辑(用好之后再「另存为模板」覆盖性地存一份新的)。 用模板建出来的板:**内容一样、身份全新** —— 所有 id 重新生成并同步重写引用,视口落回原点, 清掉只读与别名;**画布背景、网格吸附、卡片演示步骤这些刻意保留**(那是模板作者调好的)。 新板落在设置里的「新白板目录」(不是模板目录),标题取模板名,随即打开。 > **模板也会出现在白板选择器里**(「添加到白板」搜得到它)—— 它就是一份合法的 `.nboard`。 > 放进独立的模板目录只是为了"翻文件时一眼分得清",**不是隐藏**。见「已知限制」第 9 条。 ### 9. 白板 URI 与 Home 白板 **白板 URI**(`T5.06`)把某块白板里的某张卡变成一个**可点的地址** —— 写进任何笔记、任务列表、日程, 甚至库外的 App(macOS 快捷指令 / AutoHotkey 之类): ``` obsidian://nestboard?file=Boards/项目A.nboard&card=c_1a2b3c ``` - `file`(也可以写 `path` / `board`):白板路径。**可以省扩展名**(`Boards/项目A`), 也可以带反斜杠、多写一个前导 `/`、夹带前后空白 —— 这些都是人手写链接时会做的事,插件照收。 - `card`(也可以写 `cardId`):要定位的卡片 id,**可以省**(省略 = 只打开那块板、不动视口)。 - 写错了会明确告诉你是哪一种:没写 `file`、指向的不是白板(`.md` / `.canvas`)、 或者路径里有 `..`(试图跳出库)。指的那块板不存在时**只提示路径**,不会给你开一个空标签页。 **Home 白板与收件箱**(`T5.07`)—— 白板多了以后,"先想要去哪块板"本身就是负担。 给 Home 一个固定地址,两个动作即达: - **打开 Home 白板**(命令面板):没有就按你配的路径建一块; - **把当前文件放进收件箱**(命令面板;笔记上右键 →「添加到收件箱」):不必挑目标, 落进 Home 的 `Unsorted` 一栏,回头再整理。 路径在 **设置 → Nestboard → Home 白板路径**(默认 `Boards/Home.nboard`)。 **留空 = 关掉这个功能**:两条命令只会提示你去设置里填路径,文件菜单里那一项也**不会出现** (插件不会"热心地"替你把开关打开)。 > Home 那块板**已经存在时只登记、绝不覆盖** —— 它是整个功能里唯一一条按你填的路径去写盘的操作。 > 板不存在时才新建,新建出来的是**空板 + 一栏 `Unsorted`**(不是预置示例卡的样板间)。 ### 10. 白板列表(三种看法) `⌘⇧B`(或命令面板搜 `Nestboard: 打开白板列表`),它会开在右侧栏。 白板一多,"我那块板呢"就成了第一个卡住人的问题 —— 而白板的组织方式**往往不是目录**: 同一批板可能散在几个目录里,按主题连在一起。所以这个列表给同一份白板**三种看法**: | 看法 | 什么时候用 | 怎么排 | | -------- | ---------------------- | -------------------------------------------------------------------------------- | | **目录** | "我知道它在哪个文件夹" | 目录树,按名排序(`Board 2` 在 `Board 10` 前);同一层的板按标题排 | | **最近** | "我刚才还在看它" | 完全按打开顺序,新的在前(最多 20 块) | | **标签** | "那些 `#项目` 的板" | 按标签分组;一块板有多个标签就在每一组里各出现一次;没打标签的单独一组、排在最后 | 上面的**筛选框**对三种看法都生效:按标题**和路径**一起匹配,空格分开的多个词是「都要命中」, 所以敲 `项目A 周会` 能一次筛到"某目录下的某块板"。筛选不会改看法 —— 切到「标签」看, 筛出来的板仍按标签分好组。 > 几个刻意的取舍:**空目录不显示**(只沿着有白板的路径建节点,把整个 Vault 的目录结构 > 都画出来对这个列表没有用);**筛选没命中时不画空树**(一个空树只让人以为坏了); > **筛选词不会被记住、看法会被记住**(恢复一个被遗忘的筛选器,会让人下次打开侧栏看见 > 一个空列表而不知道为什么)。列的路径只在「最近」「标签」两种看法里显示 —— > 同名白板在不同目录下是完全可能的,只给标题等于给了两行看起来一样、点进去却不同的东西。 > 「最近打开」**只是历史,不是真相**:里面的路径早被改名或删除是常态,所以渲染时会逐条 > 回白板索引里核对,对不上就**静默跳过**;白板改名时那条路径也会跟着搬走 > (不搬的话它不是"变成旧名字",而是**凭空消失**)。它记在插件的 `data.json` 里, > **上限 20 条** —— 这是整份设置里唯一一个由插件自己写、你不用管的字段。 ### 11. 缩略图导航器 大板子上"我那张卡到底在哪"不必再靠滚轮找:画布**右下角**有一张整块板的小地图 (命令面板搜 `Nestboard: 切换缩略图导航器`,或 设置 → Nestboard → 缩略图导航器)。 - **点击或拖动地图** → 视口中心挪到对应位置(拖住不放会实时跟手); - **在地图上按 `Enter`** → 回到全部内容的中心(等同于 `⌘0` 适应内容); - 面板右上角 **`×`** → 收起它。 它与 `⌘0` 回答的是同一个问题,只是回答方式不同:`⌘0` 是"替我把内容摆正", 缩略图是"告诉我内容在哪、我自己点过去"。 **默认关闭** —— 它是一块常驻浮层,占不占画布应当由你点头。三处入口(命令、「×」、设置) 改的是**同一份设置**:关掉之后,新开 / 重开的白板都不会自己冒出来。 > 地图上**不画连线、不画选中态**:连线没有面积,在 176px 宽的地图上画几百条只是噪点; > 选中态由画布上那圈描边回答会清楚得多。相机跑到内容之外时**视口框整块消失**(被地图裁掉)—— > "我不在任何内容附近"本身就是要传达的信息,画一个贴在边上的假框反而会让人误以为看着某片内容。 > 移动端会把它抬到屏幕底部工具条的上方,演示模式下自动收起。 --- ## 设置 设置 → 第三方插件 → Nestboard。 | 设置项 | 默认 | 说明 | | ------------------------------ | -------------------------- | ------------------------------------------------------------------------------------------ | | 新白板目录 | `Boards` | 新建白板放哪。留空 = 库根目录 | | 模板目录 | `Templates` | 「另存为模板」写到哪;从模板新建的板仍进上面的「新白板目录」 | | Home 白板路径 | `Boards/Home.nboard` | 「打开 Home 白板」/「放进收件箱」的目标。**留空 = 关掉这两条** | | 附件存放位置 | 跟随 Obsidian 的附件设置 | 也可以指定一个自定义目录 | | 自定义附件目录 | — | 上一项选了「自定义目录」时才生效 | | 附件命名 | 加时间戳前缀 | 避免两张都叫 `image.png` 的图互相覆盖 | | 自动保存间隔 | 400 毫秒 | 最后一次改动之后等多久写盘 | | 界面语言 | 跟随 Obsidian | 内置中文 / 英文 | | 默认卡片颜色 | `1` | **只作用于之后新建的卡片**,已有的一个都不动 | | 卡片圆角 / 卡片字号 / 卡片字体 | `10px` / `13px` / 跟随主题 | 纯外观 | | 新建白板画布 → 默认背景 | 点阵 | 只写进**新文件**,已有白板保持自己的背景 | | 缩略图导航器 | **关闭** | 画布右下角的小地图;命令与「×」改的是同一个开关 | | 抓取链接预览 | **开启** | 两处会联网的能力之一;`O20` 起默认开启(授权点始终是**你点的那一下**,见「网络访问披露」) | | 地图卡静态图服务 | **不出图** | 另一处会联网的能力:四档(不出图 / OSM / Google / 高德),见下 | | 静态图服务 API Key | 空 | Google / 高德那一档要填自己的 key;「不出图」与 OSM 不填 | | 启用版本快照 | 开启 | 误删一屏卡片时唯一能救命的东西,纯本地 | | 快照位置 | 插件目录(`.obsidian`) | 想跟着 Git / Obsidian Sync 走就切到库内 `.nestboard-history/` | | 恢复默认设置 | — | 把本页所有选项恢复成默认值 | --- ## 网络访问披露 **默认情况下,本插件不主动发起任何网络请求。** 会联网的例外只有两处,而且**两处都只在你点了那一下才发请求** (渲染、导出、翻板都是零请求):**网页预览抓取**与**地图卡的静态图服务**(默认是「不出图」这一档)。 - 没有遥测、没有崩溃上报、没有更新检查、没有远程字体或图标。 - **链接预览抓取**(链接卡的标题 / 描述 / 缩略图 / 站点名 / 站点图标 / 最终网址):设置 → Nestboard → 隐私与网络里的 **「抓取链接预览」**,`O20` 起**默认开着**(不想要就在设置里关掉)。`O32` 起:**你贴进 / 新建一张带链接的 卡片时,会自动抓取那一次**(触发点仍然是你自己粘进来的那条 URL);卡面上也有**「获取预览」按钮** (想重抓随时点,右键菜单里同样有)。 它只访问**你贴进这张卡片里的那个 URL**、以及它 HTML 里声明的预览图 / 图标。关掉总开关时**一次请求都不发**。 抓取时只带一个普通浏览器的 `User-Agent`(`O24`:不少站对无 UA 的请求直接拒),**不带 Cookie / Referer**。 解析只在**这一份抓回的 HTML** 里做(`O20` 的 og 系列 + `O23` 的兜底:标题退到 `

`/`

`、摘要退到首个 `

`、Logo 退到带 `logo` 的 `` 或站点根 `/favicon.ico`),**不额外发"发现请求"**。 **不做** AI 语义解析、也不做无头浏览器渲染(与"一次点击一次请求"和移动端都不相容)—— 纯 JS 渲染(SPA) 或登录墙后的页面**抓不到就是抓不到**,卡片仍可手动补。 - **地图卡的静态图服务**(地图卡右键 →「粘贴地图链接」,或**新建地图卡**时那一步):设置 → Nestboard → 隐私与网络里的 **「地图卡静态图服务」**,**默认是「不出图」**(那一档一个请求都不发,卡片上只有坐标与链接)。 换到 OSM / Google / 高德里任意一档、并**你自己点了**「粘贴地图链接」之后,才会向那一家的 静态图接口发**一次**请求(OSM 那档不需要 key,另外两档要填你自己的 key)。 没有轮询、没有预热:渲染白板时一次都不联网。 - 抓回来的**预览图**与**地图图**都会**下载进你的 Vault**(附件目录),所以之后打开不再联网; 只有链接卡的**站点图标**保留原始远程地址(**不落盘**),加载不到时退回本地画的字母徽章。 - 你可以用开发者工具的 Network 面板验证:**开关 / 档位停在默认时请求数应为 0**; 开了之后不主动点那两条菜单项时也应为 0。 - 这条能力在 OBS 直播场景里**建议保持关闭**:把弹幕 / 聊天里来的 URL 交给插件去抓, 等于把你正在访问的地址告诉了对方站点。 ## 库外文件访问披露 **本插件不读取 Vault 之外的任何文件。** - 所有读写都通过 Obsidian 的 `Vault` API 完成,路径一律是 Vault 相对路径。 - 从系统拖入的文件是把内容**复制**进 Vault(**不移动、不修改原文件**)。 - 代码中不引用 Node 内置模块(`fs` / `path` / `crypto` 等),所以不依赖 Electron 特权。 ## 隐私与其他 - **不需要账号,不需要付费,没有服务端。** - 没有客户端遥测。 - 插件设置只存在 `<你的Vault>/.obsidian/plugins/nestboard/data.json` 里,**只存设置、不存任何内容**。 --- ## 已知限制 1. **`.nboard` 里的 `[[链接]]` 不参与 Obsidian 全局图谱。** 这是 Obsidian 的机制决定的 (`MetadataCache` 只解析 Markdown),不是本插件的取舍。想要双链就请用**引用卡**。 2. **便签卡的链接不会自动随笔记重命名。** 引用卡会(它存的是路径,由插件跟随改名)。 3. **外部改动会被保护。** 如果你在 Obsidian 之外改了 `.nboard` 文件,插件不会拿内存里的 版本覆盖它 —— 会弹冲突对话框让你选,或者把这块板切成**只读**。宁可挡住,也不静默覆盖。 4. **仅桌面端(移动端未验证)。** 代码层面没有用任何桌面端专有 API,但本项目到目前为止 只在桌面端测试过,因此 `manifest.json` 声明 `isDesktopOnly: true` —— **手机上装不了**。 等移动端实测通过再把这一位放开。 5. **大板子(>1000 卡)的性能尚未做完整基线**,可能会掉帧。 6. **导出为 Canvas 是有损的,而且往返不等于还原。** `.canvas` 表达不了的东西有: 待办卡 / 色板卡 / 白板卡 / 手绘卡(降级成一段文本)、一头悬空的连线(丢弃)、 分栏的折叠状态、卡片强调色条、虚线连线与智能走线。导出前的对话框会把这些**逐条列出来**。 另外,由于我们的分栏是"栏内自动排布",把 `.canvas` 导进来之后, 原本站在分栏里的卡片位置会被重排、宽度会被统一 —— 内容与顺序都在,**像素位置不必指望**。 7. **演示模式只能"讲整块板",没有直播那套遮挡。** 演示态下所有卡片都还在画面上(只是非焦点卡 被淡化),也没有"这张卡直播时隐藏"或一键遮罩敏感层 —— 那属于 OBS 集成(本地 HTTP 输出、 指针高亮等),尚未实现。要挡敏感内容,请另开一块板或用分栏折叠起来讲。 (直播讲解时的**临时标注层**已经有了:`⌘⇧A` 切到临时标注,画的东西不落盘,`Esc` 清空并退出。) 另外演示态下**读屏软件看到的 DOM 没有变化**(卡片顺序仍是视觉顺序)—— 无障碍支持尚未做。 8. **导出的 PDF 里,文字是位图。** 每页一张 JPEG 直接塞进 PDF,所以**不能选中、不能搜索**, 屏幕阅读器也读不出来。要可复制 / 可检索的文字请用「导出为 Markdown」。 (要可搜索的 PDF 就得嵌字体子集 —— 中文字体动辄几 MB,本项目刻意不走那条路。) 9. **模板文件也会出现在白板选择器 / 注册表里。** 模板就是合法的 `.nboard` —— 这正是它 "能用别的编辑器打开改、能进 Git、能直发给同事"的前提,所以「添加到白板」这类选择器里 也能搜到它们。放进独立的模板目录只是"翻文件时一眼分得清",**不是隐藏**。 另外,把「模板目录」设成库根(留空)时,模板列表会**刻意拒绝所有文件** —— "全库的板都算模板"不是任何人想要的。 10. **导出的 SVG 里,图片卡与手绘卡只有文字(或一个占位框),没有图。** 我们**不往 SVG 里内嵌位图** —— 内嵌会把文件撑大、还丢了矢量"可缩放"的意义。所以 SVG 更适合"版式 + 文字 + 连线", 要连图一起带走请用 PNG / PDF,或**导出为 ZIP**(附件原样打包)。 11. **引用卡"只显示某一段"这件事,导出里看不出来。** 导出(PNG / SVG / PDF / 缩略图)里的引用卡 本来就不画源笔记正文,只画一行 `路径 + 切片`(例如 `笔记.md#^blk1`)—— 所以"切了哪一段" 在导出里**只体现在那行标签**上。要真画切片得让导出管线拿到**同步**的笔记正文, 而现在读盘是异步的(不打算猜:拿 `md` 字段伪造切片比不画更糟)。 要连正文一起带走,请用**导出为 Markdown**。 12. **转过的卡片,走线按"没转过的框"绕。** 智能走线的障碍取的是卡片的**布局框**, 不是旋转后的外接框 —— 所以一张转了 45° 的卡附近,线可能贴得比视觉上更近(或绕得更远)。 绘制与命中用的是**同一份**几何,所以不会出现"看着绕开了、点下去选中的是直线"。 13. **导出的 ZIP 不压缩,也不打包笔记与子白板。** 归档里每个条目都是**原样存储**,附件字节 压过一轮再 deflate 几乎不缩水,而自己实现 deflate 是几百行容易写错、又要大样本才能验干净的 代码 —— 代价就是**包比理论值大**。另外,只打包**图片 / 文件附件**:`noteRef`(引用的笔记) 会把那一圈的链接与图一起拖进来、边界说不清,`boardRef`(子白板)是个递归(子板还有子板)、 需要环检测 —— 两者都不进包,引用本身留在 `.nboard` 里仍是链接。 --- ## 截图 ## 开发 ```bash npm install npm run dev # 监听并重建 main.js npm run typecheck # tsc --noEmit npm run lint # eslint npm run test # vitest(1901 个用例 / 88 个文件) npm run test:coverage # vitest + 覆盖率(model/ 与 export/ 低于 70% 直接失败) npm run build # 生产构建 ``` 架构、数据格式与模块划分见仓库里的 `03-数据存储与插件架构.md`; 需求与验收标准见 `01-产品定义与功能清单.md`、`04-开发任务清单.md`。 ## 许可 [MIT](./LICENSE)