Obsidian中QuickAdd插件的妙用

Keywords: #技术 #Obsidian

最近在研究 Obsidian 中怎么合理的组织笔记和附件,我认为最佳的方式就是一篇笔记一个文件夹,在这个文件夹中有一个 assets 目录专门存放图片等附件。

然而,以这样的方式进行文件管理的话,当我新创建一篇笔记时,我需要先创建一个文件夹再在其中创建一篇笔记。正如 assets 文件夹可以通过 Obsidian 的设置,在图片粘贴的时候自动创建,那么我新建笔记的这个步骤能不能也自动创建?

在新建一篇笔记时,我通常习惯使用固定的模板,配合 Obsidian 内置模板变量十分方便,当然也可以使用 QuickAdd 插件,功能更加全面。当然在 Obsidian 中有一个创建目录的指令,虽然 QuickAdd 也可以调用,但是却不能输入自定义名称。我的需求是:

按下 QuickAdd 快捷键后,出现一个输入框,然后输入文件夹名称和笔记名称,比如 test 然后按下确定键后,会创建一个文件夹和一篇 md 笔记,文件名都是 test 并且笔记在文件夹里面。

网上检索一番,发现这样的需求大概还是要用 JavaScript 脚本来实现,其他没有很好的办法。QuickAdd 中的 Macros 可以执行用户自定义脚本,于是我去翻阅 QuickAdd 官方文档Obsidian 开发者文档, 折腾了一会,写出了一个 js 脚本,利用 QuickAdd,基本上能实现需要的效果。

module.exports = async (params) => {
    const { inputPrompt } = params.quickAddApi;
    const app = params.app;

    // 获取用户输入的文件夹和笔记名称
    const folderAndNoteName = await inputPrompt("Enter folder and note name:");
    if (!folderAndNoteName) {
        new Notice("No input provided.", 5000);
        return;
    }

    try {
        // 创建文件夹
        const folderPath = folderAndNoteName.replace(/[/\\]/g, ''); // 确保路径有效
        app.vault.adapter.mkdir(folderPath);

        // 获取当前日期
        const date = window.moment().format("YYYY-MM-DD");
        const time = window.moment().format("HH:mm:ss");
        
        // 创建笔记文件
        const filePath = folderPath + '/' + folderAndNoteName + '.md';
        const fileContent = `---
title: ${folderAndNoteName}
date: ${date}
time: ${time}
tags: []
---`;
    } catch (error) {
        new Notice(`Error: ${error}`, 5000);
    }
};

这其中遇到最大的困难就是,这两个文档写的太难用了,想要的功能需要找很久,还不一定是我想的那样。最后打开新建笔记这一步,一直实现不了,app.vault.create(filePath, fileContent); 这个函数能够成功创建文件并写入内容,但是即使是成功了也返回 NULL ,以及 leaf.openFile(file); 这个函数一直不能打开文件,也不知道是不是因为接口和函数写错了,这让我百思不得其解,总之一直没有搞定。

随后,我也将这个脚本进行修改,整合进我的 Hugo 博客文章撰写的工作流之中。利用这个脚本根据日期创建对应的文件夹如 /content/post/2024/09/,在文件夹中创建新的模板笔记,利用 Obsidian 的 Git 插件实现定时推送到 GitHub 仓库,再通过 GitHub Action 构建出 HTML 文件,部署在 Github Page 上。

module.exports = async (params) => {
    const { inputPrompt } = params.quickAddApi;
    const app = params.app;

    const noteName = await inputPrompt("Enter note name:");
    if (!noteName) {
        new Notice("No input provided.", 5000);
        return;
    }

    try {
        const year = window.moment().format("YYYY");
        const month = window.moment().format("MM");
        
        const basePath = './content/post';
        const yearPath = `${basePath}/${year}`;
        const monthPath = `${yearPath}/${month}`;
        const notePath = `${monthPath}/${noteName}.md`;

        // 创建文件夹结构
        await ensureDirectoryExists(app.vault.adapter, yearPath);
        await ensureDirectoryExists(app.vault.adapter, monthPath);

        // 创建笔记文件内容
        const fileContent = `---
title: ${noteName}
date: ${window.moment().format("YYYY-MM-DD")}
description: 
tags: []
slug: 
---

<!--more-->`;

        const file = await app.vault.create(notePath, fileContent);
        // const leaf = app.workspace.getLeaf();
        // await leaf.openFile(file);
    } catch (error) {
        new Notice(`Error: ${error.message}`, 5000);
    }
};

// 确保目录存在
async function ensureDirectoryExists(adapter, path) {
    try {
        await adapter.exists(path) || await adapter.mkdir(path);
    } catch (error) {
        throw new Error(`Failed to create directory ${path}: ${error.message}`);
    }
}

image.png

image.png

你还可以将 QuickAdd 这个方法绑定到 Obsidian 的快捷键上,更加方便。

image.png