Skip to main content

run_script

脚本模式是面向高级用户的功能,允许用户在表单提交时执行自定义脚本。

脚本使用 JavaScript 编写,可以访问表单字段的值以及 Obsidian 的 API。

脚本来源

脚本有两种加载来源,分别是

  • 扩展: 从指定的目录加载符合规范的 JS 脚本文件
  • 代码: 直接在表单中编写脚本代码

脚本规范

  1. 脚本必须导出一个 entry 函数作为入口点,插件会在表单提交时调用该函数。
  2. 如果加载来源是 扩展, 脚本的 exports 还需要配置 name 字段,用户可以使用 {name}() 来执行脚本。
async function entry() {
const { app, form, requestUrl, obsidian, Notice, $selection } =
this.$context;
// write code here...
}

exports.default = {
entry: entry,
name: "My Script",
description: "This is a sample script", // 可选,脚本的描述信息,仅适用于扩展加载来源
tags: ["example", "script"], // 可选,脚本的标签,用于分类,仅适用于扩展加载来源
};

脚本上下文对象 $context

在脚本的入口函数 entry 中,我们可以通过 this.$context 来获取脚本的上下文对象,这个对象包含了以下属性:

  • app: Obsidian 的应用实例,可以访问 Obsidian 的 API。
  • form: 当前表单的实例,可以访问和修改表单字段的值。
  • requestUrl: 用于发送 HTTP 请求的工具,支持 GET、POST 等方法。
  • obsidian: Obsidian 的核心 API 对象,可以访问文件系统、设置等,详情查看 Obsidian API.
  • Notice: 用于显示通知的工具,可以用来提示用户。
  • $selection: 当前选中的文本内容,适用于在编辑器中执行脚本时获取选中的文本。
  • $clipboard: 用于访问剪贴板的工具,可以读取和写入剪贴板内容。
  • moment: 用于处理日期和时间的库,可以方便地进行日期格式化、计算等操作。

更多属性可以通过 console.log(this.$context) 查看

脚本示例

示例 1: 每日一言

https://v1.hitokoto.cn/ 获取一言,并将其插入设置到表单字段中,后续执行动作可以通过 {{@一言}} 来引用这个值。

async function entry() {
const { app, form, requestUrl, obsidian, Notice, $selection } =
this.$context;
try {
const response = await requestUrl({
url: "https://v1.hitokoto.cn/",
method: "GET",
});
if (response.status === 200) {
const data = await response.json;
form["一言"] =
data.hitokoto +
" —— " +
data.from +
"(" +
data.from_who +
")";
new Notice("一言获取成功: " + data.hitokoto);
} else {
new Notice("获取一言失败: " + response.statusText);
}
} catch (error) {
new Notice("请求失败: " + error.message);
}
}

/**
* Must reserve export.default and set a entry function
*/
exports.default = {
entry: entry,
};

返回的 json 结构参考

{
"id": 7173,
"uuid": "49eff9ca-7145-4c5f-8e62-d3dca63537fa",
"hitokoto": "即使人生是一场悲剧,也应该笑着把人生演完。",
"type": "k",
"from": "查拉图斯特如是说",
"from_who": "尼采",
"creator": "Kyanite",
"creator_uid": 8042,
"reviewer": 1,
"commit_from": "web",
"created_at": "1614946509",
"length": 21
}

示例 2: 汇总今日总支出

当前脚本可以将指定标题下的所有支出记录汇总到表单字段中,后续执行动作可以通过 {{@总支出}} 来引用这个值。

示例数据

## 日志

## 支出记录

- 09:00 早餐 11.11
- 10:00 咖啡 22.22
- 12:00 午餐 33.3
- 18:00 晚餐 55.12

汇总规则: 将指定的标题下 (form['支出记录保存位置'])的所有支出记录汇总,取每一行的最后的数字作为支出金额,最后将所有金额相加得到总支出。

async function entry() {
const { app, form, obsidian, Notice } = this.$context;
const targetTitle = form["支出记录保存位置"];
const totalField = "总支出";
let total = 0;

// 获取当前文件内容
const file = app.workspace.getActiveFile();
if (!file) {
new Notice("没有激活的文件");
return;
}

const content = await app.vault.read(file);
const lines = content.split("\n");

// 查找目标标题下的支出记录
let isTargetSection = false;
for (const line of lines) {
if (line === targetTitle) {
isTargetSection = true;
continue;
}

if (line.startsWith("#") && line !== targetTitle) {
isTargetSection = false;
}

if (isTargetSection && line.trim()) {
const parts = line.split(" ");
const amountStr = parts[parts.length - 1];
const amount = parseFloat(amountStr);
if (!isNaN(amount)) {
total += amount;
}
}
}

form[totalField] = total.toFixed(2); // 保留两位小数
new Notice(`今日总支出: ${form[totalField]}`);
}

exports.default = {
entry: entry,
};