Zotero Plugin Template Save

A plugin template for Zotero.

Project README

Zotero Plugin Template

zotero target version Using Zotero Plugin Template

This is a plugin template for Zotero.

English | ็ฎ€ไฝ“ไธญๆ–‡

๐Ÿ“– Plugin Development Documentation (Chinese, outdated)

๐Ÿ“– Plugin Development Documentation for Zotero 7

๐Ÿ› ๏ธ Zotero Plugin Toolkit | API Documentation

โ„น๏ธ Zotero Type Definitions

๐Ÿ“œ Zotero Source Code

๐Ÿ“Œ Zotero Plugin Template (This repo)

[!tip] ๐Ÿ‘ Watch this repo so that you can be notified whenever there are fixes & updates.

Plugins built with this template

GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars

If you are using this repo, I recommended that you put the following badge on your README:

Using Zotero Plugin Template

[![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)

Features

  • Event-driven, functional programming, under extensive skeleton;
  • Simple and user-friendly, works out-of-the-box.
  • โญ [New!] Auto hot reload! Whenever the source code is modified, automatically compile and reload. See hereโ†’
  • Abundant examples in src/modules/examples.ts, covering most of the commonly used APIs in plugins (using zotero-plugin-toolkit);
  • TypeScript support:
    • Full type definition support for the whole Zotero project, which is written in JavaScript (using zotero-types);
    • Global variables and environment setup;
  • Plugin develop/build/release workflow:
    • Automatically generate/update plugin id/version, update configrations, and set environment variables (development / production);
    • Automatically build and reload code in Zotero;
    • Automatically release to GitHub (using release-it);
  • Prettier and ES Lint integration.

[!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 use dtd, properties, and ftl at the same time. See the staled branch zotero6-bootstrap.

Examples

This repo provides examples for zotero-plugin-toolkit APIs.

Search @example in src/examples.ts. The examples are called in src/hooks.ts.

Basic Examples

  • registerNotifier
  • registerPrefs, unregisterPrefs

Shortcut Keys Examples

  • registerShortcuts
  • exampleShortcutLargerCallback
  • exampleShortcutSmallerCallback
  • exampleShortcutConflictionCallback

UI Examples

image

  • registerStyleSheet(the official make-it-red example)
  • registerRightClickMenuItem
  • registerRightClickMenuPopup
  • registerWindowMenuWithSeprator
  • registerExtraColumn
  • registerExtraColumnWithCustomCell
  • registerCustomItemBoxRow
  • registerLibraryTabPanel
  • registerReaderTabPanel

Preference Pane Examples

image

  • Preferences bindings
  • UI Events
  • Table
  • Locale

See src/modules/preferenceScript.ts

HelperExamples

image

  • dialogExample
  • clipboardExample
  • filePickerExample
  • progressWindowExample
  • vtableExample(See Preference Pane Examples)

PromptExamples

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.

image

  • registerAlertPromptExample

Quick Start Guide

0 Requirement

  1. Install a beta version of Zotero: https://www.zotero.org/support/beta_builds
  2. Install Node.js and Git

[!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.

1 Creat Your Repo

  1. Click Use this template

  2. Git clone your new repo

    ๐Ÿ’ก Start with GitHub Codespace

    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!

    • Goto top of the homepage, click the green button Use this template, click Open in codespace. You may need to login to your GitHub account.
    • Wait for codespace to load.
  3. Enter the repo folder

2 Config Template Settings and Enviroment

  1. 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.

  2. 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 the profilePath in zotero-cmd.json to specify which profile to use.

    cp ./scripts/zotero-cmd-template.json ./scripts/zotero-cmd.json
    vim ./scripts/zotero-cmd.json
    
  3. Install dependencies with npm install

    If you are using pnpm as the package manager for your project, you need to add public-hoist-pattern[]=*@types/bluebird* to .npmrc, see https://github.com/windingwind/zotero-types?tab=readme-ov-file#usage.

3 Coding

Start development server with npm start, it will:

  • Prebuild the plugin in development mode
  • Start Zotero with plugin loaded from build/
  • Open devtool
  • Watch src/** and addon/**.
    • If src/** changed, run esbuild and reload
    • If addon/** has changed, rebuild the plugin (in development mode) and reload

Auto Hot Reload

Tired of endless restarting? Forget about it!

  1. Run npm start.
  2. Coding. (Yes, that's all)

When file changes are detected in src or addon, the plugin will be automatically compiled and reloaded.

๐Ÿ’ก Steps to add this feature to an existing plugin
  1. Copy scripts/**.mjs
  2. Copy server, build, and stop commands in package.json
  3. Run npm install --save-dev chokidar
  4. Done.

Debug in Zotero

You can also:

4 Build

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:

  • Create/empty build/.
  • Copy addon/** to build/addon/**
  • Replace placeholders: use replace-in-file to replace keywords and configurations defined in package.json in non-build files (xhtml, json, et al.).
  • Prepare locale files to avoid conflict
    • Rename **/*.flt to **/${addonRef}-*.flt
    • Prefix each fluent message with addonRef-
  • Use Esbuild to build .ts source code to .js, build src/index.ts to ./build/addon/chrome/content/scripts.
  • (Production mode only) Zip the ./build/addon to ./build/*.xpi
  • (Production mode only) Prepare 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.

5 Release

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 to true in package.json and remove .github/workflows/release.yml. Besides that, you need to set the environment variable GITHUB_TOKEN, get it in https://github.com/settings/tokens.

About Prerelease

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 in addons.__addonID__.updates[] of update.json respectively, so that Zotero recognizes it properly, see https://www.zotero.org/support/dev/zotero_7_for_developers#updaterdf_updatesjson.

Details

About Hooks

See also src/hooks.ts

  1. When install/enable/startup triggered from Zotero, bootstrap.js > startup is called
    • Wait for Zotero ready
    • Load index.js (the main entrance of plugin code, built from index.ts)
    • Register resources if Zotero 7+
  2. In the main entrance index.js, the plugin object is injected under Zotero and hooks.ts > onStartup is called.
    • Initialize anything you want, including notify listeners, preference panes, and UI elements.
  3. When uninstall/disabled triggered from Zotero, bootstrap.js > shutdown is called.
    • events.ts > onShutdown is called. Remove UI elements, preference panes, or anything created by the plugin.
    • Remove scripts and release resources.

About Global Variables

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;

Create Elements API

The plugin template provides new APIs for bootstrap plugins. We have two reasons to use these APIs, instead of the createElement/createElementNS:

  • In bootstrap mode, plugins have to clean up all UI elements on exit (disable or uninstall), which is very annoying. Using the createElement, the plugin template will maintain these elements. Just unregisterAll at the exit.
  • Zotero 7 requires createElement()/createElementNS() โ†’ createXULElement() for remaining XUL elements, while Zotero 6 doesn't support 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

About Zotero API

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.

Directory Structure

This section shows the directory structure of a template.

  • All .js/.ts code files are in ./src;
  • Addon config files: ./addon/manifest.json;
  • UI files: ./addon/chrome/content/*.xhtml.
  • Locale files: ./addon/locale/**/*.flt;
  • Preferences file: ./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

Disclaimer

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]

Open Source Agenda is not affiliated with "Zotero Plugin Template" Project. README Source: windingwind/zotero-plugin-template
Stars
366
Open Issues
3
Last Commit
2 weeks ago
License

Open Source Agenda Badge

Open Source Agenda Rating