NoteGenNOTEGEN.

开发第一个插件

使用 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.notegenapp.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.ts

plugin.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/package

build 会完成以下工作:

  1. 严格校验 plugin.json
  2. 把源码和依赖构建为单个 UTF-8 JavaScript ESM 入口;
  3. 拒绝残留的静态或动态模块导入;
  4. 复制 manifest 与声明的本地化文件;
  5. 生成精确覆盖载荷的 integrity.json
  6. 原子替换 .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

  1. 在 NoteGen 桌面端打开“设置 → 通用 → 高级”,启用开发者模式;
  2. 打开“设置 → 插件 → 开发者”;
  3. 选择或填写 word-count/.notegen/package 的绝对路径;
  4. 点击“导入”;
  5. 到“已安装”页找到 Word Count,打开开关;
  6. 审核 editor.read 权限说明并确认。

按 Command/Ctrl + Shift + P 打开插件命令面板,搜索并运行“Count selected words”。

NoteGen 会再次验证目录并复制不可变快照,不会直接执行你的源码;开发监听器会检查构建产物的变化。

7. 修改与自动重载

在插件项目运行:

pnpm exec notegen-plugin dev

npm 发布前,使用第 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;否则结果中的 appCompatibilityCheckedfalse

作者应使用 ctx.log.info/warning/error 写入诊断,退出应用前从开发者页导出。限额和数据边界见 功能调用与权限

运行时边界

市场与开发插件不能使用 DOM、windowdocument、全局 fetch、WebSocket、Node.js 内置模块、子进程、原生扩展、Tauri API、SQLite 或原始文件路径。官方插件也遵守相同边界。

evalnew Function 不属于支持契约,不要依赖。插件只能通过传入的 ctx 使用 NoteGen 能力。

下一步