From 792263726dde32a7e3cc9666ab71d96ee471074d Mon Sep 17 00:00:00 2001 From: MuiseDestiny <51939531+MuiseDestiny@users.noreply.github.com> Date: Sat, 18 Feb 2023 21:42:39 +0800 Subject: [PATCH 1/4] add: Prompt exapmles --- src/hooks.ts | 6 +- src/modules/examples.ts | 195 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 198 insertions(+), 3 deletions(-) diff --git a/src/hooks.ts b/src/hooks.ts index c8e8fe3..7460532 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -64,7 +64,11 @@ async function onStartup() { await UIExampleFactory.registerReaderTabPanel(); - PromptExampleFactory.registerAlertPromptExample(); + PromptExampleFactory.registerNormalCommandExample(); + + PromptExampleFactory.registerAnonymousCommandExample(); + + PromptExampleFactory.registerConditionalComandExample(); await Zotero.Promise.delay(1000); diff --git a/src/modules/examples.ts b/src/modules/examples.ts index d5d7eed..85fa7a2 100644 --- a/src/modules/examples.ts +++ b/src/modules/examples.ts @@ -464,10 +464,10 @@ export class UIExampleFactory { export class PromptExampleFactory { @example - static registerAlertPromptExample() { + static registerNormalCommandExample() { ztoolkit.Prompt.register([ { - name: "Template Test", + name: "Normal Command Test", label: "Plugin Template", callback(prompt) { ztoolkit.getGlobal("alert")("Command triggered!"); @@ -475,6 +475,197 @@ export class PromptExampleFactory { }, ]); } + + @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) { + var nodes = []; + var str = ""; + var author, authorDate = ""; + if (item.firstCreator) { author = authorDate = item.firstCreator; } + var 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); + + var publicationTitle = item.getField("publicationTitle", false, true); + if (publicationTitle) { + nodes.push(`${publicationTitle}`); + } + var volumeIssue = item.getField("volume"); + var issue = item.getField("issue"); + if (issue) volumeIssue += "(" + issue + ")"; + if (volumeIssue) nodes.push(volumeIssue); + + var publisherPlace = [], field; + if ((field = item.getField("publisher"))) publisherPlace.push(field); + if ((field = item.getField("place"))) publisherPlace.push(field); + if (publisherPlace.length) nodes.push(publisherPlace.join(": ")); + + var pages = item.getField("pages"); + if (pages) nodes.push(pages); + + if (!nodes.length) { + var url = item.getField("url"); + if (url) nodes.push(url); + } + + // compile everything together + for (var i = 0, n = nodes.length; i < n; i++) { + var node = nodes[i]; + + if (i != 0) str += ", "; + + if (typeof node === "object") { + var 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) + return item.isRegularItem() && !item.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 + 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 + text.split(/\s*&&\s*/g).forEach((conditinString: string) => { + let conditions = conditinString.split(/\s+/g); + if (conditions.length == 3 && operators.indexOf(conditions[1]) != -1) { + hasValidCondition = true + 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 + 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 + prompt.exit() + prompt.showTip("Not Found.") + } + } + }]) + } + + @example + static registerConditionalComandExample() { + 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 { From 8be6b0ba491e75cbe7863a15f630fe1f33571d0e Mon Sep 17 00:00:00 2001 From: MuiseDestiny <51939531+MuiseDestiny@users.noreply.github.com> Date: Sat, 18 Feb 2023 21:48:13 +0800 Subject: [PATCH 2/4] Fix: spelling error --- src/modules/examples.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/examples.ts b/src/modules/examples.ts index 85fa7a2..237766c 100644 --- a/src/modules/examples.ts +++ b/src/modules/examples.ts @@ -643,7 +643,7 @@ export class PromptExampleFactory { } @example - static registerConditionalComandExample() { + static registerConditionalCommandExample() { ztoolkit.Prompt.register([ { name: "Conditional Command Test", From 2ff86f92db5367b98ea3295a5b879d85e373d008 Mon Sep 17 00:00:00 2001 From: MuiseDestiny <51939531+MuiseDestiny@users.noreply.github.com> Date: Sat, 18 Feb 2023 21:49:09 +0800 Subject: [PATCH 3/4] Fix: spelling error --- src/hooks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks.ts b/src/hooks.ts index 7460532..6f48853 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -68,7 +68,7 @@ async function onStartup() { PromptExampleFactory.registerAnonymousCommandExample(); - PromptExampleFactory.registerConditionalComandExample(); + PromptExampleFactory.registerConditionalCommandExample(); await Zotero.Promise.delay(1000); From 6467a120899680ef873914cb3556bfdc0a764472 Mon Sep 17 00:00:00 2001 From: MuiseDestiny <51939531+MuiseDestiny@users.noreply.github.com> Date: Sat, 18 Feb 2023 22:03:55 +0800 Subject: [PATCH 4/4] add: registerAnonymousCommandExample logic or --- src/modules/examples.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/examples.ts b/src/modules/examples.ts index 237766c..df274aa 100644 --- a/src/modules/examples.ts +++ b/src/modules/examples.ts @@ -558,10 +558,15 @@ export class PromptExampleFactory { const s = new Zotero.Search(); const operators = ['is', 'isNot', 'true', 'false', 'isInTheLast', 'isBefore', 'isAfter', 'contains', 'doesNotContain', 'beginsWith']; let hasValidCondition = false - text.split(/\s*&&\s*/g).forEach((conditinString: string) => { + let joinMode: string = "all" + if (/\s*\|\|\s*/.test(text)) { + joinMode = "any" + } + text.split(/\s*(&&|\|\|)\s*/g).forEach((conditinString: string) => { let conditions = conditinString.split(/\s+/g); if (conditions.length == 3 && operators.indexOf(conditions[1]) != -1) { hasValidCondition = true + s.addCondition("joinMode", joinMode); s.addCondition( conditions[0] as string, conditions[1] as Zotero.Search.Operator,