For developers

Remove the toolkit's zotero:// links

Plugins built with zotero-plugin-toolkit 5 or earlier register two zotero:// links when they start, even when the plugin never uses them. Toolkit 6.0.0 removed them. Here's how to drop them from your next release.

What the two links do

  • zotero://plugin installs an add-on from the link, without asking.
  • zotero://ztoolkit-debug runs code from the link, after asking.

Web pages can open zotero:// links. Each link is registered once for the whole Zotero installation, so it takes only one plugin to put it there, and it stays until every plugin that registers it has been updated.

They were never meant for users. The toolkit's author: "This is only for debugging purposes and should never be included in any plugin that is distributed for users" (windingwind/zotero-plugin-toolkit#104). Version 6.0.0 removed the install link and sets the debug link up only when a plugin calls DebugBridge.register().

In toolkit 5, the links are switched on when your plugin builds new ZoteroToolkit() (its Prompt module does it) or reads basicOptions.debug. That's why plugins started from zotero-plugin-template have them.

Which fix is yours

It depends on whether your plugin adds menus with ztoolkit.Menu, which toolkit 6 no longer has. Your plugin's checklist page says which one we'd suggest. We built test plugins both ways and ran our checks on them: neither link is found.

Fix 1

Move to toolkit 6

For plugins that don't use ztoolkit.Menu or ztoolkit.Prompt.

  1. In package.json, set zotero-plugin-toolkit to ^6.0.0 and install.
  2. Import ZoteroToolkit from zotero-plugin-toolkit/ztoolkit. Other modules still come from zotero-plugin-toolkit.
  3. If you started from zotero-plugin-template, delete its example code: src/modules/examples.ts and the calls to it in src/hooks.ts. The examples use ztoolkit.Menu and ztoolkit.Prompt.
  4. Build. TypeScript points out anything else that changed. Lines that set basicOptions.debug can stay; in 6.0.0 they do nothing.
// package.json
"zotero-plugin-toolkit": "^6.0.0"

// src/utils/ztoolkit.ts
import { ZoteroToolkit } from "zotero-plugin-toolkit/ztoolkit";
Fix 2

Stay on toolkit 5, without Prompt

For plugins that add menus with ztoolkit.Menu. Needs toolkit 4.1.1 or later: up to 4.1.0 any toolkit object switches the links on, so update to 5.1.0-beta.13 first (the version the plugin template uses, which still has Menu).

  1. Instead of new ZoteroToolkit(), build a toolkit from the modules you use, leaving out Prompt. The template already has this pattern (MyToolkit in src/utils/ztoolkit.ts).
  2. Remove any line that reads or sets basicOptions.debug, such as disableDebugBridgePassword.
  3. If you started from zotero-plugin-template, delete its Prompt examples (or all of src/modules/examples.ts and its calls in src/hooks.ts).
  4. Build. TypeScript names any module you use but left out.
// src/utils/ztoolkit.ts
import {
  BasicTool,
  MenuManager,
  ProgressWindowHelper,
  UITool,
  makeHelperTool,
  unregister,
} from "zotero-plugin-toolkit";

class MyToolkit extends BasicTool {
  UI = new UITool(this);
  Menu = new MenuManager(this);
  ProgressWindow = makeHelperTool(ProgressWindowHelper, this);
  unregisterAll() {
    unregister(this);
  }
}

function createZToolkit() {
  const _ztoolkit = new MyToolkit(); // was: new ZoteroToolkit()
  initZToolkit(_ztoolkit);
  return _ztoolkit;
}
Every toolkit 5 module and what builds it
UI = new UITool(this);
Menu = new MenuManager(this);
Keyboard = new KeyboardManager(this);
Reader = new ReaderTool(this);
ExtraField = new ExtraFieldTool(this);
FieldHooks = new FieldHookManager(this);
ProgressWindow = makeHelperTool(ProgressWindowHelper, this);
Dialog = makeHelperTool(DialogHelper, this);
Clipboard = makeHelperTool(ClipboardHelper, this);
FilePicker = makeHelperTool(FilePickerHelper, this);
VirtualizedTable = makeHelperTool(VirtualizedTableHelper, this);
Patch = makeHelperTool(PatchHelper, this);
LargePrefObject = makeHelperTool(LargePrefHelper, this);
Guide = makeHelperTool(GuideHelper, this);

Import each class you use from zotero-plugin-toolkit. log, getGlobal and the other basics come with BasicTool.

Moving your menus to something else later lets you take Fix 1, the long-term route.

Check your build

In a Zotero profile with only your plugin installed, open Tools › Developer › Run JavaScript and run:

Object.keys(Services.io.getProtocolHandler("zotero").wrappedJSObject._extensions)
  .filter((k) => k === "zotero://plugin" || k === "zotero://ztoolkit-debug")

An empty list, [], means neither link is registered. With other plugins installed you may still see them; those come from the other plugins.

What happens to your grade

We check new releases every night with the same rules and publish the results the same night. If these links were all that kept your plugin at B, the first release without them is graded A, and you're welcome to show it with the README badge. Your plugin's checklist page, at /developers/<your-plugin>, shows what's left.

Something here wrong for your plugin? Reply on the issue we opened, or respond to your card from the checklist page.