20 KiB
Zotero Plugin Template
这是 Zotero 的插件模板.
📖 插件开发文档 (中文版,已过时)
🛠️ Zotero 插件工具包 | API 文档
ℹ️ Zotero 类型定义
📌 Zotero 插件模板 (即本仓库)
Tip
👁 Watch 本仓库,以及时收到修复或更新的通知.
使用此模板构建的插件
如果你正在使用此库,我建议你将这个标志 () 放在 README 文件中:
[](https://github.com/windingwind/zotero-plugin-template)
Features 特性
- 事件驱动、函数式编程的可扩展框架;
- 简单易用,开箱即用;
- ⭐[新特性!]自动热重载!每当修改源码时,都会自动编译并重新加载插件;详情请跳转→
src/modules/examples.ts
中有丰富的示例,涵盖了插件中常用的大部分API (使用的插件工具包 zotero-plugin-toolkit,仓库地址 https://github.com/windingwind/zotero-plugin-toolkit);- TypeScript 支持:
- 为使用 JavaScript 编写的Zotero源码提供全面的类型定义支持 (使用类型定义包 zotero-types,仓库地址 https://github.com/windingwind/zotero-types);
- 全局变量和环境设置;
- 插件开发/构建/发布工作流:
- 自动生成/更新插件id和版本、更新配置和设置环境变量 (
development
/production
); - 自动在 Zotero 中构建和重新加载代码;
- 自动发布到GitHub (使用release-it);
- 自动生成/更新插件id和版本、更新配置和设置环境变量 (
- 集成Prettier和ES Lint;
Warning
Zotero本地化已升级(
dtd
已弃用,我们将不再使用.properties
). 主分支将只支持 Zotero 7.0.0-beta.12 或更高版本. 如果需要支持 Zotero 6,你可能需要同时使用dtd
、properties
和ftl
. 请参考此库的zotero6-bootstrap
分支.
Examples 示例
此库提供了 zotero-plugin-toolkit 中API的示例.
在 src/examples.ts
中搜索@example
查看示例. 这些示例在 src/hooks.ts
中调用演示.
基本示例(Basic Examples)
- registerNotifier
- registerPrefs, unregisterPrefs
快捷键示例(Shortcut Keys Examples)
- registerShortcuts
- exampleShortcutLargerCallback
- exampleShortcutSmallerCallback
- exampleShortcutConflictionCallback
UI示例(UI Examples)
- registerStyleSheet(the official make-it-red example)
- registerRightClickMenuItem
- registerRightClickMenuPopup
- registerWindowMenuWithSeprator
- registerExtraColumn
- registerExtraColumnWithCustomCell
- registerCustomItemBoxRow
- registerLibraryTabPanel
- registerReaderTabPanel
首选项面板示例(Preference Pane Examples)
- Preferences bindings
- UI Events
- Table
- Locale
详情参见 src/modules/preferenceScript.ts
帮助示例(HelperExamples)
- dialogExample
- clipboardExample
- filePickerExample
- progressWindowExample
- vtableExample(See Preference Pane Examples)
指令行示例(PromptExamples)
Obsidian风格的指令输入模块,它通过接受文本来运行插件,并在弹出窗口中显示可选项.
使用 Shift+P
激活.
- registerAlertPromptExample
Quick Start Guide 快速入门指南
0 前置要求(Requirement)
- 安装测试版 Zotero:https://www.zotero.org/support/beta_builds
- 安装 Node.js(https://nodejs.org/en/)和 Git(https://git-scm.com/)
Note
本指南假定你已经对 Zotero 插件的基本结构和工作原理有初步的了解. 如果你还不了解,请先参考官方文档(https://www.zotero.org/support/dev/zotero_7_for_developers)和官方插件样例 Make It Red(仓库地址 https://github.com/zotero/make-it-red).
1 创建你的仓库(Create Your Repo)
-
点击
Use this template
; -
使用
git clone
克隆上一步生成的仓库;💡 从 GitHub Codespace 开始
GitHub CodeSpace 使你可以直接开始开发而无需在本地下载代码/IDE/依赖.
重复下列步骤,仅需三十秒即可开始构建你的第一个插件!
- 去 homepage顶部,点击绿色按钮
Use this template
,点击Open in codespace
, 你需要登录你的GitHub账号. - 等待 codespace 加载.
- 去 homepage顶部,点击绿色按钮
-
进入项目文件夹;
2 配置模板和开发环境(Config Template Settings and Enviroment)
-
修改
./package.json
中的设置,包括:{ version: "", // to 0.0.0 author: "", description: "", homepage: "", config: { addonName: "", // name to be displayed in the plugin manager addonID: "", // ID to avoid conflict. IMPORTANT! addonRef: "", // e.g. Element ID prefix addonInstance: "", // the plugin's root instance: Zotero.${addonInstance} prefsPrefix: "extensions.zotero.${addonRef}", // the prefix of prefs releasePage: "", // URL to releases updateJSON: "", // URL to update.json }, }
Warning
注意设置 addonID 和 addonRef 以避免冲突.
如果你需要在GitHub以外的地方托管你的 XPI 包,请删除 releasePage
并添加 updateLink
,并将值设置为你的 XPI 下载地址.
-
复制 Zotero 启动配置,填入 Zotero 可执行文件路径和 profile 路径.
(可选项) 此操作仅需执行一次: 使用
/path/to/zotero -p
启动 Zotero,创建一个新的配置文件并用作开发配置文件. 将配置文件的路径profilePath
放入zotero-cmd.json
中,以指定要使用的配置文件.cp ./scripts/zotero-cmd-template.json ./scripts/zotero-cmd.json vim ./scripts/zotero-cmd.json
-
运行
npm install
以安装相关依赖如果你使用
pnpm
作为包管理器,你需要添加public-hoist-pattern[]=*@types/bluebird*
到.npmrc
, 详情请查看 zotero-types(https://github.com/windingwind/zotero-types?tab=readme-ov-file#usage)的文档.
3 开始开发(Coding)
使用 npm start
启动开发服务器,它将:
- 在开发模式下预构建插件
- 启动 Zotero ,并让其从
build/
中加载插件 - 打开开发者工具(devtool)
- 监听
src/**
和addon/**
.- 如果
src/**
修改了,运行 esbuild 并且重新加载 - 如果
addon/**
修改了,(在开发模式下)重新构建插件并且重新加载
- 如果
自动热重载
厌倦了无休止的重启吗?忘掉它,拥抱热加载!
- 运行
npm start
. - 编码. (是的,就这么简单)
当检测到 src
或 addon
中的文件修改时,插件将自动编译并重新加载.
💡 将此功能添加到现有插件的步骤
- 复制
scripts/**.mjs
- 复制
server
、build
和stop
命令到package.json
- 运行
npm install --save-dev chokidar
- 结束.
在 Zotero 中 Debug
你还可以:
-
在 Tools->Developer->Run Javascript 中测试代码片段;
-
使用
Zotero.debug()
调试输出. 在 Help->Debug Output Logging->View Output 查看输出; -
调试 UI. Zotero 建立在 Firefox XUL 框架之上. 使用 XUL Explorer 等软件调试 XUL UI.
XUL 文档: http://www.devdoc.net/web/developer.mozilla.org/en-US/docs/XUL.html
4 构建(Build)
运行 npm run build
在生产模式下构建插件,构建的结果位于 build/
目录中.
scripts/build.mjs
的运行步骤:
- 创建/清空
build/
- 复制
addon/**
到build/addon/**
- 替换占位符:使用
replace-in-file
去替换在package.json
中定义的关键字和配置 (xhtml
、.flt
等) - 准备本地化文件以避免冲突,查看官方文档了解更多(https://www.zotero.org/support/dev/zotero_7_for_developers#avoiding_localization_conflicts)
- 重命名
**/*.flt
为**/${addonRef}-*.flt
- 在每个消息前加上
addonRef-
- 重命名
- 使用 Esbuild 来将
.ts
源码构建为.js
,从src/index.ts
构建到./build/addon/chrome/content/scripts
- (仅在生产模式下工作) 压缩
./build/addon
目录为./build/*.xpi
- (仅在生产模式下工作) 准备
update.json
或update-beta.json
Note
Dev & prod 两者有什么区别?
- 此环境变量存储在
Zotero.${addonInstance}.data.env
中,控制台输出在生产模式下被禁用.- 你可以根据此变量决定用户无法查看/使用的内容.
- 在生产模式下,构建脚本将自动打包插件并更新
update.json
.
5 发布(Release)
如果要构建和发布插件,运行如下指令:
# A release-it command: version increase, npm run build, git push, and GitHub release
# release-it: https://github.com/release-it/release-it
npm run release
Note
在此模板中,release-it 被配置为在本地升级版本、构建、推送提交和 git 标签,随后GitHub Action 将重新构建插件并将 XPI 发布到 GitHub Release.
如果你需要发布一个本地构建的 XPI,将
package.json
中的release-it.github.release
设置为true
,然后移除.github/workflows/release.yml
. 此外,你还需要设置环境变量GITHUB_TOKEN
,获取 GitHub Token(https://github.com/settings/tokens).
关于预发布
该模板将 prerelease
定义为插件的测试版,当你在 release-it 中选择 prerelease
版本 (版本号中带有 -
),构建脚本将创建一个 update-beta.json
给预发布版本使用,这将确保常规版本的用户不会自动更新到测试版,只有手动下载并安装了测试版的用户才能自动更新到下一个测试版. 当下一个正式版本更新时,脚本将同步更新 update.json
和 update-beta.json
,这将使正式版和测试版用户都可以更新到最新的正式版.
Warning
严格来说,区分 Zotero 6 和 Zotero 7 兼容的插件版本应该通过
update.json
的addons.__addonID__.updates[]
中分别配置applications.zotero.strict_min_version
,这样 Zotero 才能正确识别,详情在 Zotero 7 开发文档(https://www.zotero.org/support/dev/zotero_7_for_developers#updaterdf_updatesjson)获取.
Details 更多细节
关于Hooks(About Hooks)
可以在
src/hooks.ts
中查看更多
- 当在 Zotero 中触发安装/启用/启动时,
bootstrap.js
>startup
被调用- 等待 Zotero 就绪
- 加载
index.js
(插件代码的主入口,从index.ts
中构建) - 如果是 Zotero 7 以上的版本则注册资源
- 主入口
index.js
中,插件对象被注入到Zotero
,并且hooks.ts
>onStartup
被调用.- 初始化插件需要的资源,包括通知监听器、首选项面板和UI元素.
- 当在 Zotero 中触发卸载/禁用时,
bootstrap.js
>shutdown
被调用.events.ts
>onShutdown
被调用. 移除 UI 元素、首选项面板或插件创建的任何内容.- 移除脚本并释放资源.
关于全局变量(About Global Variables)
可以在
src/index.ts
中查看更多
bootstrap插件在沙盒中运行,但沙盒中没有默认的全局变量,例如 Zotero
或 window
等我们曾在overlay插件环境中使用的变量.
此模板将以下变量注册到全局范围:
Zotero, ZoteroPane, Zotero_Tabs, window, document, rootURI, ztoolkit, addon;
创建元素 API(Create Elements API)
插件模板为 bootstrap 插件提供了一些新的API. 我们有两个原因使用这些 API,而不是使用 createElement/createElementNS
:
- 在 bootstrap 模式下,插件必须在推出(禁用或卸载)时清理所有 UI 元素,这非常麻烦. 使用
createElement
,插件模板将维护这些元素. 仅仅在退出时unregisterAll
. - Zotero 7 需要 createElement()/createElementNS() → createXULElement() 来表示其他的 XUL 元素,而 Zotero 6 并不支持
createXULElement
. 类似于 React.createElement 的APIcreateElement
检测 namespace(xul/html/svg) 并且自动创建元素,返回元素为对应的 TypeScript 元素类型.
createElement(document, "div"); // returns HTMLDivElement
createElement(document, "hbox"); // returns XUL.Box
createElement(document, "button", { namespace: "xul" }); // manually set namespace. returns XUL.Button
关于 Zotero API(About Zotero API)
Zotero 文档已过时且不完整,克隆 https://github.com/zotero/zotero 并全局搜索关键字.
⭐zotero-types 提供了最常用的 Zotero API,在默认情况下它被包含在此模板中. 你的 IDE 将为大多数的 API 提供提醒.
猜你需要:查找所需 API的技巧
在 .xhtml
/.flt
文件中搜索 UI 标签,然后在 locale 文件中找到对应的键. ,然后在 .js
/.jsx
文件中搜索此键.
目录结构(Directory Structure)
本部分展示了模板的目录结构.
- 所有的
.js/.ts
代码都在./src
; - 插件配置文件:
./addon/manifest.json
; - UI 文件:
./addon/chrome/content/*.xhtml
. - 区域设置文件:
./addon/locale/**/*.flt
; - 首选项文件:
./addon/prefs.js
;不要在
prefs.js
中换行
.
|-- .eslintrc.json # eslint conf
|-- .gitattributes # git conf
|-- .github/ # github conf
|-- .gitignore # git conf
|-- .prettierrc # prettier conf
|-- .release-it.json # release-it conf
|-- .vscode # vs code conf
| |-- extensions.json
| |-- launch.json
| |-- setting.json
| `-- toolkit.code-snippets
|-- package-lock.json # npm conf
|-- package.json # npm conf
|-- LICENSE
|-- README.md
|-- addon
| |-- bootstrap.js # addon load/unload script, like a main.c
| |-- chrome
| | `-- content
| | |-- icons/
| | |-- preferences.xhtml # preference panel
| | `-- zoteroPane.css
| |-- locale # locale
| | |-- en-US
| | | |-- addon.ftl
| | | `-- preferences.ftl
| | `-- zh-CN
| | |-- addon.ftl
| | `-- preferences.ftl
| |-- manifest.json # addon config
| `-- prefs.js
|-- build/ # build dir
|-- scripts # scripts for dev
| |-- build.mjs # script to build plugin
| |-- scripts.mjs # scripts send to Zotero, such as reload, openDevTool, etc
| |-- server.mjs # script to start a development server
| |-- start.mjs # script to start Zotero process
| |-- stop.mjs # script to kill Zotero process
| |-- utils.mjs # utils functions for dev scripts
| |-- update-template.json # template of `update.json`
| `-- zotero-cmd-template.json # template of local env
|-- src # source code
| |-- addon.ts # base class
| |-- hooks.ts # lifecycle hooks
| |-- index.ts # main entry
| |-- modules # sub modules
| | |-- examples.ts
| | `-- preferenceScript.ts
| `-- utils # utilities
| |-- locale.ts
| |-- prefs.ts
| |-- wait.ts
| `-- window.ts
|-- tsconfig.json # https://code.visualstudio.com/docs/languages/jsconfig
|-- typings # ts typings
| `-- global.d.ts
`-- update.json
Disclaimer 免责声明
在 AGPL 下使用此代码. 不提供任何保证. 遵守你所在地区的法律!
如果你想更改许可,请通过 wyzlshx@foxmail.com 与我联系.