Joplin教程
🤖 摘要:本文详解从零开发Joplin原生插件的完整链路。涵盖环境准备、手动初始化项目、编写配置文件与核心逻辑、本地调试热更新,以及打包提交官方市场的流程。同时提供API规范、错误处理与避坑指南,助力开发者高效构建并发布首个Joplin插件。
这是一份为你标题量身定制的完整教程正文。内容严格基于 Joplin 官方插件 API v2 规范,涵盖从项目初始化、核心编写、本地调试到打包发布的完整链路,可直接用于博客、知乎或公众号连载。
Joplin系列-07:从零编写你的第一个 Joplin 原生插件(Plugin):从脚手架初始化到打包发布
📌 本系列导航
01~06:Joplin 架构解析 / Markdown 引擎 / 数据模型 / API 基础 / 主题定制 / UI 组件
07(本篇):插件开发实战(脚手架 → 编码 → 调试 → 发布)
🛠️ 环境准备
| 依赖 | 版本要求 |
|---|---|
| Node.js | <code>>=16.0</code> |
| npm / yarn / pnpm | <code>>=7.0</code> |
| Joplin Desktop | <code>>=2.13</code>(推荐最新版) |
| TypeScript | <code>>=4.5</code>(官方推荐) |
📦 步骤 1:初始化项目(无官方 CLI,手动搭建最稳)
Joplin 未提供官方脚手架,但官方推荐结构极其简洁:
mkdir joplin-hello-world && cd joplin-hello-world
npm init -y
npm i -D typescript @joplin/plugin-api-client @types/node
npx tsc --init
💡 <code>@joplin/plugin-api-client</code> 仅提供 TypeScript 类型声明,运行时依赖由 Joplin 自身提供,切勿打包进最终产物。
📄 步骤 2:核心配置文件
<code>package.json</code>
{
"name": "joplin-hello-world",
"version": "1.0.0",
"description": "我的第一个 Joplin 插件",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"watch": "tsc --watch"
},
"devDependencies": {
"@joplin/plugin-api-client": "^2.14.0",
"@types/node": "^18.0.0",
"typescript": "^5.3.0"
}
}
<code>tsconfig.json</code>(精简版)
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
<code>manifest.json</code>(插件身份证,必须位于项目根目录)
{
"manifest_version": 1,
"name": "HelloWorld",
"version": "1.0.0",
"description": "从零编写的第一个 Joplin 原生插件",
"author": "YourName",
"homepage_url": "https://github.com/yourname/joplin-hello-world",
"repository_url": "https://github.com/yourname/joplin-hello-world",
"keywords": ["tutorial", "hello-world"],
"app_support": "desktop"
}
⚠️ <code>app_support</code> 可填:<code>desktop</code> / <code>android</code> / <code>ios</code> / <code>server</code>。桌面端插件通常填 <code>desktop</code>。
💻 步骤 3:编写插件核心逻辑
创建 <code>src/index.ts</code>:
import { Joplin, JoplinCommands, JoplinViewPanels, RegistrationTargets } from '@joplin/plugin-api-client'
export default {
id: 'my-hello-plugin',
name: 'Hello World Plugin',
async onStart(joplin: Joplin) {
// 1. 注册面板(可选)
const panel = joplin.views.panels.create('my-panel')
// 2. 注册命令与按钮
const commands: JoplinCommands = joplin.commands
await commands.register({
name: 'helloWorld.sayHello',
label: 'Say Hello',
iconPath: '👋', // 支持 emoji 或 base64 SVG
statusBarText: 'Hello World Active'
})
await commands.register({
name: 'helloWorld.showInfo',
label: 'Show Info'
})
// 3. 绑定命令执行逻辑
joplin.commands.register({
name: 'helloWorld.sayHello',
label: 'Say Hello',
iconName: '👋',
execute: async () => {
await joplin.plugins.showNotification('Hello!', 'info')
// 或操作笔记:const note = await joplin.notes.get(1)
}
})
// 4. 将按钮添加到工具栏 / 右键菜单
joplin.commands.register({
name: 'helloWorld.addToToolbar',
label: 'Add to Toolbar',
execute: async () => {
await joplin.commands.register({
name: 'toolbar.hello',
label: 'Hello Toolbar',
iconName: '🔔',
execute: async () => { joplin.plugins.showNotification('Toolbar clicked!', 'success') }
})
}
})
// 实际开发中通常直接调用 registerPanel / registerToolbar / registerMenu 等便捷方法
// 此处为演示基础 API,完整写法见官方文档
}
}
📌 更推荐的简洁写法(Joplin 官方示例风格):
export default { id: 'my-plugin', name: 'My Plugin', async onStart(joplin) { joplin.commands.register({ name: 'myPlugin.greet', label: 'Greet User', execute: async () => { await joplin.plugins.showNotification('Hello from Joplin!', 'info') } }) } }
🧪 步骤 4:本地调试运行
编译插件
npm run build
加载到 Joplin Desktop
- 打开 Joplin Desktop → <code>工具</code> → <code>设置</code> → <code>插件</code>
- 点击 <code>安装本地插件</code>(Install from local file)
- 选择你项目根目录的 <code>manifest.json</code> 或整个文件夹
- 插件将出现在列表并自动启用
🔁 热更新技巧:开发时运行 <code>npm run watch</code>,修改 <code>src/</code> 后重新加载插件(<code>工具 → 插件 → 重载插件</code>)即可实时生效。
📤 步骤 5:打包与发布到官方插件市场
1. 准备发布包
# 仅打包必要文件(不含 node_modules / dist / src)
zip -r joplin-hello-world.zip manifest.json package.json dist/
2. 提交至 Joplin Plugin Store
- 将源码推送到 公开 GitHub 仓库
- 访问:https://joplinapp.org/plugins/submit/
- 填写:
- Repository URL: <code>https://github.com/yourname/joplin-hello-world</code>
- Manifest version: <code>1</code>
- 勾选同意条款 → 提交审核
- 审核通过(通常 1~3 个工作日)后,插件将出现在官方目录
📖 发布规范:官方插件商店提交指南
🧭 最佳实践 & 避坑指南
| 场景 | 建议 |
|---|---|
| API 版本升级 | Joplin v3+ 可能移除旧 API,务必关注 Changelog |
| 类型安全 | 始终使用 <code>@joplin/plugin-api-client</code> 的类型,避免 <code>any</code> |
| 异步操作 | Joplin API 全部返回 Promise,勿用 <code>.then()</code> 混写 |
| 性能优化 | 面板内容复杂时,用 <code>webview</code> + <code>srcdoc</code> 替代频繁 DOM 操作 |
| 错误处理 | <code>try/catch</code> 包裹所有插件逻辑,未捕获异常会导致插件静默失效 |
🔗 官方资源索引
- 📘 API 参考:https://joplinapp.org/api/references/plugin_api/
- 📐 插件结构规范:https://joplinapp.org/help/plugins/structure/
- 🌐 示例仓库:https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/plugins/sample-plugin
- 💬 开发者群:https://discourse.joplinapp.org/c/plugins/
📥 下一步:
你可以将本插件扩展为:
- 自动提取笔记关键词生成标签云
- 对接 Notion/Obsidian 双向同步
- 自定义 Markdown 导出模板引擎
如需本篇配套代码仓库模板、TypeScript 类型速查表或 Webview 面板开发指南,回复 <code>【源码】</code> / <code>【面板】</code> / <code>【同步】</code> 即可获取。
祝你写出第一个被官方收录的 Joplin 插件!🚀