开发第一个插件
使用 NoteGen Plugin SDK 创建、构建、验证并导入一个桌面插件。
本指南会创建一个“统计选区单词数”的桌面插件。完成后,你将得到一个 TypeScript 源码项目,以及可从 NoteGen 开发者页导入的 .notegen/package 快照。
更新日期:2026-09-10。四个 SDK 包已发布 npm,官方插件签名市场已上线;社区投稿尚未开放。接口说明以当前开发分支为准,未发布的新增能力需使用对应源码版本。远程安装还要求 NoteGen 支持插件系统并内置正式根公钥。
1. 创建项目
使用 npm 创建项目
Node.js 20 或更高版本环境中运行:
npx create-notegen-plugin word-count \
--id com.example.word-count \
--name "Word Count" \
--template command
cd word-count
pnpm install把 com.example 换成你控制的反向域名命名空间。插件 ID 发布后应保持稳定;app.notegen 和 app.notegen.* 是 NoteGen 宿主内部保留命名空间,官方市场插件也不使用它们。
脚手架不会默认安装依赖。如果希望创建后立即安装,可以显式传入 --install。生成项目默认安装 npm 上的版本;测试 SDK 未发布改动时需要显式链接本地依赖。
从 SDK 源码运行
先构建 SDK 仓库:
git clone https://github.com/codexu/note-gen-plugin-sdk.git
cd note-gen-plugin-sdk
pnpm install
pnpm build然后直接运行构建后的脚手架:
node packages/create-notegen-plugin/dist/bin.js ../word-count \
--id com.example.word-count \
--name "Word Count" \
--template command下文出现的 notegen-plugin 可以替换为:
node /绝对路径/note-gen-plugin-sdk/packages/plugin-cli/dist/bin.js从源码运行时可使用 SDK checkout 中的 CLI;若项目依赖未发布的 SDK 能力,需要显式链接相应本地依赖。构建器会擦除 import type,并把运行时依赖打进单个入口。
2. 认识项目结构
生成目录如下:
word-count/
├── .gitignore
├── package.json
├── plugin.json
├── tsconfig.json
└── src/
└── main.tsplugin.json 是宿主读取的插件声明;src/main.ts 是作者源码。package.json#notegen.source 指定构建入口,默认是 src/main.ts。
NoteGen 不会在用户设备上读取这棵源码目录、安装 npm 依赖或编译 TypeScript。开发导入使用下一步生成的完整快照。
3. 声明插件能力
用下面内容替换 plugin.json:
{
"manifestVersion": 1,
"id": "com.example.word-count",
"name": "Word Count",
"description": "Count words in the active editor selection.",
"version": "0.1.0",
"apiVersion": "^0.1.0",
"minAppVersion": "0.37.0",
"platforms": ["desktop"],
"entry": "dist/main.js",
"activationEvents": [
"onCommand:com.example.word-count.count"
],
"permissions": {
"editor.read": {
"scope": "active-editor",
"description": "Read the current selection to count its words."
}
},
"contributes": {
"commands": [
{
"id": "com.example.word-count.count",
"title": "Count selected words",
"description": "Show the word count for the current selection"
}
]
},
"license": "MIT"
}manifest 只声明插件真正使用的最小权限。命令 ID、状态栏 ID 和菜单引用等贡献 ID 都必须位于插件自身命名空间下。如果插件依赖更晚版本才提供的能力,把 minAppVersion 改成你实际支持的最低 NoteGen 版本。
完整字段与限制见插件配置。
4. 编写入口
用下面内容替换 src/main.ts:
import type { PluginActivate } from "@notegen/plugin-api";
export const activate: PluginActivate = async (ctx) => {
ctx.commands.handle("com.example.word-count.count", async () => {
const selection = await ctx.editor.getSelection();
if (!selection) {
await ctx.ui.showNotice("No active Markdown editor.");
return;
}
const value = selection.text.trim();
const count = value ? value.split(/\s+/u).length : 0;
await ctx.ui.showNotice(`Selected words: ${count}`);
});
};getSelection() 在没有活动 Markdown 编辑器时返回 null。这个统计算法只用于演示;面向多语言的正式插件应自己定义并说明 Unicode 与 CJK 的统计口径。
入口必须导出具名 activate,也可以导出 deactivate。使用 import type 可以让类型引用在构建时被擦除。值导入和其他依赖必须全部打进入口;NoteGen 运行时不解析相对模块、npm 包或远程模块。
公开类型与版本策略见 接口与类型参考,运行时能力见功能调用与权限。
5. 构建并验证
使用脚手架生成的脚本:
pnpm build
pnpm validate也可以直接调用 CLI,并额外复验构建输出:
notegen-plugin build
notegen-plugin validate
notegen-plugin validate .notegen/package从 SDK 源码运行时,传入插件项目的绝对路径:
node /绝对路径/note-gen-plugin-sdk/packages/plugin-cli/dist/bin.js \
build /绝对路径/word-count
node /绝对路径/note-gen-plugin-sdk/packages/plugin-cli/dist/bin.js \
validate /绝对路径/word-count/.notegen/packagebuild 会完成以下工作:
- 严格校验
plugin.json; - 把源码和依赖构建为单个 UTF-8 JavaScript ESM 入口;
- 拒绝残留的静态或动态模块导入;
- 复制 manifest 与声明的本地化文件;
- 生成精确覆盖载荷的
integrity.json; - 原子替换
.notegen/package。
输出结构为:
word-count/.notegen/package/
├── plugin.json
├── integrity.json
└── dist/
└── main.js.notegen/package 是开发导入目录;.notegen 已由脚手架加入 .gitignore。不要把源码目录或 .notegen/releases 当作开发导入路径。
在构建前也可以运行 notegen-plugin validate 对源码项目做预检。需要模拟特定宿主版本时,可使用 --api-version 和 --app-version。
6. 导入 NoteGen
- 在 NoteGen 桌面端打开“设置 → 通用 → 高级”,启用开发者模式;
- 打开“设置 → 插件 → 开发者”;
- 选择或填写
word-count/.notegen/package的绝对路径; - 点击“导入”;
- 到“已安装”页找到 Word Count,打开开关;
- 审核
editor.read权限说明并确认。
按 Command/Ctrl + Shift + P 打开插件命令面板,搜索并运行“Count selected words”。
NoteGen 会再次验证目录并复制不可变快照,不会直接执行你的源码;开发监听器会检查构建产物的变化。
7. 修改与自动重载
在插件项目运行:
pnpm exec notegen-plugin devnpm 发布前,使用第 1 步构建出的本地 CLI 路径执行 dev。CLI 在源码变化后重建 .notegen/package,构建失败保留旧产物。NoteGen 开发者模式和开发插件均启用后自动重载,不需要按钮或开关;关闭设置页面后继续监听,宿主重启后恢复。
宿主导入不可变快照并重建运行时与界面。相同来源且未扩权的更新可保留授权;源路径变化或扩权需要重新审核。表单草稿不会跨重载保留。详见 命令行工具。
8. 排查失败
“开发者”页显示 NoteGen 宿主记录的警告和错误;“已安装”卡片显示运行状态、失败代码、消息和累计次数。这里不是插件的 console 控制台,插件代码的 console 输出当前不会被收集。
建议依次检查:
plugin.json是否为严格 JSON,且 ID、权限范围和贡献引用有效;entry是否为不超过 5 MiB 的 UTF-8.js文件;- 构建结果是否仍含外部、相对或动态模块导入;
integrity.json是否只覆盖全部载荷且每项哈希、大小正确;- 当前工作区是否已经授予所需权限;
- 开发命令是否生成新产物,开发者模式与插件是否均已启用。
notegen-plugin validate <path> --json 会把唯一一份 JSON 结果写到 stdout,适合脚本读取。命令只检查输入,不执行插件代码。若要检查 minAppVersion,还要传入目标 --app-version;否则结果中的 appCompatibilityChecked 为 false。
作者应使用 ctx.log.info/warning/error 写入诊断,退出应用前从开发者页导出。限额和数据边界见 功能调用与权限。
运行时边界
市场与开发插件不能使用 DOM、window、document、全局 fetch、WebSocket、Node.js 内置模块、子进程、原生扩展、Tauri API、SQLite 或原始文件路径。官方插件也遵守相同边界。
eval 和 new Function 不属于支持契约,不要依赖。插件只能通过传入的 ctx 使用 NoteGen 能力。