Skip to content

Commit

Permalink
Update Template
Browse files Browse the repository at this point in the history
  • Loading branch information
ChenglongMa committed Jan 10, 2024
1 parent 80652a6 commit 99d9298
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
build
logs
node_modules
package-lock.json
yarn.lock
pnpm-lock.yaml
# zotero-cmd.json
75 changes: 75 additions & 0 deletions scripts/scripts.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import details from "../package.json" assert { type: "json" };

const { addonID, addonName } = details.config;
const { version } = details;

export const reloadScript = `
(async () => {
Services.obs.notifyObservers(null, "startupcache-invalidate", null);
const { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
const addon = await AddonManager.getAddonByID("${addonID}");
await addon.reload();
const progressWindow = new Zotero.ProgressWindow({ closeOnClick: true });
progressWindow.changeHeadline("${addonName} Hot Reload");
progressWindow.progress = new progressWindow.ItemProgress(
"chrome://zotero/skin/tick.png",
"VERSION=${version}, BUILD=${new Date().toLocaleString()}. By zotero-plugin-toolkit"
);
progressWindow.progress.setProgress(100);
progressWindow.show();
progressWindow.startCloseTimer(5000);
})()`;

export const openDevToolScript = `
(async () => {
// const { BrowserToolboxLauncher } = ChromeUtils.import(
// "resource://devtools/client/framework/browser-toolbox/Launcher.jsm",
// );
// BrowserToolboxLauncher.init();
// TODO: Use the above code to open the devtool after https://github.com/zotero/zotero/pull/3387
Zotero.Prefs.set("devtools.debugger.remote-enabled", true, true);
Zotero.Prefs.set("devtools.debugger.remote-port", 6100, true);
Zotero.Prefs.set("devtools.debugger.prompt-connection", false, true);
Zotero.Prefs.set("devtools.debugger.chrome-debugging-websocket", false, true);
env =
Services.env ||
Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
env.set("MOZ_BROWSER_TOOLBOX_PORT", 6100);
Zotero.openInViewer(
"chrome://devtools/content/framework/browser-toolbox/window.html",
{
onLoad: (doc) => {
doc.querySelector("#status-message-container").style.visibility =
"collapse";
let toolboxBody;
waitUntil(
() => {
toolboxBody = doc
.querySelector(".devtools-toolbox-browsertoolbox-iframe")
?.contentDocument?.querySelector(".theme-body");
return toolboxBody;
},
() => {
toolboxBody.style = "pointer-events: all !important";
}
);
},
}
);
function waitUntil(condition, callback, interval = 100, timeout = 10000) {
const start = Date.now();
const intervalId = setInterval(() => {
if (condition()) {
clearInterval(intervalId);
callback();
} else if (Date.now() - start > timeout) {
clearInterval(intervalId);
}
}, interval);
}
})()`;
87 changes: 87 additions & 0 deletions scripts/server.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { main as build, esbuildOptions } from "./build.mjs";
import { openDevToolScript, reloadScript } from "./scripts.mjs";
import { main as startZotero } from "./start.mjs";
import { Logger } from "./utils.mjs";
import cmd from "./zotero-cmd.json" assert { type: "json" };
import { execSync } from "child_process";
import chokidar from "chokidar";
import { context } from "esbuild";
import { exit } from "process";

process.env.NODE_ENV = "development";

const { zoteroBinPath, profilePath } = cmd.exec;

const startZoteroCmd = `"${zoteroBinPath}" --debugger --purgecaches -profile "${profilePath}"`;

async function watch() {
const watcher = chokidar.watch(["src/**", "addon/**"], {
ignored: /(^|[\/\\])\../, // ignore dotfiles
persistent: true,
});

let esbuildCTX = await context(esbuildOptions);

watcher
.on("ready", () => {
Logger.info("Server Ready! \n");
})
.on("change", async (path) => {
Logger.info(`${path} changed.`);
if (path.startsWith("src")) {
await esbuildCTX.rebuild();
} else if (path.startsWith("addon")) {
await build()
// Do not abort the watcher when errors occur in builds triggered by the watcher.
.catch((err) => {
Logger.error(err);
});
}
// reload
reload();
})
.on("error", (err) => {
Logger.error("Server start failed!", err);
});
}

function reload() {
Logger.debug("Reloading...");
const url = `zotero://ztoolkit-debug/?run=${encodeURIComponent(
reloadScript,
)}`;
const command = `${startZoteroCmd} -url "${url}"`;
execSync(command);
}

function openDevTool() {
Logger.debug("Open dev tools...");
const url = `zotero://ztoolkit-debug/?run=${encodeURIComponent(
openDevToolScript,
)}`;
const command = `${startZoteroCmd} -url "${url}"`;
execSync(command);
}

async function main() {
// build
await build();

// start Zotero
startZotero(openDevTool);

// watch
await watch();
}

main().catch((err) => {
Logger.error(err);
// execSync("node scripts/stop.mjs");
exit(1);
});

process.on("SIGINT", (code) => {
execSync("node scripts/stop.mjs");
Logger.info(`Server terminated with signal ${code}.`);
exit(0);
});
17 changes: 17 additions & 0 deletions scripts/update-template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"addons": {
"__addonID__": {
"updates": [
{
"version": "__buildVersion__",
"update_link": "__updateLink__",
"applications": {
"zotero": {
"strict_min_version": "6.999"
}
}
}
]
}
}
}
129 changes: 129 additions & 0 deletions scripts/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { exec } from "child_process";
import {
existsSync,
lstatSync,
mkdirSync,
readFileSync,
readdirSync,
rmSync,
writeFileSync,
} from "fs";
import path from "path";

export function copyFileSync(source, target) {
var targetFile = target;

// If target is a directory, a new file with the same name will be created
if (existsSync(target)) {
if (lstatSync(target).isDirectory()) {
targetFile = path.join(target, path.basename(source));
}
}

writeFileSync(targetFile, readFileSync(source));
}

export function copyFolderRecursiveSync(source, target) {
var files = [];

// Check if folder needs to be created or integrated
var targetFolder = path.join(target, path.basename(source));
if (!existsSync(targetFolder)) {
mkdirSync(targetFolder);
}

// Copy
if (lstatSync(source).isDirectory()) {
files = readdirSync(source);
files.forEach(function (file) {
var curSource = path.join(source, file);
if (lstatSync(curSource).isDirectory()) {
copyFolderRecursiveSync(curSource, targetFolder);
} else {
copyFileSync(curSource, targetFolder);
}
});
}
}

export function clearFolder(target) {
if (existsSync(target)) {
rmSync(target, { recursive: true, force: true });
}

mkdirSync(target, { recursive: true });
}

export function dateFormat(fmt, date) {
let ret;
const opt = {
"Y+": date.getFullYear().toString(),
"m+": (date.getMonth() + 1).toString(),
"d+": date.getDate().toString(),
"H+": date.getHours().toString(),
"M+": date.getMinutes().toString(),
"S+": date.getSeconds().toString(),
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0"),
);
}
}
return fmt;
}

export class Logger {
static log(...args) {
console.log(...args);
}

// red
static error(...args) {
console.error("\u001b[31m [ERROR]", ...args, "\u001b[0m");
}

// yellow
static warn(...args) {
console.warn("\u001b[33m [WARN]", ...args, "\u001b[0m");
}

// blue
static debug(...args) {
console.log("\u001b[34m [DEBUG]\u001b[0m", ...args);
}

// green
static info(...args) {
console.log("\u001b[32m [INFO]", ...args, "\u001b[0m");
}

// cyan
static trace(...args) {
console.log("\u001b[36m [TRACE]\u001b[0m", ...args);
}
}

export function isRunning(query, cb) {
let platform = process.platform;
let cmd = "";
switch (platform) {
case "win32":
cmd = `tasklist`;
break;
case "darwin":
cmd = `ps -ax | grep ${query}`;
break;
case "linux":
cmd = `ps -A`;
break;
default:
break;
}
exec(cmd, (err, stdout, stderr) => {
cb(stdout.toLowerCase().indexOf(query.toLowerCase()) > -1);
});
}
20 changes: 20 additions & 0 deletions scripts/zotero-cmd-template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"usage": "Copy and rename this file to zotero-cmd.json. Edit the cmd.",
"killZoteroWindows": "taskkill /f /im zotero.exe",
"killZoteroUnix": "kill -9 $(ps -x | grep '[z]otero' | awk '{print $1}')",
"exec": {
"@comment-zoteroBinPath": "Please input the path of the Zotero binary file in `zoteroBinPath`.",
"@comment-zoteroBinPath-tip": "The path delimiter should be escaped as `\\` for win32. The path is `*/Zotero.app/Contents/MacOS/zotero` for MacOS.",
"zoteroBinPath": "/path/to/zotero.exe",

"@comment-profilePath": "Please input the path of the profile used for development in `profilePath`.",
"@comment-profilePath-tip": "Start the profile manager by `/path/to/zotero.exe -p` to create a profile for development",
"@comment-profilePath-see": "https://www.zotero.org/support/kb/profile_directory",
"profilePath": "/path/to/profile",

"@comment-dataDir": "Please input the directory where the database is located in dataDir",
"@comment-dataDir-tip": "If this field is kept empty, Zotero will start with the default data.",
"@comment-dataDir-see": "https://www.zotero.org/support/zotero_data",
"dataDir": ""
}
}

0 comments on commit 99d9298

Please sign in to comment.