init: bootstrap extension mode
This commit is contained in:
		
							parent
							
								
									9976511dc9
								
							
						
					
					
						commit
						cfd3014559
					
				
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							@ -2,6 +2,12 @@
 | 
			
		||||
 | 
			
		||||
This is an addon/plugin template for [Zotero](https://www.zotero.org/).
 | 
			
		||||
 | 
			
		||||
[Documentation](https://zotero.yuque.com/books/share/8d230829-6004-4934-b4c6-685a7001bfa0/vec88d)(Chinese, provides English translation)
 | 
			
		||||
 | 
			
		||||
> 👍You are currently in `bootstrap` extension mode. To use `overlay` mode, plsase switch to `overlay` branch in git.
 | 
			
		||||
 | 
			
		||||
> ⚠️`overlay` mode will no longer be supported in the coming Zotero 7. Please use the `bootstrap` extension mode instead. See discussion here: https://groups.google.com/g/zotero-dev/c/TT_rcLVpQwg
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
- TypeScript support;
 | 
			
		||||
@ -49,7 +55,7 @@ This section shows the directory structure of a template.
 | 
			
		||||
```shell
 | 
			
		||||
│  .gitignore
 | 
			
		||||
│  .release-it.json # release-it conf
 | 
			
		||||
|  jsconfig.json    # https://code.visualstudio.com/docs/languages/jsconfig#
 | 
			
		||||
|  tsconfig.json    # https://code.visualstudio.com/docs/languages/jsconfig#
 | 
			
		||||
│  build.js         # esbuild
 | 
			
		||||
│  LICENSE
 | 
			
		||||
│  package.json     # npm conf
 | 
			
		||||
@ -61,10 +67,10 @@ This section shows the directory structure of a template.
 | 
			
		||||
├─addon             # addon dir
 | 
			
		||||
│  │  chrome.manifest  #addon conf
 | 
			
		||||
│  │  install.rdf   # addon install conf
 | 
			
		||||
│  │  bootstrap.js  # addon load/unload script, like a main.c
 | 
			
		||||
│  │
 | 
			
		||||
│  └─chrome
 | 
			
		||||
│      ├─content    # UI
 | 
			
		||||
│      │  │  overlay.xul
 | 
			
		||||
│      │  │  preferences.xul
 | 
			
		||||
│      │  │
 | 
			
		||||
│      │  └─scripts
 | 
			
		||||
@ -152,6 +158,8 @@ You can also debug code in these ways:
 | 
			
		||||
Zotero docs are outdated or incomplete. Searching the source code of Zotero is unavoidable.  
 | 
			
		||||
Clone https://github.com/zotero/zotero and search the keyword globally. You can search the UI text in `.xul`/`.dtd` files, and then search the keys of the text value in `.js`/`.xul` files.
 | 
			
		||||
 | 
			
		||||
> ⭐The [zotero-types](https://github.com/windingwind/zotero-types) provides most frequently used Zotero APIs. It's included in this template by default.
 | 
			
		||||
 | 
			
		||||
## Disclaimer
 | 
			
		||||
 | 
			
		||||
Use this code under AGPL. No warranties are provided. Keep the laws of your locality in mind!
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										71
									
								
								addon/bootstrap.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								addon/bootstrap.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
/* Copyright 2012 Will Shanks.
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
/* global Components, Services */
 | 
			
		||||
/* global addon, APP_SHUTDOWN */
 | 
			
		||||
const { classes: Cc, utils: Cu } = Components;
 | 
			
		||||
 | 
			
		||||
Cu.import("resource://gre/modules/Services.jsm");
 | 
			
		||||
 | 
			
		||||
function install(data, reason) {}
 | 
			
		||||
 | 
			
		||||
function startup(data, reason) {
 | 
			
		||||
  // Load the addon to Zotero if window is ready
 | 
			
		||||
  const loadAddon = (window) => {
 | 
			
		||||
    console.log(window);
 | 
			
		||||
    if (window.document.readyState === "complete" && window.Zotero) {
 | 
			
		||||
      Services.scriptloader.loadSubScript(
 | 
			
		||||
        "chrome://__addonRef__/content/scripts/index.js"
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
      window.addEventListener("load", (e) => {
 | 
			
		||||
        if (window.Zotero) {
 | 
			
		||||
          Services.scriptloader.loadSubScript(
 | 
			
		||||
            "chrome://__addonRef__/content/scripts/index.js"
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Listen to windows
 | 
			
		||||
  var WindowListener = {
 | 
			
		||||
    onOpenWindow: function (xulWindow) {
 | 
			
		||||
      loadAddon(
 | 
			
		||||
        xulWindow
 | 
			
		||||
          .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
 | 
			
		||||
          .getInterface(Components.interfaces.nsIDOMWindow)
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
  Services.wm.addListener(WindowListener);
 | 
			
		||||
 | 
			
		||||
  // Scan current windows
 | 
			
		||||
  const windows = Services.wm.getEnumerator("navigator:browser");
 | 
			
		||||
  while (windows.hasMoreElements()) {
 | 
			
		||||
    loadAddon(
 | 
			
		||||
      windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow)
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function shutdown(data, reason) {
 | 
			
		||||
  if (reason === APP_SHUTDOWN) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  var _Zotero = Components.classes["@zotero.org/Zotero;1"].getService(
 | 
			
		||||
    Components.interfaces.nsISupports
 | 
			
		||||
  ).wrappedJSObject;
 | 
			
		||||
  _Zotero.AddonTemplate.events.onUnInit(_Zotero);
 | 
			
		||||
 | 
			
		||||
  Cc["@mozilla.org/intl/stringbundle;1"]
 | 
			
		||||
    .getService(Components.interfaces.nsIStringBundleService)
 | 
			
		||||
    .flushBundles();
 | 
			
		||||
 | 
			
		||||
  Cu.unload("chrome://_addonRef__/scripts/index.js");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function uninstall(data, reason) {}
 | 
			
		||||
@ -2,6 +2,3 @@ content __addonRef__ chrome/content/
 | 
			
		||||
skin __addonRef__ default	chrome/skin/default/__addonRef__/
 | 
			
		||||
locale __addonRef__ en-US chrome/locale/en-US/
 | 
			
		||||
locale __addonRef__ zh-CN chrome/locale/zh-CN/
 | 
			
		||||
 | 
			
		||||
overlay chrome://zotero/content/zoteroPane.xul chrome://__addonRef__/content/overlay.xul
 | 
			
		||||
overlay chrome://zotero/content/preferences/preferences.xul chrome://__addonRef__/content/preferences.xul
 | 
			
		||||
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<?xml-stylesheet href="chrome://__addonRef__/skin/overlay.css" type="text/css"?>
 | 
			
		||||
<!DOCTYPE overlay SYSTEM "chrome://__addonRef__/locale/overlay.dtd">
 | 
			
		||||
 | 
			
		||||
<overlay id="__addonRef__" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 | 
			
		||||
    <script src="chrome://__addonRef__/content/scripts/index.js" />
 | 
			
		||||
    <popup id="zotero-itemmenu">
 | 
			
		||||
        <menuseparator />
 | 
			
		||||
        <menuitem id="zotero-itemmenu-__addonRef__-test" label="&zotero.__addonRef__.itemmenu.test.label;" oncommand="alert('Hello World!')" class="menuitem-iconic" style="list-style-image: url('chrome://__addonRef__/skin/favicon@0.5x.png');" />
 | 
			
		||||
    </popup>
 | 
			
		||||
</overlay>
 | 
			
		||||
@ -1,14 +1,15 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<!DOCTYPE window SYSTEM "chrome://__addonRef__/locale/overlay.dtd">
 | 
			
		||||
<!DOCTYPE prefwindow SYSTEM "chrome://__addonRef__/locale/overlay.dtd">
 | 
			
		||||
 | 
			
		||||
<overlay id="__addonRef__-preferences" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
 | 
			
		||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 | 
			
		||||
<?xml-stylesheet href="chrome://zotero-platform/content/preferences.css"?>
 | 
			
		||||
 | 
			
		||||
  <prefwindow id="zotero-prefs">
 | 
			
		||||
    <prefpane id="zotero-prefpane-__addonRef__" insertafter="zotero-prefpane-advanced" label="__addonName__" image="chrome://__addonRef__/skin/favicon.png" onpaneload="Zotero.AddonTemplate.prefs.initPreferences(window)">
 | 
			
		||||
<prefwindow id="__addonRef__-prefs" title="&zotero.__addonRef__.pref.title;" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 | 
			
		||||
  <script src="chrome://zotero/content/include.js" />
 | 
			
		||||
  <prefpane id=" zotero-prefpane-__addonRef__" insertafter=" zotero-prefpane-advanced" label=" __addonName__" image=" chrome: __addonRef__ skin favicon.png" onpaneload=" Zotero.AddonTemplate.prefs.initPreferences(window)">
 | 
			
		||||
    <preferences id=" zotero-preferences-__addonRef__">
 | 
			
		||||
      <preference id=" pref-__addonRef__-enable" name=" extensions.zotero.__addonRef__.enable" type=" bool" />
 | 
			
		||||
    </preferences>
 | 
			
		||||
    <checkbox id=" zotero-prefpane-__addonRef__-enable" preference=" pref-__addonRef__-enable" label=" &zotero.__addonRef__.pref.enable.label;" />
 | 
			
		||||
  </prefpane>
 | 
			
		||||
</prefwindow>
 | 
			
		||||
</overlay>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 677 B  | 
| 
		 Before Width: | Height: | Size: 836 B After Width: | Height: | Size: 836 B  | 
@ -13,7 +13,10 @@
 | 
			
		||||
        em:description="__description__"
 | 
			
		||||
        em:homepageURL="__homepage__"
 | 
			
		||||
        em:iconURL="chrome://__addonRef__/skin/favicon.png"
 | 
			
		||||
        em:updateURL="__updaterdf__">>
 | 
			
		||||
        em:optionsURL="chrome://__addonRef__/content/preferences.xul"
 | 
			
		||||
        em:updateURL="__updaterdf__"
 | 
			
		||||
        em:multiprocessCompatible="true"
 | 
			
		||||
        em:bootstrap="true">>
 | 
			
		||||
        <em:type>2</em:type>
 | 
			
		||||
        <em:targetApplication RDF:resource="rdf:#$x61SL3"/>
 | 
			
		||||
        <em:targetApplication>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								build.js
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								build.js
									
									
									
									
									
								
							@ -115,6 +115,7 @@ async function main() {
 | 
			
		||||
      path.join(buildDir, "**/*.xul"),
 | 
			
		||||
      path.join(buildDir, "**/*.manifest"),
 | 
			
		||||
      path.join(buildDir, "addon/defaults", "**/*.js"),
 | 
			
		||||
      path.join(buildDir, "addon/bootstrap.js"),
 | 
			
		||||
      "update.rdf",
 | 
			
		||||
    ],
 | 
			
		||||
    from: [
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,6 @@
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "release-it": "^14.14.0",
 | 
			
		||||
    "zotero-types": "^0.0.3"
 | 
			
		||||
    "zotero-types": "^0.0.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -27,30 +27,32 @@ class AddonEvents extends AddonModule {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async onInit() {
 | 
			
		||||
  public async onInit(_Zotero) {
 | 
			
		||||
    // This function is the setup code of the addon
 | 
			
		||||
    Zotero.debug(`${addonName}: init called`);
 | 
			
		||||
    console.log(`${addonName}: init called`);
 | 
			
		||||
    _Zotero.debug(`${addonName}: init called`);
 | 
			
		||||
    // alert(112233);
 | 
			
		||||
 | 
			
		||||
    // Reset prefs
 | 
			
		||||
    this.resetState();
 | 
			
		||||
 | 
			
		||||
    // Register the callback in Zotero as an item observer
 | 
			
		||||
    let notifierID = Zotero.Notifier.registerObserver(this.notifierCallback, [
 | 
			
		||||
    let notifierID = _Zotero.Notifier.registerObserver(this.notifierCallback, [
 | 
			
		||||
      "tab",
 | 
			
		||||
      "item",
 | 
			
		||||
      "file",
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // Unregister callback when the window closes (important to avoid a memory leak)
 | 
			
		||||
    window.addEventListener(
 | 
			
		||||
    _Zotero.getMainWindow().addEventListener(
 | 
			
		||||
      "unload",
 | 
			
		||||
      function (e) {
 | 
			
		||||
        Zotero.Notifier.unregisterObserver(notifierID);
 | 
			
		||||
        _Zotero.Notifier.unregisterObserver(notifierID);
 | 
			
		||||
      },
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    this._Addon.views.initViews();
 | 
			
		||||
    this._Addon.views.initViews(_Zotero);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private resetState(): void {
 | 
			
		||||
@ -65,6 +67,15 @@ class AddonEvents extends AddonModule {
 | 
			
		||||
    //   Zotero.Prefs.set("addonTemplate.testPref", true);
 | 
			
		||||
    // }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onUnInit(_Zotero): void {
 | 
			
		||||
    console.log(`${addonName}: uninit called`);
 | 
			
		||||
    _Zotero.debug(`${addonName}: uninit called`);
 | 
			
		||||
    //  Remove elements and do clean up
 | 
			
		||||
    this._Addon.views.unInitViews(_Zotero);
 | 
			
		||||
    // Remove addon object
 | 
			
		||||
    _Zotero.AddonTemplate = undefined;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonEvents;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								src/index.ts
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/index.ts
									
									
									
									
									
								
							@ -1,11 +1,9 @@
 | 
			
		||||
import { Addon } from "./addon";
 | 
			
		||||
 | 
			
		||||
Zotero.AddonTemplate = new Addon();
 | 
			
		||||
 | 
			
		||||
window.addEventListener(
 | 
			
		||||
  "load",
 | 
			
		||||
  async function (e) {
 | 
			
		||||
    Zotero.AddonTemplate.events.onInit();
 | 
			
		||||
  },
 | 
			
		||||
  false
 | 
			
		||||
);
 | 
			
		||||
var _Zotero = Components.classes["@zotero.org/Zotero;1"].getService(
 | 
			
		||||
  Components.interfaces.nsISupports
 | 
			
		||||
).wrappedJSObject;
 | 
			
		||||
if (!_Zotero.AddonTemplate) {
 | 
			
		||||
  _Zotero.AddonTemplate = new Addon();
 | 
			
		||||
  _Zotero.AddonTemplate.events.onInit(_Zotero);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								src/views.ts
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/views.ts
									
									
									
									
									
								
							@ -16,9 +16,27 @@ class AddonViews extends AddonModule {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public initViews() {
 | 
			
		||||
  public initViews(_Zotero) {
 | 
			
		||||
    // You can init the UI elements that
 | 
			
		||||
    // cannot be initialized with overlay.xul
 | 
			
		||||
    console.log("Initializing UI");
 | 
			
		||||
    const _window: Window = _Zotero.getMainWindow();
 | 
			
		||||
    const menuitem = _window.document.createElement("menuitem");
 | 
			
		||||
    menuitem.id = "zotero-itemmenu-addontemplate-test";
 | 
			
		||||
    menuitem.setAttribute("label", "Addon Template");
 | 
			
		||||
    menuitem.setAttribute("oncommand", "alert('Hello World!')");
 | 
			
		||||
    menuitem.className = "menuitem-iconic";
 | 
			
		||||
    menuitem.style["list-style-image"] =
 | 
			
		||||
      "url('chrome://addontemplate/skin/favicon@0.5x.png')";
 | 
			
		||||
    _window.document.querySelector("#zotero-itemmenu").appendChild(menuitem);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public unInitViews(_Zotero) {
 | 
			
		||||
    console.log("Uninitializing UI");
 | 
			
		||||
    const _window: Window = _Zotero.getMainWindow();
 | 
			
		||||
    _window.document
 | 
			
		||||
      .querySelector("#zotero-itemmenu-addontemplate-test")
 | 
			
		||||
      ?.remove();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public showProgressWindow(
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
                <em:id>zotero@chnm.gmu.edu</em:id>
 | 
			
		||||
                <em:minVersion>5.0</em:minVersion>
 | 
			
		||||
                <em:maxVersion>*</em:maxVersion>
 | 
			
		||||
                <em:updateLink>__releasepage__</em:updateLink>
 | 
			
		||||
                <em:updateLink>https://github.com/windingwind/zotero-addon-template/releases/latest/download/zotero-addon-template.xpi</em:updateLink>
 | 
			
		||||
              </rdf:Description>
 | 
			
		||||
            </em:targetApplication>
 | 
			
		||||
            <em:targetApplication>
 | 
			
		||||
@ -19,7 +19,7 @@
 | 
			
		||||
                <em:id>juris-m@juris-m.github.io</em:id>
 | 
			
		||||
                <em:minVersion>5.0</em:minVersion>
 | 
			
		||||
                <em:maxVersion>*</em:maxVersion>
 | 
			
		||||
                <em:updateLink>__releasepage__</em:updateLink>
 | 
			
		||||
                <em:updateLink>https://github.com/windingwind/zotero-addon-template/releases/latest/download/zotero-addon-template.xpi</em:updateLink>
 | 
			
		||||
              </rdf:Description>
 | 
			
		||||
            </em:targetApplication>
 | 
			
		||||
          </rdf:Description>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user