diff --git a/src/events.ts b/src/events.ts index 49cd766..8154c4b 100644 --- a/src/events.ts +++ b/src/events.ts @@ -1,3 +1,4 @@ +import { link } from "fs"; import { AddonBase, EditorMessage } from "./base"; class AddonEvents extends AddonBase { @@ -356,6 +357,38 @@ class AddonEvents extends AddonBase { header.innerHTML = "Main Note"; header.setAttribute("style", "font-size: medium"); middle.append(header); + + // Link popup listener + const container = + _window.document.getElementsByClassName("relative-container")[0]; + const containerObserver = new MutationObserver(async (mutations) => { + for (const mut of mutations) { + for (const node of mut.addedNodes) { + // wait for ui ready + await Zotero.Promise.delay(20); + const linkElement = (node as Element).getElementsByTagName( + "a" + )[0]; + if (!linkElement) { + return; + } + const linkObserver = new MutationObserver(async (linkMuts) => { + this._Addon.views.updateEditorPopupButtons( + _window, + linkElement.getAttribute("href") + ); + }); + linkObserver.observe(linkElement, { attributes: true }); + this._Addon.views.updateEditorPopupButtons( + _window, + linkElement.getAttribute("href") + ); + } + } + }); + containerObserver.observe(container, { + childList: true, + }); } else { // This is a preview knowledge, hide openWorkspace button add show close botton this._Addon.views.changeEditorButtonView( @@ -722,8 +755,7 @@ class AddonEvents extends AddonBase { if (annotationItem.annotationComment) { const text = annotationItem.annotationComment; - let link = text.substring(text.search(/zotero:\/\/note\//g)); - link = link.substring(0, link.search('"')); + let link = this._Addon.knowledge.getLinkFromText(text); if (link) { const note = (await this._Addon.knowledge.getNoteFromLink(link)).item; diff --git a/src/knowledge.ts b/src/knowledge.ts index adc987b..2d707ec 100644 --- a/src/knowledge.ts +++ b/src/knowledge.ts @@ -289,6 +289,26 @@ class Knowledge extends AddonBase { this.setLinesToNote(note, noteLines); } + async addLinesToNote( + note: ZoteroItem, + newLines: string[], + lineIndex: number + ) { + note = note || this.getWorkspaceNote(); + if (!note) { + return; + } + let noteLines = this.getLinesInNote(note); + if (lineIndex < 0) { + lineIndex = 0; + } + this.setLinesToNote( + note, + noteLines.slice(0, lineIndex).concat(newLines, noteLines.slice(lineIndex)) + ); + await this.scrollWithRefresh(lineIndex); + } + async addSubLineToNote( note: ZoteroItem, text: string, @@ -602,7 +622,7 @@ class Knowledge extends AddonBase { const item = Zotero.Items.get(noteID); const rootNoteIds = [note.id]; - const newLines = await this.converNoteLines( + const newLines = await this.convertNoteLines( note, rootNoteIds, convertNoteLinks, @@ -675,7 +695,7 @@ class Knowledge extends AddonBase { return false; } - async converNoteLines( + async convertNoteLines( currentNote: ZoteroItem, rootNoteIds: number[], convertNoteLinks: boolean = true, @@ -701,11 +721,9 @@ class Knowledge extends AddonBase { } newLines.push(noteLines[i]); // Convert Link - let linkIndex = noteLines[i].search(/zotero:\/\/note\//g); - while (linkIndex >= 0) { + let link = this.getLinkFromText(noteLines[i]); + while (link) { Zotero.debug("convert link"); - let link = noteLines[i].substring(linkIndex); - link = link.substring(0, link.search('"')); let res = await this.getNoteFromLink(link); const subNote = res.item; if (subNote && _rootNoteIds.indexOf(subNote.id) === -1) { @@ -713,7 +731,7 @@ class Knowledge extends AddonBase { newLines.push("
"); newLines.push(`Linked Note:
`); newLines = newLines.concat( - await this.converNoteLines( + await this.convertNoteLines( subNote, _rootNoteIds, convertNoteLinks, @@ -728,12 +746,23 @@ class Knowledge extends AddonBase { noteLines[i] = noteLines[i].substring( noteLines[i].search(/<\/a>/g) + "".length ); - linkIndex = noteLines[i].search(/zotero:\/\/note\//g); + link = this.getLinkFromText(noteLines[i]); } } return newLines; } + getLinkFromText(text: string) { + // Must end with " + const linkIndex = text.search(/zotero:\/\/note\//g); + if (linkIndex === -1) { + return ""; + } + let link = text.substring(linkIndex); + link = link.substring(0, link.search('"')); + return link; + } + async getNoteFromLink(uri: string) { let [groupID, noteKey] = uri.substring("zotero://note/".length).split("/"); diff --git a/src/views.ts b/src/views.ts index 2ecdf94..3529dd1 100644 --- a/src/views.ts +++ b/src/views.ts @@ -282,6 +282,42 @@ class AddonViews extends AddonBase { .children[0].before(treeRow); } + async updateEditorPopupButtons(_window: Window, link: string) { + const note: ZoteroItem = (await this._Addon.knowledge.getNoteFromLink(link)) + .item; + if (note) { + let insertButton = _window.document.getElementById("insert-note-link"); + if (insertButton) { + insertButton.remove(); + } + insertButton = _window.document.createElement("button"); + insertButton.setAttribute("id", "insert-note-link"); + insertButton.setAttribute( + "title", + `Import Linked Note: ${note.getNoteTitle()}` + ); + insertButton.innerHTML = ``; + insertButton.addEventListener("click", async (e) => { + let newLines = []; + newLines.push(""); + newLines.push(`"); + Zotero.debug(newLines); + await this._Addon.knowledge.addLinesToNote( + undefined, + newLines, + this._Addon.knowledge.currentLine + 1 + ); + }); + _window.document + .getElementsByClassName("link-popup")[0] + .appendChild(insertButton); + } + } + async addReaderAnnotationButton(reader: ReaderObj) { if (!reader) { return false;Linked Note:
`); + newLines = newLines.concat( + await this._Addon.knowledge.convertNoteLines(note, [], true, false) + ); + newLines.push("