Joplin 插件开发脚手架实战:基于 generator-joplin 完成插件的生成、构建与发布

发布时间:2026/9/10 21:23:40
Joplin 插件开发脚手架实战:基于 generator-joplin 完成插件的生成、构建与发布 Joplin 插件开发脚手架实战基于 generator-joplin 完成插件的生成、构建与发布【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplingenerator-joplin 是 Joplin 官方基于 Yeoman 编写的插件脚手架生成器用于在本地快速搭起一个结构规范、可构建、可发布的 Joplin 插件工程。本指南以仓库内置的生成器说明文档为主体结合生成器源码与构建模板系统讲解从安装生成器、交互式创建插件到用 Webpack 产出.jpl安装包、发布到 Joplin 插件仓库以及通过 extraScripts 扩展编译范围的完整工作流。读完你将能独立生成一个插件工程并理解src、api、plugin.config.json、webpack.config.js等关键文件在构建链路中的角色。本文对应文档位于 packages/generator-joplin/generators/app/templates/GENERATOR_DOC.md。该文件会被当作模板写入每个新生成的插件工程而本仓库 packages/app-cli/tests/support/plugins/ai_chat 目录下的同名GENERATOR_DOC.md就是一次真实生成的产物可作为学习参照。generator-joplin 在仓库中的位置与运行机制从源码结构看generator-joplin 本身也是一个 npm 包位于 packages/generator-joplin其核心逻辑在 packages/generator-joplin/generators/app/index.js它是标准yeoman-generator的子类通过prompting()向用户发起交互式提问通过writing()把 templates 目录 下的模板文件复制到目标目录并用用户输入替换占位符支持普通创建new与框架升级--update两种模式两种模式的写入行为不同。所有脚手架模板集中存放在 packages/generator-joplin/generators/app/templates包括package_TEMPLATE.json、tsconfig.json、webpack.config.js、plugin.config.json、src/index.ts、src/manifest.json以及整套api/类型声明文件。快速开始安装与生成一个新插件在开始前需要本机已安装 Node.js 与 npm。随后通过 npm 全局安装 Yeoman 运行时与生成器本身npm install -g yo npm install -g generator-joplin从 generator 的源码看它依赖yeoman-generator包并通过yosay打印欢迎信息因此必须先安装yo这一全局运行环境。然后在准备存放插件代码的目录中执行yo joplin生成器会以交互式问答的方式向你收集插件元信息。对照 packages/generator-joplin/generators/app/index.js 中prompting()定义的问题列表依次需要提供交互问题对应属性说明Plugin IDpluginId全局唯一 ID格式如com.example.MyPlugin或直接使用一个 UUIDPlugin namepluginName展示在 Joplin UI 中的用户友好名称Plugin descriptionpluginDescription插件功能描述AuthorpluginAuthor作者信息Repository URLpluginRepositoryUrl源码仓库地址Homepage URLpluginHomepageUrl主页地址Package namepackageNamenpm 包名默认由插件名推导按源码中packageNameFromPluginName的逻辑生成可直接回车接受默认值也可手动修改回答完问题后生成器就会基于模板输出一整套插件工程。生成后的工程结构三个最核心的文件新生成的工程结构如下其中三个文件决定了插件的行为与元信息. ├── .gitignore / .npmignore ├── README.md ├── GENERATOR_DOC.md ├── package.json ├── tsconfig.json ├── webpack.config.js ├── plugin.config.json ├── api/ # Joplin 插件 API 的 TypeScript 类型声明 ├── script/publish/ # 发布到插件仓库的辅助脚本 └── src/ ├── index.ts # 插件源码入口 └── manifest.json # 插件清单src/index.ts插件源码的入口文件必须调用joplin.plugins.register({ onStart: async () { ... } })完成注册。模板中的默认入口会打印一句Hello world见 packages/generator-joplin/generators/app/templates/src/index.ts。src/manifest.json插件清单包含插件id、version、name、description、author、homepage_url、repository_url等信息。可参考本仓库中的生成产物 packages/app-cli/tests/support/plugins/ai_chat/src/manifest.json其中还包含manifest_version与app_min_version最低兼容的 Joplin 版本字段。plugin.config.json当需要编译“外部脚本”content scripts / webview scripts时使用默认内容为{ extraScripts: [] }具体规则见下文“External script files”一节。此外工程中还包含一套完整的api/类型声明文件如Joplin.d.ts、types.ts等。它们由生成器从模板目录直接复制使你在 TypeScript 中能够以import joplin from api的方式获得完整的类型提示对应的webpack.config.js中配置了alias: { api: ... }将api解析到该目录。生成的插件工程使用 TypeScript 编写。如果你更习惯纯 JavaScript也可以自行调整tsconfig.json与webpack.config.js的编译规则只是 TypeScript 是默认且官方推荐的形态。构建插件Webpack 三步流水线与 JPL 归档插件工程采用 Webpack 构建。按文档说明构建只需要执行npm run distdist脚本在模板的package_TEMPLATE.json中定义为三段串联执行见 packages/generator-joplin/generators/app/templates/package_TEMPLATE.jsondist: webpack --env joplin-plugin-configbuildMain webpack --env joplin-plugin-configbuildExtraScripts webpack --env joplin-plugin-configcreateArchive对照 模板中的 webpack.config.js这三步的真实作用如下buildMain编译主入口src/index.ts并把src中除 TypeScript 文件之外的资源CSS、图片、JSON 等通过copy-webpack-plugin复制到dist/。这一步开始时还会清空并重建dist/与publish/目录。buildExtraScripts逐个编译plugin.config.json中声明的extraScripts。若列表为空则直接跳过本轮。createArchive以dist/index.js为入口触发构建完成回调onBuildCompleted实际由回调执行打包逻辑——用tar把dist/下所有文件打成.jpl归档并写出配套的插件信息.json文件。构建完成后编译产物位于dist/而publish/目录下会出现两个用于发布的关键文件插件ID.jpl即插件安装包本身Joplin 客户端直接安装/加载的就是它插件ID.json插件元信息文件。构建回调会把.jpl的 SHA-256 摘要写入其_publish_hash字段把当前 git 分支与提交号写入_publish_commit字段供后续发布流程校验版本与产物。发布插件提交到 Joplin 插件仓库的三个条件插件本体通过npm publish发布到 npmjs.com 即可。发布后Joplin 侧会有一个自动化脚本拾取你的包并把它加入官方插件仓库前提是工程满足以下条件生成器默认已替你配置好若仓库中迟迟没有出现你的插件请按此排查package.json中的name必须以joplin-plugin-开头例如joplin-plugin-tocpackage.json中的keywords必须包含joplin-pluginpublish/目录下必须同时存在由npm run dist构建产生的.jpl与.json文件。之所以要求满足上述条件从模板 webpack.config.js 的validatePackageJson()函数可以印证它在打包完成时会读取package.json若包名不以joplin-plugin-开头、或keywords缺失joplin-plugin都会输出黄色警告提醒开发者补正后插件才能被官方仓库自动收录。需要说明的是npm publish发布的是 npm 包本身而.jpl/.json等发布产物通过package.json的files: [publish]白名单被打进 npm 包。另外模板package.json还默认带了一个submit脚本tsc --project script/publish/tsconfig.json node ./script/publish/dist/index.js它驱动 script/publish 下的辅助逻辑——从该目录结构verifyGitState.ts、verifyBuild.ts、authenticate.ts、submitPayload.ts可以推断发布辅助脚本会依次校验 git 状态、校验构建产物、完成鉴权并提交 payload 到插件仓库属于面向官方仓库自动化提交流程的可选能力。更新插件框架npm run update 的合并策略当 Joplin 的插件框架或构建工具升级后旧工程可以一键同步新模板npm run update该命令在模板的package.json中被展开为重新安装全局generator-joplin并以 update 模式运行生成器update: npm install -g generator-joplin yo joplin --node-package-manager npm --update --force从 packages/generator-joplin/generators/app/index.js 的writing()分支可以确认 update 模式的细节package.json与.gitignore、.npmignore采取合并而非整体覆盖分别通过mergePackageKey与mergeIgnoreFile实现尽量保留你的个性化配置src/目录src/index.ts、src/manifest.json以及README.md不会被触碰你的插件逻辑与文档保持原样webpack.config.js会被直接整体覆盖这是最容易丢失自定义内容的地方。因此文档给出了一条重要实践如果你确实需要改动webpack.config.js请把自定义逻辑放到一个独立 JS 文件中再在webpack.config.js里require引入它。这样每次执行npm run update后只需恢复那一行引入语句即可改动不会在一次升级中被抹掉。模板 webpack 配置文件头部的注释同样强调了这一点。另外update 模式在开始前会通过yosay确认提示提醒你所有配置文件会被覆盖、请先确认代码处于版本控制之下以便事后比对 diff 并重新应用自己的改动。External script files编译内容脚本与 Webview 脚本默认情况下Webpack 只编译src/index.ts以及它 import 的所有文件src下其余文件会被原样复制进插件包。对多数简单插件这已经足够但遇到两类场景就必须为“外部脚本”单独开启编译脚本本身是 TypeScript 文件——TS 必须先被编译成 JavaScript 才能在 Joplin 运行时中执行脚本require了你在package.json中新增的第三方模块——该脚本无论 JS 还是 TS必须被编译才能把这些依赖一起打包进 JPL 文件否则插件包内引用不到这些模块。启用方式是把脚本路径加入plugin.config.json的extraScripts数组例如希望编译src/webviews/index.ts{ extraScripts: [ webviews/index.ts ] }规则要点数组中的路径以src/为根目录、相对/src书写编译产物统一以.js扩展名命名并输出到插件包因此上例最终得到webviews/index.js在插件代码中引用该脚本时应使用编译后的webviews/index.js路径而不是原始的.ts路径。从模板 webpack.config.js 的buildExtraScriptsConfigs()/resolveExtraScriptPath()实现可以进一步印证webpack 会校验该相对路径在src/下真实存在随后对每个 extra script 生成一个独立的编译配置入口指向./src/路径输出统一为去掉扩展名的.js文件编译完成后的文件会覆盖buildMain阶段原样复制过来的同名 JS从而保证“不需要编译的 JS 直接复制、需要编译的 JS 得到正确产物”。该配置文件还预先声明了一批可被内容脚本以require()/joplin.require()方式直接使用的外部库如codemirror/*、lezer/*等在编译 extra scripts 时以 externals 形式排除避免重复打包。工程内真实样例一个由脚手架支撑的 AI 对话插件本仓库 packages/app-cli/tests/support/plugins/ai_chat 目录可以作为整套脚手架机制的落地范本它拥有与模板一致的结构src/index.tssrc/manifest.json、api/类型目录、plugin.config.json、tsconfig.json、webpack.config.js正是yo joplin产物的形态其package.json以joplin-plugin-ai-chat-demo命名keywords含joplin-plugin满足上文发布条件其src/index.ts演示了插件的典型用法在onStart中通过joplin.commands.register注册命令、用joplin.views.toolbarButtons.create把命令挂到编辑器工具栏再调用joplin.ai.chat()将当前笔记正文发送给用户在设置中配置的 AI 提供方并把摘要回写笔记——完整展示了“脚手架搭框架、API 实现功能”的开发模式。在生成新插件前通读这个目录的 GENERATOR_DOC.md即你在自己工程里也会拿到的那份、webpack.config.js 与 package.json能帮助你快速对齐官方工程的构建与发布约定。许可证说明脚手架默认输出的工程采用 MIT 许可。生成器模板文档末尾标注“MIT © Laurent Cozic”模板的package_TEMPLATE.json中license字段同样为MIT可在发布前根据你的实际情况调整。【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考