add: build environment (dev/prod)
change: locale filename
This commit is contained in:
		
							parent
							
								
									7e993e4c55
								
							
						
					
					
						commit
						3d1cf9ded3
					
				
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
									
									
									
									
								
							@ -13,6 +13,7 @@ This is an addon/plugin template for [Zotero](https://www.zotero.org/).
 | 
			
		||||
- TypeScript support;
 | 
			
		||||
- Build addon settings and versions automatically;
 | 
			
		||||
- Build and reload code in Zotero automatically;
 | 
			
		||||
- Development/production build environment;
 | 
			
		||||
- Release to GitHub automatically(using [release-it](https://github.com/release-it/release-it));
 | 
			
		||||
- Extensive skeleton;
 | 
			
		||||
- Some sample code of UI and lifecycle.
 | 
			
		||||
@ -42,9 +43,13 @@ This is an addon/plugin template for [Zotero](https://www.zotero.org/).
 | 
			
		||||
> Be careful to set the addonID and addonRef to avoid confliction.
 | 
			
		||||
 | 
			
		||||
- Run `npm install` to set up the plugin and install dependencies. If you don't have NodeJS installed, please download it [here](https://nodejs.org/en/);
 | 
			
		||||
- Run `npm run build` to build the plugin. The xpi for installation and the built code is under builds folder.
 | 
			
		||||
- Run `npm run build` to build the plugin in production mode. Run `npm run build-dev` to build the plugin in development mode. The xpi for installation and the built code is under builds folder.
 | 
			
		||||
 | 
			
		||||
### Plugin Life Cycle
 | 
			
		||||
> What the difference between dev & prod?
 | 
			
		||||
> - This environment variable is stored in `Zotero.AddonTemplate.env`. The outputs to console is disabled in prod mode.
 | 
			
		||||
> - You can decide what users cannot see/use based on this variable.
 | 
			
		||||
 | 
			
		||||
### About Life Cycle
 | 
			
		||||
 | 
			
		||||
1. When install/enable/startup triggered from Zotero, `bootstrap.js` > `startup` is called
 | 
			
		||||
   - Wait for Zotero ready
 | 
			
		||||
@ -182,11 +187,11 @@ This section shows the directory structure of a template.
 | 
			
		||||
│      └─locale     # locale
 | 
			
		||||
│         ├─en-US
 | 
			
		||||
│         │      overlay.dtd
 | 
			
		||||
│         │      addontemplate.properties
 | 
			
		||||
│         │      addon.properties
 | 
			
		||||
│         │
 | 
			
		||||
│         └─zh-CN
 | 
			
		||||
│         |      overlay.dtd
 | 
			
		||||
│         │      addontemplate.properties
 | 
			
		||||
│         │      addon.properties
 | 
			
		||||
│
 | 
			
		||||
├─builds            # build dir
 | 
			
		||||
│  └─.xpi
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								build.js
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								build.js
									
									
									
									
									
								
							@ -85,7 +85,9 @@ async function main() {
 | 
			
		||||
  const buildDir = "builds";
 | 
			
		||||
 | 
			
		||||
  console.log(
 | 
			
		||||
    `[Build] BUILD_DIR=${buildDir}, VERSION=${version}, BUILD_TIME=${buildTime}`
 | 
			
		||||
    `[Build] BUILD_DIR=${buildDir}, VERSION=${version}, BUILD_TIME=${buildTime}, ENV=${[
 | 
			
		||||
      process.env.NODE_ENV,
 | 
			
		||||
    ]}`
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  clearFolder(buildDir);
 | 
			
		||||
@ -98,6 +100,9 @@ async function main() {
 | 
			
		||||
  await esbuild
 | 
			
		||||
    .build({
 | 
			
		||||
      entryPoints: ["src/index.ts"],
 | 
			
		||||
      define: {
 | 
			
		||||
        __env__: process.env.NODE_ENV,
 | 
			
		||||
      },
 | 
			
		||||
      bundle: true,
 | 
			
		||||
      // Entry should be the same as addon/chrome/content/overlay.xul
 | 
			
		||||
      outfile: path.join(buildDir, "addon/chrome/content/scripts/index.js"),
 | 
			
		||||
@ -156,6 +161,17 @@ async function main() {
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  // _ = replace.sync({
 | 
			
		||||
  //   files: [path.join(buildDir, "addon/chrome/content/scripts/index.js")],
 | 
			
		||||
  //   from: [/__env__/g]
 | 
			
		||||
  // });
 | 
			
		||||
  // console.log(
 | 
			
		||||
  //   "[Build] Run replace in ",
 | 
			
		||||
  //   _.filter((f) => f.hasChanged).map(
 | 
			
		||||
  //     (f) => `${f.file} : ${f.numReplacements} / ${f.numMatches}`
 | 
			
		||||
  //   )
 | 
			
		||||
  // );
 | 
			
		||||
 | 
			
		||||
  console.log("[Build] Replace OK");
 | 
			
		||||
 | 
			
		||||
  console.log("[Build] Addon prepare OK");
 | 
			
		||||
 | 
			
		||||
@ -11,10 +11,11 @@
 | 
			
		||||
  },
 | 
			
		||||
  "main": "src/index.ts",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "node build.js",
 | 
			
		||||
    "build-dev": "cross-env NODE_ENV=development node build.js",
 | 
			
		||||
    "build": "cross-env NODE_ENV=production node build.js",
 | 
			
		||||
    "start": "node start.js",
 | 
			
		||||
    "stop": "node stop.js",
 | 
			
		||||
    "prerestart": "npm run build",
 | 
			
		||||
    "prerestart": "npm run build-dev",
 | 
			
		||||
    "restart": "node restart.js",
 | 
			
		||||
    "release": "release-it",
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
			
		||||
@ -30,11 +31,12 @@
 | 
			
		||||
  },
 | 
			
		||||
  "homepage": "https://github.com/windingwind/zotero-addon-template#readme",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "zotero-plugin-toolkit": "^0.0.9"
 | 
			
		||||
    "zotero-plugin-toolkit": "^0.0.10"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/node": "^18.11.17",
 | 
			
		||||
    "compressing": "^1.6.3",
 | 
			
		||||
    "cross-env": "^7.0.3",
 | 
			
		||||
    "esbuild": "^0.16.10",
 | 
			
		||||
    "release-it": "^14.14.3",
 | 
			
		||||
    "replace-in-file": "^6.3.5",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								src/addon.ts
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/addon.ts
									
									
									
									
									
								
							@ -4,17 +4,24 @@ import AddonViews from "./views";
 | 
			
		||||
import AddonLocale from "./locale";
 | 
			
		||||
 | 
			
		||||
import ZoteroToolkit from "zotero-plugin-toolkit";
 | 
			
		||||
import Locale from "./locale";
 | 
			
		||||
 | 
			
		||||
class Addon {
 | 
			
		||||
  // A global Zotero instance
 | 
			
		||||
  public Zotero!: _ZoteroConstructable;
 | 
			
		||||
  public events: AddonEvents;
 | 
			
		||||
  public views: AddonViews;
 | 
			
		||||
  public prefs: AddonPrefs;
 | 
			
		||||
  public locale: AddonLocale;
 | 
			
		||||
  public toolkit: ZoteroToolkit;
 | 
			
		||||
  // root path to access the resources
 | 
			
		||||
  // Root path to access the resources
 | 
			
		||||
  public rootURI!: string;
 | 
			
		||||
  // Env type, see build.js
 | 
			
		||||
  public env!: "development" | "production";
 | 
			
		||||
  // Lifecycle events
 | 
			
		||||
  public events: AddonEvents;
 | 
			
		||||
  // UI operations
 | 
			
		||||
  public views: AddonViews;
 | 
			
		||||
  // Scripts for prefpane window
 | 
			
		||||
  public prefs: AddonPrefs;
 | 
			
		||||
  // Runtime locale with .properties
 | 
			
		||||
  public locale: AddonLocale;
 | 
			
		||||
  // A toolkit instance. See zotero-plugin-toolkit
 | 
			
		||||
  public toolkit: ZoteroToolkit;
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.events = new AddonEvents(this);
 | 
			
		||||
 | 
			
		||||
@ -3,10 +3,46 @@ import AddonModule from "./module";
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
class AddonEvents extends AddonModule {
 | 
			
		||||
  private notifierCallback: any;
 | 
			
		||||
  constructor(parent: Addon) {
 | 
			
		||||
    super(parent);
 | 
			
		||||
    this.notifierCallback = {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // This function is the setup code of the addon
 | 
			
		||||
  public async onInit() {
 | 
			
		||||
    this._Addon.Zotero = Zotero;
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    this._Addon.rootURI = rootURI;
 | 
			
		||||
    const development = "development";
 | 
			
		||||
    const production = "production";
 | 
			
		||||
    // The env will be replaced after esbuild
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    this._Addon.env = __env__;
 | 
			
		||||
    this._Addon.toolkit.Tool.logOptionsGlobal.prefix = `[${config.addonName}]`;
 | 
			
		||||
    this._Addon.toolkit.Tool.logOptionsGlobal.disableConsole =
 | 
			
		||||
      this._Addon.env === "production";
 | 
			
		||||
    this._Addon.toolkit.Tool.log("init called");
 | 
			
		||||
 | 
			
		||||
    // Initialize locale provider
 | 
			
		||||
    this._Addon.locale.initLocale();
 | 
			
		||||
    // Initialize preference window
 | 
			
		||||
    this.initPrefs();
 | 
			
		||||
    // Initialize notifier callback
 | 
			
		||||
    this.initNotifier();
 | 
			
		||||
    // Initialize UI elements
 | 
			
		||||
    this._Addon.views.initViews();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onUnInit(): void {
 | 
			
		||||
    this._Addon.toolkit.Tool.log("uninit called");
 | 
			
		||||
    this.unInitPrefs();
 | 
			
		||||
    //  Remove elements and do clean up
 | 
			
		||||
    this._Addon.views.unInitViews();
 | 
			
		||||
    // Remove addon object
 | 
			
		||||
    Zotero.AddonTemplate = undefined;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private initNotifier() {
 | 
			
		||||
    const callback = {
 | 
			
		||||
      notify: async (
 | 
			
		||||
        event: string,
 | 
			
		||||
        type: string,
 | 
			
		||||
@ -26,17 +62,9 @@ class AddonEvents extends AddonModule {
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async onInit() {
 | 
			
		||||
    this._Addon.Zotero = Zotero;
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    this._Addon.rootURI = rootURI;
 | 
			
		||||
    // This function is the setup code of the addon
 | 
			
		||||
    this._Addon.toolkit.Tool.log(`${config.addonName}: init called`);
 | 
			
		||||
 | 
			
		||||
    // Register the callback in Zotero as an item observer
 | 
			
		||||
    let notifierID = Zotero.Notifier.registerObserver(this.notifierCallback, [
 | 
			
		||||
    let notifierID = Zotero.Notifier.registerObserver(callback, [
 | 
			
		||||
      "tab",
 | 
			
		||||
      "item",
 | 
			
		||||
      "file",
 | 
			
		||||
@ -50,14 +78,9 @@ class AddonEvents extends AddonModule {
 | 
			
		||||
      },
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Initialize preference window
 | 
			
		||||
    this.initPrefs();
 | 
			
		||||
    this._Addon.views.initViews();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public initPrefs() {
 | 
			
		||||
    this._Addon.toolkit.Tool.log(this._Addon.rootURI);
 | 
			
		||||
  private initPrefs() {
 | 
			
		||||
    const prefOptions = {
 | 
			
		||||
      pluginID: config.addonID,
 | 
			
		||||
      src: this._Addon.rootURI + "chrome/content/preferences.xhtml",
 | 
			
		||||
@ -81,16 +104,6 @@ class AddonEvents extends AddonModule {
 | 
			
		||||
      this._Addon.toolkit.Compat.unregisterPrefPane();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onUnInit(): void {
 | 
			
		||||
    const Zotero = this._Addon.Zotero;
 | 
			
		||||
    this._Addon.toolkit.Tool.log(`${config.addonName}: uninit called`);
 | 
			
		||||
    this.unInitPrefs();
 | 
			
		||||
    //  Remove elements and do clean up
 | 
			
		||||
    this._Addon.views.unInitViews();
 | 
			
		||||
    // Remove addon object
 | 
			
		||||
    Zotero.AddonTemplate = undefined;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonEvents;
 | 
			
		||||
 | 
			
		||||
@ -1,19 +1,18 @@
 | 
			
		||||
import Addon from "./addon";
 | 
			
		||||
import AddonModule from "./module";
 | 
			
		||||
 | 
			
		||||
import { config } from "../package.json";
 | 
			
		||||
 | 
			
		||||
class AddonLocale extends AddonModule {
 | 
			
		||||
    private stringBundle: any;
 | 
			
		||||
    constructor(parent: Addon) {
 | 
			
		||||
        super(parent);
 | 
			
		||||
        this.stringBundle = Components.classes['@mozilla.org/intl/stringbundle;1']
 | 
			
		||||
            .getService(Components.interfaces.nsIStringBundleService)
 | 
			
		||||
            .createBundle('chrome://addontemplate/locale/addontemplate.properties');
 | 
			
		||||
    }
 | 
			
		||||
  private stringBundle: any;
 | 
			
		||||
 | 
			
		||||
    public getString(localString: string): string {
 | 
			
		||||
        return this.stringBundle.GetStringFromName(localString);
 | 
			
		||||
    }
 | 
			
		||||
  public initLocale() {
 | 
			
		||||
    this.stringBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
 | 
			
		||||
      .getService(Components.interfaces.nsIStringBundleService)
 | 
			
		||||
      .createBundle(`chrome://${config.addonRef}/locale/addon.properties`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getString(localString: string): string {
 | 
			
		||||
    return this.stringBundle.GetStringFromName(localString);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddonLocale;
 | 
			
		||||
export default AddonLocale;
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ class AddonPrefs extends AddonModule {
 | 
			
		||||
    // This function is called when the prefs window is opened
 | 
			
		||||
    // See addon/chrome/content/preferences.xul onpaneload
 | 
			
		||||
    this._window = _window;
 | 
			
		||||
    this._Addon.toolkit.Tool.log(`${config.addonName}: init preferences`);
 | 
			
		||||
    this._Addon.toolkit.Tool.log("init preferences");
 | 
			
		||||
    this.updatePrefsUI();
 | 
			
		||||
    this.bindPrefEvents();
 | 
			
		||||
  }
 | 
			
		||||
@ -20,7 +20,7 @@ class AddonPrefs extends AddonModule {
 | 
			
		||||
    // You can initialize some UI elements on prefs window
 | 
			
		||||
    // with this._window.document
 | 
			
		||||
    // Or bind some events to the elements
 | 
			
		||||
    this._Addon.toolkit.Tool.log(`${config.addonName}: init preferences UI`);
 | 
			
		||||
    this._Addon.toolkit.Tool.log("init preferences UI");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private bindPrefEvents() {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user