思源笔记插件开发新手指南
你好,欢迎来到思源笔记插件开发的世界!本指南将带你从环境搭建开始,一步步了解插件的核心结构、生命周期、API 使用以及调试方法,最终创建一个简单的实用插件。
准备工作:开发环境
在开始之前,请确保你的电脑上已经安装了以下软件:
- Node.js** (LTS 版本)**:插件开发的基础运行环境。
- pnpm:官方推荐的包管理工具,速度快且高效。
- Visual Studio Code** (推荐)**:强大的代码编辑器,对 TypeScript 支持良好。
- 思源笔记桌面端:你的插件最终运行和调试的地方。
第一步:从官方示例开始
最快的入门方式就是基于官方的示例项目进行修改。
-
下载示例项目:从 GitHub 下载 plugin-sample 项目并解压。这就是你在 思源笔记插件开发大全.md 中看到的项目结构。
-
安装依赖:在 VS Code 中打开项目文件夹,打开终端,然后运行以下命令来安装项目所需的依赖包:
pnpm install -
初次构建:运行构建命令,将 TypeScript 代码编译成思源笔记可以识别的 JavaScript。
pnpm run build构建成功后,你会在项目根目录下看到一个 dist 文件夹,这里面就是插件的最终产物。
第二步:理解插件的文件结构
一个思源插件的核心文件都在你下载的示例项目中,让我们来逐一解析它们:
- plugin.json (插件清单):这是插件的“身份证”,定义了插件的元信息。
- name: 插件的唯一标识符,必须是英文。
- author: 你的名字。
- url: 你的项目或个人主页链接。
- version: 插件版本号。
- minAppVersion: 插件兼容的最低思源笔记版本。
- displayName: 插件在市场和插件列表中显示的名字(支持多语言)。
- description: 插件的简短描述(支持多语言)。
- readme: 指向说明文件的路径(支持多语言)。
- src/index.ts (入口文件):这是插件最核心的逻辑文件,几乎所有的功能代码都在这里编写。
- src/i18n/*.json (国际化文件):用于支持多语言。你可以在这里定义不同语言的文本,然后在代码中通过 this.i18n.key 的方式引用。
- package.json:Node.js 项目的标准配置文件,定义了项目依赖和脚本命令。其中 "siyuan": "0.9.8" 这样的开发依赖至关重要,它为我们提供了代码提示和类型定义。
- webpack.config.js:构建工具 Webpack 的配置文件。它负责将 src 目录下的 TypeScript (.ts) 和 SASS (.scss) 文件打包成 dist 目录下的 index.js 和 index.css。你通常不需要修改它。
第三步:插件的生命周期与核心代码
打开 src/index.ts 文件,你会看到一个继承自 Plugin 的类。插件的生命周期和主要功能都在这个类中实现。
import { Plugin, showMessage } from "siyuan";
export default class SamplePlugin extends Plugin {
// 插件被加载时会调用这个方法
async onload() {
console.log(this.i18n.helloPlugin); // 在控制台打印信息
}
// 当插件面板完全加载后调用,适合添加顶栏、状态栏图标等UI元素
onLayoutReady() {
// 在这里可以添加UI元素,比如顶栏图标
}
// 插件被禁用或卸载时会调用这个方法
onunload() {
console.log(this.i18n.byePlugin);
// 插件停用时,可以在这里保存数据、移除UI元素等
}
uninstall() {
console.log("uninstall");
// 这里可以调用 this.removeData("data.json") 来删除存储的数据
}
}
核心生命周期方法:
- onload(): 插件被激活时第一个执行的方法。通常用于打印加载信息、添加命令、设置项、加载插件所需的数据 (this.loadData)等。
- onLayoutReady(): 在思源笔记界面布局准备就绪后执行。这是添加 UI 元素(如顶部栏图标)的最佳时机。
- onunload(): 插件被禁用或卸载时执行。这是进行所有常规清理工作的最后机会,比如保存未保存的数据、移除添加的 UI 元素。
常用 API 交互
思源笔记通过 Plugin 类提供了丰富的 API 让你与软件交互。
- 国际化 (i18n):
// 假设在 i18n/zh_CN.json 中有 "greeting": "你好" console.log(this.i18n.greeting); // 会根据当前语言设置输出 "你好" 或其他语言 - 数据存储:
// 保存数据 this.saveData("my_config.json", { name: "vv", count: 1 }); // 读取数据 const config = await this.loadData("my_config.json"); console.log(config.name); // 输出 "vv" - 添加顶部栏图标:
// 在 onLayoutReady 方法中 this.addTopBar({ icon: "iconInfo", // 使用内置图标 title: this.i18n.addTopBarIcon, // 鼠标悬浮提示 position: "right", callback: () => { showMessage("Hello from top bar icon!"); } });
第四步:开发与调试
- 实时编译:在终端运行 pnpm run dev。这个命令会启动一个监视进程,当你修改并保存 src 目录下的任何文件时,它会自动重新编译,非常方便。
- 安装插件:
- 打开思源笔记的 设置 -> 关于 -> 基本信息 -> 数据文件夹。
- 进入该目录下的 data/plugins/ 文件夹。
- 将你项目中的 dist 文件夹、plugin.json、README*.md 等所有相关文件都复制到这里,并把它们统一放到一个新文件夹里,文件夹名字就是你的插件名(例如 siyuan-plugin-sample)。
- 启用与调试:
- 回到思源笔记,进入 设置 -> 集市 -> 已下载,找到你的插件并启用它。
- 按下 Ctrl+Shift+I (Windows/Linux) 或 Cmd+Option+I (Mac) 打开开发者工具(DevTools)。
- 在 Console (控制台) 标签页中,你就可以看到 console.log 输出的信息,以及代码中的任何错误。
实战:创建一个“插入当前日期”的插件
让我们来动手修改示例插件,实现一个简单但实用的功能:在顶部栏添加一个按钮,点击后在当前光标位置插入格式化的日期。
- 修改 src/i18n/zh_CN.json,添加一个新的文本:
{ "insertDate": "插入当前日期", "...": "..." } - 修改 src/index.ts,用下面的代码替换 onLayoutReady 方法:
import { Plugin, showMessage, Lute } from "siyuan"; // 引入 API 文档中提到的 Protyle 相关类型 import { getActiveTab } from "./utils"; // 我们需要一个工具函数来获取编辑器 // ... 省略其他代码 async onLayoutReady() { // ... 其他 onLayoutReady 的代码 this.addTopBar({ icon: "iconCalendar", title: this.i18n.insertDate, position: "right", callback: async () => { const tab = getActiveTab(); if (!tab) { showMessage("请先打开一个文档"); return; } const protyle = tab.model; if (protyle.editor.protyle.disabled) { showMessage("文档为只读模式,无法插入内容"); return; } // 获取当前日期并格式化 const today = new Date(); const dateString = `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`; // 使用 API 插入文本 const lute = Lute.New(); const html = lute.SpinVditorDOM(dateString); protyle.editor.insert(html); showMessage("日期已插入!"); } }); } - 创建 src/utils.ts 文件 (因为 getActiveTab 不是内置函数,我们需要自己实现):
// src/utils.ts import { getAllTabs } from "siyuan"; export function getActiveTab() { const tabs = getAllTabs(); return tabs.find(tab => tab.model?.editor?.protyle?.element?.classList.contains("protyle-wysiwyg--focused")); } - 重新构建并测试:
- 确保 pnpm run dev 正在运行。
- 将更新后的文件复制到思源的插件目录。
- 在思源中重新加载插件(禁用再启用)。
- 点击顶部栏新出现的日历图标,看看效果吧!
总结
恭喜你!你已经完成了思源笔记插件开发的整个流程。这只是一个开始,思源笔记的 API 提供了非常强大的能力,你可以:
- 操作文档块(增删改查)。
- 创建自定义的对话框和界面。
- 监听用户的各种操作事件。
- 与外部服务进行数据交互。
请务必将开发插件源码中的 API_zh_CN.md 文件作为你的重要参考,里面详细列出了可用的接口。
开发之旅愉快!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于