我是看了 这篇文章 后有所启发。它说的是作者自己实现了一个脚本,用来将 Obsidian vault 上某个目录的笔记自动拷贝到 Astro site 里的指定目录下,这样作者就不用手动拷贝,这大大简化了博客的发布流程。
我的 til 网站 和作者采用的架构是一样的,也是用 Obsidian 来写内容,用 Astro 来创建网站。之前每次写了新的 TIL 后,我都要手动将位于 Obsidian 上的笔记拷贝到 Astro 项目里对应的 src/content/tils
目录下,这点真的很烦,无形中让我越来越不喜欢去写 TIL,因为我很讨厌后面的这个手动拷贝的过程。
所以这次看到 Rach Smith 的这篇文章,我抽空就试了试。然后我发现,她这个方法需要你先运行起脚本,然后这脚本开始监听指定目录下文件的变化,如果你在 Obsidian vault 的指定目录下新增了文件或改动了文件,就会在 Astro site 上自动同步。也就是说,这需要你先运行脚本,然后在开始在 Obsidian 里写内容。这个方式跟我预期的不一样,我预期的是先在 Obsidian 里写内容,写完之后再运行脚本,然后脚本会识别到新增的文件或改动的文件,并将它们同步到 Astro site 里。
于是我按我的思路自己实现了一下。最后的代码实现如下。
import { promises as fsp } from "fs";
import path from "path";
import config from "./config.js";
async function getNote(dir, fileName) {
// ...
}
async function readNotes(dir) {
// ...
}
async function writeNote(note) {
// ...
}
(async () => {
const vaultNotes = await readNotes(config.vaultNotesPath);
const astroNotes = await readNotes(config.astroNotesPath);
const astroNoteFileNames = Object.keys(astroNotes);
for (const vaultNoteFileName in vaultNotes) {
if (!astroNoteFileNames.includes(vaultNoteFileName)) {
// add note
console.log(`Adding ${vaultNoteFileName}...`);
await writeNote(vaultNotes[vaultNoteFileName]);
} else {
if (
vaultNotes[vaultNoteFileName].content !==
astroNotes[vaultNoteFileName].content
) {
// update note
console.log(`Updating ${vaultNoteFileName}...`);
await writeNote(vaultNotes[vaultNoteFileName]);
}
}
}
for (const astroNoteFileName of astroNoteFileNames) {
if (!Object.keys(vaultNotes).includes(astroNoteFileName)) {
// remove note
console.log(`Deleting ${astroNoteFileName}...`);
await fsp.unlink(path.join(config.astroNotesPath, astroNoteFileName));
}
}
})();
这里简单说下思路。
首先,我们先来实现对新增笔记的处理。我需要分别读取 Obsidian vault 和 Astro site 各自目录下的条目,然后分别得到各自目录下的所有条目的文件名,然后遍历 vaultNotes
这边的文件名,如果遍历到的文件名在 astroNoteFileNames
里不存在,就说明这是一个新增的笔记,于是将这条笔记写入到 Astro site 里。
接着,我们再来实现对改动笔记的处理。一开始的处理还是一样,这次在遍历时,只要两边存在同样的文件名,就进一步判断内容是否有所改动,这个判断的标准也很简单,就是判断字符串是否相等,不一样的话,直接将这条笔记重新写入到 Astro site 里。
最后,要实现的是对删除笔记的处理,这个需求是一开始我没想到的。这个实现起来和新增笔记是一个相反的过程,遍历 astroNoteFileNames
,如果遍历到的文件名在 vaultNoteFileNames
里不存在,就是说这条笔记被删除了,于是将这条笔记从 Astro site 里删除掉。
OK,大功告成。之后只要在终端里运行 node scripts/index.js
就可以自动同步内容了。而同步完之后,你就可以按你的方式来部署网站了。