README file from
GithubCrystal Vault(晶体库)
把一文件夹的 Markdown 卡片变成一座能看的知识晶体库。 QQ 群:831440768
截图预览:
桌面模式:
故事线模式:
而它真正的战场是文献模式:一边读 PDF / 图片 / Markdown,一边把读到的东西当场立成结构—— 读完一章,那一章的结构也就搭好了。桌面把这些摆成一桌能拖能缩的窗, 结构窗让库的结构跟你正在读的那一页并排待着,不用切走。
卡片就是普通的 Markdown,文件夹就是文件夹。没有任何东西被锁进数据库,也不出你的 vault。
English: README.en.md。
主功能:文献模式 · 桌面
阅读器有两种版式:网格是一屏摊开 N 页(翻页扫读用),桌面是一页一扇窗 ——后者是主力,因为它把「我要同时看几样东西」这件事交回给你自己。
-
一页一扇窗,摆法自己定。 拖标题栏挪位置、拉右下角改大小, 关掉阅读器再打开,摆法原样还在。
-
桌上不只有文献页。 卡片、结构、网页都是同一种窗,共用同一套拖、缩、收。 卡片窗顶上会显示这张卡的概念,那行里的公式照常渲染。
-
收纳栏(顶栏那颗按钮)。左边出来一条竖栏,是这些窗的架子:把窗拖到栏上, 或者按窗上的「收纳」,它就收起来、栏里留一条,点一下再拿出来。 收着的窗,关掉阅读器也还在库里。
-
外部标签页(收纳栏最上面那颗
+)。填一条网址,网课、文档站就挂在你正读的 那一页旁边,和别的窗一样能拖能收。⚠️ 网页嵌不嵌得进来由那个站说了算,不是这个插件说了算:站点可以用响应头 拒绝被别的页面嵌(Google 系一律拒绝),这是浏览器的规矩,绕不过去。 所以那扇窗里常驻一颗「用系统浏览器打开」——嵌得进去当窗用,嵌不进去也始终有出路, 不会给你一个白框。
-
右栏也能收。 同一颗「收纳栏」按钮还能把右边「边看边记」那一栏挤回去,读宽一点。
+ 页:Markdown 是按行分页的
顶栏那颗「+ 页」每按一次,就把这份文献的下一段摆到桌面上。 对 Markdown 来说「一段」是行数——接着桌上最后一扇的结束行,往下 40 行。
想改某一扇看的是哪几行,就改它标题栏里那两个框:「起始行」和「结束行」, 改完按回车。旁边那颗「共 N 行」是这份文件今天的总行数,挑区间时拿它当尺子。
同样的规矩也适用于 PDF / 图片那一档:它标题栏里那个框是页码,也是改完按回车。
这是和桌面配着用的那一半。
读文献最烦的是「这块东西在库里到底长什么样」——切过去看一眼,回来就得重新找刚才那行。 结构窗把这层结构开成你桌上的一扇窗,和正在读的那一页并排:
- 看一眼,不是离开。 切走是「离开」;一扇窗只是瞥一眼。
- 固定看一颗。 顶栏那颗「晶体:…」换看哪颗,下次打开还是它。
- 顶栏挡着就收起来。 顶栏最左边那颗 ▲ 是整条栏的开关,颜色就是状态: 蓝 = 按钮都摆着;白 = 全收起来了,屏幕上只剩这一颗。再点一下全回来。 收没收起记着,下次开窗不用重收。
画线:看 / 写
顶栏那颗「画线:看 / 写」管的是拖一根线的后果:
| 档位 | 拖一根线,会发生什么 |
|---|---|
| 看(默认) | 画一根金线。它存在库里,一个字都不碰你的笔记。 |
| 写 | 往起点那张卡的正文里真写一条 [[目标卡]]——笔记跟着变。线是蓝的。 |
蓝跟金的区别说的就是这件事:金线是一种看法,蓝线是笔记里真有的东西。
你亲手拖过连接点的那一根线,接法会写进这张卡自己的 frontmatter(字段
晶体接法)——所以它跟着笔记文件走:改名、搬到别的文件夹、压缩发给别人,
都还在。没过手的那些不写,它们按位置算就够了。
蓝线接在卡片的哪一边,默认按位置算:上下叠着的两张走「下→上」,左右摆的走 「右→左」。想改成别的走法,在写模式下从你要的那条边拖一次,那一根就按你拖的走 (手动拖过的永远压过默认)。
在写模式下把蓝线框住删掉,删的是卡片正文里那条 [[链接]],不是画在屏幕上的东西。
删错了可以撤销一次(和卡片编辑那条撤销同一套)。
右键:三种落点,三种结果
- 对着卡片右键 → 隐藏这张卡片所有的入链和出链。 一张卡连进连出十几根线的时候,把它整个收干净、只留别的, 一眼就能看清剩下的结构。再右键一次就放回来; 只要有东西藏着,顶栏就会出现一颗「显示全部」,一下全放回来。
- 右键落在金线上 → 进连线编辑模式。 顶栏出现「选框:线」和「选框」两颗, 拖鼠标就能框住几根线;框住之后出现「删除实线(N)」。 (右边那颗「选框:线」点一下会变成「框:卡」,那是整批挪卡片用的,见下一节。)
- 右键空白处(在「写」档下)→ 也出现「选框」,但这一档框的是蓝线。
框住之后是「删除蓝线(N)」——按下去会从卡片正文里把对应的那条
[[链接]]删掉。
一个细节:「对着卡片右键」这个入口是由「写」档开的——在「看」档下, 右键卡片仍然是老行为(进连接模式)。但已经藏起来的卡,两种档位下右键它都管用, 不然你一切回「看」,藏起来的东西就只剩顶栏那颗按钮能救了。
收纳方框:把一片收干净,但线不算断
画面上那些虚线框是收纳方框。每个子晶体自动一个,名字就是文件夹名; 框可以改名(点名字)也可以收起(点左边那个小三角)。
框有两种颜色,含义不一样:
| 是什么 | 是容器吗 | |
|---|---|---|
| 金色(点线,暖) | 子晶体——文件夹长出来的 | 是,见下 |
| 蓝色(虚线,冷) | 你用「+ 框」自己画的 | 不是,卡片随便进出 |
金框一层一个、层层套起来(1.3.88 起)。一个文件夹的框里,装着它自己的卡, 外加它每个子文件夹各自的框,所以整棵树的层级一路看得见。框内部横着切:
┌ A ─────────────────────────────────┐
│ [A 自己的卡] ┃ [B1 的卡] ┊ [B2 的卡] │
└────────────────┸────────────┸──────┘
珊瑚橙竖线 ↑ 金色竖线 ↑
(本级 ↔ 子文件夹) (同级 ↔ 同级)
- 珊瑚橙
#FF6B6B分的是这个文件夹自己的卡和它的子文件夹; - 金色分的是两个同级子文件夹。
金框是容器。 里面的卡拖不进别的金框,也拖不过那条珊瑚橙线到上一级"自己的卡"里 ——卡片停在边界上。蓝框不能移出它所在的那个金框(拖和拉大小都出不去), 但蓝框本身不是容器,卡片照样进出。拖金框时里面所有东西跟着走,蓝框也跟。
你画的框属于你画它的那一层。 在「Python/数据分析」里建的框,切到 「Python/爬虫」就看不见了——回到那一层它原样还在。以前不是这样:框是全局的, 换一个文件夹看,别的层画的框还在原地摆着。
点「+ 框」建出来的框落在你正看着的地方(视口正中),而不是世界的某个固定角落 ——以前框建在固定的 (60,60),视口推远了就得先推回去找它。新建的卡片同理。
框里任何一块空白都能拖动整框(1.3.83 起),不只是顶上那条标题栏——按住框的边、 框的空处都行,框和里面的卡一起挪。压在卡片上时拖的仍然是卡片(卡片层级更高), 所以想挪卡片就按卡片,想挪整框就按框的空白处。拖动按格点走,见下面 「一格一格地摆」。
收起之后,框里的卡和连着它们的线一起收起来——但「那边还有东西」这件事不会丢:
- 外面凡是有蓝线连进去的卡,右上角点一个黄色实心圆点;
- 鼠标悬停那张卡,和它有关联的、正收着的框会绕边闪一圈。
不这么做的话,收起读起来就是「我的双链丢了」,而你明明没删。 框展开着的时候,里面的卡照常可以往外连蓝线——跨级连也没问题。
框:卡 —— 一次挪好几张
结构窗顶栏有两颗挨着的按钮,各管一件事,别混:
| 按钮 | 它说的是 |
|---|---|
| 选框:线 ⇄ 框:卡 | 框住的东西是什么 |
| 选框 ⇄ 退出选框 | 现在能不能框 |
默认是「选框:线」:右键进连线编辑模式之后,拖鼠标框住几根线,再点「删除实线 / 删除蓝线」。 点一下「选框:线」,它变成「框:卡」——这时拖出来的方框框的是卡片:
- 框住几张卡,它们会亮起青边;
- 按住其中任意一张拖走 = 整批一起动;
- 松手时整批一起判归属:拖进收纳方框就归它,拖到框外就移出来;
- 想清掉它们:点顶栏那颗红框的「删除卡片(n)」——连笔记文件一起进回收站。
少了这一条,把十几张卡收进一个框就只能一张一张拖;要清掉一批,就只能切回库里 一张一张走「删除卡片」。
- 按住没被框住的那张,只挪它自己——框选之后顺手拖一张别的, 意思显然是「我要挪这一张」,不是「顺便把刚才那几张也带上」。
- 「删除卡片」删的是卡片文件本身(不是解绑、不是隐藏):它连那张笔记一起进 回收站,能捡回来;那张卡所在的晶体不动。它只在真有卡被框住时才出现, 张数写在按钮上——这扇窗没有确认弹窗,按钮上的数、悬停那句话、底下那条说明 就是全部的告知。
- 按 D 在卡档里不删卡:一个裸按键就能把好几个文件扔进回收站太容易误触 (那会儿手正放在方向键上挪卡片)。要删就走那颗按钮。
- 框选本身不动你的笔记一个字——「删除实线 / 删除蓝线」那颗按钮在卡档里会 自己收起来,因为卡档里没有线可删。
- 框选完之后想让它们不亮:点一下空白,或者按 Esc。
卡片的位置会跟着笔记走
卡片摆在哪儿,写进卡片自己的 frontmatter 里(字段叫 晶体坐标)。所以换一台电脑、
装同一个插件、打开同一个库,卡片的相对摆放位置和你这台机器上一模一样——
视图状态是每台机器各存各的,只有写进文件才跟着走。
字段长这样,单位是「格」(最小单位 = 卡片宽的 1/10 = 21px),以左下角为准:
晶体坐标: [3, 5]
字段名带「晶体」前缀是故意的:这个插件装在别人的库里,而
坐标是个 太通用的名字——谁要是有个自用的同名字段,会被静默顶掉。
- 金色方框不用单独存:它的位置和大小就是里面卡片的包围盒,卡片跟着文件走, 它自然跟着走。
- 收纳方框也有自己的文件:每颗晶体一个
.crystal-boxes.json,就放在那颗晶体的 文件夹里。点开头 → Obsidian 的文件列表里看不见,也不会变成一张卡片 (适配层另外只认.md,两道都挡得住)。里面存的是框的左下角坐标、 名字、大小、收起状态和成员。手改前先关掉 Obsidian。- ⚠️ 同步通道必须带点开头的文件。FNS 走文件系统那一层,没问题; 换成会跳过
.开头的通道(Obsidian 自带的 Sync 就是),这个文件传不过去, 框就只在你这台机器上——那种情况下你不会收到任何提示。- 外来卡(「导入卡片」引过来的)也不写:它在你这层的落点和它在自己晶体里的 位置是两回事,写进去就等于改了它老家的位置。
- 写盘是拖完停一小会儿才做的(你有多端同步,拖几下就写几次会引发同步风暴)。 写完之前关掉库也会催一下,不会白摆。
一格一格地摆:卡片的格点与方向键
卡片在故事线里落在一层格点上,坐标以左下角为准——两张卡并排时,是下边对齐。
| 按键 | 一步走多远 |
|---|---|
| ← → | 42px(最小单位的 2 倍,5 步正好一张卡宽) |
| ↑ ↓ | 21px(最小单位) |
最小单位 = 卡片宽的 1/10 = 21px。 就是这么算出来的:每张卡大小一样,拿它当尺子, 整张图自然就对得齐。
拖一张卡,停在哪儿就自动落到最近的格点上;框选之后按方向键,一格一格挪。
- 收纳方框也走格点(1.3.83 起):拖动时框的左下角吸到格点上,框里的卡按 同一段位移整体挪,它们之间的相对位置一点不变。大小仍然随你拉—— 框是你画出来的容器,多大由你定,只有摆在哪儿才需要对齐。
- 金色方框(文件夹长出来的那个)按整格移动。 它的位置和大小是从里面的卡片 算出来的,自己没有坐标可吸,所以吸的是位移:框和里面的卡一起按整格的 整数倍走,同样是整体平移。
- 已经摆好的旧位置不会被集体挪动。 格点只在你下一次拖它 / 按方向键时生效 ——不然那是一次没人按过按钮的破坏。代价是一张从没被碰过的老卡可能停在格外, 动它一下就归位。
导入卡片:把别的晶体里的卡借过来
一颗晶体只画得下它自己文件夹里的卡。可你常常想让 A 晶体的卡去连 B 晶体的卡—— 这时候点结构窗顶栏的「导入卡片」,从别的晶体挑一张进来:
- 它落在窗的正中间(不是自动排到某个角落——你看得见,才知道它进来了);
- 拖它进任意一个收纳方框就归它,跨级连蓝线从此成立;
- 不想要了,点它右上角那颗 ✕。
引进来的卡是点线紫框,一眼能和本层的卡分开。它本身一个字都不动: 还在原来那个文件夹里,别人指向它的双链也都在。拿走再引回来,连你给它摆的位置都还在。
- 引一张本来就在这颗晶体里的卡会被挡下来,并告诉你为什么。
- 只有结构窗里能引;引进来之后,在晶体库的故事线上看同一颗晶体,它也在那儿。
- 「删除实线 / 删除蓝线」和它无关——引卡不会删任何东西。
- 一颗晶体最多引 500 张(这只是一个防坏存档的上限,正常用不到)。
- 引来的卡进不了子晶体框——那种框的成员是文件夹长出来的。拖进去它会告诉你 一句,要给它分组请用「+ 框」建一个手动框。
- 选择器里点文件夹名是展开它(不是"就选这个文件夹")。挑卡片的三档 (导入 / 删除卡 / 重命名卡)都是这个手感。
边看边记:读到什么,当场立成卡
阅读器右边那一栏。填卡片名 / 概念 / 来源 / 正文就能建卡,不用离开这一页。
- 想用真编辑器写:点「✎ 在编辑器里写」,它先把卡建出来,正文改用 Obsidian 自己的 实时渲染编辑器(边写边渲染、自动存盘)。
- 反悔了:点「返回」,刚建的那张卡撤掉,正文原封不动转进草稿纸。
- 草稿纸:一块用原生编辑器写的便签,落在你指定的文件夹里,不建成卡片。
- 卡片盒:搜库里的卡片,点一张就摆到桌面上,并在那张卡里留一行指回这一页的链接。
- 重命名卡片 / 重命名晶体就在这一栏。走的是 Obsidian 自己的改名通道,
所以全库指向它的
[[双链]]会一起跟着改。 - 挑文件夹那块面板抬头有一颗「取消」(1.3.83 起)。「将建在」、新建 / 删除 / 重命名晶体、删除 / 重命名卡片、结构窗挑晶体,打开的都是这块面板,关闭统一走 这一颗——它只收起面板,什么都不改。
晶体库:不读文献的时候
- 一个文件夹 = 一颗晶体。卡片目录下的每个子文件夹在环上就是一颗晶体,可以一层层钻进去, 面包屑随时告诉你站在哪儿。
- 双链变成形状。正文里写
[[另一张卡]],两张卡之间就出现一根线。故事线按连线拓扑 把整颗晶体铺开。A→B 与 B→A 合成一条、两头带箭头:一个箭头是单向,两个是互相。 - 孤岛是信号,不是错误。既没链出去也没人链它的卡会被标出来——那是还没接进任何脉络的卡。
- 先想再看。回忆模式下卡片内容默认遮住,点一下才显示;复习模式全部摊开。
- 就地改。点面板右上角那颗笔,原地改概念 / 来源 / 标签 / 正文——不跳转、不开新标签页。
- 删除走回收站。删晶体、删卡片,都按你在「文件与链接 → 删除的文件」里选的那一档,能捡回来。
为什么不直接用图谱?
图谱回答的是「这张笔记和谁有关系」——它以笔记为起点、连线是主角,而文件夹根本不在图里。 如果你的知识是按科目和章节组织的,图谱会把你所有东西搅成一团。 这正是很多人觉得它「好看但没用」的原因:他们找不到自己组织知识的那条线。
晶体库问的是另一个问题:「这一块知识里有什么、长到什么程度了」。它以文件夹为起点, 结构本身就是主角。
它不是更好的图谱,是不同的起点。
三种打开方式:全屏 / 浮窗 / 嵌入
点侧边栏图标打开晶体库,默认是全屏——铺满整个窗口、盖在笔记上。 另外两档在插件设置的「打开方式」里选,库里顶栏那颗按钮也能随时循环切 (全屏 → 浮窗 → 嵌入,按钮上写的就是下一档叫什么):
| 长什么样 | |
|---|---|
| 全屏 | 铺满整个窗口,盖在笔记上。老行为,也是出厂默认。 |
| 浮窗 | 收成屏幕上一块矩形,浮在笔记上——一边看笔记一边用库。 |
| 嵌入 | 就长在它那颗 Obsidian 标签页里,不盖任何东西。可以和别的标签页左右分屏。 |
浮窗:拖顶栏挪位置、拖右下角改大小;位置和大小跟着 vault 走, 换台机器打开也在你放的地方。
- 三档切换都会重开一次视图(阅读器里开着的文献、桌面上的窗会没)。这一档换的是 库的几何,原地改总有一块不跟着变。
- 文献阅读器、卡片面板这些也都待在当前这一档里——浮窗里点开一张卡, 面板不会盖住你的笔记;嵌入模式下它也只占这颗标签页。
- 嵌入模式不锁笔记的滚动(另外两档会——它们盖在笔记上,背后不该跟着滚)。
- dataviewjs 那种用法没有这几档(它本来就嵌在笔记里),所以那颗按钮不会出现。
遇到问题 / 想提意见
QQ 群:831440768
装不上、用着哪儿不对劲、想要个什么功能,都可以直接进来说。 (在 GitHub 上开 Issue 也一样, 只是群里问一句通常快得多。)
安装
在 设置 → 第三方插件 → 浏览 里搜 Crystal Vault。
手动装:从 最新 Release 下载
main.js / manifest.json / styles.css,放进 <你的 vault>/.obsidian/plugins/crystal-vault/,
然后在 设置 → 第三方插件 里启用。
上手
- 在插件设置里把卡片目录指到你放笔记的那个文件夹。默认是
cards—— 还没有的话,在 vault 里建一个叫这个名字的文件夹就行。 设置页会当场告诉你这个路径在不在、里面有几颗晶体。 - 往卡片目录里放一份能读的东西——你在看的那本书、那门课的讲义、那份论文。 PDF 最好(图片也行)。别放一个空文件进去:阅读器只会说一句 「这份文献里没有可显示的内容」。放进去之后它就会出现在阅读器的文献清单里, 第 6 步要用。
- 点侧边栏那颗宝石图标(或运行命令 Crystal Vault: Open)。
- 在卡片目录里建一个子文件夹——那就是一颗晶体。
- 按下面的格式写一张卡,再用
[[双链]]把它连出去。 - 点顶栏的「文献」进阅读器,选刚才放进去的那一份,开始读; 切到「桌面」,再点「结构窗」——这就是它日常的样子。
放什么格式:阅读器认 PDF / 图片(png、jpg、jpeg、gif、webp、bmp、svg、avif)/ Markdown。 PPTX 不在里面,也加不了——先自己导出成 PDF 再放进来。
⚠️ 放进卡片目录的
.md会同时是一张卡片(子文件夹 = 晶体,.md= 卡片), 也就是说那份 markdown 会一起出现在库里。想图干净就放 PDF。
卡片格式
---
概念: 一句话说清它是什么
来源: 哪本书 / 哪节课 / 哪份文献
tags: [科目, 类型]
---
先用自己的话说清它是什么……
接着看 [[02-下一张]] 连过去的原因就写在后面
==高亮== 的部分会被抽成自测点。
| 字段 | 在库里长什么样 |
|---|---|
| (文件名) | 卡片的标题,卡片- / 卡片_ 前缀会自动剥掉 |
概念 |
面板顶部那一行 |
来源 |
悬停浮层里的「来源」 |
tags |
卡面上最多显示前 6 个 |
四条让库活起来的习惯:至少连一次(不然是孤岛)· 连的时候写下理由 ·
用编号前缀控制顺序(01- 02-)· 想自测的地方用 ==高亮==。
更新记录
新的在上。这一份跟着每一版一起改,只记用户看得见的东西。
1.3.97 · 修:一篇笔记都没开的时候,桌面卡片点「编辑」会弹一句看不懂的话。
插件要挂 Obsidian 的原生编辑器,而 Obsidian 不公开导出编辑器类 —— 只能从
一个活着的笔记实例上把类「借」过来。原来的判据是「必须有一颗 Markdown 笔记开着」,
可这个前提从来没写出来过,而你的用法很可能就是从来不打开 .md 标签页
(都在晶体库里读)—— 于是每一次点「编辑」都借不到、都掉进降级那条路,
还顺带弹一句给开发看的报错。
现在借类有三条路,依次试,任何一条走通就不再往下:
- 活着的 Markdown 实例(原路,判据放宽了)
- Obsidian 的视图类型表(
viewRegistry.viewByType)—— 不需要任何笔记开着 - 上一次借成的那一份,本会话内一直有效
三条都不通时,那句话也换成正常人话了:说清楚为什么、下一步做什么, 并点明下面那个输入框照样能写(它不是错误,是降级)。
1.3.96 · 修:删掉一条蓝线,那条线还在——关掉 Obsidian 重启也在,可文件里已经没有它了, 而且它还会变成幽灵。
根因是算关系的时候读到 frontmatter 里去了。「晶体接法」那个字段长这样:
晶体接法: ["[[花式索引和布尔索引]] b t"]
目标写成 [[双链]] 是故意的——给卡片改名时 Obsidian 会连它一起改,接法不会失联。
可"算出两张卡之间有没有关系"那一步,是在整份文件上找 [[…]] 的,
于是 frontmatter 里这一条也长出一条边:
- 删蓝线删的是正文里的链接,动不到 frontmatter → 线还在
- 它在文件里 → 重启照样在
- 目标卡不在这一层时 → 变成幽灵
现在算关系只看正文。剥的只是文件最开头那一段 frontmatter——正文中间的分隔线
(--- 单独一行)不受影响。
1.3.95 · 结构窗和故事线里,「写」模式下右键空白处不再弹那条说明条。
原来是这么一条:点顶栏「选框」,然后拖出方框 · Esc 退出。它出现在"右键空白处、
进了删蓝线模式、但还什么都没选中"这一档——那时候屏幕上一个选中物都没有,弹这句话是噪音。
其余三档照旧留着,尤其是「看」模式下右键金线那一条:金色线框选唯一的入口就是顶栏 那颗「选框」按钮,少了这句用户只会盯着线发呆。
1.3.94 · 修:关掉 Obsidian 再打开,框的位置变回旧的(1.3.93 没修干净,这次是根因)。
线索是你自己给的那两句:「只要我不关 Obsidian,一切正常,关了再打开,又变成这个 bug 了」。能同时满足这两句的只有一种情况——存下去的是旧的那一份。
根因:两条持久化路线读的不是同一个对象。
进故事线 / 结构窗就是进相机档,那一刻会开一份草稿,你的改动全落在草稿里。
问题在于保存视图状态的那个函数只读 state.view,压根不看草稿——所以开着故事线时,
每一次"保存"写下去的都是那份还没并进草稿的旧状态。而边车(.crystal-boxes.json)
读的是"草稿优先"。
于是:屏幕上一切正常(界面读草稿)、边车是对的、唯独视图状态是旧的。 两条路线必然分叉,而分叉只在重开之后才显形。
现在那个函数改成和"提交草稿"用同一个式子({ ...view, ...draft }),
两条路线读同一份东西,不可能再分叉。
这条也解释了为什么 1.3.93 的时间戳没能救你:那一版保证"谁新听谁的", 而新的那一份本身就没被写进视图状态——它一直躺在草稿里。
1.3.93 · 修:关掉 Obsidian 再打开,蓝色收纳方框会跳回旧位置——而开着的时候 怎么看都是对的。
你报的原话是「只要我不关 Obsidian,一切正常,关了再打开,又变成这个 bug 了」。 这两句合起来就把它锁死了:不是跟随坏了,是那一笔没写进文件。
根因是落盘规则本身:边车(.crystal-boxes.json)一直是**「文件无条件优先」**。
那条规矩有一个它自己写明了的前提——文件永远是较新的那一份。而它不是:
写边车是异步的,而且关库那条路上催写盘的调用没有被等待 (
closeFullscreen整个是同步函数,没地方 await)。 那一笔没走完,文件就停在旧值上;而视图状态是同步写掉的,是新的。
于是开库时旧文件盖掉新状态:框跳回原处、卡片留在新位置, 看上去就是「卡片跑到蓝框外面了」——而且只在重开之后才出现。
现在每一笔都盖上时间戳,开库时逐框比时间、谁新听谁的:
- 文件不比我旧 → 听文件的(平手也让文件赢,它本来就是为跨机器准备的那一份);
- 我严格更新 → 留着我的,并把文件补写出去(不然它永远追不上);
- 两边都没有时间戳(1.3.93 之前写的存档)→ 听本地的。本地那份是这台机器上 你最后看到的样子,而文件恰恰可能是写丢的那一份。
某一次写丢了,从此不会再毁掉你的摆法——不管它是为什么丢的。 你库里那个框(m:6)现在正好是「视图状态说 2667、边车说 2730」的状态, 这一版开库就会自己取新的那个,不用你再拖一遍。
1.3.92 · 跨层拖金框,蓝框现在跟着走了。(这一条是前几版都没接住的那个。)
蓝框是按层存的——你在哪一层画的,它就记在哪一层。而金框从 1.3.88 起 逐层都有。这两件事撞在一起就是一个天天会踩的形状:
你站在浅层(比如「机器学习」),拖某个深文件夹(比如 「…/准确度的陷阱与混沌矩阵」)的金框。这个动作会带动那个文件夹里的卡—— 可你给那个文件夹画的蓝框,存在更深那一层(你是进去画的), 它压根不在这一屏上,于是一个都不跟。
然后你打开结构窗(钉着最深那层)——卡片已经在蓝框外面好一段距离了。
现在按文件夹的包含关系去找:拖一个金框,凡是在里面(它自己那层、 以及它下面任何一层)画的蓝框,只要有成员卡在这一趟里动,就一起跟着走。
那些框在浅层不画(它们属于别的层,画出来就是幽灵),所以你看不到它们动 ——但你打开结构窗时它们已经在正确的位置上了,这才是要紧的。 顺带修了落盘:跨层拖动时,边车写的是框自己那一层,不是"你站在哪一层"。
1.3.91 · 修三条,都跟「拖动金色方框」有关:
① 拖金框时,蓝色收纳方框还是不跟。 判据一直是错的,而且正好错在你这一类上:
原来问的是「我这个蓝框的全部成员是不是都在你里面」。可是一个蓝框跨两个同级 子文件夹的时候,它的共同祖先正是你当时站的那一层——而按你拍板的「本级不画框」, 那一层根本不长金框。于是哪个框都装不下它,判据回 false,代码就退回一条更老的、 「看蓝框画出来的中心落在哪」的位置判据——而你手画的框比贴身的金框大,中心落在 外面,于是静默不跟。框里混一张引进来的外来卡也是同一个下场。
现在换成一句充要的话:这一趟要动的卡,恰好就是那个金框底下的所有卡。 蓝框里只要有任何一张在里面,它就得跟;一张都不在,它就该留在原地。 跟你怎么画、画多大、收没收起,全都无关。
顺带:收起来的蓝框现在也跟着走了(它那条标题栏摆在重心上,位移得从它真正的 位置加起,以前干脆跳过了它)。
② 金框的身份被拼重复了。 同一个文件夹,站在不同层看会拿到不同的 id——而框的 名字和收起状态是按 id 存的两张全局表。所以「我在这一层把它收起来了,换一层它又自己 展开了」,改名同理,而且不报错。根因是递归发框时把完整路径又和父路径拼了一遍。
③ 边框位置的那个文件,会被静默丢掉一笔。 这个是从你库里真实的数据里查出来的:
data.json(视图状态,每次拖动同步写) m:6 x=3003 bottom=294
.crystal-boxes.json(边车,11:55:52) m:6 x=2709 bottom=252
两份对不上,而落盘规则是文件优先——所以下次开库那个框会跳回旧位置、卡片却
留在新的地方,看就是「卡片跑到蓝框外面去了」,跟你拖不拖没关系。根因是关库那条
路上催写盘的调用没有被等待(closeFullscreen 整个是同步函数),而排队表又在写
成之前就被清空了。现在改成写成了才出队,并把合并窗口从一个 700ms 的防抖压到
一个 tick(同一次松手里的几笔合并,跨 tick 立刻写)——窗口小到几乎没有。
1.3.90 · 结构窗顶栏能整条收起来了。 最左边那颗 ▲ 现在是一颗按钮两种状态, 颜色就是状态:
- 蓝 = 顶栏所有按钮都摆着(默认,和以前一样);
- 白 = 全收起来,屏幕上只剩这一颗 ▲;再点一下全回来。
收没收起记着,下次开窗不用重收。(它顶替了 1.3.84 那对只收晶体名的 ▲/▼—— 那把粒度更细,但现在这一颗一次就把名字和按钮一起收了,所以 ▼ 撤掉了。)
为什么这回敢连"换晶体"那颗入口一起收(上一版的注释里明令禁止过):出口就在 原地——同一颗 ▲ 再点一下全回来。原来那条禁令防的是"入口在需要它的那一刻恰好 不可见,而且没有回头路",这两件事不一样。底线没松:收起态下这颗 ▲ 永远 留在屏幕上,它是唯一能把顶栏叫回来的东西。
1.3.89 · 修两条(都是 1.3.88 带出来的):
① 拖金色方框时,里面的蓝色收纳方框还是不跟着走。 你报的原话是「打开结构窗时候, 卡片已经移出蓝色方框之外好一段距离了,但是这个蓝色方框里面仍然算着这些卡片, 然后移动蓝色方框,就连同这些物理位置上不在这个方框里面的卡片一起移动」。
根因是 1.3.88 那条跟随的判据写错了:它问的是「蓝框的中心落不落在金框矩形里」。 而蓝框是你手画的,通常比那个贴身的金框大——往一边探出去之后中心就跑到金框外面, 于是这一趟一个跟随者都找不到,一声不响。
现在改成看成员:一个蓝框"住在"哪个金框里,看它收的那几张卡是不是全都在那个 金框里。这个判据跟你怎么画无关。顺带两条:
- 拖外层的金框,住在里层的蓝框也跟着(拖 A 的时候 C 里的卡同样在动);
- 蓝框"不许移出金框"那条约束用的是同一个判据——它原来有一模一样的毛病, 蓝框画大一点约束就静默失效了。
② 金色方框的标题栏下面,加了一条金色实线。 金框现在一层层套着,抬头和数据之间 没有分界,一眼看不出"这一条是这个框的名字"还是"里面某个子框的东西"。
1.3.88 · 金色方框一层一层地分开了。 以前一个文件夹长出来的金框,会把它整棵 子树的卡全摊平吞进去——A 里面嵌着 B1、B2,B2 里面又嵌着 C 的时候,屏幕上只有 A 一个 框,四层的卡混在一起,层级完全看不出来,而那正是结构窗存在的意义。
现在每一层文件夹都发一个框,框就自然套起来了,一个框内部按你拍板的方式横着切:
┌ A ─────────────────────────────────┐
│ [A 自己的卡] ┃ [B1 的卡] ┊ [B2 的卡] │
└────────────────┸────────────┸──────┘
珊瑚橙竖线 ↑ 金色竖线 ↑
(本级 ↔ 子文件夹) (同级 ↔ 同级)
- 珊瑚橙
#FF6B6B实线分的是跨层:这个文件夹自己的卡 ↔ 它的子文件夹; - 金色实线(和框同一个金)分的是同级:两个兄弟子文件夹之间。 再深一层也一样——C 在 B2 里,B2 内部又是「B2 自己的卡 ┃ C」,还是珊瑚橙。
另外三条一起改了(都是同一次报告的):
- 蓝色收纳方框现在压在金色方框上面。 金框变成嵌套的之后,一个蓝框常常嵌在好几层 金框里面,不给它一个更高的层级就会被内层金框盖住。
- 金框是容器了:里面的卡拖不进别的金框,也不能拖进上一级"自己的卡"那一块 (就是珊瑚橙线的另一边)。拖动时卡片停在那条边界上,不是滑进去再弹回来。 蓝色收纳方框也不能移出它所在的那个金框——拖和拉大小都出不去。 而蓝框不是容器:卡片照样可以拖进拖出。
- 拖金框,里面所有元素跟着走。 卡片本来就跟着;这次补上的是蓝色收纳方框 ——它是个自己记着矩形的容器,以前拖金框时它钉在原地不动。
1.3.87 · 连线接法现在跟着卡片走——把一颗晶体压缩发给别人,对方打开时线的 走向和你这边一模一样。(用户 10-01 报:「压缩发给朋友,他那边只有左右连线」。)
根因是接法一直存在本机:它在视图状态里,而且键是"你当时站在哪一层"。所以 换台电脑是空的、把文件夹复制到库里别处键也对不上——压缩包本身没带走它。 现在它写进卡片自己的 frontmatter:
晶体接法: ["[[02-中继]] b t"]
一条 = 「往 02-中继 那根线,从我的下边出去、进它的上边」(t/r/b/l 是上下右左)。
只在你亲手拖过连接点的那些线才写,没动过的一律不写(默认接法是按位置算出来的,
本来就换哪台电脑都一样)。一张卡手动调过 10 根线,也就多约 250 字节。
- 目标写成
[[双链]]的形状,所以给那张卡改名时 Obsidian 会连它一起改, 接法不会失联。- 老接法会在开库时自动搬进文件(一次最多搬一批,剩下的下次开接着搬)。
- 顺手把「写进文件却读不回来」那条路堵了:解析器原来被调两道,第二道拿到的 已经是对象,被当成字符串整表丢掉——文件里写着、屏幕上却没生效,一声不响。
1.3.86 · 修:蓝色连线不管卡片怎么摆,永远从左右两边接。上下叠着的两张卡, 线也是从右边出去、绕一圈回到左边。根因是"没有手工指定时"的兜底判据写死了左右 (只看谁在左谁在右)。现在改成按位置挑面对面的一边:上下叠着的走「下→上」, 左右摆的走「右→左」。 这件事跟换电脑还有一层关系:你亲手拖过的接法是存在本机视图状态里的,不跟着 卡片走——所以你把资料搬到别人电脑上一跑,一条接法都不在,整屏退化成清一色左右。 改成按位置算之后,默认接法是从排布推出来的,哪台电脑都一样;你亲手拖过的那根 仍然以你拖的为准(手动 > 自动)。
1.3.85 · 修:点方框的名字改不了名了——1.3.83 带进来的。1.3.83 让整个方框
都能起手拖动,而拖动在按下的那一刻就把指针抓走了。于是「按在名字上、原地松手」
那一下:按下的目标是名字、松开的目标变成了整个方框,而 click 的目标是这两者的
最近公共祖先——落到方框上,那就查不到名字了,改名当场哑掉。
(1.3.83 之前它只在空框上是好的:那会儿空框在守卫上直接早退,压根没抓指针。
我放开那道早退的时候,把「空框能拖」和「点名字改名」共用的一扇门一起拆了。)
改法和 panzoom / holodrag 里早就写着的那条一致:过了 4px 才抓指针。
没真拖的那一下,从头到尾什么都没发生。
1.3.84 · 修:结构窗顶栏的晶体名太长,会把后面的按钮挤出窗外。那条栏是
不换行、也没有宽度上限的,而晶体名是里面唯一会长的东西——名字一长,它一路
往右顶,而窗的外层是 overflow:hidden,被顶出去的按钮就再也点不到了。
现在给名字封了顶(超长用省略号,完整的那颗在悬停提示里),顶栏本身也改成到边
换行——两道一起上,按钮再也不会跑出窗外。名字左边多了一对 ▲ / ▼:
▲ 收起名字,▼ 放出来(收起后那颗按钮缩成「晶体」两个字,换晶体的入口还在)。
收起来的这件事记进偏好,下次开窗不用重收。
(顺带一句:上一版 1.3.83 修好的「空方框拖不动」,要是你还看得到,多半是插件
没重载——在 设置 → 第三方插件 里把它关掉再打开一次。)
1.3.83 · 四条,都在故事线 / 结构窗里(用户 09-30)。
方框整块都能拖了。 以前只有顶上那条 26px 的标题栏能抓,现在框里任何一块空白 都能起手。压在卡片上时拖的仍然是卡片——卡片层级比框高,这一条是层级给的,不用额外判 (所以「拖卡片区域不会拖框」是白拿的)。代价说清楚:在框的空白处按下不再平移画面, 推画面请拖框外面,或者用滚轮。顺带修好一条:一个还没装卡的框以前拖不动, 现在也能摆了。
金色方框里的连线,走线方式和进到那个文件夹里一样了。 「接法」(这根线从卡片的 哪一边出去、怎么拐)是按层记的,站在外面看金色方框时查不到那一份,就退回默认的 「看谁在左谁在右」——同一对卡、同一根线,两个地方长得不一样,而屏幕上没有任何东西 解释这件事。现在各层的接法都算数,当前这一层优先。
方框也走格点了。 手动框吸到格点上(判据和卡片同一把尺子,左下角),框里的卡 按同一段位移整体挪——相对位置一点不变,不会被挤到一起;金色方框没有自己的坐标, 退一步按整格移动。大小仍然随你拉,只有摆在哪才需要对齐。 (格点 1.3.34 撤过一次,这一版按你的要求装回来。)
挑文件夹那块面板的抬头多了一颗「取消」。 将建在、新建 / 删除 / 重命名晶体、 删除 / 重命名卡片、结构窗挑晶体——它们打开的都是这块面板,关法从这一版起统一成 这一颗(以前只能再点一次「将建在」把它收起来,那颗按钮叫「将建在」,不像一个"关")。
1.3.82 · 新增:结构窗里可以一次删掉一批卡片。框选卡片(顶栏「框:卡」+「选框」, 框住几张)之后,顶栏多出一颗红框的「删除卡片(n)」——点一下,这几张 连笔记文件一起进回收站(能捡回来),卡片所在的晶体不动。 删的是文件,所以代价写了三处:按钮上的张数、悬停那句话、底下那条说明条 ——这扇窗没有确认弹窗是既定的规矩(09-20 定的),说明条就是仅有的告知。 按 D 不删卡:一个裸按键就能把好几个文件扔进回收站,太容易误触 (那会儿手正放在方向键上挪卡片)。要删就走那颗按钮。 (库那一屏的卡档仍然只有移动——那边没有这颗按钮。)
1.3.81 · 修:点「编辑」会凭空多出一个空白标签页(全屏 / 浮窗 / 嵌入都中)。
根因是插件向宿主"借一颗现成的标签页"时用的是 getLeaf(false),而那句话的语义
不是"拿一颗现成的"——宿主内部走的是 getUnpinnedLeaf():"拿一颗没被钉住的",
当前活动的那颗要是钉住的,它就当场造一个新的空页。你在阅读器里时,活动的那颗
正是晶体库自己,于是每点一次 ✎ 就多一个。
实证是往宿主 Console 挂了个探针,在标签页被插进 DOM 的那一刻打出了调用栈
(mountEditor → getLeaf → getUnpinnedLeaf → setActiveLeaf → … → insertBefore)。
改法:那个位置根本不需要一颗真标签页,只需要它的"类"——改成从已经查到的
markdown 标签页上取构造器,只是查表,不激活、不新建。
1.3.80 · 修:别的机器改过的卡,这边从 1.3.59 起就没跟上过。多设备同步把 改好的正文、概念、来源、标签、坐标传过来时,一样都不会变,屏幕上什么都不发生—— 看着像通知根本没送到。根因是加「晶体坐标」那一次,调用参数错位了一格, 卡片对象被挤掉;而那个名字在作用域里正好还有一份,于是不报错。 测试只逮到 2 条,实际断掉的是整条同步链路。
1.3.79 · 修:新卡还是落在"默认坐标"。1.3.77 里我拿屏幕坐标当世界坐标用了, 而这两者只在"相机停在原点、缩放 1"时才重合——所以新卡永远落在一个 和你推到哪儿毫无关系的固定地方。现在先换算再落座:你说的"当前视口"就是相机 此刻的位置,新卡因而真的落在你正看着的那一屏右边 5%、上下居中。
1.3.78 · 修:浮窗 / 嵌入档下点「编辑」会把笔记开到一颗空标签页旁边。 根因不在"编辑"本身,在它依赖的那个前提:从"当前活动的那颗叶子"裂一半—— 而这两档多了一颗属于插件自己的标签页,它完全可以就是活动的那颗。 现在 split 的基准自己挑一颗已有的 markdown 叶子。全屏档逐字不变 (那两档下"最近用过的那颗"本来就是你的笔记)。
1.3.77 · 修:建在子文件夹里的新卡还是落在默认坐标——建卡有两条路, 我只在其中一条里摆了位,而你走的恰好是另一条(「✎ 在编辑器里写」)。 两条路都是"建一张卡",位置这件事只能一样。落点也按你定的公式改成 视口右侧 5%(卡片右边缘落在"右边减 5% 宽"上,纵向居中), 不吸附格点——你给的是具体公式,硬吸反而会差半格。
1.3.76 · 修:建在子文件夹里的新卡不会被摆进结构窗的视口(落回默认位置)。 判据原来写的是"卡片所属晶体的链必须和你看着的那一层完全相等",而卡片常常建在 更深的子文件夹里——它明明画在这一屏上(取卡片是递归的),却被这条判据挡掉了。
1.3.75 · 阅读器顶栏可以收起来了:顶栏最右端多一颗图标,点一下把它压成一颗图标, 桌面就多出一条——结构窗和页面窗能摆到原先顶栏占的位置上。图标两档之间转 180° (展开态箭头朝上=按下去内容往上走,收起态朝下=按下去挤回来), 图形始终是同一个,状态的差别由鼠标悬停那句话讲清楚。展开时被压在顶栏下面的窗 会跟着往下让。
1.3.74 · 修 1.3.73 的四处 + 一处你报的:嵌入档那个"跟着标签页大小走"的观察器 因为一个声明顺序错误从来没建起来过(而且被一个 catch 吞掉了,没留任何痕迹); 嵌入档按整块屏幕而不是标签页缩放(卡片会撑出半宽的分屏);连点两下切换按钮会跳档; 顶栏那颗按钮的刷新漏了重排。另外:把卡片存进晶体库之后,结构窗现在会实时显示 ——以前要关一次再打开(刷新的收口从"逐个入口"移到了"库重画就刷窗")。
1.3.73 · 新增第三档「嵌入」:库就长在它那颗 Obsidian 标签页里,不盖任何东西, 可以和别的标签页分屏。顶栏那颗按钮变成三档循环(全屏 → 浮窗 → 嵌入), 按钮上写的就是下一档叫什么。嵌入模式不锁笔记的滚动(另外两档会,它们盖在笔记上)。
1.3.72 · 浮窗模式的六处修正:卫星和悬浮窗跑偏(它们的坐标是屏幕坐标,
而它们住的那一层是"层内坐标",浮窗时差一个窗口原点);右下角抓手关库后还留在笔记上
(而且只增不减);拖拽监听没摘(每开一次漏六个);卡片面板会高于窗口
(vh 量的永远是视口)→ 现在 CSS 改问"这一层多大";顶栏在窄窗口里被裁掉
(连 ✕ 都点不到)→ 改成可换行;窗口比屏幕宽时抓手跑到屏幕外。
1.3.71 · 修 1.3.70 的致命错误:晶体库打不开(报 Cannot access 'j' before initialization)。
原因是我把 viewBox 的声明放在了用到它的那行之后(一个 TDZ 错误),而生产包里变量名被压成
一个字母,从报错上完全看不出是谁。现在声明挪到了使用之前。
1.3.70 · 浮窗模式:库可以不占满屏,收成一块可拖可缩的矩形浮在笔记上方, 一边看笔记一边用库。插件设置里选默认档,库里顶栏那颗按钮随时切。 (版本号从 1.3.60 跳到这里:这是一次架构调整——库第一次有了"占多少屏幕"这个概念, 所有"拿视口当边界"的坐标计算都改成了"拿这一层界面当边界"。)
1.3.60 · 收纳方框落盘:每颗晶体一个 .crystal-boxes.json(点开头,Obsidian 里看不见),
名字、大小、收起状态、成员都在里面。老版本里只存在本机的位置,升级后第一次开库会自动搬进去。
1.3.59 · 卡片坐标写进卡片自己的 frontmatter(晶体坐标: [3, 5],以左下角为准)
——换台电脑打开,相对摆放位置一样。同时:收纳方框取消格点(拖到哪停哪),
新建的卡片和 + 框 落在你正看着的地方(以前建在世界的固定角落,视口推远了得推回去找)。
1.3.58 · 收纳方框按晶体分层。以前它是全局的——换一个文件夹看,别的层画的框还在原地摆着。
1.3.57 · 卡片的格点与方向键:拖动吸附到格点,选中后方向键一格一格挪。 最小单位 = 卡片宽的 1/10,坐标以左下角为准。
1.3.56 · 修「导入卡片」的四件事。其中两件要紧的:在挑卡片的选择器里点文件夹名 会静默改掉你的「将建在」;外来卡拖进子晶体框时一声不响(现在会告诉你去用「+ 框」)。
1.3.55 · 导入卡片:从别的晶体引一张卡到这一屏上来,拖进收纳方框, 跨级连蓝线从此成立。卡片本身一个字都不动。
1.3.54 · 框选卡片、整批拖走。顶栏多一颗「框:卡」——框住几张,按住其中任意一张 整批一起动,松手整批判归属。在这之前,把十几张卡收进一个框只能一张一张拖。
1.3.53 · 修:拖框走的世界距离和卡片不一致(相机会缩放时框走得短);收起态的框一拖就把卡片甩到框外。
1.3.52 · 收纳方框改成「你自己画的框」:可以拖、可以拉大小,不再只是卡片周围一圈算出来的外壳。 收起之后外面有蓝线连进来的卡会点一个黄点,鼠标悬停它,相关的框边框闪一圈。
1.3.51 · 收纳方框的颜色加深。第一版太浅,在库自绘的深底上几乎看不见。
1.3.50 · 修:空框不画 → 「点了 + 框 一点反应都没有」。建完框要能把卡拖进去,而拖进去的前提是屏幕上看得见那个框。
1.3.49 · 拖收纳方框的标题栏 = 整组卡片一起挪。
1.3.48 · 手动收纳方框的入口「+ 框」;卡片拖进拖出;删框(框只是分组,删框不动你的卡)。
1.3.47 · 修:方框没被清场,每重画一次就叠一层。
1.3.46 · 结构窗的收纳方框:每个子晶体自动一个,可改名、可收起;收起后里面的卡和线一起收起来, 但「那边还有东西」这件事不丢。
1.3.45 · 桌面卡片窗顶上补一行「概念」。
1.3.44 · 结构窗那一节补全(看 / 写模式、右键三种落点);+页的 markdown 按行分页、改完按回车; 上手补一步「往卡片目录里放一份能读的东西」。README 在这版重写过一次——把文献模式 · 桌面提到主功能位置。
1.3.43 · 重命名卡片 / 重命名晶体两颗按钮;修「别人在 Obsidian 里改了名,插件不知道」—— 以前会在图上留下一张灰色的、点进去什么都没有的卡。
1.3.42 · 每一扇窗都有一颗「收纳」,不带条件。
1.3.41 · 收纳栏最上面那颗 +:外部标签页,可以内嵌 deepseek、Google 这些站点。
1.3.40 · 阅读器的收纳栏,以及「边看边记」那一栏的开关。
1.3.39 · 故事线也有「看 / 写」两档了:写模式下拖线真写 [[双链]]、选框删蓝线、一层撤销。
1.3.38 · 去掉写模式里那个「为什么连过去?」输入框——连着拖几根线时每根都被它截一下。
理由照样可以手写在 ]] 后面,只是不再由插件代劳。
1.3.37 · 写模式下多一颗「选框」删蓝线:框住几根,从卡片正文里精确挖掉那条 [[链接]]
(两个方向一起删、逐字节可还原、一次撤销)。
1.3.36 · 蓝线改成和金线一样的折线(直线 + 圆弧拐角),不再是贝塞尔弧 ——弧线从卡片中段穿过去,两根一交就看不出谁接谁。
1.3.35 · 蓝线能从上 / 下 / 左 / 右接(认你拖的那个连接点); 写模式下右键一张卡就藏掉它所有入链出链,顶栏「显示全部」一键收回;橡皮筋预览和落地同形同色。
1.1.31 / 1.1.3 / 1.1.2 / 1.1.1 / 1.1.0 · 草稿纸、边看边记的「返回」、删除卡片; 草稿纸从一堆文字改成摆到桌面上的一张真卡。几个补丁版本号是因为发过的号不能复用。
1.0.2 / 1.0.1 / 1.0.0 · 默认卡片目录改成中性的 cards;按自动审查改三处;首次提交。