From 738ebf2057dfccac6f792a94023d4b528831ff17 Mon Sep 17 00:00:00 2001 From: xiangyu <3170102889@zju.edu.cn> Date: Sat, 30 Apr 2022 22:23:24 +0800 Subject: [PATCH] add: export note to markdown --- src/events.ts | 98 ++++++++++++++++++++----- src/knowledge.ts | 126 +++++++++++++++++++++++++++------ src/views.ts | 48 +++++++++++-- src/zotero-protocol-handler.js | 35 +-------- typing/global.d.ts | 5 ++ 5 files changed, 235 insertions(+), 77 deletions(-) diff --git a/src/events.ts b/src/events.ts index 1446550..5a1e4c4 100644 --- a/src/events.ts +++ b/src/events.ts @@ -59,7 +59,17 @@ class AddonEvents extends AddonBase { public async onEditorEvent(message: EditorMessage) { Zotero.debug(`Knowledge4Zotero: onEditorEvent\n${message.type}`); - if (message.type === "addNoteInstance") { + if (message.type === "openWorkspace") { + /* + message.content = {} + */ + await this._Addon.knowledge.openWorkspaceWindow(); + } else if (message.type === "addNoteInstance") { + /* + message.content = { + editorInstance, + } + */ let mainKnowledgeID = parseInt( Zotero.Prefs.get("Knowledge4Zotero.mainKnowledgeID") ); @@ -71,22 +81,34 @@ class AddonEvents extends AddonBase { Zotero.debug(`Knowledge4Zotero: main Knowledge`); this._Addon.views.addEditorButton( message.content.editorInstance, - "mainKnowledge", - isMainKnowledge ? "isMainKnowledge" : "setMainKnowledge", + "workspace", + isMainKnowledge ? "isMainKnowledge" : "notMainKnowledge", isMainKnowledge - ? "This Note is Knowledge Workspace" - : "Use Current Note as Knowledge Workspace", - new EditorMessage("setMainKnowledge", {}) + ? "Edit the main knowledge in Workspace" + : "Open Workspace", + "start", + new EditorMessage("openWorkspace", {}) ); this._Addon.views.addEditorButton( message.content.editorInstance, "addToKnowledge", "addToKnowledge", "Add Note Link to Knowledge Workspace", + "middle", new EditorMessage("addToKnowledge", { itemID: message.content.editorInstance._item.id, }) ); + this._Addon.views.addEditorButton( + message.content.editorInstance, + "export", + "export", + "Export Markdown with linked Notes", + "end", + new EditorMessage("export", { + itemID: message.content.editorInstance._item.id, + }) + ); if (!message.content.editorInstance._knowledgeSelectionInitialized) { this.addEditorDocumentEventListener( message.content.editorInstance, @@ -95,12 +117,36 @@ class AddonEvents extends AddonBase { ); message.content.editorInstance._knowledgeSelectionInitialized = true; } + } else if (message.type === "enterWorkspace") { + /* + message.content = { + editorInstance, + params: "main" | "preview" + } + */ + if (message.content.params === "main") { + // This is a main knowledge, hide all buttons except the export button and add title + } else { + // This is a preview knowledge, hide openWorkspace button add show close botton + } + } else if (message.type === "leaveWorkspace") { + /* + message.content = { + editorInstance, + params: "main" | "preview" + } + */ + if (message.content.params === "main") { + // This is a main knowledge, show all buttons and remove title + } else { + // This is a preview knowledge, show openWorkspace button add hide close botton + } } else if (message.type === "addToKnowledge") { /* message.content = { editorInstance } - */ + */ Zotero.debug("Knowledge4Zotero: addToKnowledge"); this._Addon.knowledge.addLinkToNote( undefined, @@ -112,8 +158,7 @@ class AddonEvents extends AddonBase { message.content = { editorInstance } - */ - // TODO: Complete this part + */ Zotero.debug("Knowledge4Zotero: setMainKnowledge"); let mainKnowledgeID = parseInt( Zotero.Prefs.get("Knowledge4Zotero.mainKnowledgeID") @@ -132,29 +177,36 @@ class AddonEvents extends AddonBase { message.content.editorInstance._item.id ); // Set the button to selected state - this._Addon.views.changeEditorButton( + this._Addon.views.changeEditorButtonView( message.content.event.target, "isMainKnowledge", - "This Note is Knowledge Workspace" + "Edit the main knowledge in Workspace" ); - // TODO: update workspace window here - await this._Addon.knowledge.setWorkspaceMainNote(); + await this._Addon.knowledge.setWorkspaceNote("main"); for (let editor of Zotero.Notes._editorInstances) { await editor._initPromise; if (editor._item.id === mainKnowledgeID) { let button = - editor._iframeWindow.document.getElementById("mainKnowledge"); + editor._iframeWindow.document.getElementById("workspace"); if (button) { - this._Addon.views.changeEditorButton( + this._Addon.views.changeEditorButtonView( button, - "setMainKnowledge", - "Use Current Note as Knowledge Workspace" + "notMainKnowledge", + "Open Workspace" ); } } } } } else if (message.type === "onNoteLink") { + /* + message.content = { + params: { + item: ZoteroItem | boolean, + infoText: string + } + } + */ if (!message.content.params.item) { Zotero.debug(`Knowledge4Zotero: ${message.content.params.infoText}`); } @@ -163,7 +215,8 @@ class AddonEvents extends AddonBase { ); let _window = this._Addon.knowledge.getWorkspaceWindow(); if (_window) { - this._Addon.knowledge.setWorkspacePreviewNote( + this._Addon.knowledge.setWorkspaceNote( + "preview", message.content.params.item ); (_window as Window).focus(); @@ -203,6 +256,15 @@ class AddonEvents extends AddonBase { this._Addon.knowledge.currentLine = currentLineIndex; Zotero.debug(`Knowledge4Zotero: line ${currentLineIndex} selected.`); } + } else if (message.type === "export") { + /* + message.content = { + editorInstance + } + */ + await this._Addon.knowledge.exportNoteToFile( + message.content.editorInstance._item + ); } else { Zotero.debug(`Knowledge4Zotero: message not handled.`); } diff --git a/src/knowledge.ts b/src/knowledge.ts index ad75a92..3549673 100644 --- a/src/knowledge.ts +++ b/src/knowledge.ts @@ -1,4 +1,4 @@ -import { AddonBase } from "./base"; +import { AddonBase, EditorMessage } from "./base"; const TreeModel = require("./treemodel"); @@ -34,7 +34,7 @@ class Knowledge extends AddonBase { ); this.workspaceWindow = win; await this.waitWorkspaceRedy(); - this.setWorkspaceMainNote(); + this.setWorkspaceNote("main"); } } @@ -51,35 +51,46 @@ class Knowledge extends AddonBase { return t < 500; } - async setWorkspaceMainNote(note: ZoteroItem = undefined) { + async getWorkspaceEditor(type: "main" | "preview" = "main") { + let _window = this.getWorkspaceWindow() as Window; + if (!_window) { + return; + } + await this.waitWorkspaceRedy(); + return _window.document.getElementById(`zotero-note-editor-${type}`); + } + + async setWorkspaceNote( + type: "main" | "preview" = "main", + note: ZoteroItem = undefined + ) { let _window = this.getWorkspaceWindow() as Window; note = note || this.getWorkspaceNote(); if (!_window) { return; } await this.waitWorkspaceRedy(); - let noteEditor: any = _window.document.getElementById( - "zotero-note-editor-main" - ); - noteEditor.mode = "edit"; - noteEditor.viewMode = "library"; - noteEditor.parent = null; - noteEditor.item = note; - } - - async setWorkspacePreviewNote(note: ZoteroItem) { - let _window = this.getWorkspaceWindow() as Window; - if (!_window) { - return; + let noteEditor: any = await this.getWorkspaceEditor(type); + let lastEditorInstance = noteEditor._editorInstance as EditorInstance; + if (lastEditorInstance) { + await this._Addon.events.onEditorEvent( + new EditorMessage("leaveWorkspace", { + editorInstance: lastEditorInstance, + params: type, + }) + ); } - await this.waitWorkspaceRedy(); - let noteEditor: any = _window.document.getElementById( - "zotero-note-editor-preview" - ); noteEditor.mode = "edit"; noteEditor.viewMode = "library"; noteEditor.parent = null; noteEditor.item = note; + + await this._Addon.events.onEditorEvent( + new EditorMessage("enterWorkspace", { + editorInstance: noteEditor, + params: type, + }) + ); } getLinesInNote(note: ZoteroItem): string[] { @@ -396,6 +407,81 @@ class Knowledge extends AddonBase { return text; } + async exportNoteToFile(note: ZoteroItem, convertNoteLinks: boolean = true) { + let exporter = new Zotero_File_Exporter(); + + if (convertNoteLinks) { + let item: ZoteroItem = new Zotero.Item("note"); + let noteLines = this.getLinesInNote(note); + let newLines = []; + for (let i in noteLines) { + newLines.push(noteLines[i]); + let linkIndex = noteLines[i].search(/zotero:\/\/note\//g); + while (linkIndex >= 0) { + let link = noteLines[i].substring(linkIndex); + link = link.substring(0, link.search('"')); + let res = await this.getNoteFromLink(link); + if (res.item && res.item.id !== note.id) { + Zotero.debug(`Knowledge4Zotero: Exporting sub-note ${link}`); + newLines.push("
"); + newLines.push( + `"); + } + noteLines[i] = noteLines[i].substring( + noteLines[i].search(/zotero:\/\/note\//g) + ); + noteLines[i] = noteLines[i].substring( + noteLines[i].search(/<\/a>/g) + "".length + ); + linkIndex = noteLines[i].search(/zotero:\/\/note\//g); + } + } + item.setNote(`Linked Note: ${res.item.getNoteTitle()}
` + ); + let linkedLines = this.getLinesInNote(res.item); + newLines = newLines.concat(linkedLines); + newLines.push("