Joplin 插件开发脚手架 generator-joplin 完全指南:从 Yeoman 生成到构建、发布与框架升级 Joplin 插件开发脚手架 generator-joplin 完全指南从 Yeoman 生成到构建、发布与框架升级【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin本指南以仓库内 GENERATOR_DOC.md 为骨架结合generator-joplin脚手架的真实源码与editor_context_menu示例插件完整讲解如何用 Yeoman 生成 Joplin 插件工程、理解插件入口与 manifest 结构、用 Webpack 构建 JPL 分发包、配置外部脚本content scripts / webview scripts、发布到官方插件仓库以及安全地升级插件框架。读完本文你将具备从零创建、构建到发布一个 Joplin 插件的完整实战能力并能读懂脚手架内部每个构建阶段的工作原理。一、为什么 Joplin 需要插件脚手架Joplin 是一款注重隐私、支持全平台同步的笔记应用其桌面端与移动端都开放了插件 API。一个 Joplin 插件本质上是一个可被应用加载的 JS 模块由manifest.json声明元数据、由入口文件调用joplin.*API 注册功能。直接手写这套工程需要处理 TypeScript 编译、Webpack 打包、api/类型声明、.jpl归档等大量样板文件因此官方提供了基于 Yeoman 的脚手架工具generator-joplin当前仓库内版本为 3.7.2一条命令即可生成结构完整、开箱可构建的项目模板。本仓库在 packages/app-cli/tests/support/plugins/editor_context_menu/ 下内置了一个由该脚手架生成的示例插件Editor Context Menu Demo演示如何在编辑器右键菜单中加入自定义命令全文将反复以它为实例进行对照讲解。二、安装与生成三步拿到一个可运行的插件工程2.1 安装 Yeoman 与生成器脚手架运行在 Node.js 之上要求先安装 Yeoman 与generator-joplin使用 npm 全局安装即可npm install -g yo npm install -g generator-joplin安装成功后在任意空目录中运行生成命令yo joplin2.2 交互式问答脚手架询问哪些信息执行yo joplin后生成器会以交互式提问的方式收集插件元数据。这些提问定义在 generators/app/index.js 中共 6 个必答问题提问项字段名说明Plugin IDpluginId全局唯一 ID格式如com.example.MyPlugin或直接使用 UUID最终写入 manifest 的id字段Plugin namepluginName展示在界面上的用户友好名称Plugin descriptionpluginDescription插件描述最终写入 manifest 的description字段AuthorpluginAuthor作者名Repository URLpluginRepositoryUrl源码仓库地址Homepage URLpluginHomepageUrl插件主页地址完成上述问答后生成器还会自动推导 npm 包名并询问是否采用默认值见 index.js。默认包名的推导规则实现在 utils.js 的packageNameFromPluginName函数中将* ~ . ( ) ! : [ ]等特殊字符替换为-经slugify转成小写字母去除首尾多余的-强制添加joplin-plugin-前缀如插件名 Editor Context Menu Demo 会得到joplin-plugin-editor-context-menu-demo包名总长度限制在 214 字符以内。2.3 生成结果脚手架写入哪些文件生成器在 writing() 阶段落盘的文件分为两类框架文件每次生成/升级都会写入package.json模板为package_TEMPLATE.json、tsconfig.json、webpack.config.js、plugin.config.json、.gitignore、.npmignore、GENERATOR_DOC.md源码与文档升级时不覆盖src/index.ts、src/manifest.json、README.md另会整体拷贝api/类型声明目录与script/发布脚本目录。其中最关键的两个文件src/index.ts插件源码入口joplin.plugins.register在此被调用src/manifest.json插件清单声明名称、版本、最低应用版本等信息。三、理解插件工程入口、manifest 与一个真实示例3.1 manifest.json插件的身份证以示例插件 src/manifest.json 为例字段含义如下{ id: org.joplinapp.plugins.EditorContextMenuDemo, manifest_version: 1, app_min_version: 1.4, name: Editor Context Menu Demo, description: , version: 1.0.0, author: , homepage_url: }id全局唯一标识构建时会被用来命名.jpl归档与.json信息文件缺失会导致构建失败webpack 配置中readManifest会显式抛错见 webpack.config.jsmanifest_version清单格式版本当前为 1app_min_version支持该插件所需的最低 Joplin 版本name/description/version/author/homepage_url展示与分发元数据还可以通过categories字段声明插件分类但分类名必须是小写且来自webpack.config.js中定义的合法集合appearance、developer tools、productivity、themes、integrations、viewer、search、tags、editor、files、personal knowledge management见 webpack.config.js重复分类或非法分类都会使构建直接报错validateCategories。3.2 src/index.ts入口与插件 API 的最小闭环示例插件的完整入口只有 16 行src/index.ts却演示了 Joplin 插件最核心的三个 API 调用import joplin from api; import { MenuItemLocation } from api/types; joplin.plugins.register({ onStart: async function() { await joplin.commands.register({ name: sayHi, label: Say Hi, execute: async () { await joplin.commands.execute(replaceSelection, hi!); }, }); await joplin.views.menuItems.create(myContextMenuItem, sayHi, MenuItemLocation.EditorContextMenu); }, });joplin.plugins.register({ onStart })注册插件并声明启动回调onStart是插件生命周期的起点joplin.commands.register(...)注册一个名为sayHi的自定义命令execute内通过joplin.commands.execute(replaceSelection, hi!)复用内置命令将当前选中文本替换为hi!joplin.views.menuItems.create(id, commandName, location)把命令挂载到MenuItemLocation.EditorContextMenu编辑器右键菜单这是本示例插件名 Editor Context Menu Demo 的由来。生成的插件工程在api/目录下提供了完整 TypeScript 类型声明Joplin.d.ts、JoplinCommands.d.ts、JoplinViewsMenuItems.d.ts等编辑器可获得完整的智能提示与类型检查。通过joplin命名空间下的各子模块commands、views、settings、data、contentScripts 等插件可以访问笔记数据、注册命令、创建菜单项/工具栏按钮/面板等。四、构建插件Webpack 三阶段流水线4.1 npm run dist 到底做了什么脚手架生成的package.json中构建脚本为模板见 package_TEMPLATE.jsonscripts: { dist: webpack --env joplin-plugin-configbuildMain webpack --env joplin-plugin-configbuildExtraScripts webpack --env joplin-plugin-configcreateArchive, prepare: npm run dist }webpack.config.js通过--joplin-plugin-config参数导出三种配置main() 中的 configs 对象按顺序执行buildMain编译src/index.ts为dist/index.js并把src/下其余非 TypeScript 文件CSS、JSON、图片等静态资源整体拷贝到dist/排除.ts/.tsx因为它们已被编译产出见 pluginConfig 的 CopyPlugin。运行该阶段前会先清空并重建dist/与publish/目录buildExtraScripts编译plugin.config.json中extraScripts声明的外部脚本详见下一节编译产物会覆盖第一步拷贝的同名 JS 文件——需要编译的脚本被正确编译不需要编译的脚本直接拷贝createArchive以dist/index.js为占位入口触发on-build-webpack钩子执行打包与校验详见 4.3。4.2 构建产物dist 与 publishdist/编译后的完整插件内容主入口index.js 静态资源 编译后的外部脚本publish/分发目录包含两个文件manifest.id.jpl用 tar 打包dist/全部内容生成的插件归档createPluginArchive这是 Joplin 应用可直接安装的分发格式manifest.id.json插件信息文件由 manifest 追加_publish_hash.jpl的 SHA-256 摘要格式sha256:hex与_publish_commit当前 git 分支与提交号生成createPluginInfo。4.3 构建期自动校验createArchive完成后会依次执行校验onBuildCompleteddist/为空则直接报错Plugin archive was not created读取package.json检查包名是否以joplin-plugin-开头、keywords 是否包含joplin-plugin缺失仅警告不阻断见 validatePackageJson建议使用prepare脚本而非postinstall以保证发布前构建一定被执行若当前目录不是 git 仓库会友好提示并在插件信息文件中省略 git 信息currentGitInfo。因此本地调试循环非常简单npm run dist→ 在 Joplin 中通过工具 → 选项 → 插件 → 从文件安装选择publish/*.jpl即可加载插件。模板默认使用 TypeScriptts-loader负责编译如需改为纯 JavaScript调整webpack.config.js与tsconfig.json即可。五、外部脚本文件content scripts 与 webview scripts5.1 为什么需要 extraScriptsWebpack 默认只编译src/index.ts及其 import 的模块其他文件只是被原样拷贝。但对于以下两类脚本需要额外的编译步骤GENERATOR_DOC.md 明确列出TypeScript 脚本.ts文件必须被编译为 JavaScript 才能被 Joplin 执行依赖第三方 npm 模块的脚本无论 JS 还是 TS必须打包编译使依赖随 JPL 归档一起分发否则在 Joplin 运行时无法解析这些模块。典型场景即插件 API 中的 joplin.contentScripts注入页面的内容脚本与joplin.views.panels面板的addScriptwebview 脚本。5.2 配置方法在项目根目录的plugin.config.json中声明示例为空数组见 plugin.config.json{ extraScripts: [] }规则如下extraScripts为数组每个元素是一个相对于src/的路径例如src/webviews/index.ts应写为webviews/index.ts编译产物固定为.js扩展名并输出到插件包中即webviews/index.js——在代码中引用外部脚本时必须使用这个编译后的路径。webpack.config.js中resolveExtraScriptPath会按./src/name解析路径webpack.config.js文件不存在会抛错输出文件名会去掉原扩展名并统一为.js同时以 CommonJS 库格式导出libraryTarget: commonjs。若extraScripts为空数组buildExtraScripts阶段无事可做webpack 会直接以退出码 0 结束webpack.config.js。六、发布插件两种路径6.1 传统方式npm publish将插件发布到 npm 后官方脚本会自动将其收录进 Joplin 插件仓库前提是满足三个条件GENERATOR_DOC.md 原文逐条列出package.json中的name以joplin-plugin-开头如joplin-plugin-tocpackage.json中的keywords包含joplin-pluginpublish/目录内存在.jpl与.json文件由npm run dist构建产生。脚手架生成时已自动设置好包名与 keywords并保证publish/目录文件正确因此在package.json的files字段也仅保留publish见示例 package.jsonnpm publish只会把构建产物推送到 npm。若插件迟迟未出现在官方插件库中按上述三个条件逐一排查即可。6.2 新方式npm run submit新版模板还内置了一套自动化提交流程模板见 script/publish/index.ts执行npm run submit会依次完成四个阶段verifyBuild校验元数据与构建产物verifyGitState校验 git 状态要求提交干净、可追溯authenticate通过 GitHub OAuth Device Flow 获取认证令牌依赖octokit/auth-oauth-devicesubmitPayload携带构建元数据、提交哈希与令牌提交发布请求。任一步骤失败都会以非零退出码结束并打印Submission failed错误信息。七、升级插件框架npm run update 的合并策略Joplin 插件 API 与构建工具链持续演进脚手架提供了升级命令GENERATOR_DOC.md 原文npm run update底层实际执行的是模板 package_TEMPLATE.jsonnpm install -g generator-joplin yo joplin --node-package-manager npm --update --force升级时会显示确认提示说明升级将覆盖配置文件不会改动src/内容与 README.mdindex.js。生成器的合并策略由 index.js writing() 与 utils.js 实现package.json智能合并而非覆盖。已有键保留用户值devDependencies一律以框架版本为准覆盖否则依赖无法随框架升级scripts中的dist、prepare、update必须取自框架模板这些脚本不正确会导致插件无法构建keywords确保包含joplin-plugin.gitignore/.npmignore逐行合并去重同时保留用户自定义忽略项mergeIgnoreFilesrc/目录与README.md绝不触碰用户源码安全plugin.config.json当前升级策略是保留现有内容webpack.config.js会被整体覆盖这是唯一容易引发问题的文件。针对webpack.config.js会被覆盖的问题GENERATOR_DOC.md 给出了官方建议不要直接修改webpack.config.js而是新建一个独立 JS 文件并在 webpack.config.js 中 require 引入。这样升级后只需恢复那一行 require 语句即可改动最小化。同理升级前务必保证代码已纳入版本控制以便通过 diff 审查覆盖点并重新应用自定义内容。八、常见问题速查现象原因与处理构建报 Manifest plugin ID is not setsrc/manifest.json缺少id字段补上全局唯一 ID见 webpack.config.js构建报分类非法或重复manifest 的categories必须是小写且属于 11 个合法分类之一且不可重复构建报 dist directory is emptydist/为空导致无法打 JPL 包插件未出现在官方仓库依次检查包名joplin-plugin-前缀、keywords 含joplin-plugin、publish/内有.jpl与.json构建时出现黄色 WARNING多为包名/关键词不符或使用了postinstall脚本属警告不阻断构建但会影响发布非 git 目录构建构建仍成功但插件信息文件不含_publish_commit字段引用外部脚本路径 404确认使用的是编译后的.js路径如webviews/index.js而非源文件.ts路径九、总结generator-joplin把 Joplin 插件从手写样板工程变成了一条命令的工程化流程yo joplin交互式生成项目 → 理解src/index.ts与src/manifest.json双核心 →npm run dist走完 buildMain / buildExtraScripts / createArchive 三阶段产出.jpl分发包 →npm publish或npm run submit进入官方插件库 →npm run update安全升级框架。而 editor_context_menu 示例插件则完整示范了注册命令 挂载到编辑器右键菜单的最小实现可作为任何 Joplin 插件开发的起点模板。后续深入可继续阅读GENERATOR_DOC.md脚手架官方说明、webpack.config.js构建流水线实现、generators/app/index.js生成器交互与文件写入逻辑、api/ 目录完整插件 API 类型声明。【免费下载链接】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),仅供参考