diff --git a/addon/chrome/content/icons/favicon.png b/addon/chrome/content/icons/favicon.png
deleted file mode 100644
index 8a57ded..0000000
Binary files a/addon/chrome/content/icons/favicon.png and /dev/null differ
diff --git a/addon/chrome/content/icons/favicon.svg b/addon/chrome/content/icons/favicon.svg
new file mode 100644
index 0000000..4a04acd
--- /dev/null
+++ b/addon/chrome/content/icons/favicon.svg
@@ -0,0 +1,14 @@
+
+
+
\ No newline at end of file
diff --git a/addon/chrome/content/icons/favicon@0.5x.png b/addon/chrome/content/icons/favicon@0.5x.png
deleted file mode 100644
index 30e8037..0000000
Binary files a/addon/chrome/content/icons/favicon@0.5x.png and /dev/null differ
diff --git a/addon/chrome/content/icons/favicon@0.5x.svg b/addon/chrome/content/icons/favicon@0.5x.svg
new file mode 100644
index 0000000..4a04acd
--- /dev/null
+++ b/addon/chrome/content/icons/favicon@0.5x.svg
@@ -0,0 +1,14 @@
+
+
+
\ No newline at end of file
diff --git a/addon/chrome/content/preferences.xhtml b/addon/chrome/content/preferences.xhtml
index af67264..873b9da 100644
--- a/addon/chrome/content/preferences.xhtml
+++ b/addon/chrome/content/preferences.xhtml
@@ -1,36 +1,10 @@
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
\ No newline at end of file
diff --git a/addon/chrome/content/zoteroPane.css b/addon/chrome/content/zoteroPane.css
index 8c95c1e..e69de29 100644
--- a/addon/chrome/content/zoteroPane.css
+++ b/addon/chrome/content/zoteroPane.css
@@ -1,3 +0,0 @@
-.makeItRed {
- background-color: tomato;
-}
diff --git a/addon/locale/en-US/addon.ftl b/addon/locale/en-US/addon.ftl
index 892d267..25e47b0 100644
--- a/addon/locale/en-US/addon.ftl
+++ b/addon/locale/en-US/addon.ftl
@@ -1,6 +1,6 @@
startup-begin = Addon is loading
startup-finish = Addon is ready
-menuitem-label = Addon Template: Helper Examples
+menuitem-label = Action-cmd: menu action
menupopup-label = Addon Template: Menupopup
menuitem-submenulabel = Addon Template
menuitem-filemenulabel = Addon Template: File Menuitem
diff --git a/addon/locale/en-US/preferences.ftl b/addon/locale/en-US/preferences.ftl
index 57189e0..adfd4c9 100644
--- a/addon/locale/en-US/preferences.ftl
+++ b/addon/locale/en-US/preferences.ftl
@@ -1,4 +1,4 @@
-pref-title = Addon Template Example
+pref-title = See settings in Settings/Advanced/Config Editor
pref-enable =
.label = Enable
pref-input = Input
diff --git a/addon/locale/zh-CN/addon.ftl b/addon/locale/zh-CN/addon.ftl
index 16d97d3..7092a0a 100644
--- a/addon/locale/zh-CN/addon.ftl
+++ b/addon/locale/zh-CN/addon.ftl
@@ -1,6 +1,6 @@
startup-begin = 插件加载中
startup-finish = 插件已就绪
-menuitem-label = 插件模板: 帮助工具样例
+menuitem-label = Action-cmd: menu action
menupopup-label = 插件模板: 弹出菜单
menuitem-submenulabel = 插件模板:子菜单
menuitem-filemenulabel = 插件模板: 文件菜单
diff --git a/addon/locale/zh-CN/preferences.ftl b/addon/locale/zh-CN/preferences.ftl
index b20243b..ea853a6 100644
--- a/addon/locale/zh-CN/preferences.ftl
+++ b/addon/locale/zh-CN/preferences.ftl
@@ -1,4 +1,4 @@
-pref-title = 插件模板设置示例
+pref-title = 目前设置在"设置/高级/编辑器"下
pref-enable =
.label = 开启
pref-input = 输入
diff --git a/addon/manifest.json b/addon/manifest.json
index 0c356c6..822e108 100644
--- a/addon/manifest.json
+++ b/addon/manifest.json
@@ -6,8 +6,8 @@
"homepage_url": "__homepage__",
"author": "__author__",
"icons": {
- "48": "chrome/content/icons/favicon@0.5x.png",
- "96": "chrome/content/icons/favicon.png"
+ "48": "chrome/content/icons/favicon@0.5x.svg",
+ "96": "chrome/content/icons/favicon.svg"
},
"applications": {
"zotero": {
@@ -17,4 +17,4 @@
"strict_max_version": "7.0.*"
}
}
-}
+}
\ No newline at end of file
diff --git a/addon/prefs.js b/addon/prefs.js
index be8f47d..bfd7bae 100644
--- a/addon/prefs.js
+++ b/addon/prefs.js
@@ -1,3 +1,5 @@
/* eslint-disable no-undef */
-pref("__prefsPrefix__.enable", true);
-pref("__prefsPrefix__.input", "This is input");
+pref('__prefsPrefix__.menu.jsOrCmd', true)
+pref('__prefsPrefix__.menu.jsPath', 'D:\\Project\\Python工具\\extract_pdf_image\\test.js')
+pref('__prefsPrefix__.menu.cmd', 'D:\\Python310\\pythonw.exe')
+pref('__prefsPrefix__.menu.args', '"D:\\Project\\Python工具\\extract_pdf_image\\extract_pdf_image.py"')
diff --git a/src/actions/menu.ts b/src/actions/menu.ts
new file mode 100644
index 0000000..f8487b3
--- /dev/null
+++ b/src/actions/menu.ts
@@ -0,0 +1,16 @@
+import { MenuTask } from "../tasks"
+import { config } from "../../package.json"
+
+
+export async function menuAction(task: MenuTask) {
+ const jsOrCmd = Zotero.Prefs.get(`${config.addonRef}.menu.jsOrCmd`) as boolean
+ const args = (Zotero.Prefs.get(`${config.addonRef}.menu.args`) as string).split(/\s*,\s*/).map(el => el.trim().replace(/^\"|\"$/g, "")).filter(el => el)
+ args.push(`"${JSON.stringify(task)}"`)
+ if (jsOrCmd) {
+ const content = await OS.File.read(Zotero.Prefs.get(`${config.addonRef}.menu.jsPath`) as string, { encoding: "utf-8" }) as string;
+ // new Function(content)(task)
+ eval(content)
+ } else {
+ await Zotero.Utilities.Internal.exec(Zotero.Prefs.get(`${config.addonRef}.menu.cmd`) as string, args)
+ }
+}
\ No newline at end of file
diff --git a/src/addon.ts b/src/addon.ts
index a9a70af..f971315 100644
--- a/src/addon.ts
+++ b/src/addon.ts
@@ -14,10 +14,7 @@ class Addon {
};
prefs?: {
window: Window;
- columns: Array;
- rows: Array<{ [dataKey: string]: string }>;
};
- dialog?: DialogHelper;
};
// Lifecycle hooks
public hooks: typeof hooks;
diff --git a/src/hooks.ts b/src/hooks.ts
index 7b000f9..8c46221 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -1,16 +1,16 @@
import {
BasicExampleFactory,
- HelperExampleFactory,
- KeyExampleFactory,
- PromptExampleFactory,
UIExampleFactory,
} from "./modules/examples";
import { config } from "../package.json";
import { getString, initLocale } from "./utils/locale";
import { registerPrefsScripts } from "./modules/preferenceScript";
import { createZToolkit } from "./utils/ztoolkit";
+import { addMenuTask, MenuTask } from "./tasks"
+import { menuAction } from "./actions/menu"
async function onStartup() {
+ Components.utils.import("resource://gre/modules/osfile.jsm");
await Promise.all([
Zotero.initializationPromise,
Zotero.unlockPromise,
@@ -20,77 +20,22 @@ async function onStartup() {
BasicExampleFactory.registerPrefs();
- BasicExampleFactory.registerNotifier();
-
await onMainWindowLoad(window);
}
async function onMainWindowLoad(win: Window): Promise {
// Create ztoolkit for every window
addon.data.ztoolkit = createZToolkit();
-
- const popupWin = new ztoolkit.ProgressWindow(config.addonName, {
- closeOnClick: true,
- closeTime: -1,
- })
- .createLine({
- text: getString("startup-begin"),
- type: "default",
- progress: 0,
- })
- .show();
-
- KeyExampleFactory.registerShortcuts();
-
- await Zotero.Promise.delay(1000);
- popupWin.changeLine({
- progress: 30,
- text: `[30%] ${getString("startup-begin")}`,
- });
-
UIExampleFactory.registerStyleSheet();
-
UIExampleFactory.registerRightClickMenuItem();
-
- UIExampleFactory.registerRightClickMenuPopup();
-
- UIExampleFactory.registerWindowMenuWithSeparator();
-
- await UIExampleFactory.registerExtraColumn();
-
- await UIExampleFactory.registerExtraColumnWithCustomCell();
-
- await UIExampleFactory.registerCustomItemBoxRow();
-
- UIExampleFactory.registerLibraryTabPanel();
-
- await UIExampleFactory.registerReaderTabPanel();
-
- PromptExampleFactory.registerNormalCommandExample();
-
- PromptExampleFactory.registerAnonymousCommandExample();
-
- PromptExampleFactory.registerConditionalCommandExample();
-
- await Zotero.Promise.delay(1000);
-
- popupWin.changeLine({
- progress: 100,
- text: `[100%] ${getString("startup-finish")}`,
- });
- popupWin.startCloseTimer(5000);
-
- addon.hooks.onDialogEvents("dialogExample");
}
async function onMainWindowUnload(win: Window): Promise {
ztoolkit.unregisterAll();
- addon.data.dialog?.window?.close();
}
function onShutdown(): void {
ztoolkit.unregisterAll();
- addon.data.dialog?.window?.close();
// Remove addon object
addon.data.alive = false;
delete Zotero[config.addonInstance];
@@ -107,16 +52,7 @@ async function onNotify(
extraData: { [key: string]: any },
) {
// You can add your code to the corresponding notify type
- ztoolkit.log("notify", event, type, ids, extraData);
- if (
- event == "select" &&
- type == "tab" &&
- extraData[ids[0]].type == "reader"
- ) {
- BasicExampleFactory.exampleNotifierCallback();
- } else {
- return;
- }
+
}
/**
@@ -136,47 +72,21 @@ async function onPrefsEvent(type: string, data: { [key: string]: any }) {
}
function onShortcuts(type: string) {
- switch (type) {
- case "larger":
- KeyExampleFactory.exampleShortcutLargerCallback();
- break;
- case "smaller":
- KeyExampleFactory.exampleShortcutSmallerCallback();
- break;
- case "confliction":
- KeyExampleFactory.exampleShortcutConflictingCallback();
- break;
- default:
- break;
- }
+
}
function onDialogEvents(type: string) {
- switch (type) {
- case "dialogExample":
- HelperExampleFactory.dialogExample();
- break;
- case "clipboardExample":
- HelperExampleFactory.clipboardExample();
- break;
- case "filePickerExample":
- HelperExampleFactory.filePickerExample();
- break;
- case "progressWindowExample":
- HelperExampleFactory.progressWindowExample();
- break;
- case "vtableExample":
- HelperExampleFactory.vtableExample();
- break;
- default:
- break;
- }
+
}
// Add your hooks here. For element click, etc.
// Keep in mind hooks only do dispatch. Don't add code that does real jobs in hooks.
// Otherwise the code would be hard to read and maintian.
-
+async function onMenuActionInBatch(tasks: Array) {
+ for (const task of tasks) {
+ await menuAction(task);
+ }
+}
export default {
onStartup,
onShutdown,
@@ -186,4 +96,5 @@ export default {
onPrefsEvent,
onShortcuts,
onDialogEvents,
+ onMenuActionInBatch
};
diff --git a/src/modules/examples.ts b/src/modules/examples.ts
index d493760..db2b2de 100644
--- a/src/modules/examples.ts
+++ b/src/modules/examples.ts
@@ -1,187 +1,21 @@
import { config } from "../../package.json";
import { getString } from "../utils/locale";
-
-function example(
- target: any,
- propertyKey: string | symbol,
- descriptor: PropertyDescriptor,
-) {
- const original = descriptor.value;
- descriptor.value = function (...args: any) {
- try {
- ztoolkit.log(`Calling example ${target.name}.${String(propertyKey)}`);
- return original.apply(this, args);
- } catch (e) {
- ztoolkit.log(`Error in example ${target.name}.${String(propertyKey)}`, e);
- throw e;
- }
- };
- return descriptor;
-}
+import { addMenuTask, MenuTask } from "../tasks"
export class BasicExampleFactory {
- @example
- static registerNotifier() {
- const callback = {
- notify: async (
- event: string,
- type: string,
- ids: number[] | string[],
- extraData: { [key: string]: any },
- ) => {
- if (!addon?.data.alive) {
- this.unregisterNotifier(notifierID);
- return;
- }
- addon.hooks.onNotify(event, type, ids, extraData);
- },
- };
-
- // Register the callback in Zotero as an item observer
- const notifierID = Zotero.Notifier.registerObserver(callback, [
- "tab",
- "item",
- "file",
- ]);
-
- // Unregister callback when the window closes (important to avoid a memory leak)
- window.addEventListener(
- "unload",
- (e: Event) => {
- this.unregisterNotifier(notifierID);
- },
- false,
- );
- }
-
- @example
- static exampleNotifierCallback() {
- new ztoolkit.ProgressWindow(config.addonName)
- .createLine({
- text: "Open Tab Detected!",
- type: "success",
- progress: 100,
- })
- .show();
- }
-
- @example
- private static unregisterNotifier(notifierID: string) {
- Zotero.Notifier.unregisterObserver(notifierID);
- }
-
- @example
static registerPrefs() {
const prefOptions = {
pluginID: config.addonID,
src: rootURI + "chrome/content/preferences.xhtml",
label: getString("prefs-title"),
- image: `chrome://${config.addonRef}/content/icons/favicon.png`,
+ image: `chrome://${config.addonRef}/content/icons/favicon.svg`,
defaultXUL: true,
};
ztoolkit.PreferencePane.register(prefOptions);
}
}
-export class KeyExampleFactory {
- @example
- static registerShortcuts() {
- const keysetId = `${config.addonRef}-keyset`;
- const cmdsetId = `${config.addonRef}-cmdset`;
- const cmdSmallerId = `${config.addonRef}-cmd-smaller`;
- // Register an event key for Alt+L
- ztoolkit.Shortcut.register("event", {
- id: `${config.addonRef}-key-larger`,
- key: "L",
- modifiers: "alt",
- callback: (keyOptions) => {
- addon.hooks.onShortcuts("larger");
- },
- });
- // Register an element key using for Alt+S
- ztoolkit.Shortcut.register("element", {
- id: `${config.addonRef}-key-smaller`,
- key: "S",
- modifiers: "alt",
- xulData: {
- document,
- command: cmdSmallerId,
- _parentId: keysetId,
- _commandOptions: {
- id: cmdSmallerId,
- document,
- _parentId: cmdsetId,
- oncommand: `Zotero.${config.addonInstance}.hooks.onShortcuts('smaller')`,
- },
- },
- });
- // Here we register an conflict key for Alt+S
- // just to show how the confliction check works.
- // This is something you should avoid in your plugin.
- ztoolkit.Shortcut.register("event", {
- id: `${config.addonRef}-key-smaller-conflict`,
- key: "S",
- modifiers: "alt",
- callback: (keyOptions) => {
- ztoolkit.getGlobal("alert")("Smaller! This is a conflict key.");
- },
- });
- // Register an event key to check confliction
- ztoolkit.Shortcut.register("event", {
- id: `${config.addonRef}-key-check-conflict`,
- key: "C",
- modifiers: "alt",
- callback: (keyOptions) => {
- addon.hooks.onShortcuts("confliction");
- },
- });
- new ztoolkit.ProgressWindow(config.addonName)
- .createLine({
- text: "Example Shortcuts: Alt+L/S/C",
- type: "success",
- })
- .show();
- }
-
- @example
- static exampleShortcutLargerCallback() {
- new ztoolkit.ProgressWindow(config.addonName)
- .createLine({
- text: "Larger!",
- type: "default",
- })
- .show();
- }
-
- @example
- static exampleShortcutSmallerCallback() {
- new ztoolkit.ProgressWindow(config.addonName)
- .createLine({
- text: "Smaller!",
- type: "default",
- })
- .show();
- }
-
- @example
- static exampleShortcutConflictingCallback() {
- const conflictingGroups = ztoolkit.Shortcut.checkAllKeyConflicting();
- new ztoolkit.ProgressWindow("Check Key Conflicting")
- .createLine({
- text: `${conflictingGroups.length} groups of conflicting keys found. Details are in the debug output/console.`,
- })
- .show(-1);
- ztoolkit.log(
- "Conflicting:",
- conflictingGroups,
- "All keys:",
- ztoolkit.Shortcut.getAll(),
- );
- }
-}
-
export class UIExampleFactory {
- @example
static registerStyleSheet() {
const styles = ztoolkit.UI.createElement(document, "link", {
properties: {
@@ -191,776 +25,22 @@ export class UIExampleFactory {
},
});
document.documentElement.appendChild(styles);
- document
- .getElementById("zotero-item-pane-content")
- ?.classList.add("makeItRed");
}
-
- @example
static registerRightClickMenuItem() {
- const menuIcon = `chrome://${config.addonRef}/content/icons/favicon@0.5x.png`;
+ const menuIcon = `chrome://${config.addonRef}/content/icons/favicon@0.5x.svg`;
// item menuitem with icon
ztoolkit.Menu.register("item", {
tag: "menuitem",
- id: "zotero-itemmenu-addontemplate-test",
+ id: "zotero-action-cmd-menu",
label: getString("menuitem-label"),
- commandListener: (ev) => addon.hooks.onDialogEvents("dialogExample"),
- icon: menuIcon,
- });
- }
-
- @example
- static registerRightClickMenuPopup() {
- ztoolkit.Menu.register(
- "item",
- {
- tag: "menu",
- label: getString("menupopup-label"),
- children: [
- {
- tag: "menuitem",
- label: getString("menuitem-submenulabel"),
- oncommand: "alert('Hello World! Sub Menuitem.')",
- },
- ],
- },
- "before",
- document.querySelector(
- "#zotero-itemmenu-addontemplate-test",
- ) as XUL.MenuItem,
- );
- }
-
- @example
- static registerWindowMenuWithSeparator() {
- ztoolkit.Menu.register("menuFile", {
- tag: "menuseparator",
- });
- // menu->File menuitem
- ztoolkit.Menu.register("menuFile", {
- tag: "menuitem",
- label: getString("menuitem-filemenulabel"),
- oncommand: "alert('Hello World! File Menuitem.')",
- });
- }
-
- @example
- static async registerExtraColumn() {
- await ztoolkit.ItemTree.register(
- "test1",
- "text column",
- (
- field: string,
- unformatted: boolean,
- includeBaseMapped: boolean,
- item: Zotero.Item,
- ) => {
- return field + String(item.id);
- },
- {
- iconPath: "chrome://zotero/skin/cross.png",
- },
- );
- }
-
- @example
- static async registerExtraColumnWithCustomCell() {
- await ztoolkit.ItemTree.register(
- "test2",
- "custom column",
- (
- field: string,
- unformatted: boolean,
- includeBaseMapped: boolean,
- item: Zotero.Item,
- ) => {
- return String(item.id);
- },
- {
- renderCell(index, data, column) {
- ztoolkit.log("Custom column cell is rendered!");
- const span = document.createElementNS(
- "http://www.w3.org/1999/xhtml",
- "span",
- );
- span.className = `cell ${column.className}`;
- span.style.background = "#0dd068";
- span.innerText = "⭐" + data;
- return span;
- },
- },
- );
- }
-
- @example
- static async registerCustomItemBoxRow() {
- await ztoolkit.ItemBox.register(
- "itemBoxFieldEditable",
- "Editable Custom Field",
- (field, unformatted, includeBaseMapped, item, original) => {
- return (
- ztoolkit.ExtraField.getExtraField(item, "itemBoxFieldEditable") || ""
+ commandListener: (ev) => {
+ addon.hooks.onMenuActionInBatch(
+ ZoteroPane.getSelectedItems(true)
+ .map((id) => addMenuTask(id))
+ .filter((task) => task) as MenuTask[]
);
},
- {
- editable: true,
- setFieldHook: (field, value, loadIn, item, original) => {
- window.alert("Custom itemBox value is changed and saved to extra!");
- ztoolkit.ExtraField.setExtraField(
- item,
- "itemBoxFieldEditable",
- value,
- );
- return true;
- },
- index: 1,
- },
- );
-
- await ztoolkit.ItemBox.register(
- "itemBoxFieldNonEditable",
- "Non-Editable Custom Field",
- (field, unformatted, includeBaseMapped, item, original) => {
- return (
- "[CANNOT EDIT THIS]" + (item.getField("title") as string).slice(0, 10)
- );
- },
- {
- editable: false,
- index: 2,
- },
- );
- }
-
- @example
- static registerLibraryTabPanel() {
- const tabId = ztoolkit.LibraryTabPanel.register(
- getString("tabpanel-lib-tab-label"),
- (panel: XUL.Element, win: Window) => {
- const elem = ztoolkit.UI.createElement(win.document, "vbox", {
- children: [
- {
- tag: "h2",
- properties: {
- innerText: "Hello World!",
- },
- },
- {
- tag: "div",
- properties: {
- innerText: "This is a library tab.",
- },
- },
- {
- tag: "button",
- namespace: "html",
- properties: {
- innerText: "Unregister",
- },
- listeners: [
- {
- type: "click",
- listener: () => {
- ztoolkit.LibraryTabPanel.unregister(tabId);
- },
- },
- ],
- },
- ],
- });
- panel.append(elem);
- },
- {
- targetIndex: 1,
- },
- );
- }
-
- @example
- static async registerReaderTabPanel() {
- const tabId = await ztoolkit.ReaderTabPanel.register(
- getString("tabpanel-reader-tab-label"),
- (
- panel: XUL.TabPanel | undefined,
- deck: XUL.Deck,
- win: Window,
- reader: _ZoteroTypes.ReaderInstance,
- ) => {
- if (!panel) {
- ztoolkit.log(
- "This reader do not have right-side bar. Adding reader tab skipped.",
- );
- return;
- }
- ztoolkit.log(reader);
- const elem = ztoolkit.UI.createElement(win.document, "vbox", {
- id: `${config.addonRef}-${reader._instanceID}-extra-reader-tab-div`,
- // This is important! Don't create content for multiple times
- // ignoreIfExists: true,
- removeIfExists: true,
- children: [
- {
- tag: "h2",
- properties: {
- innerText: "Hello World!",
- },
- },
- {
- tag: "div",
- properties: {
- innerText: "This is a reader tab.",
- },
- },
- {
- tag: "div",
- properties: {
- innerText: `Reader: ${reader._title.slice(0, 20)}`,
- },
- },
- {
- tag: "div",
- properties: {
- innerText: `itemID: ${reader.itemID}.`,
- },
- },
- {
- tag: "button",
- namespace: "html",
- properties: {
- innerText: "Unregister",
- },
- listeners: [
- {
- type: "click",
- listener: () => {
- ztoolkit.ReaderTabPanel.unregister(tabId);
- },
- },
- ],
- },
- ],
- });
- panel.append(elem);
- },
- {
- targetIndex: 1,
- },
- );
- }
-}
-
-export class PromptExampleFactory {
- @example
- static registerNormalCommandExample() {
- ztoolkit.Prompt.register([
- {
- name: "Normal Command Test",
- label: "Plugin Template",
- callback(prompt) {
- ztoolkit.getGlobal("alert")("Command triggered!");
- },
- },
- ]);
- }
-
- @example
- static registerAnonymousCommandExample() {
- ztoolkit.Prompt.register([
- {
- id: "search",
- callback: async (prompt) => {
- // https://github.com/zotero/zotero/blob/7262465109c21919b56a7ab214f7c7a8e1e63909/chrome/content/zotero/integration/quickFormat.js#L589
- function getItemDescription(item: Zotero.Item) {
- const nodes = [];
- let str = "";
- let author,
- authorDate = "";
- if (item.firstCreator) {
- author = authorDate = item.firstCreator;
- }
- let date = item.getField("date", true, true) as string;
- if (date && (date = date.substr(0, 4)) !== "0000") {
- authorDate += " (" + parseInt(date) + ")";
- }
- authorDate = authorDate.trim();
- if (authorDate) nodes.push(authorDate);
-
- const publicationTitle = item.getField(
- "publicationTitle",
- false,
- true,
- );
- if (publicationTitle) {
- nodes.push(`${publicationTitle}`);
- }
- let volumeIssue = item.getField("volume");
- const issue = item.getField("issue");
- if (issue) volumeIssue += "(" + issue + ")";
- if (volumeIssue) nodes.push(volumeIssue);
-
- const publisherPlace = [];
- let field;
- if ((field = item.getField("publisher")))
- publisherPlace.push(field);
- if ((field = item.getField("place"))) publisherPlace.push(field);
- if (publisherPlace.length) nodes.push(publisherPlace.join(": "));
-
- const pages = item.getField("pages");
- if (pages) nodes.push(pages);
-
- if (!nodes.length) {
- const url = item.getField("url");
- if (url) nodes.push(url);
- }
-
- // compile everything together
- for (let i = 0, n = nodes.length; i < n; i++) {
- const node = nodes[i];
-
- if (i != 0) str += ", ";
-
- if (typeof node === "object") {
- const label = document.createElement("label");
- label.setAttribute("value", str);
- label.setAttribute("crop", "end");
- str = "";
- } else {
- str += node;
- }
- }
- str.length && (str += ".");
- return str;
- }
- function filter(ids: number[]) {
- ids = ids.filter(async (id) => {
- const item = (await Zotero.Items.getAsync(id)) as Zotero.Item;
- return item.isRegularItem() && !(item as any).isFeedItem;
- });
- return ids;
- }
- const text = prompt.inputNode.value;
- prompt.showTip("Searching...");
- const s = new Zotero.Search();
- s.addCondition("quicksearch-titleCreatorYear", "contains", text);
- s.addCondition("itemType", "isNot", "attachment");
- let ids = await s.search();
- // prompt.exit will remove current container element.
- // @ts-ignore ignore
- prompt.exit();
- const container = prompt.createCommandsContainer();
- container.classList.add("suggestions");
- ids = filter(ids);
- console.log(ids.length);
- if (ids.length == 0) {
- const s = new Zotero.Search();
- const operators = [
- "is",
- "isNot",
- "true",
- "false",
- "isInTheLast",
- "isBefore",
- "isAfter",
- "contains",
- "doesNotContain",
- "beginsWith",
- ];
- let hasValidCondition = false;
- let joinMode = "all";
- if (/\s*\|\|\s*/.test(text)) {
- joinMode = "any";
- }
- text.split(/\s*(&&|\|\|)\s*/g).forEach((conditinString: string) => {
- const conditions = conditinString.split(/\s+/g);
- if (
- conditions.length == 3 &&
- operators.indexOf(conditions[1]) != -1
- ) {
- hasValidCondition = true;
- s.addCondition(
- "joinMode",
- joinMode as Zotero.Search.Operator,
- "",
- );
- s.addCondition(
- conditions[0] as string,
- conditions[1] as Zotero.Search.Operator,
- conditions[2] as string,
- );
- }
- });
- if (hasValidCondition) {
- ids = await s.search();
- }
- }
- ids = filter(ids);
- console.log(ids.length);
- if (ids.length > 0) {
- ids.forEach((id: number) => {
- const item = Zotero.Items.get(id);
- const title = item.getField("title");
- const ele = ztoolkit.UI.createElement(document, "div", {
- namespace: "html",
- classList: ["command"],
- listeners: [
- {
- type: "mousemove",
- listener: function () {
- // @ts-ignore ignore
- prompt.selectItem(this);
- },
- },
- {
- type: "click",
- listener: () => {
- prompt.promptNode.style.display = "none";
- Zotero_Tabs.select("zotero-pane");
- ZoteroPane.selectItem(item.id);
- },
- },
- ],
- styles: {
- display: "flex",
- flexDirection: "column",
- justifyContent: "start",
- },
- children: [
- {
- tag: "span",
- styles: {
- fontWeight: "bold",
- overflow: "hidden",
- textOverflow: "ellipsis",
- whiteSpace: "nowrap",
- },
- properties: {
- innerText: title,
- },
- },
- {
- tag: "span",
- styles: {
- overflow: "hidden",
- textOverflow: "ellipsis",
- whiteSpace: "nowrap",
- },
- properties: {
- innerHTML: getItemDescription(item),
- },
- },
- ],
- });
- container.appendChild(ele);
- });
- } else {
- // @ts-ignore ignore
- prompt.exit();
- prompt.showTip("Not Found.");
- }
- },
- },
- ]);
- }
-
- @example
- static registerConditionalCommandExample() {
- ztoolkit.Prompt.register([
- {
- name: "Conditional Command Test",
- label: "Plugin Template",
- // The when function is executed when Prompt UI is woken up by `Shift + P`, and this command does not display when false is returned.
- when: () => {
- const items = ZoteroPane.getSelectedItems();
- return items.length > 0;
- },
- callback(prompt) {
- prompt.inputNode.placeholder = "Hello World!";
- const items = ZoteroPane.getSelectedItems();
- ztoolkit.getGlobal("alert")(
- `You select ${items.length} items!\n\n${items
- .map(
- (item, index) =>
- String(index + 1) + ". " + item.getDisplayTitle(),
- )
- .join("\n")}`,
- );
- },
- },
- ]);
- }
-}
-
-export class HelperExampleFactory {
- @example
- static async dialogExample() {
- const dialogData: { [key: string | number]: any } = {
- inputValue: "test",
- checkboxValue: true,
- loadCallback: () => {
- ztoolkit.log(dialogData, "Dialog Opened!");
- },
- unloadCallback: () => {
- ztoolkit.log(dialogData, "Dialog closed!");
- },
- };
- const dialogHelper = new ztoolkit.Dialog(10, 2)
- .addCell(0, 0, {
- tag: "h1",
- properties: { innerHTML: "Helper Examples" },
- })
- .addCell(1, 0, {
- tag: "h2",
- properties: { innerHTML: "Dialog Data Binding" },
- })
- .addCell(2, 0, {
- tag: "p",
- properties: {
- innerHTML:
- "Elements with attribute 'data-bind' are binded to the prop under 'dialogData' with the same name.",
- },
- styles: {
- width: "200px",
- },
- })
- .addCell(3, 0, {
- tag: "label",
- namespace: "html",
- attributes: {
- for: "dialog-checkbox",
- },
- properties: { innerHTML: "bind:checkbox" },
- })
- .addCell(
- 3,
- 1,
- {
- tag: "input",
- namespace: "html",
- id: "dialog-checkbox",
- attributes: {
- "data-bind": "checkboxValue",
- "data-prop": "checked",
- type: "checkbox",
- },
- properties: { label: "Cell 1,0" },
- },
- false,
- )
- .addCell(4, 0, {
- tag: "label",
- namespace: "html",
- attributes: {
- for: "dialog-input",
- },
- properties: { innerHTML: "bind:input" },
- })
- .addCell(
- 4,
- 1,
- {
- tag: "input",
- namespace: "html",
- id: "dialog-input",
- attributes: {
- "data-bind": "inputValue",
- "data-prop": "value",
- type: "text",
- },
- },
- false,
- )
- .addCell(5, 0, {
- tag: "h2",
- properties: { innerHTML: "Toolkit Helper Examples" },
- })
- .addCell(
- 6,
- 0,
- {
- tag: "button",
- namespace: "html",
- attributes: {
- type: "button",
- },
- listeners: [
- {
- type: "click",
- listener: (e: Event) => {
- addon.hooks.onDialogEvents("clipboardExample");
- },
- },
- ],
- children: [
- {
- tag: "div",
- styles: {
- padding: "2.5px 15px",
- },
- properties: {
- innerHTML: "example:clipboard",
- },
- },
- ],
- },
- false,
- )
- .addCell(
- 7,
- 0,
- {
- tag: "button",
- namespace: "html",
- attributes: {
- type: "button",
- },
- listeners: [
- {
- type: "click",
- listener: (e: Event) => {
- addon.hooks.onDialogEvents("filePickerExample");
- },
- },
- ],
- children: [
- {
- tag: "div",
- styles: {
- padding: "2.5px 15px",
- },
- properties: {
- innerHTML: "example:filepicker",
- },
- },
- ],
- },
- false,
- )
- .addCell(
- 8,
- 0,
- {
- tag: "button",
- namespace: "html",
- attributes: {
- type: "button",
- },
- listeners: [
- {
- type: "click",
- listener: (e: Event) => {
- addon.hooks.onDialogEvents("progressWindowExample");
- },
- },
- ],
- children: [
- {
- tag: "div",
- styles: {
- padding: "2.5px 15px",
- },
- properties: {
- innerHTML: "example:progressWindow",
- },
- },
- ],
- },
- false,
- )
- .addCell(
- 9,
- 0,
- {
- tag: "button",
- namespace: "html",
- attributes: {
- type: "button",
- },
- listeners: [
- {
- type: "click",
- listener: (e: Event) => {
- addon.hooks.onDialogEvents("vtableExample");
- },
- },
- ],
- children: [
- {
- tag: "div",
- styles: {
- padding: "2.5px 15px",
- },
- properties: {
- innerHTML: "example:virtualized-table",
- },
- },
- ],
- },
- false,
- )
- .addButton("Confirm", "confirm")
- .addButton("Cancel", "cancel")
- .addButton("Help", "help", {
- noClose: true,
- callback: (e) => {
- dialogHelper.window?.alert(
- "Help Clicked! Dialog will not be closed.",
- );
- },
- })
- .setDialogData(dialogData)
- .open("Dialog Example");
- addon.data.dialog = dialogHelper;
- await dialogData.unloadLock.promise;
- addon.data.dialog = undefined;
- addon.data.alive &&
- ztoolkit.getGlobal("alert")(
- `Close dialog with ${dialogData._lastButtonId}.\nCheckbox: ${dialogData.checkboxValue}\nInput: ${dialogData.inputValue}.`,
- );
- ztoolkit.log(dialogData);
- }
-
- @example
- static clipboardExample() {
- new ztoolkit.Clipboard()
- .addText(
- "![Plugin Template](https://github.com/windingwind/zotero-plugin-template)",
- "text/unicode",
- )
- .addText(
- 'Plugin Template',
- "text/html",
- )
- .copy();
- ztoolkit.getGlobal("alert")("Copied!");
- }
-
- @example
- static async filePickerExample() {
- const path = await new ztoolkit.FilePicker(
- "Import File",
- "open",
- [
- ["PNG File(*.png)", "*.png"],
- ["Any", "*.*"],
- ],
- "image.png",
- ).open();
- ztoolkit.getGlobal("alert")(`Selected ${path}`);
- }
-
- @example
- static progressWindowExample() {
- new ztoolkit.ProgressWindow(config.addonName)
- .createLine({
- text: "ProgressWindow Example!",
- type: "success",
- progress: 100,
- })
- .show();
- }
-
- @example
- static vtableExample() {
- ztoolkit.getGlobal("alert")("See src/modules/preferenceScript.ts");
+ icon: menuIcon,
+ });
}
-}
+}
\ No newline at end of file
diff --git a/src/modules/preferenceScript.ts b/src/modules/preferenceScript.ts
index ef6e5b9..3b478b2 100644
--- a/src/modules/preferenceScript.ts
+++ b/src/modules/preferenceScript.ts
@@ -6,33 +6,7 @@ export async function registerPrefsScripts(_window: Window) {
// See addon/chrome/content/preferences.xul onpaneload
if (!addon.data.prefs) {
addon.data.prefs = {
- window: _window,
- columns: [
- {
- dataKey: "title",
- label: getString("prefs-table-title"),
- fixedWidth: true,
- width: 100,
- },
- {
- dataKey: "detail",
- label: getString("prefs-table-detail"),
- },
- ],
- rows: [
- {
- title: "Orange",
- detail: "It's juicy",
- },
- {
- title: "Banana",
- detail: "It's sweet",
- },
- {
- title: "Apple",
- detail: "I mean the fruit APPLE",
- },
- ],
+ window: _window
};
} else {
addon.data.prefs.window = _window;
@@ -42,90 +16,12 @@ export async function registerPrefsScripts(_window: Window) {
}
async function updatePrefsUI() {
- // You can initialize some UI elements on prefs window
- // with addon.data.prefs.window.document
- // Or bind some events to the elements
const renderLock = ztoolkit.getGlobal("Zotero").Promise.defer();
if (addon.data.prefs?.window == undefined) return;
- const tableHelper = new ztoolkit.VirtualizedTable(addon.data.prefs?.window)
- .setContainerId(`${config.addonRef}-table-container`)
- .setProp({
- id: `${config.addonRef}-prefs-table`,
- // Do not use setLocale, as it modifies the Zotero.Intl.strings
- // Set locales directly to columns
- columns: addon.data.prefs?.columns,
- showHeader: true,
- multiSelect: true,
- staticColumns: true,
- disableFontSizeScaling: true,
- })
- .setProp("getRowCount", () => addon.data.prefs?.rows.length || 0)
- .setProp(
- "getRowData",
- (index) =>
- addon.data.prefs?.rows[index] || {
- title: "no data",
- detail: "no data",
- },
- )
- // Show a progress window when selection changes
- .setProp("onSelectionChange", (selection) => {
- new ztoolkit.ProgressWindow(config.addonName)
- .createLine({
- text: `Selected line: ${addon.data.prefs?.rows
- .filter((v, i) => selection.isSelected(i))
- .map((row) => row.title)
- .join(",")}`,
- progress: 100,
- })
- .show();
- })
- // When pressing delete, delete selected line and refresh table.
- // Returning false to prevent default event.
- .setProp("onKeyDown", (event: KeyboardEvent) => {
- if (event.key == "Delete" || (Zotero.isMac && event.key == "Backspace")) {
- addon.data.prefs!.rows =
- addon.data.prefs?.rows.filter(
- (v, i) => !tableHelper.treeInstance.selection.isSelected(i),
- ) || [];
- tableHelper.render();
- return false;
- }
- return true;
- })
- // For find-as-you-type
- .setProp(
- "getRowString",
- (index) => addon.data.prefs?.rows[index].title || "",
- )
- // Render the table.
- .render(-1, () => {
- renderLock.resolve();
- });
+
await renderLock.promise;
- ztoolkit.log("Preference table rendered!");
}
function bindPrefEvents() {
- addon.data
- .prefs!.window.document.querySelector(
- `#zotero-prefpane-${config.addonRef}-enable`,
- )
- ?.addEventListener("command", (e) => {
- ztoolkit.log(e);
- addon.data.prefs!.window.alert(
- `Successfully changed to ${(e.target as XUL.Checkbox).checked}!`,
- );
- });
- addon.data
- .prefs!.window.document.querySelector(
- `#zotero-prefpane-${config.addonRef}-input`,
- )
- ?.addEventListener("change", (e) => {
- ztoolkit.log(e);
- addon.data.prefs!.window.alert(
- `Successfully changed to ${(e.target as HTMLInputElement).value}!`,
- );
- });
}
diff --git a/src/tasks.ts b/src/tasks.ts
new file mode 100644
index 0000000..81d451d
--- /dev/null
+++ b/src/tasks.ts
@@ -0,0 +1,27 @@
+export interface MenuTask {
+ id: string,
+ pdfUrl: string
+}
+
+export function addMenuTask(
+ itemId: number
+) {
+ const item = Zotero.Items.get(itemId);
+ // item.getBestAttachment()
+ if (item?.isRegularItem()) {
+ const attachments = item.getAttachments();
+ if (attachments && attachments.length) {
+ const attachment = Zotero.Items.get(attachments[0]);
+
+ if (attachment.isPDFAttachment()) {
+ const newTask: MenuTask = {
+ id: item.getField("id") as string,
+ pdfUrl: attachment.getFilePath() as string
+ };
+ ztoolkit.log("MenuTask -----------------------------------------------------");
+ ztoolkit.log(newTask)
+ return newTask
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/update.json b/update.json
index f5c857f..1f4339c 100644
--- a/update.json
+++ b/update.json
@@ -1,10 +1,10 @@
{
"addons": {
- "addontemplate@euclpts.com": {
+ "ZoteroActionCMD": {
"updates": [
{
- "version": "1.0.2",
- "update_link": "https://github.com/windingwind/zotero-addon-template/releases/latest/download/zotero-addon-template.xpi",
+ "version": "1.0.0",
+ "update_link": "https://github.com/Bowen-0x00/zotero-action-cmd/releases/latest/download/zotero-action-cmd.xpi",
"applications": {
"zotero": {
"strict_min_version": "6.999"