change: using plugin toolkit for migration zo 6->7
This commit is contained in:
parent
c2f63fcd11
commit
b7b3c66749
|
|
@ -51,14 +51,15 @@
|
|||
"unified": "^10.1.2",
|
||||
"unist-util-visit": "^4.1.1",
|
||||
"unist-util-visit-parents": "^5.1.1",
|
||||
"yamljs": "^0.3.0"
|
||||
"yamljs": "^0.3.0",
|
||||
"zotero-plugin-toolkit": "^0.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/diff": "^5.0.2",
|
||||
"@types/jquery": "^3.5.14",
|
||||
"@types/node": "^17.0.31",
|
||||
"esbuild": "^0.14.34",
|
||||
"compressing": "^1.5.1",
|
||||
"esbuild": "^0.14.34",
|
||||
"release-it": "^14.14.0",
|
||||
"zotero-types": "^0.1.2"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import EditorController from "./editor/editorController";
|
|||
import EditorImageViewer from "./editor/imageViewerWindow";
|
||||
import TemplateWindow from "./template/templateWindow";
|
||||
import { SyncUtils } from "./sync/syncUtils";
|
||||
import ZoteroToolkit from "zotero-plugin-toolkit";
|
||||
|
||||
class Knowledge4Zotero {
|
||||
public ZoteroEvents: ZoteroEvents;
|
||||
|
|
@ -58,6 +59,8 @@ class Knowledge4Zotero {
|
|||
public EditorController: EditorController;
|
||||
public EditorImageViewer: EditorImageViewer;
|
||||
|
||||
public toolkit: ZoteroToolkit;
|
||||
|
||||
constructor() {
|
||||
this.ZoteroEvents = new ZoteroEvents(this);
|
||||
this.ZoteroViews = new ZoteroViews(this);
|
||||
|
|
@ -82,6 +85,10 @@ class Knowledge4Zotero {
|
|||
this.NoteExportWindow = new NoteExportWindow(this);
|
||||
this.NoteParse = new NoteParse(this);
|
||||
this.knowledge = new TemplateAPI(this);
|
||||
|
||||
this.toolkit = new ZoteroToolkit();
|
||||
// Disable since we are still using overlay
|
||||
this.toolkit.UI.enableElementRecordGlobal = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,10 @@ class EditorController extends AddonBase {
|
|||
|
||||
injectScripts(_window: Window) {
|
||||
if (!_window.document.getElementById("betternotes-script")) {
|
||||
const messageScript = _window.document.createElement("script");
|
||||
const messageScript = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"script"
|
||||
) as HTMLScriptElement;
|
||||
messageScript.id = "betternotes-script";
|
||||
messageScript.innerHTML = `__placeholder:editorScript.js__`;
|
||||
_window.document.head.append(messageScript);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import { CopyHelper, EditorMessage } from "../utils";
|
||||
import { EditorMessage } from "../utils";
|
||||
import AddonBase from "../module";
|
||||
|
||||
class EditorViews extends AddonBase {
|
||||
|
|
@ -95,13 +95,19 @@ class EditorViews extends AddonBase {
|
|||
setMainNoteDropDown,
|
||||
"left"
|
||||
);
|
||||
const titleNode = _window.document.createElement("div");
|
||||
const titleNode = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
titleNode.innerHTML = "Set Recent Main Notes";
|
||||
titleNode.title = "Click item to set it main note";
|
||||
titleNode.style.textAlign = "center";
|
||||
popup.childNodes[0].before(
|
||||
titleNode,
|
||||
_window.document.createElement("hr")
|
||||
this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"hr"
|
||||
) as HTMLHRElement
|
||||
);
|
||||
setMainNoteDropDown.addEventListener("mouseleave", (e) => {
|
||||
popup.remove();
|
||||
|
|
@ -125,7 +131,10 @@ class EditorViews extends AddonBase {
|
|||
if (isMainNote) {
|
||||
// This is a main knowledge, hide all buttons except the export button and add title
|
||||
addLinkDropDown.innerHTML = "";
|
||||
const header = _window.document.createElement("div");
|
||||
const header = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
header.setAttribute("title", "This is a Main Note");
|
||||
header.innerHTML = "Main Note";
|
||||
header.setAttribute("style", "font-size: medium");
|
||||
|
|
@ -290,7 +299,10 @@ class EditorViews extends AddonBase {
|
|||
);
|
||||
|
||||
// Title style only for normal window
|
||||
const style = _window.document.createElement("style");
|
||||
const style = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"style"
|
||||
) as HTMLStyleElement;
|
||||
style.id = "bn-headings";
|
||||
style.innerHTML = `
|
||||
.primary-editor h1::before {
|
||||
|
|
@ -344,7 +356,10 @@ class EditorViews extends AddonBase {
|
|||
) {
|
||||
const dropdownPopup = moreDropdown.querySelector(".popup");
|
||||
if (dropdownPopup) {
|
||||
const refreshButton = _window.document.createElement("button");
|
||||
const refreshButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
refreshButton.classList.add("option");
|
||||
refreshButton.innerText = "Refresh Editor";
|
||||
refreshButton.addEventListener("click", (e) => {
|
||||
|
|
@ -366,7 +381,10 @@ class EditorViews extends AddonBase {
|
|||
state: instance._state,
|
||||
});
|
||||
});
|
||||
const previewButton = _window.document.createElement("button");
|
||||
const previewButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
previewButton.classList.add("option");
|
||||
previewButton.innerText = "Preview in Workspace";
|
||||
previewButton.addEventListener("click", async (e) => {
|
||||
|
|
@ -376,7 +394,10 @@ class EditorViews extends AddonBase {
|
|||
instance._item
|
||||
);
|
||||
});
|
||||
const copyLinkButton = _window.document.createElement("button");
|
||||
const copyLinkButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
copyLinkButton.classList.add("option");
|
||||
copyLinkButton.innerText = "Copy Note Link";
|
||||
copyLinkButton.addEventListener("click", (e) => {
|
||||
|
|
@ -387,7 +408,7 @@ class EditorViews extends AddonBase {
|
|||
: linkText
|
||||
}</a></p>`;
|
||||
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(linkText, "text/unicode")
|
||||
.addText(linkHTML, "text/html")
|
||||
.copy();
|
||||
|
|
@ -397,8 +418,10 @@ class EditorViews extends AddonBase {
|
|||
);
|
||||
});
|
||||
|
||||
const copyLinkAtLineButton =
|
||||
_window.document.createElement("button");
|
||||
const copyLinkAtLineButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
copyLinkAtLineButton.classList.add("option");
|
||||
copyLinkAtLineButton.innerText = "Copy Note Link of Current Line";
|
||||
copyLinkAtLineButton.addEventListener("click", (e) => {
|
||||
|
|
@ -410,7 +433,7 @@ class EditorViews extends AddonBase {
|
|||
? noteItem.getNoteTitle().trim()
|
||||
: linkText
|
||||
}</a></p>`;
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(linkText, "text/unicode")
|
||||
.addText(linkHTML, "text/html")
|
||||
.copy();
|
||||
|
|
@ -421,7 +444,10 @@ class EditorViews extends AddonBase {
|
|||
} Copied`
|
||||
);
|
||||
});
|
||||
const importButton = _window.document.createElement("button");
|
||||
const importButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
importButton.classList.add("option");
|
||||
importButton.innerText = "Import from MarkDown";
|
||||
importButton.addEventListener("click", async (e) => {
|
||||
|
|
@ -457,16 +483,28 @@ class EditorViews extends AddonBase {
|
|||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const _document = editorInstances._iframeWindow.document;
|
||||
const knowledgeToolBar = _document.createElement("div");
|
||||
const knowledgeToolBar = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
knowledgeToolBar.setAttribute("id", "knowledge-tools");
|
||||
knowledgeToolBar.setAttribute("class", "toolbar");
|
||||
const start = _document.createElement("div");
|
||||
const start = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
start.setAttribute("id", "knowledge-tools-start");
|
||||
start.setAttribute("class", "start");
|
||||
const middle = _document.createElement("div");
|
||||
const middle = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
middle.setAttribute("id", "knowledge-tools-middle");
|
||||
middle.setAttribute("class", "middle");
|
||||
const end = _document.createElement("div");
|
||||
const end = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
end.setAttribute("id", "knowledge-tools-end");
|
||||
end.setAttribute("class", "end");
|
||||
knowledgeToolBar.append(start, middle, end);
|
||||
|
|
@ -506,10 +544,16 @@ class EditorViews extends AddonBase {
|
|||
(e) => e.getAttribute("id") !== `knowledge-tools-${position}`
|
||||
);
|
||||
}
|
||||
const dropdown = _document.createElement("div");
|
||||
const dropdown = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
dropdown.setAttribute("class", "dropdown");
|
||||
dropdown.setAttribute("id", id);
|
||||
const button = _document.createElement("button");
|
||||
const button = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
button.setAttribute("class", "toolbar-button");
|
||||
button.setAttribute("title", title);
|
||||
button.setAttribute("eventType", eventType);
|
||||
|
|
@ -544,11 +588,17 @@ class EditorViews extends AddonBase {
|
|||
if (!knowledgeToolBar) {
|
||||
await this.addEditorToolBar(editorInstances);
|
||||
}
|
||||
const popup = _document.createElement("div");
|
||||
const popup = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
popup.setAttribute("class", "popup");
|
||||
popup.setAttribute("id", id);
|
||||
for (let buttonParam of buttons) {
|
||||
const button = _document.createElement("button");
|
||||
const button = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
button.setAttribute("class", "option");
|
||||
button.setAttribute(
|
||||
"style",
|
||||
|
|
@ -604,7 +654,10 @@ class EditorViews extends AddonBase {
|
|||
if (insertButton) {
|
||||
insertButton.remove();
|
||||
}
|
||||
insertButton = _window.document.createElement("button");
|
||||
insertButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
insertButton.setAttribute("id", insertButtonId);
|
||||
insertButton.setAttribute(
|
||||
"title",
|
||||
|
|
@ -700,7 +753,10 @@ class EditorViews extends AddonBase {
|
|||
if (updateButton) {
|
||||
updateButton.remove();
|
||||
}
|
||||
updateButton = _window.document.createElement("button");
|
||||
updateButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
updateButton.setAttribute("id", updateButtonId);
|
||||
updateButton.setAttribute(
|
||||
"title",
|
||||
|
|
@ -765,7 +821,10 @@ class EditorViews extends AddonBase {
|
|||
if (openInWindowButton) {
|
||||
openInWindowButton.remove();
|
||||
}
|
||||
openInWindowButton = _window.document.createElement("button");
|
||||
openInWindowButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
openInWindowButton.setAttribute("id", openInWindowButtonId);
|
||||
openInWindowButton.setAttribute("title", "Open In New Window");
|
||||
openInWindowButton.innerHTML = this.icons["openInNewWindow"];
|
||||
|
|
@ -788,10 +847,10 @@ class EditorViews extends AddonBase {
|
|||
if (previewContainer) {
|
||||
previewContainer.remove();
|
||||
}
|
||||
previewContainer = _window.document.createElementNS(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
previewContainer = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"div"
|
||||
);
|
||||
) as HTMLDivElement;
|
||||
previewContainer.id = "note-link-preview";
|
||||
previewContainer.className = "ProseMirror primary-editor";
|
||||
previewContainer.innerHTML =
|
||||
|
|
@ -840,7 +899,10 @@ class EditorViews extends AddonBase {
|
|||
const _window = instance._iframeWindow;
|
||||
|
||||
_window.document.querySelector("#bn-image-preview")?.remove();
|
||||
const previewButton = _window.document.createElement("button");
|
||||
const previewButton = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"button"
|
||||
) as HTMLButtonElement;
|
||||
previewButton.innerHTML = `<div class="icon"><svg t="1668689809930" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8872" width="16" height="16"><path d="M978.346667 149.333333c0 11.776-9.557333 21.333333-21.333333 21.333333L167.68 170.666667l0 448c0 35.285333 28.714667 64 64 64l554.666667 0c35.285333 0 64-28.714667 64-42.666667l0-154.496L850.346667 356.309333 850.346667 277.930667c0-11.776 9.557333-21.333333 21.333333-21.333333s21.333333 9.557333 21.333333 21.333333l0 78.378667 0 129.194667L893.013333 640c0 37.504-47.829333 85.333333-106.666667 85.333333l-205.568 0 169.557333 169.514667c8.32 8.32 8.32 21.845333 0 30.165333-8.362667 8.362667-21.845333 8.362667-30.208 0L520.405333 725.333333l-16.810667 0-199.722667 199.68c-8.32 8.362667-21.845333 8.362667-30.165333 0-8.32-8.32-8.32-21.845333 0-30.165333L443.306667 725.333333 231.68 725.333333c-58.837333 0-106.666667-47.829333-106.666667-106.666667L125.013333 170.666667l-64 0c-11.776 0-21.333333-9.557333-21.333333-21.333333S49.194667 128 61.013333 128l405.333333 0L466.346667 85.333333l85.333333 0 0 42.666667 405.333333 0C968.789333 128 978.346667 137.557333 978.346667 149.333333zM618.666667 405.333333l-194.986667-128 0 256L618.666667 405.333333z" p-id="8873"></path></svg>Preview</div>`;
|
||||
previewButton.id = "bn-image-preview";
|
||||
previewButton.addEventListener("click", (e) => {
|
||||
|
|
@ -904,7 +966,7 @@ class EditorViews extends AddonBase {
|
|||
);
|
||||
};
|
||||
|
||||
const elementOptions: XULElementOptions = {
|
||||
const elementOptions = {
|
||||
tag: "fragment",
|
||||
subElementOptions: [
|
||||
{
|
||||
|
|
@ -918,12 +980,12 @@ class EditorViews extends AddonBase {
|
|||
id: "menupopup-resizeImage",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [["label", "Resize Image"]],
|
||||
attributes: { label: "Resize Image" },
|
||||
customCheck: checkImageSelected,
|
||||
listeners: [
|
||||
[
|
||||
"command",
|
||||
(e) => {
|
||||
{
|
||||
type: "command",
|
||||
listener: (e: Event) => {
|
||||
const newWidth = parseFloat(
|
||||
prompt(
|
||||
"Enter new width (px):",
|
||||
|
|
@ -939,8 +1001,7 @@ class EditorViews extends AddonBase {
|
|||
);
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -955,11 +1016,11 @@ class EditorViews extends AddonBase {
|
|||
id: "menupopup-copylink",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [["label", "Copy Note Link"]],
|
||||
attributes: { label: "Copy Note Link" },
|
||||
listeners: [
|
||||
[
|
||||
"command",
|
||||
(e) => {
|
||||
{
|
||||
type: "command",
|
||||
listener: (e: Event) => {
|
||||
const linkText = this._Addon.NoteUtils.getNoteLink(noteItem);
|
||||
const linkHTML = `<p><a href="${linkText}" rel="noopener noreferrer nofollow">${
|
||||
noteItem.getNoteTitle().trim()
|
||||
|
|
@ -967,7 +1028,7 @@ class EditorViews extends AddonBase {
|
|||
: linkText
|
||||
}</a></p>`;
|
||||
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(linkText, "text/unicode")
|
||||
.addText(linkHTML, "text/html")
|
||||
.copy();
|
||||
|
|
@ -976,8 +1037,7 @@ class EditorViews extends AddonBase {
|
|||
"Note Link Copied"
|
||||
);
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -985,11 +1045,11 @@ class EditorViews extends AddonBase {
|
|||
id: "menupopup-copylinkline",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [["label", `Copy Note Link of Line ${lineIndex + 1}`]],
|
||||
attributes: { label: `Copy Note Link of Line ${lineIndex + 1}` },
|
||||
listeners: [
|
||||
[
|
||||
"command",
|
||||
(e) => {
|
||||
{
|
||||
type: "command",
|
||||
listener: ((e: Event) => {
|
||||
const linkText = this._Addon.NoteUtils.getNoteLink(noteItem, {
|
||||
withLine: true,
|
||||
});
|
||||
|
|
@ -998,7 +1058,7 @@ class EditorViews extends AddonBase {
|
|||
? noteItem.getNoteTitle().trim()
|
||||
: linkText
|
||||
}</a></p>`;
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(linkText, "text/unicode")
|
||||
.addText(linkHTML, "text/html")
|
||||
.copy();
|
||||
|
|
@ -1006,9 +1066,8 @@ class EditorViews extends AddonBase {
|
|||
"Better Notes",
|
||||
`Note Link of Line ${lineIndex + 1} Copied`
|
||||
);
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
}) as EventListener,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -1016,18 +1075,15 @@ class EditorViews extends AddonBase {
|
|||
id: "menupopup-insertTextTemplateMenu",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [["label", "Insert Template (Text)"]],
|
||||
attributes: { label: "Insert Template (Text)" },
|
||||
subElementOptions: [
|
||||
{
|
||||
tag: "menupopup",
|
||||
id: `menu_insert${instance._item.id}TextTemplatePopup`,
|
||||
ignoreIfExists: true,
|
||||
attributes: [
|
||||
[
|
||||
"onpopupshowing",
|
||||
`Zotero.Knowledge4Zotero.ZoteroViews.updateTemplateMenu('Text', Zotero.Knowledge4Zotero.EditorController.activeEditor._popup.ownerDocument, '${instance._item.id}', false);`,
|
||||
],
|
||||
],
|
||||
attributes: {
|
||||
onpopupshowing: `Zotero.Knowledge4Zotero.ZoteroViews.updateTemplateMenu('Text', Zotero.Knowledge4Zotero.EditorController.activeEditor._popup.ownerDocument, '${instance._item.id}', false);`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -1036,18 +1092,15 @@ class EditorViews extends AddonBase {
|
|||
id: "menupopup-insertItemTemplate",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [["label", "Insert Template (Item)"]],
|
||||
attributes: { label: "Insert Template (Item)" },
|
||||
subElementOptions: [
|
||||
{
|
||||
tag: "menupopup",
|
||||
id: `menu_insert${instance._item.id}ItemTemplatePopup`,
|
||||
ignoreIfExists: true,
|
||||
attributes: [
|
||||
[
|
||||
"onpopupshowing",
|
||||
`Zotero.Knowledge4Zotero.ZoteroViews.updateTemplateMenu('Item', Zotero.Knowledge4Zotero.EditorController.activeEditor._popup.ownerDocument, '${instance._item.id}', false);`,
|
||||
],
|
||||
],
|
||||
attributes: {
|
||||
onpopupshowing: `Zotero.Knowledge4Zotero.ZoteroViews.updateTemplateMenu('Item', Zotero.Knowledge4Zotero.EditorController.activeEditor._popup.ownerDocument, '${instance._item.id}', false);`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -1062,49 +1115,42 @@ class EditorViews extends AddonBase {
|
|||
id: "menupopup-lineprevious",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [
|
||||
[
|
||||
"label",
|
||||
`L${lineIndex + 1}:${shorten(
|
||||
lineElements[lineIndex].innerText,
|
||||
25
|
||||
)}`,
|
||||
],
|
||||
["disabled", true],
|
||||
],
|
||||
attributes: {
|
||||
label: `L${lineIndex + 1}:${shorten(
|
||||
lineElements[lineIndex].innerText,
|
||||
25
|
||||
)}`,
|
||||
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
tag: "menuitem",
|
||||
id: "menupopup-insertposition",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [
|
||||
["label", "<--- Insert Anchor"],
|
||||
["disabled", true],
|
||||
],
|
||||
attributes: { label: "<--- Insert Anchor", disabled: true },
|
||||
},
|
||||
{
|
||||
tag: "menuitem",
|
||||
id: "menupopup-linenext",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [
|
||||
[
|
||||
"label",
|
||||
attributes: {
|
||||
label:
|
||||
lineIndex + 1 >= lineElements.length
|
||||
? "End of Note"
|
||||
: `L${lineIndex + 2}:${shorten(
|
||||
lineElements[lineIndex + 1].innerText,
|
||||
25
|
||||
)}`,
|
||||
],
|
||||
["disabled", true],
|
||||
],
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const fragment = this._Addon.ZoteroViews.createXULElement(
|
||||
const fragment = this._Addon.toolkit.UI.creatElementsFromJSON(
|
||||
instance._popup.ownerDocument,
|
||||
elementOptions
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import AddonBase from "../module";
|
||||
import { CopyHelper, pick } from "../utils";
|
||||
|
||||
class EditorImageViewer extends AddonBase {
|
||||
_window: Window;
|
||||
|
|
@ -87,7 +86,9 @@ class EditorImageViewer extends AddonBase {
|
|||
this._window.document
|
||||
.querySelector("#copy")
|
||||
.addEventListener("click", (e) => {
|
||||
new CopyHelper().addImage(this.srcList[this.idx]).copy();
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addImage(this.srcList[this.idx])
|
||||
.copy();
|
||||
this._Addon.ZoteroViews.showProgressWindow(
|
||||
"Better Notes",
|
||||
"Image Copied."
|
||||
|
|
@ -108,7 +109,7 @@ class EditorImageViewer extends AddonBase {
|
|||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
let ext = Zotero.MIME.getPrimaryExtension(mime, "");
|
||||
const filename = await pick(
|
||||
const filename = await this._Addon.toolkit.Tool.openFilePicker(
|
||||
Zotero.getString("noteEditor.saveImageAs"),
|
||||
"save",
|
||||
[[`Image(*.${ext})`, `*.${ext}`]],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
*/
|
||||
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import { pick } from "../utils";
|
||||
import AddonBase from "../module";
|
||||
|
||||
class NoteExport extends AddonBase {
|
||||
|
|
@ -84,7 +83,7 @@ class NoteExport extends AddonBase {
|
|||
}
|
||||
|
||||
if (options.exportMD) {
|
||||
const filename = await pick(
|
||||
const filename = await this._Addon.toolkit.Tool.openFilePicker(
|
||||
`${Zotero.getString("fileInterface.export")} MarkDown Document`,
|
||||
"save",
|
||||
[["MarkDown File(*.md)", "*.md"]],
|
||||
|
|
@ -109,7 +108,7 @@ class NoteExport extends AddonBase {
|
|||
instance._iframeWindow.postMessage({ type: "exportDocx" }, "*");
|
||||
await this._docxPromise.promise;
|
||||
console.log(this._docxBlob);
|
||||
const filename = await pick(
|
||||
const filename = await this._Addon.toolkit.Tool.openFilePicker(
|
||||
`${Zotero.getString("fileInterface.export")} MS Word Document`,
|
||||
"save",
|
||||
[["MS Word Document(*.docx)", "*.docx"]],
|
||||
|
|
@ -160,7 +159,7 @@ class NoteExport extends AddonBase {
|
|||
}
|
||||
}
|
||||
if (options.exportFreeMind) {
|
||||
const filename = await pick(
|
||||
const filename = await this._Addon.toolkit.Tool.openFilePicker(
|
||||
`${Zotero.getString("fileInterface.export")} FreeMind`,
|
||||
"save",
|
||||
[["FreeMind(*.mm)", "*.mm"]],
|
||||
|
|
@ -196,7 +195,7 @@ class NoteExport extends AddonBase {
|
|||
this._exportFileInfo = [];
|
||||
let filedir =
|
||||
options.filedir ||
|
||||
(await pick(
|
||||
(await this._Addon.toolkit.Tool.openFilePicker(
|
||||
Zotero.getString(
|
||||
options.useSync ? "sync.sync" : "fileInterface.export"
|
||||
) + " MarkDown",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import AddonBase from "../module";
|
||||
import { pick } from "../utils";
|
||||
|
||||
class NoteImport extends AddonBase {
|
||||
constructor(parent: Knowledge4Zotero) {
|
||||
|
|
@ -18,7 +17,7 @@ class NoteImport extends AddonBase {
|
|||
append?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
const filepath = await pick(
|
||||
const filepath = await this._Addon.toolkit.Tool.openFilePicker(
|
||||
`${Zotero.getString("fileInterface.import")} MarkDown Document`,
|
||||
"open",
|
||||
[["MarkDown File(*.md)", "*.md"]]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ const asciidoctor = require("asciidoctor")();
|
|||
import YAML = require("yamljs");
|
||||
import AddonBase from "../module";
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import { getDOMParser } from "../utils";
|
||||
import { NodeMode } from "../sync/syncUtils";
|
||||
|
||||
class NoteParse extends AddonBase {
|
||||
|
|
@ -486,7 +485,7 @@ class NoteParse extends AddonBase {
|
|||
.join("\n")}</div>`;
|
||||
console.log(this.parseHTMLLines(item.getNote()).slice(0, lineCount));
|
||||
|
||||
let parser = getDOMParser();
|
||||
const parser = this._Addon.toolkit.Compat.getDOMParser();
|
||||
let doc = parser.parseFromString(note, "text/html");
|
||||
|
||||
// Make sure this is the new note
|
||||
|
|
@ -599,7 +598,7 @@ class NoteParse extends AddonBase {
|
|||
if (noteText.search(/data-schema-version/g) === -1) {
|
||||
noteText = `<div data-schema-version="8">${noteText}\n</div>`;
|
||||
}
|
||||
let parser = getDOMParser();
|
||||
const parser = this._Addon.toolkit.Compat.getDOMParser();
|
||||
let doc = parser.parseFromString(noteText, "text/html");
|
||||
|
||||
let metadataContainer: HTMLElement = doc.querySelector(
|
||||
|
|
@ -609,7 +608,7 @@ class NoteParse extends AddonBase {
|
|||
}
|
||||
|
||||
parseLineText(line: string): string {
|
||||
const parser = getDOMParser();
|
||||
const parser = this._Addon.toolkit.Compat.getDOMParser();
|
||||
try {
|
||||
if (line.search(/data-schema-version/g) === -1) {
|
||||
line = `<div data-schema-version="8">${line}</div>`;
|
||||
|
|
|
|||
|
|
@ -73,7 +73,10 @@ class NoteUtils extends AddonBase {
|
|||
lineIndex
|
||||
);
|
||||
const frag = _document.createDocumentFragment();
|
||||
const temp = _document.createElement("div");
|
||||
const temp = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
temp.innerHTML = text;
|
||||
while (temp.firstChild) {
|
||||
frag.appendChild(temp.firstChild);
|
||||
|
|
@ -365,7 +368,10 @@ class NoteUtils extends AddonBase {
|
|||
lineIndex
|
||||
);
|
||||
const frag = _document.createDocumentFragment();
|
||||
const temp = _document.createElement("div");
|
||||
const temp = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
temp.innerHTML = noteLines[lineIndex];
|
||||
while (temp.firstChild) {
|
||||
frag.appendChild(temp.firstChild);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ class ReaderViews extends AddonBase {
|
|||
continue;
|
||||
}
|
||||
moreButton.setAttribute("knowledgeinit", "true");
|
||||
const createNoteButton = _document.createElement("div");
|
||||
const createNoteButton = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
createNoteButton.setAttribute("style", "margin: 5px;");
|
||||
createNoteButton.title = "Quick Note";
|
||||
createNoteButton.innerHTML = this.icons["createNote"];
|
||||
|
|
@ -66,7 +69,10 @@ class ReaderViews extends AddonBase {
|
|||
moreButton.before(createNoteButton);
|
||||
if (annotationItem.annotationType === "image") {
|
||||
// Image OCR
|
||||
const ocrButton = _document.createElement("div");
|
||||
const ocrButton = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"div"
|
||||
) as HTMLDivElement;
|
||||
ocrButton.setAttribute("style", "margin: 5px;");
|
||||
ocrButton.innerHTML = this.icons["ocrTex"];
|
||||
ocrButton.title = "OCR LaTex";
|
||||
|
|
|
|||
|
|
@ -45,16 +45,26 @@ class SyncListWindow extends AddonBase {
|
|||
}
|
||||
for (const note of notes) {
|
||||
const syncInfo = this._Addon.SyncUtils.getSyncStatus(note);
|
||||
const listitem = this._window.document.createElement(
|
||||
"listitem"
|
||||
const listitem = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listitem",
|
||||
"xul"
|
||||
) as XUL.ListItem;
|
||||
listitem.setAttribute("id", note.id);
|
||||
|
||||
const icon = this._window.document.createElement("listcell");
|
||||
const icon = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listcell",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
icon.setAttribute("class", "listcell-iconic");
|
||||
icon.setAttribute("image", "chrome://zotero/skin/treeitem-note.png");
|
||||
|
||||
const name = this._window.document.createElement("listcell");
|
||||
const name = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listcell",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
name.setAttribute("label", `${note.getNoteTitle()}-${note.key}`);
|
||||
|
||||
let lastSyncString: string;
|
||||
|
|
@ -71,10 +81,18 @@ class SyncListWindow extends AddonBase {
|
|||
} else {
|
||||
lastSyncString = new Date(lastSyncTime).toLocaleString();
|
||||
}
|
||||
const lastSync = this._window.document.createElement("listcell");
|
||||
const lastSync = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listcell",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
lastSync.setAttribute("label", lastSyncString);
|
||||
|
||||
const syncPath = this._window.document.createElement("listcell");
|
||||
const syncPath = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listcell",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
syncPath.setAttribute(
|
||||
"label",
|
||||
`${decodeURIComponent(syncInfo.path)}/${decodeURIComponent(
|
||||
|
|
|
|||
|
|
@ -51,9 +51,17 @@ class TemplateWindow extends AddonBase {
|
|||
e.parentElement.removeChild(e);
|
||||
}
|
||||
for (const template of templates) {
|
||||
const listitem = this._window.document.createElement("listitem");
|
||||
const listitem = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listitem",
|
||||
"xul"
|
||||
) as XUL.ListItem;
|
||||
listitem.setAttribute("id", template.name);
|
||||
const name = this._window.document.createElement("listcell");
|
||||
const name = this._Addon.toolkit.UI.createElement(
|
||||
this._window.document,
|
||||
"listcell",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
name.setAttribute("label", template.name);
|
||||
if (
|
||||
this._Addon.TemplateController._systemTemplateNames.includes(
|
||||
|
|
|
|||
100
src/utils.ts
100
src/utils.ts
|
|
@ -27,104 +27,6 @@ class NoteTemplate {
|
|||
text?: string;
|
||||
}
|
||||
|
||||
class CopyHelper {
|
||||
transferable: any;
|
||||
clipboardService: any;
|
||||
|
||||
constructor() {
|
||||
this.transferable = Components.classes[
|
||||
"@mozilla.org/widget/transferable;1"
|
||||
].createInstance(Components.interfaces.nsITransferable);
|
||||
this.clipboardService = Components.classes[
|
||||
"@mozilla.org/widget/clipboard;1"
|
||||
].getService(Components.interfaces.nsIClipboard);
|
||||
this.transferable.init(null);
|
||||
}
|
||||
|
||||
public addText(source: string, type: "text/html" | "text/unicode") {
|
||||
const str = Components.classes[
|
||||
"@mozilla.org/supports-string;1"
|
||||
].createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = source;
|
||||
this.transferable.addDataFlavor(type);
|
||||
this.transferable.setTransferData(type, str, source.length * 2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addImage(source: string) {
|
||||
let parts = source.split(",");
|
||||
if (!parts[0].includes("base64")) {
|
||||
return;
|
||||
}
|
||||
let mime = parts[0].match(/:(.*?);/)[1];
|
||||
let bstr = atob(parts[1]);
|
||||
let n = bstr.length;
|
||||
let u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
let imgTools = Components.classes["@mozilla.org/image/tools;1"].getService(
|
||||
Components.interfaces.imgITools
|
||||
);
|
||||
let imgPtr = Components.classes[
|
||||
"@mozilla.org/supports-interface-pointer;1"
|
||||
].createInstance(Components.interfaces.nsISupportsInterfacePointer);
|
||||
imgPtr.data = imgTools.decodeImageFromArrayBuffer(u8arr.buffer, mime);
|
||||
this.transferable.addDataFlavor(mime);
|
||||
this.transferable.setTransferData(mime, imgPtr, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public copy() {
|
||||
this.clipboardService.setData(
|
||||
this.transferable,
|
||||
null,
|
||||
Components.interfaces.nsIClipboard.kGlobalClipboard
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function pick(
|
||||
title: string,
|
||||
mode: "open" | "save" | "folder",
|
||||
filters?: [string, string][],
|
||||
suggestion?: string
|
||||
): Promise<string> {
|
||||
const fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(
|
||||
Components.interfaces.nsIFilePicker
|
||||
);
|
||||
|
||||
if (suggestion) fp.defaultString = suggestion;
|
||||
|
||||
mode = {
|
||||
open: Components.interfaces.nsIFilePicker.modeOpen,
|
||||
save: Components.interfaces.nsIFilePicker.modeSave,
|
||||
folder: Components.interfaces.nsIFilePicker.modeGetFolder,
|
||||
}[mode];
|
||||
|
||||
fp.init(window, title, mode);
|
||||
|
||||
for (const [label, ext] of filters || []) {
|
||||
fp.appendFilter(label, ext);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return new Promise((resolve) => {
|
||||
fp.open((userChoice) => {
|
||||
switch (userChoice) {
|
||||
case Components.interfaces.nsIFilePicker.returnOK:
|
||||
case Components.interfaces.nsIFilePicker.returnReplace:
|
||||
resolve(fp.file.path);
|
||||
break;
|
||||
|
||||
default: // aka returnCancel
|
||||
resolve("");
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
enum SyncCode {
|
||||
UpToDate = 0,
|
||||
NoteAhead,
|
||||
|
|
@ -153,8 +55,6 @@ export {
|
|||
EditorMessage,
|
||||
OutlineType,
|
||||
NoteTemplate,
|
||||
CopyHelper,
|
||||
pick,
|
||||
SyncCode,
|
||||
NodeMode,
|
||||
getDOMParser,
|
||||
|
|
|
|||
|
|
@ -48,10 +48,11 @@ class WorkspaceOutline extends AddonBase {
|
|||
"chrome://Knowledge4Zotero/content/mindMap.html",
|
||||
"chrome://Knowledge4Zotero/content/bubbleMap.html",
|
||||
];
|
||||
const iframe =
|
||||
this._Addon.WorkspaceWindow.workspaceWindow.document.createElement(
|
||||
"iframe"
|
||||
);
|
||||
const iframe = this._Addon.toolkit.UI.createElement(
|
||||
this._Addon.WorkspaceWindow.workspaceWindow.document,
|
||||
"iframe",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
iframe.setAttribute("id", "mindmapIframe");
|
||||
iframe.setAttribute("src", srcList[this.currentOutline]);
|
||||
mindmap.append(iframe);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import { EditorMessage, OutlineType, pick } from "../utils";
|
||||
import { EditorMessage, OutlineType } from "../utils";
|
||||
import AddonBase from "../module";
|
||||
|
||||
class WorkspaceWindow extends AddonBase {
|
||||
|
|
@ -83,7 +83,11 @@ class WorkspaceWindow extends AddonBase {
|
|||
onClose: () => (this.workspaceTabId = ""),
|
||||
});
|
||||
this.workspaceTabId = id;
|
||||
const _iframe = window.document.createElement("browser");
|
||||
const _iframe = this._Addon.toolkit.UI.createElement(
|
||||
document,
|
||||
"browser",
|
||||
"xul"
|
||||
) as XUL.Element;
|
||||
_iframe.setAttribute("class", "reader");
|
||||
_iframe.setAttribute("flex", "1");
|
||||
_iframe.setAttribute("type", "content");
|
||||
|
|
@ -198,7 +202,7 @@ class WorkspaceWindow extends AddonBase {
|
|||
);
|
||||
} else if (e.data.type === "saveSVGReturn") {
|
||||
console.log(e.data.image);
|
||||
const filename = await pick(
|
||||
const filename = await this._Addon.toolkit.Tool.openFilePicker(
|
||||
`${Zotero.getString("fileInterface.export")} SVG Image`,
|
||||
"save",
|
||||
[["SVG File(*.svg)", "*.svg"]],
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
import TreeModel = require("tree-model");
|
||||
import Knowledge4Zotero from "../addon";
|
||||
import { CopyHelper, EditorMessage } from "../utils";
|
||||
import { EditorMessage } from "../utils";
|
||||
import AddonBase from "../module";
|
||||
|
||||
class ZoteroEvents extends AddonBase {
|
||||
|
|
@ -377,7 +377,7 @@ class ZoteroEvents extends AddonBase {
|
|||
}
|
||||
},
|
||||
copyLink: async () => {
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(link, "text/unicode")
|
||||
.addText(
|
||||
(e.target as HTMLLinkElement).outerHTML,
|
||||
|
|
@ -767,10 +767,10 @@ class ZoteroEvents extends AddonBase {
|
|||
|
||||
if (currentLine >= 0) {
|
||||
// Compute annotation lines length
|
||||
const temp = document.createElementNS(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
const temp = this._Addon.toolkit.UI.createElement(
|
||||
document,
|
||||
"div"
|
||||
);
|
||||
) as HTMLDivElement;
|
||||
temp.innerHTML = html;
|
||||
const elementList = this._Addon.NoteParse.parseHTMLElements(temp);
|
||||
// Move cursor foward
|
||||
|
|
@ -930,7 +930,7 @@ class ZoteroEvents extends AddonBase {
|
|||
const html = newLines.join("\n");
|
||||
if (!targetItem) {
|
||||
console.log(html);
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(html, "text/html")
|
||||
.addText(
|
||||
await this._Addon.NoteParse.parseHTMLToMD(html),
|
||||
|
|
@ -1049,7 +1049,7 @@ class ZoteroEvents extends AddonBase {
|
|||
if (!targetItem) {
|
||||
console.log(html);
|
||||
|
||||
new CopyHelper()
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(html, "text/html")
|
||||
.addText(
|
||||
await this._Addon.NoteParse.parseHTMLToMD(html),
|
||||
|
|
@ -1283,7 +1283,9 @@ class ZoteroEvents extends AddonBase {
|
|||
}
|
||||
const html = await this._Addon.NoteParse.parseMDToHTML(source);
|
||||
console.log(source, html);
|
||||
new CopyHelper().addText(html, "text/html").copy();
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(html, "text/html")
|
||||
.copy();
|
||||
|
||||
this._Addon.ZoteroViews.showProgressWindow(
|
||||
"Better Notes",
|
||||
|
|
@ -1303,7 +1305,9 @@ class ZoteroEvents extends AddonBase {
|
|||
}
|
||||
const html = this._Addon.NoteParse.parseAsciiDocToHTML(source);
|
||||
console.log(source, html);
|
||||
new CopyHelper().addText(html, "text/html").copy();
|
||||
this._Addon.toolkit.Tool.getCopyHelper()
|
||||
.addText(html, "text/html")
|
||||
.copy();
|
||||
|
||||
this._Addon.ZoteroViews.showProgressWindow(
|
||||
"Better Notes",
|
||||
|
|
|
|||
|
|
@ -68,51 +68,45 @@ class ZoteroViews extends AddonBase {
|
|||
let addNoteItem = document
|
||||
.getElementById("zotero-tb-note-add")
|
||||
.getElementsByTagName("menuitem")[1];
|
||||
let buttons = this.createXULElement(document, {
|
||||
let buttons = this._Addon.toolkit.UI.creatElementsFromJSON(document, {
|
||||
tag: "fragment",
|
||||
subElementOptions: [
|
||||
{
|
||||
tag: "menuitem",
|
||||
id: "zotero-tb-knowledge-create-mainnote",
|
||||
attributes: [
|
||||
["label", "New Main Note"],
|
||||
["class", "menuitem-iconic"],
|
||||
[
|
||||
"style",
|
||||
attributes: {
|
||||
label: "New Main Note",
|
||||
class: "menuitem-iconic",
|
||||
style:
|
||||
"list-style-image: url('chrome://Knowledge4Zotero/skin/favicon.png');",
|
||||
],
|
||||
],
|
||||
},
|
||||
listeners: [
|
||||
[
|
||||
"click",
|
||||
(e) => {
|
||||
{
|
||||
type: "click",
|
||||
listener: (e) => {
|
||||
this._Addon.ZoteroEvents.onEditorEvent(
|
||||
new EditorMessage("createWorkspace", {})
|
||||
);
|
||||
},
|
||||
false,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tag: "menuitem",
|
||||
id: "zotero-tb-knowledge-import-md",
|
||||
attributes: [
|
||||
["label", "Import MarkDown as Note"],
|
||||
["class", "menuitem-iconic"],
|
||||
[
|
||||
"style",
|
||||
attributes: {
|
||||
label: "Import MarkDown as Note",
|
||||
class: "menuitem-iconic",
|
||||
style:
|
||||
"list-style-image: url('chrome://Knowledge4Zotero/skin/favicon.png');",
|
||||
],
|
||||
],
|
||||
},
|
||||
listeners: [
|
||||
[
|
||||
"click",
|
||||
async (e) => {
|
||||
{
|
||||
type: "click",
|
||||
listener: async (e) => {
|
||||
await this._Addon.NoteImport.doImport();
|
||||
},
|
||||
false,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
@ -122,62 +116,95 @@ class ZoteroViews extends AddonBase {
|
|||
|
||||
public addOpenWorkspaceButton() {
|
||||
// Left collection tree view button
|
||||
const treeRow = document.createElement("html:div");
|
||||
treeRow.setAttribute("class", "row");
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px;"
|
||||
);
|
||||
const span1 = document.createElement("span");
|
||||
span1.setAttribute("class", "cell label primary");
|
||||
const span2 = document.createElement("span");
|
||||
span2.setAttribute("class", "icon icon-twisty twisty open");
|
||||
span2.innerHTML = this.icons["openWorkspaceCollectionView"];
|
||||
const span3 = document.createElement("span");
|
||||
span3.setAttribute("class", "icon icon-bg cell-icon");
|
||||
span3.setAttribute(
|
||||
"style",
|
||||
"background-image:url(chrome://Knowledge4Zotero/skin/favicon.png)"
|
||||
);
|
||||
const span4 = document.createElement("span");
|
||||
span4.setAttribute("class", "cell-text");
|
||||
span4.setAttribute("style", "margin-left: 6px;");
|
||||
span4.innerHTML = Zotero.locale.includes("zh")
|
||||
? "打开工作区"
|
||||
: "Open Workspace";
|
||||
span1.append(span2, span3, span4);
|
||||
treeRow.append(span1);
|
||||
treeRow.addEventListener("click", async (e) => {
|
||||
if (e.shiftKey) {
|
||||
await this._Addon.WorkspaceWindow.openWorkspaceWindow("window", true);
|
||||
} else {
|
||||
await this._Addon.WorkspaceWindow.openWorkspaceWindow();
|
||||
}
|
||||
});
|
||||
treeRow.addEventListener("mouseover", (e: XUL.XULEvent) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px; background-color: grey;"
|
||||
);
|
||||
});
|
||||
treeRow.addEventListener("mouseleave", (e: XUL.XULEvent) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px;"
|
||||
);
|
||||
});
|
||||
treeRow.addEventListener("mousedown", (e: XUL.XULEvent) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px; color: #FFFFFF;"
|
||||
);
|
||||
});
|
||||
treeRow.addEventListener("mouseup", (e: XUL.XULEvent) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px;"
|
||||
);
|
||||
});
|
||||
const treeRow = this._Addon.toolkit.UI.creatElementsFromJSON(document, {
|
||||
tag: "html:div",
|
||||
attributes: {
|
||||
class: "row",
|
||||
style: "max-height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px;",
|
||||
},
|
||||
listeners: [
|
||||
{
|
||||
type: "click",
|
||||
listener: async (e: MouseEvent) => {
|
||||
if (e.shiftKey) {
|
||||
await this._Addon.WorkspaceWindow.openWorkspaceWindow(
|
||||
"window",
|
||||
true
|
||||
);
|
||||
} else {
|
||||
await this._Addon.WorkspaceWindow.openWorkspaceWindow();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "mouseover",
|
||||
listener: (e) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"max-height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px; background-color: grey;"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "mouseleave",
|
||||
listener: (e) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"max-height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px;"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "mousedown",
|
||||
listener: (e) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"max-height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px; color: #FFFFFF;"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "mouseup",
|
||||
listener: (e) => {
|
||||
treeRow.setAttribute(
|
||||
"style",
|
||||
"max-height: 22px; margin: 0 0 0 0; padding: 0 6px 0 6px;"
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
subElementOptions: [
|
||||
{
|
||||
tag: "div",
|
||||
attributes: {
|
||||
class: "icon icon-twisty twisty open",
|
||||
},
|
||||
directAttributes: {
|
||||
innerHTML: this.icons["openWorkspaceCollectionView"],
|
||||
},
|
||||
},
|
||||
{
|
||||
tag: "div",
|
||||
attributes: {
|
||||
class: "icon icon-bg cell-icon",
|
||||
style:
|
||||
"background-image:url(chrome://Knowledge4Zotero/skin/favicon.png)",
|
||||
},
|
||||
},
|
||||
{
|
||||
tag: "div",
|
||||
attributes: {
|
||||
class: "cell-text",
|
||||
style: "margin-left: 6px;",
|
||||
},
|
||||
directAttributes: {
|
||||
innerHTML: Zotero.locale.includes("zh")
|
||||
? "打开工作区"
|
||||
: "Open Workspace",
|
||||
},
|
||||
},
|
||||
],
|
||||
}) as HTMLDivElement;
|
||||
document
|
||||
.getElementById("zotero-collections-tree-container")
|
||||
.children[0].before(treeRow);
|
||||
|
|
@ -223,7 +250,11 @@ class ZoteroViews extends AddonBase {
|
|||
];
|
||||
}
|
||||
for (const template of templates) {
|
||||
const menuitem = _document.createElement("menuitem");
|
||||
const menuitem = this._Addon.toolkit.UI.createElement(
|
||||
_document,
|
||||
"menuitem",
|
||||
"xul"
|
||||
) as XUL.MenuItem;
|
||||
// menuitem.setAttribute("id", template.name);
|
||||
menuitem.setAttribute("label", template.name);
|
||||
menuitem.setAttribute(
|
||||
|
|
@ -244,6 +275,7 @@ class ZoteroViews extends AddonBase {
|
|||
}
|
||||
}
|
||||
|
||||
// To deprecate
|
||||
public updateCitationStyleMenu() {
|
||||
const _window = this._Addon.WorkspaceMenu.getWorkspaceMenuWindow();
|
||||
Zotero.debug(`updateCitationStyleMenu`);
|
||||
|
|
@ -255,14 +287,18 @@ class ZoteroViews extends AddonBase {
|
|||
|
||||
// add styles to list
|
||||
const styles = Zotero.Styles.getVisible();
|
||||
styles.forEach(function (style) {
|
||||
styles.forEach((style) => {
|
||||
const val = JSON.stringify({
|
||||
mode: "bibliography",
|
||||
contentType: "html",
|
||||
id: style.styleID,
|
||||
locale: "",
|
||||
});
|
||||
const itemNode = document.createElement("menuitem") as XUL.MenuItem;
|
||||
const itemNode = this._Addon.toolkit.UI.createElement(
|
||||
_window.document,
|
||||
"menuitem",
|
||||
"xul"
|
||||
) as XUL.MenuItem;
|
||||
itemNode.setAttribute("value", val);
|
||||
itemNode.setAttribute("label", style.title);
|
||||
itemNode.setAttribute("type", "checkbox");
|
||||
|
|
@ -413,68 +449,6 @@ class ZoteroViews extends AddonBase {
|
|||
await this.waitProgressWindow(progressWindow);
|
||||
return progressWindow.progress._hbox.ownerDocument;
|
||||
}
|
||||
|
||||
public createXULElement(doc: Document, options: XULElementOptions) {
|
||||
const createElement: () => XUL.Element =
|
||||
options.tag === "fragment"
|
||||
? () => doc.createDocumentFragment()
|
||||
: Zotero.platformMajorVersion <= 60
|
||||
? () =>
|
||||
doc.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
options.tag
|
||||
)
|
||||
: // @ts-ignore
|
||||
() => doc.createXULElement(options.tag);
|
||||
if (
|
||||
options.id &&
|
||||
(options.checkExistanceParent
|
||||
? options.checkExistanceParent
|
||||
: doc
|
||||
).querySelector(`#${options.id}`)
|
||||
) {
|
||||
if (options.ignoreIfExists) {
|
||||
return undefined;
|
||||
}
|
||||
if (options.removeIfExists) {
|
||||
doc.querySelector(`#${options.id}`).remove();
|
||||
}
|
||||
}
|
||||
if (options.customCheck && !options.customCheck()) {
|
||||
return undefined;
|
||||
}
|
||||
const element = createElement();
|
||||
if (options.id) {
|
||||
element.id = options.id;
|
||||
}
|
||||
if (options.styles?.length) {
|
||||
options.styles.forEach(([k, v]) => {
|
||||
element.style[k] = v;
|
||||
});
|
||||
}
|
||||
if (options.directAttributes?.length) {
|
||||
options.directAttributes.forEach(([k, v]) => {
|
||||
element[k] = v;
|
||||
});
|
||||
}
|
||||
if (options.attributes?.length) {
|
||||
options.attributes.forEach(([k, v]) => {
|
||||
element.setAttribute(k, v);
|
||||
});
|
||||
}
|
||||
if (options.listeners?.length) {
|
||||
options.listeners.forEach(([type, cbk, option]) => {
|
||||
element.addEventListener(type, cbk, option);
|
||||
});
|
||||
}
|
||||
if (options.subElementOptions?.length) {
|
||||
const subElements = options.subElementOptions
|
||||
.map((options) => this.createXULElement(doc, options))
|
||||
.filter((e) => e);
|
||||
element.append(...subElements);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
export default ZoteroViews;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,3 @@
|
|||
declare interface XULElementOptions {
|
||||
tag: string;
|
||||
id?: string;
|
||||
styles?: Array<[string, string]>;
|
||||
directAttributes?: Array<[string, string | boolean | number]>;
|
||||
attributes?: Array<[string, string | boolean | number]>;
|
||||
listeners?: Array<
|
||||
[
|
||||
string,
|
||||
EventListenerOrEventListenerObject,
|
||||
boolean | AddEventListenerOptions
|
||||
]
|
||||
>;
|
||||
checkExistanceParent?: HTMLElement;
|
||||
ignoreIfExists?: boolean;
|
||||
removeIfExists?: boolean;
|
||||
customCheck?: () => boolean;
|
||||
subElementOptions?: Array<XULElementOptions>;
|
||||
}
|
||||
|
||||
declare interface SyncStatus {
|
||||
path: string;
|
||||
filename: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue