A plugin template for Zotero.
This is a plugin template for Zotero.
๐ Plugin Development Documentation (Chinese, outdated)
๐ Plugin Development Documentation for Zotero 7
๐ ๏ธ Zotero Plugin Toolkit | API Documentation
โน๏ธ Zotero Type Definitions
๐ Zotero Plugin Template (This repo)
[!tip] ๐ Watch this repo so that you can be notified whenever there are fixes & updates.
If you are using this repo, I recommended that you put the following badge on your README:
[![Using Zotero Plugin Template](https://img.shields.io/badge/Using-Zotero%20Plugin%20Template-blue?style=flat-square&logo=github)](https://github.com/windingwind/zotero-plugin-template)
src/modules/examples.ts
, covering most of the commonly used APIs in plugins (using zotero-plugin-toolkit);development
/ production
);[!warning] The localization system is upgraded (
dtd
is deprecated and we do not use.properties
anymore). Only supports Zotero 7.0.0-beta.12 or higher now. If you want to support Zotero 6, you may need to usedtd
,properties
, andftl
at the same time. See the staled branchzotero6-bootstrap
.
This repo provides examples for zotero-plugin-toolkit APIs.
Search @example
in src/examples.ts
. The examples are called in src/hooks.ts
.
See src/modules/preferenceScript.ts
An Obsidian-style prompt(popup command input) module. It accepts text command to run callback, with optional display in the popup.
Activate with Shift+P
.
[!note] This guide assumes that you have an initial understanding of the basic structure and workings of the Zotero plugin. If you don't, please refer to the documentation and official plugin examples Make It Red first.
Click Use this template
Git clone your new repo
GitHub CodeSpace enables you getting started without the need to download code/IDE/dependencies locally.
Replace the steps above and build you first plugin in 30 seconds!
Use this template
, click Open in codespace
. You may need to login to your GitHub account.Enter the repo folder
Modify the settings in ./package.json
, including:
{
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] Be careful to set the addonID and addonRef to avoid conflict.
If you need to host your XPI packages outside of GitHub, remove releasePage
and add updateLink
with the value set to your XPI download URL.
Copy zotero command line config file. Modify the commands that starts your installation of the beta Zotero.
(Optional) Do this only once: Start the beta Zotero with
/path/to/zotero -p
. Create a new profile and use it as your development profile. Put the path of the profile into theprofilePath
inzotero-cmd.json
to specify which profile to use.
cp ./scripts/zotero-cmd-template.json ./scripts/zotero-cmd.json
vim ./scripts/zotero-cmd.json
Install dependencies with npm install
If you are using
pnpm
as the package manager for your project, you need to addpublic-hoist-pattern[]=*@types/bluebird*
to.npmrc
, see https://github.com/windingwind/zotero-types?tab=readme-ov-file#usage.
Start development server with npm start
, it will:
build/
src/**
and addon/**
.
src/**
changed, run esbuild and reloadaddon/**
has changed, rebuild the plugin (in development mode) and reloadTired of endless restarting? Forget about it!
npm start
.When file changes are detected in src
or addon
, the plugin will be automatically compiled and reloaded.
scripts/**.mjs
server
, build
, and stop
commands in package.json
npm install --save-dev chokidar
You can also:
Zotero.debug()
. Find the outputs in Help->Debug Output Logging->View Output;XUL Documentation: http://www.devdoc.net/web/developer.mozilla.org/en-US/docs/XUL.html
Run npm run build
to build the plugin in production mode, and the xpi for installation and the built code is under build
folder.
Steps in scripts/build.mjs
:
build/
.addon/**
to build/addon/**
replace-in-file
to replace keywords and configurations defined in package.json
in non-build files (xhtml
, json
, et al.).**/*.flt
to **/${addonRef}-*.flt
addonRef-
.ts
source code to .js
, build src/index.ts
to ./build/addon/chrome/content/scripts
../build/addon
to ./build/*.xpi
update.json
or update-beta.json
[!note]
What's the difference between dev & prod?
- This environment variable is stored in
Zotero.${addonInstance}.data.env
. The outputs to console is disabled in prod mode.- You can decide what users cannot see/use based on this variable.
- In production mode, the build script will pack the plugin and update the
update.json
.
To build and release, use
# 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] In this template, release-it is configured to locally bump the version, build, and push commits and git.tags, subsequently GitHub Action will rebuild the plugin and publish the XPI to GitHub Release.
If you need to release a locally built XPI, set
release-it.github.release
totrue
inpackage.json
and remove.github/workflows/release.yml
. Besides that, you need to set the environment variableGITHUB_TOKEN
, get it in https://github.com/settings/tokens.
The template defines prerelease
as the beta version of the plugin, when you select a prerelease
version in release-it (with -
in the version number), the build script will create a new update-beta.json
for prerelease use, which ensures that users of the regular version won't be able to update to the beta, only users who have manually downloaded and installed the beta will be able to update to the next beta automatically. When the next regular release is updated, both update.json
and update-beta.json
will be updated so that both regular and beta users can update to the new regular release.
[!warning] Strictly, distinguishing between Zotero 6 and Zotero 7 compatible plugin versions should be done by configuring
applications.zotero.strict_min_version
inaddons.__addonID__.updates[]
ofupdate.json
respectively, so that Zotero recognizes it properly, see https://www.zotero.org/support/dev/zotero_7_for_developers#updaterdf_updatesjson.
See also
src/hooks.ts
bootstrap.js
> startup
is called
index.js
(the main entrance of plugin code, built from index.ts
)index.js
, the plugin object is injected under Zotero
and hooks.ts
> onStartup
is called.
bootstrap.js
> shutdown
is called.
events.ts
> onShutdown
is called. Remove UI elements, preference panes, or anything created by the plugin.See also
src/index.ts
The bootstrapped plugin runs in a sandbox, which does not have default global variables like Zotero
or window
, which we used to have in the overlay plugins' window environment.
This template registers the following variables to the global scope:
Zotero, ZoteroPane, Zotero_Tabs, window, document, rootURI, ztoolkit, addon;
The plugin template provides new APIs for bootstrap plugins. We have two reasons to use these APIs, instead of the createElement/createElementNS
:
createElement
, the plugin template will maintain these elements. Just unregisterAll
at the exit.createXULElement
. The React.createElement-like API createElement
detects namespace(xul/html/svg) and creates elements automatically, with the return element in the corresponding TS element type.createElement(document, "div"); // returns HTMLDivElement
createElement(document, "hbox"); // returns XUL.Box
createElement(document, "button", { namespace: "xul" }); // manually set namespace. returns XUL.Button
Zotero docs are outdated and incomplete. Clone https://github.com/zotero/zotero and search the keyword globally.
โญThe zotero-types provides most frequently used Zotero APIs. It's included in this template by default. Your IDE would provide hint for most of the APIs.
A trick for finding the API you want:
Search the UI label in .xhtml
/.flt
files, find the corresponding key in locale file. Then search this keys in .js
/.jsx
files.
This section shows the directory structure of a template.
.js/.ts
code files are in ./src
;./addon/manifest.json
;./addon/chrome/content/*.xhtml
../addon/locale/**/*.flt
;./addon/prefs.js
;
Don't break the lines in the
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
Use this code under AGPL. No warranties are provided. Keep the laws of your locality in mind!
If you want to change the license, please contact me at [email protected]