diff --git a/addon/chrome/content/bubbleMap.html b/addon/chrome/content/bubbleMap.html
index d194737..74f350e 100644
--- a/addon/chrome/content/bubbleMap.html
+++ b/addon/chrome/content/bubbleMap.html
@@ -172,12 +172,12 @@
),
$(go.Panel, "Auto"),
);
- window.parent.postMessage({ type: "ready" }, "*");
+ window.postMessage({ type: "ready" }, "*");
getData();
}
function getData() {
- window.parent.postMessage({ type: "getMindMapData" }, "*");
+ window.postMessage({ type: "getMindMapData" }, "*");
}
function setData(nodes) {
@@ -219,17 +219,16 @@
var oldnode = adorn.adornedPart;
var olddata = oldnode.data;
if (olddata.noteLink) {
- window.parent.postMessage(
+ window.postMessage(
{ type: "openNote", link: olddata.noteLink, id: olddata.key },
"*",
);
} else {
- window.parent.postMessage(
+ window.postMessage(
{
type: "jumpNode",
lineIndex: olddata.lineIndex,
id: olddata.key,
- workspaceType: window.workspaceType || "tab",
},
"*",
);
@@ -243,12 +242,11 @@
alert("Link cannot be edited in mind map");
return false;
}
- window.parent.postMessage(
+ window.postMessage(
{
type: "editNode",
lineIndex: data.lineIndex,
text: data.text,
- workspaceType: window.workspaceType || "tab",
},
"*",
);
@@ -259,30 +257,31 @@
switch (e.data.type) {
case "setMindMapData":
setData(e.data.nodes);
- window.workspaceType = e.data.workspaceType;
break;
case "saveImage":
const imgString = Diagram.makeImageData({
scale: 1,
});
- window.parent.postMessage(
+ window.postMessage(
{
type: "saveImageReturn",
image: imgString,
},
"*",
);
+ break;
case "saveSVG":
const svgElement = Diagram.makeSvg({
scale: 1,
});
- window.parent.postMessage(
+ window.postMessage(
{
type: "saveSVGReturn",
image: svgElement.outerHTML,
},
"*",
);
+ break;
default:
break;
}
diff --git a/addon/chrome/content/icons/outline-20.svg b/addon/chrome/content/icons/outline-20.svg
new file mode 100644
index 0000000..99e7236
--- /dev/null
+++ b/addon/chrome/content/icons/outline-20.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/addon/chrome/content/icons/save-20.svg b/addon/chrome/content/icons/save-20.svg
new file mode 100644
index 0000000..69edd92
--- /dev/null
+++ b/addon/chrome/content/icons/save-20.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/addon/chrome/content/mindMap.html b/addon/chrome/content/mindMap.html
index 3a65026..833de88 100644
--- a/addon/chrome/content/mindMap.html
+++ b/addon/chrome/content/mindMap.html
@@ -146,7 +146,7 @@
});
// read in the predefined graph using the JSON format data held in the "mySavedModel" textarea
- window.parent.postMessage({ type: "ready" }, "*");
+ window.postMessage({ type: "ready" }, "*");
getData();
}
@@ -240,7 +240,7 @@
}
function getData() {
- window.parent.postMessage({ type: "getMindMapData" }, "*");
+ window.postMessage({ type: "getMindMapData" }, "*");
}
function setData(nodes) {
@@ -281,17 +281,16 @@
var oldnode = adorn.adornedPart;
var olddata = oldnode.data;
if (olddata.noteLink) {
- window.parent.postMessage(
+ window.postMessage(
{ type: "openNote", link: olddata.noteLink, id: olddata.key },
"*",
);
} else {
- window.parent.postMessage(
+ window.postMessage(
{
type: "jumpNode",
lineIndex: olddata.lineIndex,
id: olddata.key,
- workspaceType: window.workspaceType || "tab",
},
"*",
);
@@ -305,12 +304,11 @@
alert("Link cannot be edited in mind map");
return false;
}
- window.parent.postMessage(
+ window.postMessage(
{
type: "editNode",
lineIndex: data.lineIndex,
text: data.text,
- workspaceType: window.workspaceType || "tab",
},
"*",
);
@@ -321,30 +319,31 @@
switch (e.data.type) {
case "setMindMapData":
setData(e.data.nodes);
- window.workspaceType = e.data.workspaceType;
break;
case "saveImage":
const imgString = Diagram.makeImageData({
scale: 1,
});
- window.parent.postMessage(
+ window.postMessage(
{
type: "saveImageReturn",
image: imgString,
},
"*",
);
+ break;
case "saveSVG":
const svgElement = Diagram.makeSvg({
scale: 1,
});
- window.parent.postMessage(
+ window.postMessage(
{
type: "saveSVGReturn",
image: svgElement.outerHTML,
},
"*",
);
+ break;
default:
break;
}
@@ -354,7 +353,7 @@
try {
init();
} catch (e) {
- window.parent.postMessage({ type: "error", event: e }, "*");
+ window.postMessage({ type: "error", event: e }, "*");
}
});
diff --git a/addon/chrome/content/styles/context.css b/addon/chrome/content/styles/context.css
new file mode 100644
index 0000000..253e369
--- /dev/null
+++ b/addon/chrome/content/styles/context.css
@@ -0,0 +1,3 @@
+bn-context {
+ min-width: 182px;
+}
\ No newline at end of file
diff --git a/addon/chrome/content/styles/details.css b/addon/chrome/content/styles/details.css
new file mode 100644
index 0000000..25f9fdb
--- /dev/null
+++ b/addon/chrome/content/styles/details.css
@@ -0,0 +1,3 @@
+bn-details pane-header {
+ display: none;
+}
\ No newline at end of file
diff --git a/addon/chrome/content/styles/editor.css b/addon/chrome/content/styles/editor.css
new file mode 100644
index 0000000..797a4a0
--- /dev/null
+++ b/addon/chrome/content/styles/editor.css
@@ -0,0 +1,49 @@
+.primary-editor > h1::before {
+ margin-left: -64px !important;
+ padding-left: 40px !important;
+ content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Ctitle%3E%E6%9C%AA%E6%A0%87%E9%A2%98-1%3C%2Ftitle%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M12.29%2C16.8H11.14V12.33H6.07V16.8H4.92V7H6.07v4.3h5.07V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M18.05%2C16.8H16.93V8.41a4%2C4%2C0%2C0%2C1-.9.53%2C6.52%2C6.52%2C0%2C0%2C1-1.14.44l-.32-1a8.2%2C8.2%2C0%2C0%2C0%2C1.67-.67%2C6.31%2C6.31%2C0%2C0%2C0%2C1.39-1h.42Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
+}
+.primary-editor > h2::before {
+ margin-left: -64px !important;
+ padding-left: 40px !important;
+ content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.a%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22a%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22a%22%20d%3D%22M14.14%2C16.8v-.48a4.1%2C4.1%2C0%2C0%2C1%2C.14-1.11%2C2.86%2C2.86%2C0%2C0%2C1%2C.45-.91%2C5.49%2C5.49%2C0%2C0%2C1%2C.83-.86c.33-.29.75-.61%2C1.24-1a7.43%2C7.43%2C0%2C0%2C0%2C.9-.73%2C3.9%2C3.9%2C0%2C0%2C0%2C.57-.7%2C2.22%2C2.22%2C0%2C0%2C0%2C.3-.66%2C2.87%2C2.87%2C0%2C0%2C0%2C.11-.77%2C1.89%2C1.89%2C0%2C0%2C0-.47-1.32%2C1.66%2C1.66%2C0%2C0%2C0-1.28-.5A3.17%2C3.17%2C0%2C0%2C0%2C15.7%2C8a3.49%2C3.49%2C0%2C0%2C0-1.08.76l-.68-.65a4.26%2C4.26%2C0%2C0%2C1%2C1.39-1A4%2C4%2C0%2C0%2C1%2C17%2C6.84a2.62%2C2.62%2C0%2C0%2C1%2C2.83%2C2.67%2C3.58%2C3.58%2C0%2C0%2C1-.15%2C1%2C3.09%2C3.09%2C0%2C0%2C1-.41.9%2C5.53%2C5.53%2C0%2C0%2C1-.67.81%2C9%2C9%2C0%2C0%2C1-.95.79c-.46.32-.84.59-1.13.82a4.68%2C4.68%2C0%2C0%2C0-.71.64%2C2%2C2%2C0%2C0%2C0-.38.6%2C2.08%2C2.08%2C0%2C0%2C0-.11.69h4.88v1Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22a%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
+}
+.primary-editor > h3::before {
+ margin-left: -64px !important;
+ padding-left: 40px !important;
+ content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M14%2C16.14l.51-.8a4.75%2C4.75%2C0%2C0%2C0%2C1.1.52%2C4.27%2C4.27%2C0%2C0%2C0%2C1.12.16%2C2.29%2C2.29%2C0%2C0%2C0%2C1.64-.52A1.77%2C1.77%2C0%2C0%2C0%2C19%2C14.17a1.7%2C1.7%2C0%2C0%2C0-.68-1.48%2C3.6%2C3.6%2C0%2C0%2C0-2.06-.48H15.4v-1h.77A3%2C3%2C0%2C0%2C0%2C18%2C10.81a1.65%2C1.65%2C0%2C0%2C0%2C.6-1.41%2C1.47%2C1.47%2C0%2C0%2C0-.47-1.19A1.67%2C1.67%2C0%2C0%2C0%2C17%2C7.79a3.33%2C3.33%2C0%2C0%2C0-2.08.73l-.59-.75a4.4%2C4.4%2C0%2C0%2C1%2C1.28-.71A4.35%2C4.35%2C0%2C0%2C1%2C17%2C6.84a2.84%2C2.84%2C0%2C0%2C1%2C2%2C.65%2C2.21%2C2.21%2C0%2C0%2C1%2C.74%2C1.78%2C2.35%2C2.35%2C0%2C0%2C1-.49%2C1.5%2C2.7%2C2.7%2C0%2C0%2C1-1.46.89v0a2.74%2C2.74%2C0%2C0%2C1%2C1.65.74%2C2.15%2C2.15%2C0%2C0%2C1%2C.66%2C1.65%2C2.64%2C2.64%2C0%2C0%2C1-.9%2C2.12%2C3.44%2C3.44%2C0%2C0%2C1-2.34.78%2C5.3%2C5.3%2C0%2C0%2C1-1.48-.2A5%2C5%2C0%2C0%2C1%2C14%2C16.14Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
+}
+.primary-editor > h4::before {
+ margin-left: -64px !important;
+ padding-left: 40px !important;
+ content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M19.43%2C6.92v6.59h1.05v1.05H19.43V16.9H18.31V14.56H13.66v-1c.43-.49.87-1%2C1.31-1.57s.87-1.13%2C1.27-1.7S17%2C9.14%2C17.36%2C8.57a16.51%2C16.51%2C0%2C0%2C0%2C.86-1.65Zm-4.49%2C6.59h3.37V8.63c-.34.61-.67%2C1.15-1%2C1.63s-.6.91-.87%2C1.3-.56.74-.81%2C1Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
+}
+.primary-editor > h5::before {
+ margin-left: -64px !important;
+ padding-left: 40px !important;
+ content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M14%2C16l.58-.76a3.67%2C3.67%2C0%2C0%2C0%2C1%2C.58A3.44%2C3.44%2C0%2C0%2C0%2C16.8%2C16a2.17%2C2.17%2C0%2C0%2C0%2C1.58-.6A2%2C2%2C0%2C0%2C0%2C19%2C13.88a1.85%2C1.85%2C0%2C0%2C0-.64-1.5%2C2.83%2C2.83%2C0%2C0%2C0-1.86-.54c-.27%2C0-.55%2C0-.86%2C0s-.58%2C0-.81.06L15.17%2C7H19.7V8H16.14l-.2%2C2.88.47%2C0h.43a3.5%2C3.5%2C0%2C0%2C1%2C2.43.79%2C2.74%2C2.74%2C0%2C0%2C1%2C.88%2C2.16%2C3%2C3%2C0%2C0%2C1-.94%2C2.3%2C3.41%2C3.41%2C0%2C0%2C1-2.4.87%2C4.45%2C4.45%2C0%2C0%2C1-1.5-.24A4.81%2C4.81%2C0%2C0%2C1%2C14%2C16Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
+}
+.primary-editor > h6::before {
+ margin-left: -64px !important;
+ padding-left: 40px !important;
+ content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M20.18%2C13.7a3.24%2C3.24%2C0%2C0%2C1-.88%2C2.38%2C2.94%2C2.94%2C0%2C0%2C1-2.2.9%2C2.69%2C2.69%2C0%2C0%2C1-2.31-1.17A5.59%2C5.59%2C0%2C0%2C1%2C14%2C12.49a12.18%2C12.18%2C0%2C0%2C1%2C.2-2.14%2C5.16%2C5.16%2C0%2C0%2C1%2C.84-2A3.65%2C3.65%2C0%2C0%2C1%2C16.27%2C7.2%2C3.71%2C3.71%2C0%2C0%2C1%2C18%2C6.84%2C3.14%2C3.14%2C0%2C0%2C1%2C19%2C7a3.59%2C3.59%2C0%2C0%2C1%2C1%2C.5l-.56.77a2.3%2C2.3%2C0%2C0%2C0-1.49-.48A2.3%2C2.3%2C0%2C0%2C0%2C16.79%2C8a3%2C3%2C0%2C0%2C0-.92.85%2C3.79%2C3.79%2C0%2C0%2C0-.56%2C1.25%2C6.56%2C6.56%2C0%2C0%2C0-.19%2C1.65h0a2.61%2C2.61%2C0%2C0%2C1%2C1-.84%2C2.91%2C2.91%2C0%2C0%2C1%2C1.23-.28%2C2.63%2C2.63%2C0%2C0%2C1%2C2%2C.85A3.09%2C3.09%2C0%2C0%2C1%2C20.18%2C13.7ZM19%2C13.78a2.28%2C2.28%2C0%2C0%2C0-.5-1.62%2C1.67%2C1.67%2C0%2C0%2C0-1.29-.54%2C2%2C2%2C0%2C0%2C0-1.5.58%2C2%2C2%2C0%2C0%2C0-.56%2C1.4%2C2.65%2C2.65%2C0%2C0%2C0%2C.55%2C1.74%2C1.85%2C1.85%2C0%2C0%2C0%2C2.78.1A2.38%2C2.38%2C0%2C0%2C0%2C19%2C13.78Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
+}
+.primary-editor > p,
+.primary-editor h1,
+.primary-editor h2,
+.primary-editor h3,
+.primary-editor h4,
+.primary-editor h5,
+.primary-editor h6,
+.primary-editor pre,
+.primary-editor blockquote,
+.primary-editor table,
+.primary-editor ul,
+.primary-editor ol,
+.primary-editor hr {
+ max-width: unset;
+}
+
+body[no-bn-toolbar] #BetterNotes-toolbar {
+ display: none;
+}
diff --git a/addon/chrome/content/styles/outline.css b/addon/chrome/content/styles/outline.css
new file mode 100644
index 0000000..4598945
--- /dev/null
+++ b/addon/chrome/content/styles/outline.css
@@ -0,0 +1,39 @@
+bn-outline,
+.container {
+ width: 100%;
+ height: 100%;
+ background: var(--material-sidepane);
+}
+
+bn-outline {
+ min-width: 100px;
+ flex-direction: column;
+}
+
+@media (-moz-platform: macos) {
+ #__addonRef__-left-toolbar {
+ -moz-window-dragging: drag;
+ }
+}
+
+#__addonRef__-left-toolbar {
+ background: var(--material-toolbar);
+ border-bottom: var(--material-panedivider);
+ padding: 6px 8px;
+}
+
+bn-outline .zotero-tb-button {
+ width: 28px;
+ height: 28px;
+ margin: 0px 4px 0px 4px;
+ fill: currentColor;
+ -moz-context-properties: fill, fill-opacity;
+}
+
+#__addonRef__-setOutline {
+ list-style-image: url("chrome://__addonRef__/content/icons/outline-20.svg");
+}
+
+#__addonRef__-saveOutline {
+ list-style-image: url("chrome://__addonRef__/content/icons/save-20.svg");
+}
diff --git a/addon/chrome/content/styles/workspace.css b/addon/chrome/content/styles/workspace.css
new file mode 100644
index 0000000..5ad9b5a
--- /dev/null
+++ b/addon/chrome/content/styles/workspace.css
@@ -0,0 +1,11 @@
+bn-workspace,
+.container {
+ width: 100%;
+ height: 100%;
+ background: var(--material-sidepane);
+ flex-grow: 1;
+}
+
+bn-workspace #__addonRef__-editor-main #links-container {
+ display: none;
+}
diff --git a/addon/chrome/content/treeView.html b/addon/chrome/content/treeView.html
index 3476800..e9b1cbe 100644
--- a/addon/chrome/content/treeView.html
+++ b/addon/chrome/content/treeView.html
@@ -43,7 +43,7 @@
}
#treeview {
- padding: 20px;
+ padding: 8px;
}
.drive-header {
@@ -72,13 +72,18 @@
color: var(--fill-primary);
}
+ .dx-treeview-item {
+ border-radius: 5px;
+ cursor: auto;
+ }
+
.dx-treeview-toggle-item-visibility {
color: var(--fill-primary);
}
:not(.dx-state-focused) > .dx-treeview-item.dx-state-hover {
color: var(--fill-primary);
- background-color: var(--fill-quinary);
+ background-color: transparent;
}
.dx-state-focused > .dx-treeview-item {
@@ -94,7 +99,7 @@
var cachedNodes = null;
function init() {
window.addEventListener("message", handler, false);
- window.parent.postMessage({ type: "ready" }, "*");
+ window.postMessage({ type: "ready" }, "*");
getData();
}
@@ -151,7 +156,7 @@
return;
}
- window.parent.postMessage(
+ window.postMessage(
{
type: "moveNode",
fromID: parseInt(fromNode.itemData.id),
@@ -295,7 +300,7 @@
function jumpNode(e) {
var itemData = e.itemData;
if (itemData.noteLink) {
- window.parent.postMessage(
+ window.postMessage(
{
type: "openNote",
link: itemData.noteLink,
@@ -304,12 +309,11 @@
"*",
);
} else {
- window.parent.postMessage(
+ window.postMessage(
{
type: "jumpNode",
lineIndex: itemData.lineIndex,
id: parseInt(itemData.id),
- workspaceType: window.workspaceType || "tab",
},
"*",
);
@@ -319,7 +323,7 @@
const noteIcon = ``;
function getData() {
- window.parent.postMessage({ type: "getMindMapData" }, "*");
+ window.postMessage({ type: "getMindMapData" }, "*");
}
function setData(nodes, expandLevel) {
@@ -384,7 +388,6 @@
console.log(e);
if (e.data.type === "setMindMapData") {
setData(e.data.nodes, e.data.expandLevel);
- window.workspaceType = e.data.workspaceType;
}
}
@@ -392,7 +395,7 @@
try {
init();
} catch (e) {
- window.parent.postMessage({ type: "error", event: e }, "*");
+ window.postMessage({ type: "error", event: e }, "*");
}
});
diff --git a/addon/locale/en-US/outline.ftl b/addon/locale/en-US/outline.ftl
new file mode 100644
index 0000000..aa31812
--- /dev/null
+++ b/addon/locale/en-US/outline.ftl
@@ -0,0 +1,20 @@
+setOutline =
+ .tooltiptext = Change outline mode
+useTreeView =
+ .label = Tree View
+useMindMap =
+ .label = Mind Map
+useBubbleMap =
+ .label = Bubble Map
+saveOutline =
+ .tooltiptext = Save as...
+saveOutlineImage =
+ .label = Outline image
+ .tooltiptext = Only in mind map/bubble map mode
+saveOutlineSVG =
+ .label = Outline SVG
+ .tooltiptext = Only in mind map/bubble map mode
+saveOutlineFreeMind =
+ .label = Outline FreeMind
+saveMore =
+ .label = MarkDown, Docx, PDF...
diff --git a/package.json b/package.json
index 66f3ca5..d99b862 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"unist-util-visit": "^5.0.0",
"unist-util-visit-parents": "^6.0.1",
"yamljs": "^0.3.0",
- "zotero-plugin-toolkit": "^2.3.23"
+ "zotero-plugin-toolkit": "^2.3.26"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
diff --git a/scripts/build-extras.mjs b/scripts/build-extras.mjs
index cefdd93..d00cda6 100644
--- a/scripts/build-extras.mjs
+++ b/scripts/build-extras.mjs
@@ -5,19 +5,9 @@ const buildDir = "build";
export async function main() {
await build({
- entryPoints: ["src/extras/editorScript.ts"],
+ entryPoints: ["./src/extras/*.ts"],
+ outdir: path.join(buildDir, "addon/chrome/content/scripts"),
bundle: true,
- outfile: path.join(
- buildDir,
- "addon/chrome/content/scripts/editorScript.js",
- ),
- target: ["firefox102"],
- }).catch(() => exit(1));
-
- await build({
- entryPoints: ["src/extras/docxWorker.ts"],
- bundle: true,
- outfile: path.join(buildDir, "addon/chrome/content/scripts/docxWorker.js"),
target: ["firefox102"],
}).catch(() => exit(1));
}
diff --git a/scripts/build.mjs b/scripts/build.mjs
index 96bd4a1..495ef39 100644
--- a/scripts/build.mjs
+++ b/scripts/build.mjs
@@ -49,6 +49,7 @@ function replaceString(buildTime) {
`${buildDir}/addon/**/*.xhtml`,
`${buildDir}/addon/**/*.html`,
`${buildDir}/addon/**/*.json`,
+ `${buildDir}/addon/**/*.css`,
`${buildDir}/addon/prefs.js`,
`${buildDir}/addon/manifest.json`,
`${buildDir}/addon/bootstrap.js`,
diff --git a/src/addon.ts b/src/addon.ts
index c378645..fe9fbbe 100644
--- a/src/addon.ts
+++ b/src/addon.ts
@@ -7,7 +7,6 @@ import { LargePrefHelper } from "zotero-plugin-toolkit/dist/helpers/largePref";
import ToolkitGlobal from "zotero-plugin-toolkit/dist/managers/toolkitGlobal";
import { getPref, setPref } from "./utils/prefs";
-import { OutlineType } from "./utils/workspace";
import { SyncDataType } from "./modules/sync/managerWindow";
import hooks from "./hooks";
import api from "./api";
@@ -46,21 +45,6 @@ class Addon {
};
};
notify: Array>;
- workspace: {
- mainId: number;
- previewId: number;
- tab: {
- active: boolean;
- id?: string;
- container?: XUL.Box;
- };
- window: {
- active: boolean;
- window?: Window;
- container?: XUL.Box;
- };
- outline: OutlineType;
- };
imageViewer: {
window?: Window;
srcList: string[];
@@ -105,38 +89,6 @@ class Addon {
diff: {},
},
notify: [],
- workspace: {
- get mainId(): number {
- return parseInt(getPref("mainKnowledgeID") as string);
- },
- set mainId(id: number) {
- setPref("mainKnowledgeID", id);
- const recentMainNoteIds = getPref("recentMainNoteIds") as string;
- const recentMainNoteIdsArr = recentMainNoteIds
- ? recentMainNoteIds.split(",").map((id) => parseInt(id))
- : [];
- const idx = recentMainNoteIdsArr.indexOf(id);
- if (idx !== -1) {
- recentMainNoteIdsArr.splice(idx, 1);
- }
- recentMainNoteIdsArr.unshift(id);
- setPref(
- "recentMainNoteIds",
- recentMainNoteIdsArr
- .slice(0, 10)
- .filter((id) => Zotero.Items.get(id).isNote())
- .join(","),
- );
- },
- previewId: -1,
- tab: {
- active: false,
- },
- window: {
- active: false,
- },
- outline: OutlineType.treeView,
- },
imageViewer: {
window: undefined,
srcList: [],
diff --git a/src/api.ts b/src/api.ts
index 4922069..5bbabaf 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -44,7 +44,6 @@ import {
DEFAULT_TEMPLATES,
} from "./modules/template/data";
import { renderTemplatePreview } from "./modules/template/preview";
-import { getWorkspaceEditor } from "./modules/workspace/content";
import { parseCitationHTML } from "./utils/citation";
import {
getEditorInstance,
@@ -65,11 +64,10 @@ import {
addLineToNote,
updateRelatedNotes,
getRelatedNoteIds,
+ getNoteTreeFlattened,
} from "./utils/note";
-const workspace = {
- getWorkspaceEditor,
-};
+const workspace = {};
const sync = {
isSyncNote,
@@ -148,6 +146,7 @@ const note = {
insert: addLineToNote,
updateRelatedNotes,
getRelatedNoteIds,
+ getNoteTreeFlattened,
};
export default {
diff --git a/src/elements/base.ts b/src/elements/base.ts
new file mode 100644
index 0000000..76e10b7
--- /dev/null
+++ b/src/elements/base.ts
@@ -0,0 +1,60 @@
+import { config } from "../../package.json";
+
+export class PluginCEBase extends XULElementBase {
+ _addon!: typeof addon;
+
+ connectedCallback(): void {
+ this._addon = Zotero[config.addonInstance];
+ Zotero.UIProperties.registerRoot(this);
+ super.connectedCallback();
+ }
+
+ _wrapID(key: string) {
+ if (key.startsWith(config.addonRef)) {
+ return key;
+ }
+ return `${config.addonRef}-${key}`;
+ }
+
+ _unwrapID(id: string) {
+ if (id.startsWith(config.addonRef)) {
+ return id.slice(config.addonRef.length + 1);
+ }
+ return id;
+ }
+
+ _queryID(key: string) {
+ return this.querySelector(`#${this._wrapID(key)}`) as XUL.Element | null;
+ }
+
+ _parseContentID(dom: DocumentFragment) {
+ dom.querySelectorAll("*[id]").forEach(elem => {
+ elem.id = this._wrapID(elem.id);
+ })
+ return dom;
+ }
+
+ _loadPersist() {
+ const persistValues = Zotero.Prefs.get("pane.persist") as string;
+ if (!persistValues) return;
+ const serializedValues = JSON.parse(persistValues) as Record<
+ string,
+ Record
+ >;
+
+ for (const id in serializedValues) {
+ const el = this.querySelector(`#${id}`) as HTMLElement;
+ if (!el) {
+ continue;
+ }
+
+ const elValues = serializedValues[id];
+ for (const attr in elValues) {
+ el.setAttribute(attr, elValues[attr]);
+ if (["width", "height"].includes(attr)) {
+ el.style[attr as any] = `${elValues[attr]}px`;
+ }
+ }
+ }
+ }
+}
diff --git a/src/elements/context.ts b/src/elements/context.ts
new file mode 100644
index 0000000..febba36
--- /dev/null
+++ b/src/elements/context.ts
@@ -0,0 +1,47 @@
+import { config } from "../../package.json";
+import { PluginCEBase } from "./base";
+
+export class ContextPane extends PluginCEBase {
+ _item?: Zotero.Item;
+
+ _details!: any;
+ _sidenav: any;
+
+ get item() {
+ return this._item;
+ }
+
+ set item(val) {
+ this._item = val;
+ }
+
+ get content() {
+ return this._parseContentID(
+ MozXULElement.parseXULToFragment(`
+
+
+
+
+
+`),
+ );
+ }
+
+ init(): void {
+ this._details = this._queryID("container");
+ this._sidenav = this._queryID("sidenav");
+ }
+
+ render() {
+ if (!this.item) return;
+ this._details.mode = this.item.isEditable() ? null : "view";
+ this._details.item = this.item;
+ this._details.parentID = this.item.parentID;
+ this._details.sidenav = this._sidenav;
+ this._details.render();
+ this._sidenav.toggleDefaultStatus();
+ }
+}
diff --git a/src/elements/detailsPane.ts b/src/elements/detailsPane.ts
new file mode 100644
index 0000000..197197b
--- /dev/null
+++ b/src/elements/detailsPane.ts
@@ -0,0 +1,30 @@
+import { config } from "../../package.json";
+const ItemDetails = customElements.get("item-details")! as any;
+
+export class NoteDetails extends ItemDetails {
+ content = MozXULElement.parseXULToFragment(`
+
+
+
+
+
+
+
+
+
+
+
+
+`);
+
+ forceUpdateSideNav() {
+ this._sidenav
+ .querySelectorAll("toolbarbutton")
+ .forEach((elem: HTMLElement) => (elem.parentElement!.hidden = true));
+ super.forceUpdateSideNav();
+ }
+}
diff --git a/src/elements/outlinePane.ts b/src/elements/outlinePane.ts
new file mode 100644
index 0000000..81d816e
--- /dev/null
+++ b/src/elements/outlinePane.ts
@@ -0,0 +1,379 @@
+import { FilePickerHelper } from "zotero-plugin-toolkit/dist/helpers/filePicker";
+import { config } from "../../package.json";
+import { showHintWithLink } from "../utils/hint";
+import { formatPath } from "../utils/str";
+import { waitUtilAsync } from "../utils/wait";
+import { OutlineType } from "../utils/workspace";
+import { PluginCEBase } from "./base";
+import {
+ getEditorInstance,
+ moveHeading,
+ updateHeadingTextAtLine,
+} from "../utils/editor";
+import { getNoteLinkParams } from "../utils/link";
+import { getNoteTree, getNoteTreeNodeById } from "../utils/note";
+import { getPref } from "../utils/prefs";
+
+export class OutlinePane extends PluginCEBase {
+ _outlineType: OutlineType = OutlineType.empty;
+ _item?: Zotero.Item;
+ _editorElement!: EditorElement;
+
+ _outlineContainer!: HTMLIFrameElement;
+ _notifierID!: string;
+
+ static outlineSources = [
+ "",
+ `chrome://${config.addonRef}/content/treeView.html`,
+ `chrome://${config.addonRef}/content/mindMap.html`,
+ `chrome://${config.addonRef}/content/bubbleMap.html`,
+ ];
+
+ static outlineMenuIDs = {
+ "": OutlineType.empty,
+ useTreeView: OutlineType.treeView,
+ useMindMap: OutlineType.mindMap,
+ useBubbleMap: OutlineType.bubbleMap,
+ };
+
+ get content() {
+ return this._parseContentID(
+ MozXULElement.parseXULToFragment(`
+
+
+
+
+
+
+
+
+
+
+
+`),
+ );
+ }
+
+ get outlineType() {
+ return this._outlineType;
+ }
+
+ set outlineType(newType) {
+ if (newType === OutlineType.empty) {
+ newType = OutlineType.treeView;
+ }
+ if (newType > OutlineType.bubbleMap) {
+ newType = OutlineType.treeView;
+ }
+
+ this._outlineType = newType;
+ }
+
+ get item() {
+ return this._item;
+ }
+
+ set item(val) {
+ this._item = val;
+ }
+
+ get editor() {
+ return this._editorElement._editorInstance;
+ }
+
+ init(): void {
+ MozXULElement.insertFTLIfNeeded(`${config.addonRef}-outline.ftl`);
+
+ this._outlineContainer = this._queryID("outline") as unknown as HTMLIFrameElement;
+
+ this._queryID("left-toolbar")?.addEventListener(
+ "command",
+ this.toolbarButtonCommandHandler,
+ );
+
+ this._notifierID = Zotero.Notifier.registerObserver(
+ this,
+ ["item"],
+ "attachmentsBox",
+ );
+
+ this._loadPersist();
+ }
+
+ destroy(): void {
+ Zotero.Notifier.unregisterObserver(this._notifierID);
+ this._outlineContainer.contentWindow?.removeEventListener(
+ "message",
+ this.messageHandler,
+ );
+ }
+
+ notify(
+ event: string,
+ type: string,
+ ids: number[] | string[],
+ extraData: { [key: string]: any },
+ ) {
+ if (!this.item) return;
+ if (event === "modify" && type === "item") {
+ if ((ids as number[]).includes(this.item.id)) {
+ this.updateOutline();
+ if (getPref("workspace.autoUpdateRelatedNotes")) {
+ this._addon.api.note.updateRelatedNotes(this.item.id);
+ }
+ }
+ }
+ }
+
+ async render() {
+ if (this.outlineType === OutlineType.empty) {
+ this.outlineType = OutlineType.treeView;
+ }
+ await this.updateOutline();
+ }
+
+ async updateOutline() {
+ if (!this.item) return;
+
+ this._outlineContainer.contentWindow?.removeEventListener(
+ "message",
+ this.messageHandler,
+ );
+
+ this._outlineContainer.setAttribute("src", OutlinePane.outlineSources[this.outlineType]);
+
+ await waitUtilAsync(
+ () => this._outlineContainer.contentWindow?.document.readyState === "complete",
+ );
+ this._outlineContainer.contentWindow?.addEventListener(
+ "message",
+ this.messageHandler,
+ );
+ this._outlineContainer.contentWindow?.postMessage(
+ {
+ type: "setMindMapData",
+ nodes: this._addon.api.note.getNoteTreeFlattened(this.item, {
+ keepLink: !!getPref("workspace.outline.keepLinks"),
+ }),
+ expandLevel: getPref("workspace.outline.expandLevel"),
+ },
+ "*",
+ );
+
+ // Update button hidden
+ const isTreeView = this.outlineType === OutlineType.treeView;
+ for (const key of ["saveImage", "saveSVG"]) {
+ const elem = this._queryID(key);
+ if (isTreeView) {
+ elem?.setAttribute("disabled", "true");
+ } else {
+ elem?.removeAttribute("disabled");
+ }
+ }
+
+ // Update set outline menu
+ this._queryID("setOutlinePopup")?.childNodes.forEach((elem) =>
+ (elem as XUL.MenuItem).removeAttribute("checked"),
+ );
+ this._queryID(
+ Object.keys(OutlinePane.outlineMenuIDs)[this.outlineType],
+ )?.setAttribute("checked", "true");
+ }
+
+ saveImage(type: "saveSVG" | "saveImage") {
+ this._outlineContainer.contentWindow?.postMessage(
+ {
+ type,
+ },
+ "*",
+ );
+ }
+
+ async saveFreeMind() {
+ if (!this.item?.id) return;
+ // TODO: uncouple this part
+ const filename = await new FilePickerHelper(
+ `${Zotero.getString("fileInterface.export")} FreeMind XML`,
+ "save",
+ [["FreeMind XML File(*.mm)", "*.mm"]],
+ `${this.item.getNoteTitle()}.mm`,
+ ).open();
+ if (filename) {
+ await addon.api.$export.saveFreeMind(filename, this.item.id);
+ }
+ }
+
+ toolbarButtonCommandHandler = async (ev: Event) => {
+ if (!this.item) return;
+ const type = this._unwrapID((ev.target as XUL.ToolBarButton).id);
+ switch (type) {
+ case "useTreeView":
+ case "useMindMap":
+ case "useBubbleMap": {
+ this.outlineType = OutlinePane.outlineMenuIDs[type];
+ await this.updateOutline();
+ break;
+ }
+ case "saveImage":
+ case "saveSVG": {
+ this.saveImage(type);
+ break;
+ }
+ case "saveFreeMind": {
+ this.saveFreeMind();
+ break;
+ }
+ case "saveMore": {
+ this._addon.hooks.onShowExportNoteOptions([this.item.id]);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ };
+
+ messageHandler = async (ev: MessageEvent) => {
+ switch (ev.data.type) {
+ case "jumpNode": {
+ if (!this.editor) {
+ return;
+ }
+ this._addon.api.editor.scroll(this.editor, ev.data.lineIndex);
+ return;
+ }
+ case "openNote": {
+ const linkParams = getNoteLinkParams(ev.data.link);
+ if (!linkParams.noteItem) {
+ return;
+ }
+ this._addon.hooks.onOpenNote(linkParams.noteItem.id, "preview", {
+ lineIndex: linkParams.lineIndex || undefined,
+ });
+ return;
+ }
+ case "moveNode": {
+ if (!this.item) return;
+ const tree = getNoteTree(this.item);
+ const fromNode = getNoteTreeNodeById(this.item, ev.data.fromID, tree);
+ const toNode = getNoteTreeNodeById(this.item, ev.data.toID, tree);
+ moveHeading(
+ getEditorInstance(this.item.id),
+ fromNode!,
+ toNode!,
+ ev.data.moveType,
+ );
+ return;
+ }
+ case "editNode": {
+ if (!this.editor) {
+ return;
+ }
+ updateHeadingTextAtLine(
+ this.editor,
+ ev.data.lineIndex,
+ ev.data.text.replace(/[\r\n]/g, ""),
+ );
+ return;
+ }
+ case "saveSVGReturn": {
+ const filename = await new FilePickerHelper(
+ `${Zotero.getString("fileInterface.export")} SVG Image`,
+ "save",
+ [["SVG File(*.svg)", "*.svg"]],
+ `${this.item?.getNoteTitle()}.svg`,
+ ).open();
+ if (filename) {
+ await Zotero.File.putContentsAsync(
+ formatPath(filename),
+ ev.data.image,
+ );
+ showHintWithLink(
+ `Image Saved to ${filename}`,
+ "Show in Folder",
+ (ev) => {
+ Zotero.File.reveal(filename);
+ },
+ );
+ }
+ return;
+ }
+ case "saveImageReturn": {
+ const filename = await new FilePickerHelper(
+ `${Zotero.getString("fileInterface.export")} PNG Image`,
+ "save",
+ [["PNG File(*.png)", "*.png"]],
+ `${this.item?.getNoteTitle()}.png`,
+ ).open();
+ if (filename) {
+ const parts = ev.data.image.split(",");
+ const bstr = atob(parts[1]);
+ let n = bstr.length;
+ const u8arr = new Uint8Array(n);
+ while (n--) {
+ u8arr[n] = bstr.charCodeAt(n);
+ }
+ await IOUtils.write(formatPath(filename), u8arr);
+ showHintWithLink(
+ `Image Saved to ${filename}`,
+ "Show in Folder",
+ (ev) => {
+ Zotero.File.reveal(filename);
+ },
+ );
+ }
+ return;
+ }
+ default:
+ return;
+ }
+ };
+}
diff --git a/src/elements/workspace.ts b/src/elements/workspace.ts
new file mode 100644
index 0000000..235b02e
--- /dev/null
+++ b/src/elements/workspace.ts
@@ -0,0 +1,116 @@
+import { config } from "../../package.json";
+import { waitUtilAsync } from "../utils/wait";
+import { PluginCEBase } from "./base";
+import { ContextPane } from "./context";
+import { OutlinePane } from "./outlinePane";
+
+export class Workspace extends PluginCEBase {
+ _item?: Zotero.Item;
+
+ _editorElement!: EditorElement;
+ _outline!: OutlinePane;
+ _context!: ContextPane;
+
+ get content() {
+ return this._parseContentID(
+ MozXULElement.parseXULToFragment(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+`),
+ );
+ }
+
+ get containerType() {
+ return this.getAttribute("container-type") || "";
+ }
+
+ set containerType(val: string) {
+ this.setAttribute("container-type", val);
+ }
+
+ get item() {
+ return this._item;
+ }
+
+ set item(val) {
+ this._item = val;
+ this._outline.item = val;
+ this._context.item = val;
+ }
+
+ get editor() {
+ return this._editorElement._editorInstance;
+ }
+
+ init(): void {
+ // MozXULElement.insertFTLIfNeeded(`${config.addonRef}-workspace.ftl`);
+
+ this._outline = this._queryID("left-container") as unknown as OutlinePane;
+ this._editorElement = this._queryID("editor-main") as EditorElement;
+ this._outline._editorElement = this._editorElement;
+
+ this._context = this._queryID("right-container") as unknown as ContextPane;
+
+ this._loadPersist();
+ }
+
+ destroy(): void {}
+
+ async render() {
+ await this._outline.render();
+ await this.updateEditor();
+ await this._context.render();
+ }
+
+ async updateEditor() {
+ const editorElem = this._queryID("editor-main") as EditorElement;
+ await waitUtilAsync(() => Boolean(editorElem._initialized));
+ if (!editorElem._initialized) {
+ throw new Error("initNoteEditor: waiting initialization failed");
+ }
+ editorElem.mode = "edit";
+ editorElem.viewMode = "library";
+ editorElem.parent = this.item?.parentItem;
+ editorElem.item = this.item;
+ await waitUtilAsync(() => Boolean(editorElem._editorInstance));
+ await editorElem._editorInstance._initPromise;
+ // Hide BN toolbar
+ editorElem._editorInstance._iframeWindow.document.body.setAttribute(
+ "no-bn-toolbar",
+ "true",
+ );
+ // TODO: implement jump to
+ // if (typeof options.lineIndex === "number") {
+ // addon.api.editor.scroll(editorElem._editorInstance, options.lineIndex);
+ // }
+ // if (typeof options.sectionName === "string") {
+ // addon.api.editor.scrollToSection(
+ // editorElem._editorInstance,
+ // options.sectionName,
+ // );
+ // }
+ return;
+ }
+}
diff --git a/src/extras/workspace.ts b/src/extras/workspace.ts
new file mode 100644
index 0000000..2b134de
--- /dev/null
+++ b/src/extras/workspace.ts
@@ -0,0 +1,17 @@
+import { ContextPane } from "../elements/context";
+import { NoteDetails } from "../elements/detailsPane";
+import { OutlinePane } from "../elements/outlinePane";
+import { Workspace } from "../elements/workspace";
+
+const elements = {
+ "bn-context": ContextPane,
+ "bn-outline": OutlinePane,
+ "bn-details": NoteDetails,
+ "bn-workspace": Workspace,
+};
+
+for (const [key, constructor] of Object.entries(elements)) {
+ if (!customElements.get(key)) {
+ customElements.define(key, constructor);
+ }
+}
diff --git a/src/hooks.ts b/src/hooks.ts
index a687c68..88fdcb7 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -11,15 +11,9 @@ import { registerMenus } from "./modules/menu";
import {
registerWorkspaceTab,
openWorkspaceTab,
+ onTabSelect,
} from "./modules/workspace/tab";
-import {
- initWorkspace,
- initWorkspaceEditor,
- toggleNotesPane,
- toggleOutlinePane,
- togglePreviewPane,
- updateOutline,
-} from "./modules/workspace/content";
+import { initWorkspace } from "./modules/workspace/content";
import { registerNotify } from "./modules/notify";
import { openWorkspaceWindow } from "./modules/workspace/window";
import { registerReaderAnnotationButton } from "./modules/reader";
@@ -34,16 +28,12 @@ import { showSyncDiff } from "./modules/sync/diffWindow";
import { showSyncInfo } from "./modules/sync/infoWindow";
import { showSyncManager } from "./modules/sync/managerWindow";
import { showTemplateEditor } from "./modules/template/editorWindow";
-import {
- createNoteFromTemplate,
- createWorkspaceNote,
- createNoteFromMD,
-} from "./modules/createNote";
-import { annotationTagAction } from "./modules/annotationTagAction";
+import { createNoteFromTemplate, createNoteFromMD } from "./modules/createNote";
import { createZToolkit } from "./utils/ztoolkit";
import { waitUtilAsync } from "./utils/wait";
import { initSyncList } from "./modules/sync/api";
import { getPref } from "./utils/prefs";
+import { patchViewItems } from "./modules/viewItems";
async function onStartup() {
await Promise.all([
@@ -74,6 +64,11 @@ async function onStartup() {
async function onMainWindowLoad(win: Window): Promise {
await waitUtilAsync(() => document.readyState === "complete");
+
+ Services.scriptloader.loadSubScript(
+ `chrome://${config.addonRef}/content/scripts/workspace.js`,
+ win,
+ );
// Create ztoolkit for every window
addon.data.ztoolkit = createZToolkit();
@@ -84,6 +79,8 @@ async function onMainWindowLoad(win: Window): Promise {
registerWorkspaceTab(win);
initTemplates();
+
+ patchViewItems(win);
}
async function onMainWindowUnload(win: Window): Promise {
@@ -102,25 +99,16 @@ function onShutdown(): void {
* Any operations should be placed in a function to keep this funcion clear.
*/
function onNotify(
- event: string,
- type: string,
- ids: number[] | string[],
- extraData: { [key: string]: any },
+ event: Parameters<_ZoteroTypes.Notifier.Notify>["0"],
+ type: Parameters<_ZoteroTypes.Notifier.Notify>["1"],
+ ids: Parameters<_ZoteroTypes.Notifier.Notify>["2"],
+ extraData: Parameters<_ZoteroTypes.Notifier.Notify>["3"],
) {
if (extraData.skipBN) {
return;
}
- // Workspace main note update
- if (event === "modify" && type === "item") {
- if ((ids as number[]).includes(addon.data.workspace.mainId)) {
- addon.data.workspace.tab.active &&
- updateOutline(addon.data.workspace.tab.container!);
- addon.data.workspace.window.active &&
- updateOutline(addon.data.workspace.window.container!);
- if (getPref("workspace.autoUpdateRelatedNotes")) {
- addon.api.note.updateRelatedNotes(addon.data.workspace.mainId);
- }
- }
+ if (event === "select" && type === "tab") {
+ onTabSelect(extraData[ids[0]].type);
}
if (event === "modify" && type === "item") {
const modifiedNotes = Zotero.Items.get(ids).filter((item) => item.isNote());
@@ -131,10 +119,6 @@ function onNotify(
reason: "item-modify",
});
}
- }
- // Insert annotation when assigning tag starts with @
- if (event === "add" && type === "item-tag") {
- annotationTagAction(ids as number[], extraData);
} else {
return;
}
@@ -170,23 +154,14 @@ function onOpenNote(
return;
}
if (mode === "auto") {
- if (noteId === addon.data.workspace.mainId) {
- mode = "workspace";
- } else if (
- addon.data.workspace.tab.active ||
- addon.data.workspace.window.active
- ) {
- mode = "preview";
- } else {
- mode = "standalone";
- }
+ mode = "workspace";
}
switch (mode) {
case "preview":
- addon.hooks.onSetWorkspaceNote(noteId, "preview", options);
+ // addon.hooks.onSetWorkspaceNote(noteId, "preview", options);
break;
case "workspace":
- addon.hooks.onSetWorkspaceNote(noteId, "main", options);
+ // addon.hooks.onSetWorkspaceNote(noteId, "main", options);
break;
case "standalone":
ZoteroPane.openNoteWindow(noteId);
@@ -196,60 +171,13 @@ function onOpenNote(
}
}
-function onSetWorkspaceNote(
- noteId: number,
- type: "main" | "preview" = "main",
- options: {
- lineIndex?: number;
- sectionName?: string;
- } = {},
-) {
- if (type === "main") {
- addon.data.workspace.mainId = noteId;
- addon.data.workspace.tab.active &&
- updateOutline(addon.data.workspace.tab.container!);
- addon.data.workspace.window.active &&
- updateOutline(addon.data.workspace.window.container!);
- }
- if (addon.data.workspace.window.active) {
- initWorkspaceEditor(
- addon.data.workspace.window.container!,
- type,
- noteId,
- options,
- );
- type === "preview" &&
- addon.hooks.onToggleWorkspacePane(
- "preview",
- true,
- addon.data.workspace.window.container,
- );
- addon.data.workspace.window.window?.focus();
- }
- if (addon.data.workspace.tab.active) {
- initWorkspaceEditor(
- addon.data.workspace.tab.container!,
- type,
- noteId,
- options,
- );
- type === "preview" &&
- addon.hooks.onToggleWorkspacePane(
- "preview",
- true,
- addon.data.workspace.tab.container,
- );
- Zotero_Tabs.select(addon.data.workspace.tab.id!);
- }
-}
-
-function onOpenWorkspace(type: "tab" | "window" = "tab") {
+function onOpenWorkspace(item: Zotero.Item, type: "tab" | "window" = "tab") {
if (type === "window") {
- openWorkspaceWindow();
+ openWorkspaceWindow(item);
return;
}
if (type === "tab") {
- openWorkspaceTab();
+ openWorkspaceTab(item);
return;
}
}
@@ -261,19 +189,19 @@ function onToggleWorkspacePane(
visibility?: boolean,
container?: XUL.Box,
) {
- switch (type) {
- case "outline":
- toggleOutlinePane(visibility, container);
- break;
- case "preview":
- togglePreviewPane(visibility, container);
- break;
- case "notes":
- toggleNotesPane(visibility);
- break;
- default:
- break;
- }
+ // switch (type) {
+ // case "outline":
+ // toggleOutlinePane(visibility, container);
+ // break;
+ // case "preview":
+ // togglePreviewPane(visibility, container);
+ // break;
+ // case "notes":
+ // toggleNotesPane(visibility);
+ // break;
+ // default:
+ // break;
+ // }
}
const onSyncing = callSyncing;
@@ -296,8 +224,6 @@ const onShowSyncDiff = showSyncDiff;
const onShowTemplateEditor = showTemplateEditor;
-const onCreateWorkspaceNote = createWorkspaceNote;
-
const onCreateNoteFromTemplate = createNoteFromTemplate;
const onCreateNoteFromMD = createNoteFromMD;
@@ -315,7 +241,6 @@ export default {
onPrefsEvent,
onOpenNote,
onInitWorkspace,
- onSetWorkspaceNote,
onOpenWorkspace,
onToggleWorkspacePane,
onSyncing,
@@ -328,7 +253,6 @@ export default {
onShowSyncInfo,
onShowSyncManager,
onShowTemplateEditor,
- onCreateWorkspaceNote,
onCreateNoteFromTemplate,
onCreateNoteFromMD,
};
diff --git a/src/modules/annotationTagAction.ts b/src/modules/annotationTagAction.ts
deleted file mode 100644
index 0293ba3..0000000
--- a/src/modules/annotationTagAction.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { addLineToNote, getNoteTreeFlattened } from "../utils/note";
-
-export { annotationTagAction };
-
-async function annotationTagAction(
- ids: Array,
- extraData: Record,
-) {
- const workspaceNote = Zotero.Items.get(addon.data.workspace.mainId);
- if (!workspaceNote || !workspaceNote.isNote()) {
- return;
- }
- const nodes = getNoteTreeFlattened(workspaceNote);
- const headings: string[] = nodes.map((node) => node.model.name);
-
- for (const tagId of ids.filter((t) =>
- (extraData[t].tag as string).startsWith("@"),
- )) {
- const tagName = (extraData[tagId].tag as string).slice(1).trim();
- if (headings.includes(tagName) || tagName === "@") {
- let lineIndex: number;
- if (tagName === "@") {
- lineIndex = -1;
- } else {
- const targetNode = nodes.find((node) => node.model.name === tagName);
- lineIndex = targetNode?.model.endIndex;
- }
-
- const annotationItem = Zotero.Items.get((tagId as string).split("-")[0]);
- if (!annotationItem.isAnnotation()) {
- continue;
- }
- await addLineToNote(
- workspaceNote,
- await addon.api.convert.annotations2html([annotationItem], {
- noteItem: workspaceNote,
- }),
- lineIndex,
- );
- }
- }
-}
diff --git a/src/modules/createNote.ts b/src/modules/createNote.ts
index 702db0c..5740bbe 100644
--- a/src/modules/createNote.ts
+++ b/src/modules/createNote.ts
@@ -1,45 +1,7 @@
import { getString } from "../utils/locale";
-import { config } from "../../package.json";
import { formatPath } from "../utils/str";
-export { createWorkspaceNote, createNoteFromTemplate, createNoteFromMD };
-
-async function createWorkspaceNote() {
- const currentCollection = ZoteroPane.getSelectedCollection();
- if (!currentCollection) {
- window.alert(getString("alert.notValidCollectionError"));
- return;
- }
- const confirmOperation = window.confirm(
- `${getString(
- "menuAddNote.newMainNote.confirmHead",
- // @ts-ignore
- )} '${currentCollection.getName()}' ${getString(
- "menuAddNote.newMainNote.confirmTail",
- )}`,
- );
- if (!confirmOperation) {
- return;
- }
- const header = window.prompt(
- getString("menuAddNote.newMainNote.enterNoteTitle"),
- `New Note ${new Date().toLocaleString()}`,
- );
- const noteID = await ZoteroPane.newNote();
- const noteItem = Zotero.Items.get(noteID);
- noteItem.setNote(
- `${header}
\n
`,
- );
- await noteItem.saveTx();
- addon.hooks.onSetWorkspaceNote(noteID, "main");
- if (
- !addon.data.workspace.tab.active &&
- !addon.data.workspace.window.active &&
- window.confirm(getString("menuAddNote.newMainNote.openWorkspaceTab"))
- ) {
- addon.hooks.onOpenWorkspace("tab");
- }
-}
+export { createNoteFromTemplate, createNoteFromMD };
function getLibraryParentId() {
return ZoteroPane.getSelectedItems().filter((item) => item.isRegularItem())[0]
diff --git a/src/modules/editor/inject.ts b/src/modules/editor/inject.ts
index eb4afea..379e061 100644
--- a/src/modules/editor/inject.ts
+++ b/src/modules/editor/inject.ts
@@ -16,47 +16,13 @@ export async function injectEditorScripts(win: Window) {
);
}
-export function injectEditorCSS(win: Window) {
+export async function injectEditorCSS(win: Window) {
ztoolkit.UI.appendElement(
{
tag: "style",
id: "betternotes-style",
properties: {
- innerHTML: `
- .primary-editor > h1::before {
- margin-left: -64px !important;
- padding-left: 40px !important;
- content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Ctitle%3E%E6%9C%AA%E6%A0%87%E9%A2%98-1%3C%2Ftitle%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M12.29%2C16.8H11.14V12.33H6.07V16.8H4.92V7H6.07v4.3h5.07V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M18.05%2C16.8H16.93V8.41a4%2C4%2C0%2C0%2C1-.9.53%2C6.52%2C6.52%2C0%2C0%2C1-1.14.44l-.32-1a8.2%2C8.2%2C0%2C0%2C0%2C1.67-.67%2C6.31%2C6.31%2C0%2C0%2C0%2C1.39-1h.42Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
- }
- .primary-editor > h2::before {
- margin-left: -64px !important;
- padding-left: 40px !important;
- content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.a%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22a%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22a%22%20d%3D%22M14.14%2C16.8v-.48a4.1%2C4.1%2C0%2C0%2C1%2C.14-1.11%2C2.86%2C2.86%2C0%2C0%2C1%2C.45-.91%2C5.49%2C5.49%2C0%2C0%2C1%2C.83-.86c.33-.29.75-.61%2C1.24-1a7.43%2C7.43%2C0%2C0%2C0%2C.9-.73%2C3.9%2C3.9%2C0%2C0%2C0%2C.57-.7%2C2.22%2C2.22%2C0%2C0%2C0%2C.3-.66%2C2.87%2C2.87%2C0%2C0%2C0%2C.11-.77%2C1.89%2C1.89%2C0%2C0%2C0-.47-1.32%2C1.66%2C1.66%2C0%2C0%2C0-1.28-.5A3.17%2C3.17%2C0%2C0%2C0%2C15.7%2C8a3.49%2C3.49%2C0%2C0%2C0-1.08.76l-.68-.65a4.26%2C4.26%2C0%2C0%2C1%2C1.39-1A4%2C4%2C0%2C0%2C1%2C17%2C6.84a2.62%2C2.62%2C0%2C0%2C1%2C2.83%2C2.67%2C3.58%2C3.58%2C0%2C0%2C1-.15%2C1%2C3.09%2C3.09%2C0%2C0%2C1-.41.9%2C5.53%2C5.53%2C0%2C0%2C1-.67.81%2C9%2C9%2C0%2C0%2C1-.95.79c-.46.32-.84.59-1.13.82a4.68%2C4.68%2C0%2C0%2C0-.71.64%2C2%2C2%2C0%2C0%2C0-.38.6%2C2.08%2C2.08%2C0%2C0%2C0-.11.69h4.88v1Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22a%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
- }
- .primary-editor > h3::before {
- margin-left: -64px !important;
- padding-left: 40px !important;
- content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M14%2C16.14l.51-.8a4.75%2C4.75%2C0%2C0%2C0%2C1.1.52%2C4.27%2C4.27%2C0%2C0%2C0%2C1.12.16%2C2.29%2C2.29%2C0%2C0%2C0%2C1.64-.52A1.77%2C1.77%2C0%2C0%2C0%2C19%2C14.17a1.7%2C1.7%2C0%2C0%2C0-.68-1.48%2C3.6%2C3.6%2C0%2C0%2C0-2.06-.48H15.4v-1h.77A3%2C3%2C0%2C0%2C0%2C18%2C10.81a1.65%2C1.65%2C0%2C0%2C0%2C.6-1.41%2C1.47%2C1.47%2C0%2C0%2C0-.47-1.19A1.67%2C1.67%2C0%2C0%2C0%2C17%2C7.79a3.33%2C3.33%2C0%2C0%2C0-2.08.73l-.59-.75a4.4%2C4.4%2C0%2C0%2C1%2C1.28-.71A4.35%2C4.35%2C0%2C0%2C1%2C17%2C6.84a2.84%2C2.84%2C0%2C0%2C1%2C2%2C.65%2C2.21%2C2.21%2C0%2C0%2C1%2C.74%2C1.78%2C2.35%2C2.35%2C0%2C0%2C1-.49%2C1.5%2C2.7%2C2.7%2C0%2C0%2C1-1.46.89v0a2.74%2C2.74%2C0%2C0%2C1%2C1.65.74%2C2.15%2C2.15%2C0%2C0%2C1%2C.66%2C1.65%2C2.64%2C2.64%2C0%2C0%2C1-.9%2C2.12%2C3.44%2C3.44%2C0%2C0%2C1-2.34.78%2C5.3%2C5.3%2C0%2C0%2C1-1.48-.2A5%2C5%2C0%2C0%2C1%2C14%2C16.14Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
- }
- .primary-editor > h4::before {
- margin-left: -64px !important;
- padding-left: 40px !important;
- content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M19.43%2C6.92v6.59h1.05v1.05H19.43V16.9H18.31V14.56H13.66v-1c.43-.49.87-1%2C1.31-1.57s.87-1.13%2C1.27-1.7S17%2C9.14%2C17.36%2C8.57a16.51%2C16.51%2C0%2C0%2C0%2C.86-1.65Zm-4.49%2C6.59h3.37V8.63c-.34.61-.67%2C1.15-1%2C1.63s-.6.91-.87%2C1.3-.56.74-.81%2C1Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
- }
- .primary-editor > h5::before {
- margin-left: -64px !important;
- padding-left: 40px !important;
- content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M14%2C16l.58-.76a3.67%2C3.67%2C0%2C0%2C0%2C1%2C.58A3.44%2C3.44%2C0%2C0%2C0%2C16.8%2C16a2.17%2C2.17%2C0%2C0%2C0%2C1.58-.6A2%2C2%2C0%2C0%2C0%2C19%2C13.88a1.85%2C1.85%2C0%2C0%2C0-.64-1.5%2C2.83%2C2.83%2C0%2C0%2C0-1.86-.54c-.27%2C0-.55%2C0-.86%2C0s-.58%2C0-.81.06L15.17%2C7H19.7V8H16.14l-.2%2C2.88.47%2C0h.43a3.5%2C3.5%2C0%2C0%2C1%2C2.43.79%2C2.74%2C2.74%2C0%2C0%2C1%2C.88%2C2.16%2C3%2C3%2C0%2C0%2C1-.94%2C2.3%2C3.41%2C3.41%2C0%2C0%2C1-2.4.87%2C4.45%2C4.45%2C0%2C0%2C1-1.5-.24A4.81%2C4.81%2C0%2C0%2C1%2C14%2C16Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
- }
- .primary-editor > h6::before {
- margin-left: -64px !important;
- padding-left: 40px !important;
- content: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2218px%22%20height%3D%2218px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2015.56%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3A%23666%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M11.17%2C16.8H10V12.33H5V16.8H3.8V7H5v4.3H10V7h1.15Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M20.18%2C13.7a3.24%2C3.24%2C0%2C0%2C1-.88%2C2.38%2C2.94%2C2.94%2C0%2C0%2C1-2.2.9%2C2.69%2C2.69%2C0%2C0%2C1-2.31-1.17A5.59%2C5.59%2C0%2C0%2C1%2C14%2C12.49a12.18%2C12.18%2C0%2C0%2C1%2C.2-2.14%2C5.16%2C5.16%2C0%2C0%2C1%2C.84-2A3.65%2C3.65%2C0%2C0%2C1%2C16.27%2C7.2%2C3.71%2C3.71%2C0%2C0%2C1%2C18%2C6.84%2C3.14%2C3.14%2C0%2C0%2C1%2C19%2C7a3.59%2C3.59%2C0%2C0%2C1%2C1%2C.5l-.56.77a2.3%2C2.3%2C0%2C0%2C0-1.49-.48A2.3%2C2.3%2C0%2C0%2C0%2C16.79%2C8a3%2C3%2C0%2C0%2C0-.92.85%2C3.79%2C3.79%2C0%2C0%2C0-.56%2C1.25%2C6.56%2C6.56%2C0%2C0%2C0-.19%2C1.65h0a2.61%2C2.61%2C0%2C0%2C1%2C1-.84%2C2.91%2C2.91%2C0%2C0%2C1%2C1.23-.28%2C2.63%2C2.63%2C0%2C0%2C1%2C2%2C.85A3.09%2C3.09%2C0%2C0%2C1%2C20.18%2C13.7ZM19%2C13.78a2.28%2C2.28%2C0%2C0%2C0-.5-1.62%2C1.67%2C1.67%2C0%2C0%2C0-1.29-.54%2C2%2C2%2C0%2C0%2C0-1.5.58%2C2%2C2%2C0%2C0%2C0-.56%2C1.4%2C2.65%2C2.65%2C0%2C0%2C0%2C.55%2C1.74%2C1.85%2C1.85%2C0%2C0%2C0%2C2.78.1A2.38%2C2.38%2C0%2C0%2C0%2C19%2C13.78Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M21%2C5a2.25%2C2.25%2C0%2C0%2C1%2C2.25%2C2.25v9.56A2.25%2C2.25%2C0%2C0%2C1%2C21%2C19H3A2.25%2C2.25%2C0%2C0%2C1%2C.75%2C16.78V7.22A2.25%2C2.25%2C0%2C0%2C1%2C3%2C5H21m0-.75H3a3%2C3%2C0%2C0%2C0-3%2C3v9.56a3%2C3%2C0%2C0%2C0%2C3%2C3H21a3%2C3%2C0%2C0%2C0%2C3-3V7.22a3%2C3%2C0%2C0%2C0-3-3Z%22%20transform%3D%22translate(0%20-4.22)%22%2F%3E%3C%2Fsvg%3E") !important;
- }
- .primary-editor > p, .primary-editor h1, .primary-editor h2, .primary-editor h3, .primary-editor h4, .primary-editor h5, .primary-editor h6, .primary-editor pre, .primary-editor blockquote, .primary-editor table, .primary-editor ul, .primary-editor ol, .primary-editor hr{
- max-width: unset
- }
- `,
+ innerHTML: await getFileContent(rootURI + "chrome/content/styles/editor.css"),
},
ignoreIfExists: true,
},
diff --git a/src/modules/editor/toolbar.ts b/src/modules/editor/toolbar.ts
index 373f959..a680b62 100644
--- a/src/modules/editor/toolbar.ts
+++ b/src/modules/editor/toolbar.ts
@@ -4,17 +4,12 @@ import { getLineAtCursor, getSectionAtCursor } from "../../utils/editor";
import { showHint } from "../../utils/hint";
import { getNoteLink, getNoteLinkParams } from "../../utils/link";
import { getString } from "../../utils/locale";
-import {
- addLineToNote,
- getNoteTreeFlattened,
- getNoteType,
-} from "../../utils/note";
+import { addLineToNote, getNoteTreeFlattened } from "../../utils/note";
import { getPref } from "../../utils/prefs";
import { slice } from "../../utils/str";
export async function initEditorToolbar(editor: Zotero.EditorInstance) {
const noteItem = editor._item;
- const noteType = getNoteType(noteItem.id);
const toolbar = await registerEditorToolbar(editor, makeId("toolbar"));
// Settings
@@ -56,22 +51,7 @@ export async function initEditorToolbar(editor: Zotero.EditorInstance) {
id: makeId("settings-openWorkspace"),
text: getString("editor.toolbar.settings.openWorkspace"),
callback: (e) => {
- addon.hooks.onOpenWorkspace("tab");
- },
- },
- {
- id: makeId("settings-setWorkspace"),
- text: getString("editor.toolbar.settings.setWorkspace"),
- callback: (e) => {
- addon.hooks.onSetWorkspaceNote(e.editor._item.id, "main");
- },
- },
- {
- id: makeId("settings-previewInWorkspace"),
- text: getString("editor.toolbar.settings.previewInWorkspace"),
- callback: (e) => {
- addon.hooks.onOpenWorkspace("tab");
- addon.hooks.onSetWorkspaceNote(e.editor._item.id, "preview");
+ addon.hooks.onOpenWorkspace(noteItem, "tab");
},
},
{
@@ -221,103 +201,95 @@ export async function initEditorToolbar(editor: Zotero.EditorInstance) {
});
// Center button
- if (noteType === "main") {
- registerEditorToolbarElement(
+
+ const onTriggerMenu = (ev: MouseEvent) => {
+ editor._iframeWindow.focus();
+ const linkMenu: PopupData[] = getLinkMenuData(editor);
+ editor._iframeWindow.document
+ .querySelector(`#${makeId("link")}`)!
+ .querySelector(".toolbar-button")!.innerHTML = ICONS.linkAfter;
+
+ const popup = registerEditorToolbarPopup(
editor,
- toolbar,
+ linkButton,
+ `${config.addonRef}-link-popup`,
"middle",
- ztoolkit.UI.createElement(editor._iframeWindow.document, "div", {
- properties: { innerHTML: getString("editor.toolbar.main") },
- }),
+ linkMenu,
);
- } else {
- const onTriggerMenu = (ev: MouseEvent) => {
- editor._iframeWindow.focus();
- const linkMenu: PopupData[] = getLinkMenuData(editor);
- editor._iframeWindow.document
- .querySelector(`#${makeId("link")}`)!
- .querySelector(".toolbar-button")!.innerHTML = ICONS.linkAfter;
+ };
- const popup = registerEditorToolbarPopup(
- editor,
- linkButton,
- `${config.addonRef}-link-popup`,
- "middle",
- linkMenu,
- );
- };
+ const onExitMenu = (ev: MouseEvent) => {
+ editor._iframeWindow.document
+ .querySelector(`#${makeId("link-popup")}`)
+ ?.remove();
+ editor._iframeWindow.document
+ .querySelector(`#${makeId("link")}`)!
+ .querySelector(".toolbar-button")!.innerHTML = ICONS.addon;
+ };
- const onExitMenu = (ev: MouseEvent) => {
- editor._iframeWindow.document
- .querySelector(`#${makeId("link-popup")}`)
- ?.remove();
- editor._iframeWindow.document
- .querySelector(`#${makeId("link")}`)!
- .querySelector(".toolbar-button")!.innerHTML = ICONS.addon;
- };
-
- const onClickMenu = async (ev: MouseEvent) => {
- const mainNote = Zotero.Items.get(addon.data.workspace.mainId) || null;
- if (!mainNote?.isNote()) {
- return;
- }
- const lineIndex = parseInt(
- (ev.target as HTMLDivElement).id.split("-").pop() || "-1",
- );
- const forwardLink = getNoteLink(noteItem);
- const backLink = getNoteLink(mainNote, { ignore: true, lineIndex });
- addLineToNote(
- mainNote,
- await addon.api.template.runTemplate(
- "[QuickInsertV2]",
- "link, linkText, subNoteItem, noteItem",
- [
- forwardLink,
- noteItem.getNoteTitle().trim() || forwardLink,
- noteItem,
- mainNote,
- ],
- ),
- lineIndex,
- );
- addLineToNote(
- noteItem,
- await addon.api.template.runTemplate(
- "[QuickBackLinkV2]",
- "link, linkText, subNoteItem, noteItem",
- [
- backLink,
- mainNote.getNoteTitle().trim() || "Workspace Note",
- noteItem,
- mainNote,
- "",
- ],
- ),
- );
- onExitMenu(ev);
- ev.stopPropagation();
- };
-
- const linkButton = await registerEditorToolbarDropdown(
- editor,
- toolbar,
- makeId("link"),
- ICONS.addon,
- getString("editor.toolbar.link.title"),
- "middle",
- onClickMenu,
+ const onClickMenu = async (ev: MouseEvent) => {
+ // TODO: fix link
+ return;
+ const mainNote = Zotero.Items.get(addon.data.workspace.mainId) || null;
+ if (!mainNote?.isNote()) {
+ return;
+ }
+ const lineIndex = parseInt(
+ (ev.target as HTMLDivElement).id.split("-").pop() || "-1",
);
+ const forwardLink = getNoteLink(noteItem);
+ const backLink = getNoteLink(mainNote, { ignore: true, lineIndex });
+ addLineToNote(
+ mainNote,
+ await addon.api.template.runTemplate(
+ "[QuickInsertV2]",
+ "link, linkText, subNoteItem, noteItem",
+ [
+ forwardLink,
+ noteItem.getNoteTitle().trim() || forwardLink,
+ noteItem,
+ mainNote,
+ ],
+ ),
+ lineIndex,
+ );
+ addLineToNote(
+ noteItem,
+ await addon.api.template.runTemplate(
+ "[QuickBackLinkV2]",
+ "link, linkText, subNoteItem, noteItem",
+ [
+ backLink,
+ mainNote.getNoteTitle().trim() || "Workspace Note",
+ noteItem,
+ mainNote,
+ "",
+ ],
+ ),
+ );
+ onExitMenu(ev);
+ ev.stopPropagation();
+ };
- linkButton.addEventListener("mouseenter", onTriggerMenu);
- linkButton.addEventListener("mouseleave", onExitMenu);
- linkButton.addEventListener("mouseleave", onExitMenu);
- linkButton.addEventListener("click", (ev) => {
- if ((ev.target as HTMLElement).classList.contains("option")) {
- onClickMenu(ev);
- }
- });
- editor._iframeWindow.document.addEventListener("click", onExitMenu);
- }
+ const linkButton = await registerEditorToolbarDropdown(
+ editor,
+ toolbar,
+ makeId("link"),
+ ICONS.addon,
+ getString("editor.toolbar.link.title"),
+ "middle",
+ onClickMenu,
+ );
+
+ linkButton.addEventListener("mouseenter", onTriggerMenu);
+ linkButton.addEventListener("mouseleave", onExitMenu);
+ linkButton.addEventListener("mouseleave", onExitMenu);
+ linkButton.addEventListener("click", (ev) => {
+ if ((ev.target as HTMLElement).classList.contains("option")) {
+ onClickMenu(ev);
+ }
+ });
+ editor._iframeWindow.document.addEventListener("click", onExitMenu);
// Export
// const exportButton = await registerEditorToolbarDropdown(
diff --git a/src/modules/export/api.ts b/src/modules/export/api.ts
index 19455c8..91c4c18 100644
--- a/src/modules/export/api.ts
+++ b/src/modules/export/api.ts
@@ -212,7 +212,7 @@ async function toFreeMind(noteItem: Zotero.Item) {
}
async function embedLinkedNotes(noteItem: Zotero.Item): Promise {
- const parser = ztoolkit.getDOMParser();
+ const parser = new DOMParser();
const globalCitationData = getNoteCitationData(noteItem as Zotero.Item);
diff --git a/src/modules/menu.ts b/src/modules/menu.ts
index aa8d78d..1c688a5 100644
--- a/src/modules/menu.ts
+++ b/src/modules/menu.ts
@@ -17,22 +17,6 @@ export function registerMenus() {
);
},
});
- ztoolkit.Menu.register("item", {
- tag: "menuitem",
- label: getString("menuItem.setMainNote"),
- icon: `chrome://${config.addonRef}/content/icons/favicon.png`,
- commandListener: (ev) => {
- addon.hooks.onSetWorkspaceNote(ZoteroPane.getSelectedItems()[0].id);
- },
- getVisibility: (elem, ev) => {
- const items = ZoteroPane.getSelectedItems();
- return (
- items.length == 1 &&
- items[0].isNote() &&
- items[0].id !== addon.data.workspace.mainId
- );
- },
- });
// menuEdit
const menuEditAnchor = document.querySelector(
@@ -133,88 +117,66 @@ export function registerMenus() {
menuFileAnchor,
);
- document
- .querySelector(`#${recentMainNotesMenuId}`)
- ?.addEventListener("popupshowing", () => {
- const popup = document.querySelector(`#${recentMainNotesMenuPopupId}`)!;
- removeChildren(popup);
- const children = Zotero.Items.get(
- ((getPref("recentMainNoteIds") as string) || "")
- .split(",")
- .map((id) => parseInt(id))
- .filter((id) => id !== addon.data.workspace.mainId),
- )
- .filter((item) => item.isNote())
- .map((item) => ({
- tag: "menuitem",
- attributes: {
- label: slice(
- `${slice(item.getNoteTitle().trim() || item.key, 30)} - ${
- item.parentItem
- ? "📄" + item.parentItem.getField("title")
- : "📁" +
- Zotero.Collections.get(item.getCollections())
- .map(
- (collection) => (collection as Zotero.Collection).name,
- )
- .join(", ")
- }`,
- 200,
- ),
- },
- listeners: [
- {
- type: "command",
- listener: () => {
- addon.hooks.onSetWorkspaceNote(item.id, "main");
- addon.hooks.onOpenWorkspace();
- },
- },
- ],
- }));
- const defaultChildren = [
- {
- tag: "menuitem",
- attributes: {
- label: getString("menuFile-openRecent-empty"),
- disabled: true,
- },
- },
- ];
+ // document
+ // .querySelector(`#${recentMainNotesMenuId}`)
+ // ?.addEventListener("popupshowing", () => {
+ // const popup = document.querySelector(`#${recentMainNotesMenuPopupId}`)!;
+ // removeChildren(popup);
+ // const children = Zotero.Items.get(
+ // ((getPref("recentMainNoteIds") as string) || "")
+ // .split(",")
+ // .map((id) => parseInt(id))
+ // .filter((id) => id !== addon.data.workspace.mainId),
+ // )
+ // .filter((item) => item.isNote())
+ // .map((item) => ({
+ // tag: "menuitem",
+ // attributes: {
+ // label: slice(
+ // `${slice(item.getNoteTitle().trim() || item.key, 30)} - ${
+ // item.parentItem
+ // ? "📄" + item.parentItem.getField("title")
+ // : "📁" +
+ // Zotero.Collections.get(item.getCollections())
+ // .map(
+ // (collection) => (collection as Zotero.Collection).name,
+ // )
+ // .join(", ")
+ // }`,
+ // 200,
+ // ),
+ // },
+ // listeners: [
+ // {
+ // type: "command",
+ // listener: () => {
+ // addon.hooks.onSetWorkspaceNote(item.id, "main");
+ // addon.hooks.onOpenWorkspace();
+ // },
+ // },
+ // ],
+ // }));
+ // const defaultChildren = [
+ // {
+ // tag: "menuitem",
+ // attributes: {
+ // label: getString("menuFile-openRecent-empty"),
+ // disabled: true,
+ // },
+ // },
+ // ];
- ztoolkit.UI.appendElement(
- {
- tag: "fragment",
- children: children.length === 0 ? defaultChildren : children,
- enableElementRecord: false,
- },
- popup,
- );
- return true;
- });
+ // ztoolkit.UI.appendElement(
+ // {
+ // tag: "fragment",
+ // children: children.length === 0 ? defaultChildren : children,
+ // enableElementRecord: false,
+ // },
+ // popup,
+ // );
+ // return true;
+ // });
- ztoolkit.Menu.register(
- "menuFile",
- {
- tag: "menuitem",
- label: getString("menuFile-openMainNote"),
- icon: `chrome://${config.addonRef}/content/icons/favicon.png`,
- commandListener: async (ev) => {
- const selectedIds = await itemPicker();
- if (
- selectedIds?.length === 1 &&
- Zotero.Items.get(selectedIds[0]).isNote()
- ) {
- addon.hooks.onSetWorkspaceNote(selectedIds[0], "main");
- addon.hooks.onOpenWorkspace();
- } else {
- window.alert(getString("menuFile-openMainNote-error"));
- }
- },
- },
- "after",
- menuFileAnchor,
- );
ztoolkit.Menu.register(
"menuFile",
{ tag: "menuseparator" },
@@ -256,28 +218,11 @@ export function registerMenus() {
"after",
menuFileAnchor,
);
- ztoolkit.Menu.register(
- "menuFile",
- {
- tag: "menuitem",
- label: getString("menuAddNote.newMainNote"),
- icon: `chrome://${config.addonRef}/content/icons/favicon.png`,
- commandListener: addon.hooks.onCreateWorkspaceNote,
- },
- "after",
- menuFileAnchor,
- );
// create note menu in library
const newNoteMenu = document
.querySelector("#zotero-tb-note-add")
?.querySelector("menupopup") as XUL.MenuPopup;
- ztoolkit.Menu.register(newNoteMenu, {
- tag: "menuitem",
- label: getString("menuAddNote.newMainNote"),
- icon: `chrome://${config.addonRef}/content/icons/favicon.png`,
- commandListener: addon.hooks.onCreateWorkspaceNote,
- });
ztoolkit.Menu.register(newNoteMenu, {
tag: "menuitem",
label: getString("menuAddNote.newTemplateStandaloneNote"),
diff --git a/src/modules/viewItems.ts b/src/modules/viewItems.ts
new file mode 100644
index 0000000..43e76f1
--- /dev/null
+++ b/src/modules/viewItems.ts
@@ -0,0 +1,28 @@
+import { PatchHelper } from "zotero-plugin-toolkit/dist/helpers/patch";
+
+export function patchViewItems(win: Window) {
+ // @ts-ignore
+ const ZoteroPane = win.ZoteroPane;
+ new PatchHelper().setData({
+ target: ZoteroPane,
+ funcSign: "viewItems",
+ patcher: (origin) =>
+ function (items: Zotero.Item[], event?: KeyboardEvent) {
+ if (!addon.data.alive || event?.shiftKey) {
+ // @ts-ignore
+ return origin.apply(this, [items, event]);
+ }
+ const otherItems = [];
+ for (const item of items) {
+ if (item.isNote()) {
+ addon.hooks.onOpenWorkspace(item, "tab");
+ continue;
+ }
+ otherItems.push(item);
+ }
+ // @ts-ignore
+ return origin.apply(this, [otherItems, event]);
+ },
+ enabled: true,
+ });
+}
diff --git a/src/modules/workspace/content.ts b/src/modules/workspace/content.ts
index 9ca1ec9..97fb6f2 100644
--- a/src/modules/workspace/content.ts
+++ b/src/modules/workspace/content.ts
@@ -1,489 +1,20 @@
-import { config } from "../../../package.json";
-import { ICONS } from "../../utils/config";
-import { itemPicker } from "../../utils/itemPicker";
-import { getString } from "../../utils/locale";
-import { getNoteTreeFlattened } from "../../utils/note";
-import { getPref } from "../../utils/prefs";
-import { waitUtilAsync } from "../../utils/wait";
-import { OutlineType } from "../../utils/workspace";
import { saveFreeMind as _saveFreeMind } from "../export/freemind";
-function makeId(key: string) {
- return `betternotes-workspace-${key}`;
-}
-
-export function initWorkspace(container: XUL.Box | undefined) {
+export function initWorkspace(container: XUL.Box, item: Zotero.Item) {
if (!container) {
return;
}
- function makeTooltipProp(
- id: string,
- content: string,
- title: string,
- callback: (ev: Event) => void,
- ) {
- return {
- id,
- tag: "button",
- namespace: "html",
- classList: ["tool-button"],
- properties: {
- innerHTML: content,
- title,
- },
- listeners: [
- {
- type: "click",
- listener: callback,
- },
- ],
- };
- }
- ztoolkit.UI.appendElement(
- {
- tag: "hbox",
- id: makeId("top-container"),
- styles: { width: "100%", height: "100%" },
- properties: {},
- attributes: {
- flex: "1",
- },
- children: [
- {
- tag: "vbox",
- id: makeId("outline-container"),
- styles: {
- overflow: "hidden",
- display: "flex",
- flexDirection: "column",
- },
- attributes: {
- width: "330",
- minwidth: "300",
- flex: "1",
- },
- children: [
- {
- tag: "link",
- properties: {
- rel: "stylesheet",
- href: `chrome://${config.addonRef}/content/toolbutton.css`,
- },
- },
- {
- tag: "div",
- id: makeId("outline-content"),
- styles: {
- height: "100%",
- },
- children: [
- {
- tag: "iframe",
- id: makeId("outline-iframe"),
- properties: {
- width: "100%",
- },
- styles: {
- border: "0",
- height: "100%",
- },
- },
- ],
- },
- {
- tag: "div",
- id: makeId("outline-buttons"),
- styles: {
- height: "50px",
- display: "flex",
- flexDirection: "row",
- justifyContent: "space-between",
- margin: "10px 20px 10px 20px",
- },
- children: [
- makeTooltipProp(
- makeId("switchOutline"),
- ICONS.switchOutline,
- getString("workspace.switchOutline"),
- (ev) => {
- setOutline(container);
- },
- ),
- makeTooltipProp(
- makeId("saveOutlineImage"),
- ICONS.saveOutlineImage,
- getString("workspace.saveOutlineImage"),
- (ev) => {
- saveImage(container);
- },
- ),
- makeTooltipProp(
- makeId("saveOutlineFreeMind"),
- ICONS.saveOutlineFreeMind,
- getString("workspace.saveOutlineFreeMind"),
- (ev) => {
- saveFreeMind();
- },
- ),
- ],
- },
- ],
- },
- {
- tag: "splitter",
- id: makeId("outline-splitter"),
- attributes: { collapse: "before" },
- children: [
- {
- tag: "grippy",
- },
- ],
- },
- {
- tag: "vbox",
- id: makeId("editor-main-container"),
- attributes: {
- flex: "1",
- width: "700",
- },
- styles: {
- background: "var(--material-background50)",
- },
- },
- {
- tag: "splitter",
- id: makeId("preview-splitter"),
- attributes: { collapse: "after", state: "collapsed" },
- children: [
- {
- tag: "grippy",
- },
- ],
- },
- {
- tag: "vbox",
- id: makeId("editor-preview-container"),
- attributes: {
- flex: "1",
- width: "500",
- },
- },
- ],
- },
- container,
- );
- // Manually add custom editor items in Zotero 7
+
+ container.style.minWidth = "0px";
+ container.style.minHeight = "0px";
+
// @ts-ignore
const customElements = container.ownerGlobal
.customElements as CustomElementRegistry;
- const mainEditorContainer = container.querySelector(
- `#${makeId("editor-main-container")}`,
- );
- const previewEditorContainer = container.querySelector(
- `#${makeId("editor-preview-container")}`,
- );
- const mainEditor = new (customElements.get("note-editor")!)();
- mainEditor.id = makeId("editor-main");
- mainEditor.setAttribute("flex", "1");
- const previewEditor = new (customElements.get("note-editor")!)();
- previewEditor.id = makeId("editor-preview");
- previewEditor.setAttribute("flex", "1");
- mainEditorContainer?.append(mainEditor);
- previewEditorContainer?.append(previewEditor);
- const outlineContainer = container.querySelector(
- `#${makeId("outline-container")}`,
- ) as XUL.Box;
- outlineContainer.style.background = "var(--material-sidepane)";
- const outlineMut = new (ztoolkit.getGlobal("MutationObserver"))(
- (mutations) => {
- if (outlineContainer.getAttribute("collapsed") === "true") {
- outlineContainer.style.removeProperty("display");
- } else {
- outlineContainer.style.display = "flex";
- }
- },
- );
- outlineMut.observe(outlineContainer, {
- attributes: true,
- attributeFilter: ["collapsed"],
- });
-
- setOutline(container, OutlineType.treeView);
- initWorkspaceEditor(container, "main", addon.data.workspace.mainId);
-}
-
-export async function initWorkspaceEditor(
- container: XUL.Box,
- type: "main" | "preview",
- noteId: number,
- options: {
- lineIndex?: number;
- sectionName?: string;
- } = {},
-) {
- const noteItem = Zotero.Items.get(noteId);
- if (!noteItem || !noteItem.isNote()) {
- ztoolkit.UI.appendElement(
- {
- tag: "div",
- id: makeId("emptyWorkspaceGuide"),
- styles: {
- position: "absolute",
- top: "0",
- left: "0",
- width: "100%",
- height: "100%",
- display: "flex",
- flexDirection: "column",
- justifyContent: "center",
- alignItems: "center",
- textAlign: "center",
- backgroundColor: "rgba(255,255,255,0.8)",
- zIndex: "100",
- },
- children: [
- {
- tag: "div",
- properties: {
- innerHTML: getString("workspace-emptyWorkspaceGuideInfo"),
- },
- styles: {
- fontSize: "20px",
- fontWeight: "bold",
- color: "gray",
- },
- },
- {
- tag: "button",
- namespace: "xul",
- properties: {
- label: getString("workspace-emptyWorkspaceGuideOpen"),
- },
- styles: {
- fontSize: "16px",
- },
- listeners: [
- {
- type: "command",
- listener: async (ev) => {
- const selectedIds = await itemPicker();
- if (
- selectedIds?.length === 1 &&
- Zotero.Items.get(selectedIds[0]).isNote()
- ) {
- addon.hooks.onSetWorkspaceNote(selectedIds[0], "main");
- addon.hooks.onOpenWorkspace();
- } else {
- window.alert(getString("menuFile-openMainNote-error"));
- }
- },
- },
- ],
- },
- {
- tag: "div",
- properties: {
- innerHTML: getString("workspace-emptyWorkspaceGuideOr"),
- },
- styles: {
- fontSize: "16px",
- color: "gray",
- },
- },
- {
- tag: "button",
- namespace: "xul",
- properties: {
- label: getString("workspace-emptyWorkspaceGuideCreate"),
- },
- styles: {
- fontSize: "16px",
- },
- listeners: [
- {
- type: "command",
- listener: () => {
- addon.hooks.onCreateWorkspaceNote();
- },
- },
- ],
- },
- ],
- },
- container,
- );
- return;
- } else {
- container.querySelector(`#${makeId("emptyWorkspaceGuide")}`)?.remove();
- }
- const editorElem = container.querySelector(
- `#${makeId("editor-" + type)}`,
- ) as EditorElement;
- await waitUtilAsync(() => Boolean(editorElem._initialized))
- .then(() => ztoolkit.log("ok"))
- .catch(() => ztoolkit.log("fail"));
- if (!editorElem._initialized) {
- throw new Error("initNoteEditor: waiting initialization failed");
- }
- editorElem.mode = "edit";
- editorElem.viewMode = "library";
- editorElem.parent = undefined;
- editorElem.item = noteItem;
- await waitUtilAsync(() => Boolean(editorElem._editorInstance));
- await editorElem._editorInstance._initPromise;
- if (typeof options.lineIndex === "number") {
- addon.api.editor.scroll(editorElem._editorInstance, options.lineIndex);
- }
- if (typeof options.sectionName === "string") {
- addon.api.editor.scrollToSection(
- editorElem._editorInstance,
- options.sectionName,
- );
- }
- return;
-}
-
-function getContainerType(
- container: XUL.Box | undefined,
-): "tab" | "window" | "unknown" {
- if (!container) {
- return "unknown";
- }
- return (container.getAttribute("workspace-type") || "unknown") as
- | "tab"
- | "window"
- | "unknown";
-}
-
-export function toggleOutlinePane(visibility?: boolean, container?: XUL.Box) {
- const splitter = container?.querySelector(`#${makeId("outline-splitter")}`);
- if (typeof visibility === "undefined") {
- visibility = splitter?.getAttribute("state") === "collapsed";
- }
- splitter?.setAttribute("state", visibility ? "open" : "collapsed");
-}
-
-export function togglePreviewPane(visibility?: boolean, container?: XUL.Box) {
- const splitter = container?.querySelector(`#${makeId("preview-splitter")}`);
- if (typeof visibility === "undefined") {
- visibility = splitter?.getAttribute("state") === "collapsed";
- }
- splitter?.setAttribute("state", visibility ? "open" : "collapsed");
-}
-
-export function toggleNotesPane(visibility?: boolean) {
- const splitter = document?.querySelector("#zotero-context-splitter");
- if (typeof visibility === "undefined") {
- visibility = splitter?.getAttribute("state") === "collapsed";
- }
- splitter?.setAttribute("state", visibility ? "open" : "collapsed");
-}
-
-export function getWorkspaceEditor(
- workspaceType: "tab" | "window",
- editorType: "main" | "preview" = "main",
-) {
- const container =
- workspaceType === "tab"
- ? addon.data.workspace.tab.container
- : addon.data.workspace.window.container;
- return (
- container?.querySelector(`#${makeId(`editor-${editorType}`)}`) as
- | EditorElement
- | undefined
- )?._editorInstance;
-}
-
-const SRC_LIST = [
- "",
- `chrome://${config.addonRef}/content/treeView.html`,
- `chrome://${config.addonRef}/content/mindMap.html`,
- `chrome://${config.addonRef}/content/bubbleMap.html`,
-];
-
-function setOutline(
- container: XUL.Box,
- newType: OutlineType = OutlineType.empty,
-) {
- if (newType === OutlineType.empty) {
- newType = addon.data.workspace.outline + 1;
- }
- if (newType > OutlineType.bubbleMap) {
- newType = OutlineType.treeView;
- }
- addon.data.workspace.outline = newType;
- (
- container.querySelector(`#${makeId("saveOutlineImage")}`) as HTMLDivElement
- ).hidden = newType === OutlineType.treeView;
- (
- container.querySelector(
- `#${makeId("saveOutlineFreeMind")}`,
- ) as HTMLDivElement
- ).hidden = newType === OutlineType.treeView;
- const iframe = container.querySelector(
- `#${makeId("outline-iframe")}`,
- ) as HTMLIFrameElement;
- iframe.setAttribute("src", SRC_LIST[addon.data.workspace.outline]);
- updateOutline(container);
- updateOutlineButtons(container);
-}
-
-export async function updateOutline(container: XUL.Box) {
- const iframe = container.querySelector(
- `#${makeId("outline-iframe")}`,
- ) as HTMLIFrameElement;
- await waitUtilAsync(
- () => iframe.contentWindow?.document.readyState === "complete",
- );
- iframe.contentWindow?.postMessage(
- {
- type: "setMindMapData",
- nodes: getNoteTreeFlattened(
- Zotero.Items.get(addon.data.workspace.mainId),
- { keepLink: !!getPref("workspace.outline.keepLinks") },
- ),
- workspaceType: getContainerType(container),
- expandLevel: getPref("workspace.outline.expandLevel"),
- },
- "*",
- );
-}
-
-function updateOutlineButtons(container: XUL.Box) {
- const outlineType = addon.data.workspace.outline;
- const isTreeView = outlineType === OutlineType.treeView;
- (
- container.querySelector(`#${makeId("saveOutlineImage")}`) as HTMLDivElement
- ).style.visibility = isTreeView ? "hidden" : "visible";
- (
- container.querySelector(
- `#${makeId("saveOutlineFreeMind")}`,
- ) as HTMLDivElement
- ).style.visibility = isTreeView ? "hidden" : "visible";
-}
-
-function saveImage(container: XUL.Box) {
- const iframe = container.querySelector(
- `#${makeId("outline-iframe")}`,
- ) as HTMLIFrameElement;
- iframe.contentWindow?.postMessage(
- {
- type: "saveSVG",
- },
- "*",
- );
-}
-
-async function saveFreeMind() {
- // TODO: uncouple this part
- const filename = await new ztoolkit.FilePicker(
- `${Zotero.getString("fileInterface.export")} FreeMind XML`,
- "save",
- [["FreeMind XML File(*.mm)", "*.mm"]],
- `${Zotero.Items.get(addon.data.workspace.mainId).getNoteTitle()}.mm`,
- ).open();
- if (filename) {
- await _saveFreeMind(filename, addon.data.workspace.mainId);
- }
+ const workspace = new (customElements.get("bn-workspace")!)() as any;
+ container.append(workspace);
+ workspace.item = item;
+ workspace.containerType = "tab";
+ workspace.render();
}
diff --git a/src/modules/workspace/message.ts b/src/modules/workspace/message.ts
deleted file mode 100644
index 61ae324..0000000
--- a/src/modules/workspace/message.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import {
- getEditorInstance,
- moveHeading,
- updateHeadingTextAtLine,
-} from "../../utils/editor";
-import { showHintWithLink } from "../../utils/hint";
-import { getNoteLinkParams } from "../../utils/link";
-import { getNoteTree, getNoteTreeNodeById } from "../../utils/note";
-import { formatPath } from "../../utils/str";
-
-export async function messageHandler(ev: MessageEvent) {
- switch (ev.data.type) {
- case "jumpNode": {
- const editor = addon.api.workspace.getWorkspaceEditor(
- ev.data.workspaceType,
- "main",
- );
- if (!editor) {
- return;
- }
- addon.api.editor.scroll(editor, ev.data.lineIndex);
- return;
- }
- case "openNote": {
- const linkParams = getNoteLinkParams(ev.data.link);
- if (!linkParams.noteItem) {
- return;
- }
- addon.hooks.onOpenNote(linkParams.noteItem.id, "preview", {
- lineIndex: linkParams.lineIndex || undefined,
- });
- return;
- }
- case "moveNode": {
- const noteItem = Zotero.Items.get(addon.data.workspace.mainId);
- const tree = getNoteTree(noteItem);
- const fromNode = getNoteTreeNodeById(noteItem, ev.data.fromID, tree);
- const toNode = getNoteTreeNodeById(noteItem, ev.data.toID, tree);
- moveHeading(
- getEditorInstance(noteItem.id),
- fromNode!,
- toNode!,
- ev.data.moveType,
- );
- return;
- }
- case "editNode": {
- const editor = addon.api.workspace.getWorkspaceEditor(
- ev.data.workspaceType,
- "main",
- );
- if (!editor) {
- return;
- }
- updateHeadingTextAtLine(
- editor,
- ev.data.lineIndex,
- ev.data.text.replace(/[\r\n]/g, ""),
- );
- return;
- }
- case "saveSVGReturn": {
- const filename = await new ztoolkit.FilePicker(
- `${Zotero.getString("fileInterface.export")} SVG Image`,
- "save",
- [["SVG File(*.svg)", "*.svg"]],
- `${Zotero.Items.get(addon.data.workspace.mainId).getNoteTitle()}.svg`,
- ).open();
- if (filename) {
- await Zotero.File.putContentsAsync(formatPath(filename), ev.data.image);
- showHintWithLink(
- `Image Saved to ${filename}`,
- "Show in Folder",
- (ev) => {
- Zotero.File.reveal(filename);
- },
- );
- }
- return;
- }
- default:
- return;
- }
-}
diff --git a/src/modules/workspace/tab.ts b/src/modules/workspace/tab.ts
index 72e3004..d443f83 100644
--- a/src/modules/workspace/tab.ts
+++ b/src/modules/workspace/tab.ts
@@ -1,13 +1,7 @@
import { config } from "../../../package.json";
-import { ICONS } from "../../utils/config";
-import { showHint } from "../../utils/hint";
-import { getString } from "../../utils/locale";
-import { getPref, setPref } from "../../utils/prefs";
-import { waitUtilAsync } from "../../utils/wait";
-// TODO: uncouple these imports
-import { messageHandler } from "./message";
+import { initWorkspace } from "./content";
-export const TAB_TYPE = "betternotes";
+export const TAB_TYPE = "note";
export function registerWorkspaceTab(win: Window) {
const doc = win.document;
@@ -29,18 +23,17 @@ export function registerWorkspaceTab(win: Window) {
{
type: "command",
listener: (ev) => {
- if ((ev as MouseEvent).shiftKey) {
- addon.hooks.onOpenWorkspace("window");
- } else {
- addon.hooks.onOpenWorkspace("tab");
- }
+ // if ((ev as MouseEvent).shiftKey) {
+ // addon.hooks.onOpenWorkspace("window");
+ // } else {
+ // addon.hooks.onOpenWorkspace("tab");
+ // }
},
},
],
},
spacer,
) as XUL.ToolBarButton;
- win.addEventListener("message", messageHandler, false);
const collectionSearch = doc.querySelector("#zotero-collections-search")!;
const ob = new (ztoolkit.getGlobal("MutationObserver"))((muts) => {
tabButton.hidden = !!collectionSearch?.classList.contains("visible");
@@ -54,347 +47,47 @@ export function registerWorkspaceTab(win: Window) {
"unload",
() => {
ob.disconnect();
- win.removeEventListener("message", messageHandler);
},
{ once: true },
);
}
-export async function openWorkspaceTab() {
- if (addon.data.workspace.tab.active) {
- Zotero_Tabs.select(addon.data.workspace.tab.id!);
+export async function openWorkspaceTab(item: Zotero.Item) {
+ const currentTab = Zotero_Tabs._tabs.find(
+ (tab) => tab.data?.itemID == item.id,
+ );
+ if (currentTab) {
+ Zotero_Tabs.select(currentTab.id);
return;
}
const { id, container } = Zotero_Tabs.add({
type: TAB_TYPE,
- title: getString("tab.name"),
+ title: item.getNoteTitle(),
index: 1,
data: {
- itemID: addon.data.workspace.mainId,
+ itemID: item.id,
},
select: false,
- onClose: () => {
- deActivateWorkspaceTab();
- },
+ onClose: () => {},
});
- addon.data.workspace.tab.id = id;
- container.setAttribute("workspace-type", "tab");
- addon.data.workspace.tab.container = container;
-
- await activateWorkspaceTab();
+ initWorkspace(container, item);
Zotero_Tabs.select(id);
}
-function hoverWorkspaceTab(hovered: boolean) {
- Array.from(document.querySelectorAll(".tab-toggle")).forEach((elem) => {
- (elem as HTMLDivElement).style.visibility = hovered ? "visible" : "hidden";
- });
- const tabElem = document.querySelector(
- `.tabs-wrapper .tab[data-id=${addon.data.workspace.tab.id}]`,
- ) as HTMLDivElement;
- const content = tabElem.querySelector(".tab-name") as HTMLDivElement;
- content.removeAttribute("style");
- if (hovered) {
- content.style["-moz-box-pack" as any] = "start";
- }
-}
+let contextPaneOpen: boolean | undefined = undefined;
-function updateWorkspaceTabToggleButton(
- type: "outline" | "preview" | "notes",
- state: "open" | "collapsed",
-) {
- const elem = document.querySelector(
- `#betternotes-tab-toggle-${type}`,
- ) as HTMLDivElement;
- if (!elem) {
+export function onTabSelect(tabType: string) {
+ const ZoteroContextPane = ztoolkit.getGlobal("ZoteroContextPane");
+ const splitter = ZoteroContextPane.getSplitter();
+
+ if (tabType === TAB_TYPE) {
+ contextPaneOpen = splitter.getAttribute("state") != "collapsed";
+ splitter.setAttribute("state", "collapsed");
+ } else if (typeof contextPaneOpen !== "undefined") {
+ splitter.setAttribute("state", contextPaneOpen ? "open" : "collapsed");
+ contextPaneOpen = undefined;
+ } else {
return;
}
- if (state !== "collapsed") {
- state = "open";
- }
- elem.innerHTML = ICONS[`workspace_${type}_${state}`];
-}
-
-function registerWorkspaceTabPaneObserver() {
- const outlineSplitter = document.querySelector(
- "#betternotes-workspace-outline-splitter",
- );
- const outlineMut = new (ztoolkit.getGlobal("MutationObserver"))((muts) => {
- updateWorkspaceTabToggleButton(
- "outline",
- outlineSplitter!.getAttribute("state")! as "open" | "collapsed",
- );
- });
- outlineMut.observe(outlineSplitter!, {
- attributes: true,
- attributeFilter: ["state"],
- });
- const previewSplitter = document.querySelector(
- "#betternotes-workspace-preview-splitter",
- );
- const previeweMut = new (ztoolkit.getGlobal("MutationObserver"))((muts) => {
- updateWorkspaceTabToggleButton(
- "preview",
- previewSplitter!.getAttribute("state")! as "open" | "collapsed",
- );
- });
- previeweMut.observe(previewSplitter!, {
- attributes: true,
- attributeFilter: ["state"],
- });
- const notesSplitter = document.querySelector("#zotero-context-splitter");
- const notesMut = new (ztoolkit.getGlobal("MutationObserver"))((muts) => {
- updateWorkspaceTabToggleButton(
- "notes",
- notesSplitter!.getAttribute("state")! as "open" | "collapsed",
- );
- });
- notesMut.observe(notesSplitter!, {
- attributes: true,
- attributeFilter: ["state"],
- });
-}
-
-function isContextPaneInitialized() {
- return (
- (document.querySelector(".notes-pane-deck")?.childElementCount || 0) > 0
- );
-}
-
-export async function activateWorkspaceTab() {
- if (Zotero_Tabs.selectedType === TAB_TYPE && isContextPaneInitialized()) {
- const tabToolbar = document.querySelector("#zotero-tab-toolbar") as XUL.Box;
- tabToolbar && (tabToolbar.style.visibility = "collapse");
- const toolbar = document.querySelector(
- "#zotero-context-toolbar-extension",
- ) as XUL.Box;
- if (toolbar) {
- toolbar.style.visibility = "collapse";
- toolbar.nextElementSibling?.setAttribute("selectedIndex", "1");
- }
- }
-
- if (addon.data.workspace.tab.active) {
- ztoolkit.log("workspace tab is already active");
- return;
- }
- setWorkspaceTabStatus(true);
- // reset tab style
- await waitUtilAsync(() =>
- Boolean(
- document.querySelector(
- `.tabs-wrapper .tab[data-id=${addon.data.workspace.tab.id}]`,
- ),
- ),
- );
- const tabElem = document.querySelector(
- `.tabs-wrapper .tab[data-id=${addon.data.workspace.tab.id}]`,
- ) as HTMLDivElement;
- tabElem.removeAttribute("style");
- const content = tabElem.querySelector(".tab-name") as HTMLDivElement;
- const close = tabElem.querySelector(".tab-close") as HTMLDivElement;
- content.removeAttribute("style");
- content.append(document.createTextNode(getString("tab.name")));
- close.style.removeProperty("visibility");
- ztoolkit.UI.insertElementBefore(
- {
- tag: "fragment",
- children: [
- {
- tag: "div",
- id: "betternotes-tab-toggle-outline",
- classList: ["tab-close", "tab-toggle"],
- styles: {
- right: "56px",
- },
- properties: {
- innerHTML: ICONS.workspace_outline_open,
- },
- listeners: [
- {
- type: "click",
- listener: (ev) => {
- addon.hooks.onToggleWorkspacePane(
- "outline",
- undefined,
- addon.data.workspace.tab.container,
- );
- },
- },
- ],
- },
- {
- tag: "div",
- id: "betternotes-tab-toggle-preview",
- classList: ["tab-close", "tab-toggle"],
- styles: {
- right: "40px",
- },
- properties: {
- innerHTML: ICONS.workspace_preview_collapsed,
- },
- listeners: [
- {
- type: "click",
- listener: (ev) => {
- addon.hooks.onToggleWorkspacePane(
- "preview",
- undefined,
- addon.data.workspace.tab.container,
- );
- },
- },
- ],
- },
- {
- tag: "div",
- id: "betternotes-tab-toggle-notes",
- classList: ["tab-close", "tab-toggle"],
- styles: {
- right: "24px",
- },
- properties: {
- innerHTML:
- document
- .querySelector("#zotero-context-splitter")
- ?.getAttribute("state") === "open"
- ? ICONS.workspace_notes_open
- : ICONS.workspace_notes_collapsed,
- },
- listeners: [
- {
- type: "click",
- listener: (ev) => {
- if (isContextPaneInitialized()) {
- addon.hooks.onToggleWorkspacePane("notes");
- return;
- }
- showHint(getString("workspace.notesPane.hint"));
- },
- },
- ],
- },
- ],
- },
- close,
- );
- hoverWorkspaceTab(false);
- tabElem.addEventListener("mouseenter", () => {
- if (Zotero_Tabs.selectedType !== "betternotes") {
- return;
- }
- hoverWorkspaceTab(true);
- });
- tabElem.addEventListener("mousedown", () => hoverWorkspaceTab(true));
- tabElem.addEventListener("mouseleave", () => hoverWorkspaceTab(false));
- tabElem.addEventListener("mousedown", async (ev) => {
- if (ev.button !== 2) {
- return;
- }
- await Zotero.Promise.delay(300);
- const menu = document
- .querySelector("#zotero-itemmenu")
- ?.parentElement?.lastElementChild?.querySelector("menu")
- ?.querySelector("menupopup")?.lastElementChild;
- menu?.addEventListener("click", () => {
- addon.hooks.onOpenWorkspace("window");
- });
- });
- // load workspace content
- const container = addon.data.workspace.tab.container;
- initWorkspaceTabDragDrop(container, tabElem);
- addon.hooks.onInitWorkspace(container);
- registerWorkspaceTabPaneObserver();
- setWorkspaceTabStatus(true);
-}
-
-export function deActivateWorkspaceTab() {
- const tabToolbar = document.querySelector("#zotero-tab-toolbar") as XUL.Box;
- tabToolbar && tabToolbar.style.removeProperty("visibility");
- const toolbar = document.querySelector(
- "#zotero-context-toolbar-extension",
- ) as XUL.Box;
- toolbar?.style.removeProperty("visibility");
- setWorkspaceTabStatus(false);
-}
-
-function setWorkspaceTabStatus(status: boolean) {
- addon.data.workspace.tab.active = status;
- setPref("workspace.tab.active", status);
-}
-
-function initWorkspaceTabDragDrop(
- container?: XUL.Box,
- tabElem?: HTMLDivElement,
-) {
- if (!container) {
- return;
- }
- const rect = tabElem?.getBoundingClientRect();
- ztoolkit.UI.appendElement(
- {
- tag: "div",
- id: "bn-workspace-tab-drop",
- styles: {
- background: "#252526",
- opacity: "0.6",
- width: "100%",
- height: "100px",
- position: "fixed",
- left: "0px",
- top: `${rect?.bottom}px`,
- textAlign: "center",
- display: "flex",
- visibility: "hidden",
- zIndex: "65535",
- },
- properties: {
- hidden: true,
- ondrop: (ev: DragEvent) => {
- addon.hooks.onOpenWorkspace("window");
- },
- ondragenter: (ev: DragEvent) => {
- ev.preventDefault();
- ev.stopPropagation();
- dropElem.style.opacity = "0.9";
- if (ev.dataTransfer) {
- ev.dataTransfer.dropEffect = "move";
- }
- },
- ondragover: (ev: DragEvent) => {
- ev.preventDefault();
- ev.stopPropagation();
- },
- ondragleave: (ev: DragEvent) => {
- ev.preventDefault();
- ev.stopPropagation();
- dropElem.style.opacity = "0.6";
- },
- },
- children: [
- {
- tag: "div",
- styles: {
- margin: "auto",
- textAlign: "center",
- color: "#fff",
- },
- properties: {
- innerHTML: getString("tab.openInWindow"),
- },
- },
- ],
- enableElementRecord: false,
- },
- container,
- );
- const dropElem = container.querySelector(
- "#bn-workspace-tab-drop",
- ) as HTMLDivElement;
- tabElem?.addEventListener("dragstart", (ev) => {
- dropElem.style.visibility = "visible";
- });
- tabElem?.addEventListener("dragend", (ev) => {
- dropElem.style.visibility = "hidden";
- });
+ ZoteroContextPane.update();
}
diff --git a/src/modules/workspace/window.ts b/src/modules/workspace/window.ts
index 855702b..382c83a 100644
--- a/src/modules/workspace/window.ts
+++ b/src/modules/workspace/window.ts
@@ -1,12 +1,6 @@
import { config } from "../../../package.json";
-import { isWindowAlive } from "../../utils/window";
-import { messageHandler } from "./message";
-export async function openWorkspaceWindow() {
- if (isWindowAlive(addon.data.workspace.window.window)) {
- addon.data.workspace.window.window?.focus();
- return;
- }
+export async function openWorkspaceWindow(item: Zotero.Item) {
const windowArgs = {
_initPromise: Zotero.Promise.defer(),
};
@@ -17,16 +11,9 @@ export async function openWorkspaceWindow() {
windowArgs,
)!;
await windowArgs._initPromise.promise;
- addon.data.workspace.window.active = true;
- addon.data.workspace.window.window = win;
- addon.data.workspace.window.container = win.document.querySelector(
+
+ const container = win.document.querySelector(
"#workspace-container",
) as XUL.Box;
- addon.hooks.onInitWorkspace(addon.data.workspace.window.container);
- win.addEventListener("message", messageHandler, false);
- win.addEventListener("unload", function onWindowUnload(ev) {
- addon.data.workspace.window.active = false;
- this.window.removeEventListener("unload", onWindowUnload, false);
- this.window.removeEventListener("message", messageHandler, false);
- });
+ addon.hooks.onInitWorkspace(container, item);
}
diff --git a/src/utils/note.ts b/src/utils/note.ts
index 4a7ad7c..b15a549 100644
--- a/src/utils/note.ts
+++ b/src/utils/note.ts
@@ -11,7 +11,6 @@ export {
parseHTMLLines,
getLinesInNote,
addLineToNote,
- getNoteType,
getNoteTree,
getNoteTreeFlattened,
getNoteTreeNodeById,
@@ -197,7 +196,7 @@ async function renderNoteHTML(
refNotes = [noteItem];
}
- const parser = ztoolkit.getDOMParser();
+ const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const imageAttachments = refNotes.reduce((acc, note) => {
acc.push(...Zotero.Items.get(note.getAttachments()));
@@ -269,22 +268,12 @@ async function renderNoteHTML(
return doc.body.innerHTML;
}
-function getNoteType(id: number) {
- if (id === addon.data.workspace.mainId) {
- return "main";
- } else if (id === addon.data.workspace.previewId) {
- return "preview";
- } else {
- return "default";
- }
-}
-
function getNoteTree(
note: Zotero.Item,
parseLink: boolean = true,
): TreeModel.Node {
const noteLines = getLinesInNote(note);
- const parser = ztoolkit.getDOMParser();
+ const parser = new DOMParser();
const tree = new TreeModel();
const root = tree.parse({
id: -1,
@@ -422,7 +411,7 @@ async function copyEmbeddedImagesInHTML(
ztoolkit.log(attachments);
- const doc = ztoolkit.getDOMParser().parseFromString(html, "text/html");
+ const doc = new DOMParser().parseFromString(html, "text/html");
// Copy note image attachments and replace keys in the new note
for (const attachment of attachments) {
diff --git a/src/utils/wait.ts b/src/utils/wait.ts
index 4183d14..f03b3f6 100644
--- a/src/utils/wait.ts
+++ b/src/utils/wait.ts
@@ -5,12 +5,12 @@ export function waitUntil(
timeout = 10000,
) {
const start = Date.now();
- const intervalId = ztoolkit.getGlobal("setInterval")(() => {
+ const intervalId = setInterval(() => {
if (condition()) {
- ztoolkit.getGlobal("clearInterval")(intervalId);
+ clearInterval(intervalId);
callback();
} else if (Date.now() - start > timeout) {
- ztoolkit.getGlobal("clearInterval")(intervalId);
+ clearInterval(intervalId);
}
}, interval);
}
@@ -22,12 +22,12 @@ export function waitUtilAsync(
) {
return new Promise((resolve, reject) => {
const start = Date.now();
- const intervalId = ztoolkit.getGlobal("setInterval")(() => {
+ const intervalId = setInterval(() => {
if (condition()) {
- ztoolkit.getGlobal("clearInterval")(intervalId);
+ clearInterval(intervalId);
resolve();
} else if (Date.now() - start > timeout) {
- ztoolkit.getGlobal("clearInterval")(intervalId);
+ clearInterval(intervalId);
reject();
}
}, interval);
diff --git a/typings/global.d.ts b/typings/global.d.ts
index 0cae16c..a659262 100644
--- a/typings/global.d.ts
+++ b/typings/global.d.ts
@@ -33,3 +33,22 @@ declare const addon: import("../src/addon").default;
declare const __env__: "production" | "development";
declare class Localization {}
+
+declare class XULElementBase extends HTMLElement {
+ get content(): DocumentFragment;
+ init(): void;
+ destroy(): void;
+ connectedCallback(): void;
+ disconnectedCallback(): void;
+ attributeChangedCallback(
+ name: string,
+ oldValue: string,
+ newValue: string,
+ ): void;
+ static get observedAttributes(): string[];
+}
+
+declare class MozXULElement {
+ static parseXULToFragment(xul: string): Fragment;
+ static insertFTLIfNeeded(ftl: string): void;
+}