Fold Text
unlistedby AIRUIMAX
把任意文本折叠成可展开的 Callout,正文只留一行标题,点开才展开。Fold any text into a collapsible callout.
Fold Text · 折叠文本
把批注写在笔记里,但不占正文的地方。
选中一段文字(或直接粘贴),一键折叠成可展开的 Callout——正文里只留一行标题当作"被批注过"的痕迹,内容点开才看到。不点开,它一个字都不占地方。
正文里这句 ==条件表达式的真假决定执行路径== 我没太懂。
> [!question]- 💬 批注 · 为什么不是 == 比较 ← 收起时只看到这行
> 因为 Python 里 == 是比较运算符,a == b 整体求值为 True/False……
为什么不用现成的批注插件
市场里的批注插件(如 Side Comments、SideNote)都把批注数据存在笔记之外——sidecar JSON 文件或侧边栏面板里。代价是:卸载插件,批注就没了;换编辑器,批注就看不见了。
本插件的批注就是标准 Markdown 的 Callout 语法:
| 外挂式批注插件 | Fold Text | |
|---|---|---|
| 批注存在哪 | 笔记外的 JSON / 侧边栏 | 就在 .md 正文里 |
| 卸载插件后 | 批注丢失 | 完整保留 |
| 换编辑器 / 发到别处 | 批注不可见 | 正常显示(退化为普通引用块) |
| 是否需要额外数据文件 | 需要 | 不需要,只是文本 |
换句话说:我们不是给笔记加了一个"批注系统",而是用 Markdown 原生语法把批注写出来。
适用场景
批注折叠是它的本质,但机制通用——任何"想留痕、不想占地方"的内容都能装:
| 场景 | 说明 |
|---|---|
| 批注 / 注释 | 正文划线 + 折叠批注,正文只留一条痕迹 |
| AI 对话归档 | 把和 AI 的讨论粘进来收进折叠块。AI 输出常含空行、代码块、表格,最容易破坏折叠格式,本插件自动处理 |
| 答案解析 | 复习时把答案折叠,先自己答再点开对 |
| 长引用 / 原文摘录 | 大段引文收起来,不打断自己的行文节奏 |
| 剧透 / 敏感内容 | 点开才看到 |
安装
手动安装
- 到 Releases 下载
main.js和manifest.json - 在你的库中创建目录:
<你的库>/.obsidian/plugins/fold-text/ - 把两个文件放进去
- 重启 Obsidian → 设置 → 第三方插件 → 关闭受限模式 → 启用 Fold Text
从源码安装
git clone https://github.com/AIRUIMAX/obsidian-fold-text.git
# 把 main.js 和 manifest.json 复制到 <你的库>/.obsidian/plugins/fold-text/
零依赖、无需构建,
main.js直接可用。
使用
方式一:选中转(内容已经在笔记里)
- 选中要折叠的文本
Ctrl+P打开命令面板,运行:
| 命令 | 效果 |
|---|---|
Fold Text: 包成折叠 Callout | > [!note]- 首行摘要(默认,收起) |
Fold Text: 包成展开 Callout | > [!note] 首行摘要(展开) |
Fold Text: 折叠 Callout(question 黄) | > [!question]- 首行摘要 |
Fold Text: 仅转义不包壳 | 只给每行补 >,不加外壳 |
方式二:弹窗粘贴(内容还在剪贴板)
适合刚从别处复制好、还没进笔记的时候:
Ctrl+P→Fold Text: 打开弹窗粘贴(生成折叠 Callout)- 弹窗里操作:
| 区域 | 说明 |
|---|---|
| 标题 | 留空 = 自动取正文首行;填了就用手填的 |
| Callout 类型 | 下拉框当场切换 note / question / tip / info / example / abstract / quote |
| 默认状态 | 折叠(收起)/ 展开 |
| 正文内容 | 大文本框,可上下滚动 |
- 点 确认(或
Ctrl/Cmd + Enter)→ 折叠块插入到当前光标处 Esc或「取消」放弃
贴心处理:
- 编辑器里已有选中文本时,打开弹窗会自动带进去当初始内容
- 光标所在行已有文字时,插入前自动换行,不会和已有内容粘在一起
- 当前没有打开的笔记时,结果复制到剪贴板并提示,内容不丢
效果对比
转换前(原始内容带空行 / 代码块 / 表格,直接塞进 Callout 会破坏折叠):
## 关于 Wrapper
Wrapper 把 WHERE 条件对象化。
| 类型 | 用途 |
|---|---|
| QueryWrapper | 查 |
转换后(折叠稳定,正文只剩标题行):
> [!note]- 关于 Wrapper
> ## 关于 Wrapper
>
> Wrapper 把 WHERE 条件对象化。
>
> | 类型 | 用途 |
> |---|---|
> | QueryWrapper | 查 |
>
折叠为什么会失效?(本插件解决的核心问题)
Obsidian 的折叠 Callout 有个隐性的硬要求:块内每一行都必须以 > 开头,空行也要写成单独一个 >。
只要中间漏了一行(尤其是空行),整个块就被打断——前半段还是 Callout,后半段漏成普通文本,折叠随之失效。这也是「感觉内容一长就折不起来」的真实原因。
从 AI 或网页复制来的内容天然带空行、代码块、表格,手工逐行补 > 几乎不可能不出错。本插件把它自动化:
| 情况 | 处理 |
|---|---|
| 空行 | 写成单独一行 >(折叠不断裂的关键) |
| 代码块 ``` 围栏及内部 | 每行补 > |
| 表格 | 每行补 >,表格在 Callout 内正常渲染 |
Windows 换行 \r\n | 先统一成 \n,不产生幽灵空行 |
内容里已有 > | 先摘掉一层再统一重加,不会变成 > > > |
| 选中内容首尾有空行 | 自动裁掉,不生成空的首行 |
首行带 # / 列表符 / 粗体 / 反引号 | 剥掉标记后再当标题 |
| 自动标题超长 | 按码点截断(Array.from),emoji 不会被截成半个乱码 |
| 手填标题全为空格 | 视为未填,回退自动取首行 |
| 手填标题超长 | 不截断(你亲手写的) |
| 没选中任何文本 | 提示「请先选中要转换的文本」,不静默失败 |
设置项
设置 → 第三方插件 → Fold Text:
| 设置 | 说明 | 默认 |
|---|---|---|
| 默认 Callout 类型 | 包壳时使用的类型 | note |
| 默认折叠状态 | 收起 / 展开 | 收起 |
| 标题截断长度 | 自动标题最多保留几个字(按码点,emoji 安全) | 48 |
| 自动添加标题 | 关闭则只生成 > [!note]- 空标题 | 开启 |
| 仅在指定文件夹显示命令 | 命令只在指定文件夹内出现在命令面板 | 关闭 |
命令可见性控制
如果你的库是分层结构的(如 课堂笔记/、读书/),开启此项并填入文件夹名(逗号分隔):
课堂笔记, 读书
命令只会在这些文件夹(及子文件夹)内的笔记中显示,不污染其他场景的命令面板。
已知限制
- 转换是一次性的:转换后再编辑内容,新增的行不会自动补
> - 「仅指定文件夹显示命令」只控制命令面板可见性,不限制在其他文件夹执行
- 弹窗模式插入到当前光标处;若当前没有打开的编辑器,改为复制到剪贴板
- 折叠只是视觉隐藏,超长内容(1~2 万字以上)仍建议拆分,或改用标题折叠
开发
npm run verify # 语法检查 + 15 项单元测试
npm test # 只跑测试
测试原理:把 require('obsidian') 替换为空壳,使纯文本处理逻辑(convertToCallout / deriveTitle)能在纯 Node 下运行。
发版流程见 RELEASING.md。
许可
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.