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;
|
- TypeScript support;
|
||||||
- Build addon settings and versions automatically;
|
- Build addon settings and versions automatically;
|
||||||
- Build and reload code in Zotero 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));
|
- Release to GitHub automatically(using [release-it](https://github.com/release-it/release-it));
|
||||||
- Extensive skeleton;
|
- Extensive skeleton;
|
||||||
- Some sample code of UI and lifecycle.
|
- 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.
|
> 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 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
|
1. When install/enable/startup triggered from Zotero, `bootstrap.js` > `startup` is called
|
||||||
- Wait for Zotero ready
|
- Wait for Zotero ready
|
||||||
@ -182,11 +187,11 @@ This section shows the directory structure of a template.
|
|||||||
│ └─locale # locale
|
│ └─locale # locale
|
||||||
│ ├─en-US
|
│ ├─en-US
|
||||||
│ │ overlay.dtd
|
│ │ overlay.dtd
|
||||||
│ │ addontemplate.properties
|
│ │ addon.properties
|
||||||
│ │
|
│ │
|
||||||
│ └─zh-CN
|
│ └─zh-CN
|
||||||
│ | overlay.dtd
|
│ | overlay.dtd
|
||||||
│ │ addontemplate.properties
|
│ │ addon.properties
|
||||||
│
|
│
|
||||||
├─builds # build dir
|
├─builds # build dir
|
||||||
│ └─.xpi
|
│ └─.xpi
|
||||||
|
18
build.js
18
build.js
@ -85,7 +85,9 @@ async function main() {
|
|||||||
const buildDir = "builds";
|
const buildDir = "builds";
|
||||||
|
|
||||||
console.log(
|
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);
|
clearFolder(buildDir);
|
||||||
@ -98,6 +100,9 @@ async function main() {
|
|||||||
await esbuild
|
await esbuild
|
||||||
.build({
|
.build({
|
||||||
entryPoints: ["src/index.ts"],
|
entryPoints: ["src/index.ts"],
|
||||||
|
define: {
|
||||||
|
__env__: process.env.NODE_ENV,
|
||||||
|
},
|
||||||
bundle: true,
|
bundle: true,
|
||||||
// Entry should be the same as addon/chrome/content/overlay.xul
|
// Entry should be the same as addon/chrome/content/overlay.xul
|
||||||
outfile: path.join(buildDir, "addon/chrome/content/scripts/index.js"),
|
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] Replace OK");
|
||||||
|
|
||||||
console.log("[Build] Addon prepare OK");
|
console.log("[Build] Addon prepare OK");
|
||||||
|
@ -11,10 +11,11 @@
|
|||||||
},
|
},
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"scripts": {
|
"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",
|
"start": "node start.js",
|
||||||
"stop": "node stop.js",
|
"stop": "node stop.js",
|
||||||
"prerestart": "npm run build",
|
"prerestart": "npm run build-dev",
|
||||||
"restart": "node restart.js",
|
"restart": "node restart.js",
|
||||||
"release": "release-it",
|
"release": "release-it",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
@ -30,11 +31,12 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/windingwind/zotero-addon-template#readme",
|
"homepage": "https://github.com/windingwind/zotero-addon-template#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"zotero-plugin-toolkit": "^0.0.9"
|
"zotero-plugin-toolkit": "^0.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^18.11.17",
|
||||||
"compressing": "^1.6.3",
|
"compressing": "^1.6.3",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"esbuild": "^0.16.10",
|
"esbuild": "^0.16.10",
|
||||||
"release-it": "^14.14.3",
|
"release-it": "^14.14.3",
|
||||||
"replace-in-file": "^6.3.5",
|
"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 AddonLocale from "./locale";
|
||||||
|
|
||||||
import ZoteroToolkit from "zotero-plugin-toolkit";
|
import ZoteroToolkit from "zotero-plugin-toolkit";
|
||||||
import Locale from "./locale";
|
|
||||||
|
|
||||||
class Addon {
|
class Addon {
|
||||||
|
// A global Zotero instance
|
||||||
public Zotero!: _ZoteroConstructable;
|
public Zotero!: _ZoteroConstructable;
|
||||||
public events: AddonEvents;
|
// Root path to access the resources
|
||||||
public views: AddonViews;
|
|
||||||
public prefs: AddonPrefs;
|
|
||||||
public locale: AddonLocale;
|
|
||||||
public toolkit: ZoteroToolkit;
|
|
||||||
// root path to access the resources
|
|
||||||
public rootURI!: string;
|
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() {
|
constructor() {
|
||||||
this.events = new AddonEvents(this);
|
this.events = new AddonEvents(this);
|
||||||
|
@ -3,10 +3,46 @@ import AddonModule from "./module";
|
|||||||
import { config } from "../package.json";
|
import { config } from "../package.json";
|
||||||
|
|
||||||
class AddonEvents extends AddonModule {
|
class AddonEvents extends AddonModule {
|
||||||
private notifierCallback: any;
|
|
||||||
constructor(parent: Addon) {
|
constructor(parent: Addon) {
|
||||||
super(parent);
|
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 (
|
notify: async (
|
||||||
event: string,
|
event: string,
|
||||||
type: 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
|
// Register the callback in Zotero as an item observer
|
||||||
let notifierID = Zotero.Notifier.registerObserver(this.notifierCallback, [
|
let notifierID = Zotero.Notifier.registerObserver(callback, [
|
||||||
"tab",
|
"tab",
|
||||||
"item",
|
"item",
|
||||||
"file",
|
"file",
|
||||||
@ -50,14 +78,9 @@ class AddonEvents extends AddonModule {
|
|||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize preference window
|
|
||||||
this.initPrefs();
|
|
||||||
this._Addon.views.initViews();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public initPrefs() {
|
private initPrefs() {
|
||||||
this._Addon.toolkit.Tool.log(this._Addon.rootURI);
|
|
||||||
const prefOptions = {
|
const prefOptions = {
|
||||||
pluginID: config.addonID,
|
pluginID: config.addonID,
|
||||||
src: this._Addon.rootURI + "chrome/content/preferences.xhtml",
|
src: this._Addon.rootURI + "chrome/content/preferences.xhtml",
|
||||||
@ -81,16 +104,6 @@ class AddonEvents extends AddonModule {
|
|||||||
this._Addon.toolkit.Compat.unregisterPrefPane();
|
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;
|
export default AddonEvents;
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import Addon from "./addon";
|
|
||||||
import AddonModule from "./module";
|
import AddonModule from "./module";
|
||||||
|
import { config } from "../package.json";
|
||||||
|
|
||||||
class AddonLocale extends AddonModule {
|
class AddonLocale extends AddonModule {
|
||||||
private stringBundle: any;
|
private stringBundle: any;
|
||||||
constructor(parent: Addon) {
|
|
||||||
super(parent);
|
public initLocale() {
|
||||||
this.stringBundle = Components.classes['@mozilla.org/intl/stringbundle;1']
|
this.stringBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
||||||
.getService(Components.interfaces.nsIStringBundleService)
|
.getService(Components.interfaces.nsIStringBundleService)
|
||||||
.createBundle('chrome://addontemplate/locale/addontemplate.properties');
|
.createBundle(`chrome://${config.addonRef}/locale/addon.properties`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getString(localString: string): string {
|
public getString(localString: string): string {
|
||||||
|
@ -11,7 +11,7 @@ class AddonPrefs extends AddonModule {
|
|||||||
// This function is called when the prefs window is opened
|
// This function is called when the prefs window is opened
|
||||||
// See addon/chrome/content/preferences.xul onpaneload
|
// See addon/chrome/content/preferences.xul onpaneload
|
||||||
this._window = _window;
|
this._window = _window;
|
||||||
this._Addon.toolkit.Tool.log(`${config.addonName}: init preferences`);
|
this._Addon.toolkit.Tool.log("init preferences");
|
||||||
this.updatePrefsUI();
|
this.updatePrefsUI();
|
||||||
this.bindPrefEvents();
|
this.bindPrefEvents();
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ class AddonPrefs extends AddonModule {
|
|||||||
// You can initialize some UI elements on prefs window
|
// You can initialize some UI elements on prefs window
|
||||||
// with this._window.document
|
// with this._window.document
|
||||||
// Or bind some events to the elements
|
// 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() {
|
private bindPrefEvents() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user