diff --git a/addon/chrome/content/lib/css/copy-tex.css b/addon/chrome/content/lib/css/copy-tex.css new file mode 100644 index 0000000..6999c63 --- /dev/null +++ b/addon/chrome/content/lib/css/copy-tex.css @@ -0,0 +1,13 @@ +/* Force selection of entire .katex/.katex-display blocks, so that we can + * copy/paste the entire source code. If you omit this CSS, partial + * selections of a formula will work, but will copy the ugly HTML + * representation instead of the LaTeX source code. (Full selections will + * still produce the LaTeX source code.) + */ +.katex, +.katex-display { + -webkit-user-select: all; + -moz-user-select: all; + user-select: all; +} + diff --git a/addon/chrome/content/lib/js/copy-tex.min.js b/addon/chrome/content/lib/js/copy-tex.min.js new file mode 100644 index 0000000..9e9d26e --- /dev/null +++ b/addon/chrome/content/lib/js/copy-tex.min.js @@ -0,0 +1 @@ +!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var l in n)("object"==typeof exports?exports:e)[l]=n[l]}}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={},t={inline:["$","$"],display:["$$","$$"]},n=function(e,n){void 0===n&&(n=t);for(var l=e.querySelectorAll(".katex-mathml + .katex-html"),r=0;r, + ids: Array, extraData: object ) => { if (event === "modify" && type === "item") { @@ -338,22 +338,15 @@ class AddonEvents extends AddonBase { }); } - const switchTexButton: Element = await this._Addon.views.addEditorButton( + await this._Addon.views.addEditorButton( message.content.editorInstance, "knowledge-switchTex", "switchTex", `LaTex View ${Zotero.isWin ? "Ctrl" : "⌘"}+/`, - "switchTex", + "switchEditorTex", "middle", "builtin" ); - switchTexButton.addEventListener("click", (e) => { - this.onEditorEvent( - new EditorMessage("switchEditorTex", { - editorInstance: message.content.editorInstance, - }) - ); - }); message.content.editorInstance._iframeWindow.document.addEventListener( "keyup", @@ -404,7 +397,35 @@ class AddonEvents extends AddonBase { ); _window.document.body.append(texStyle); + const copytexStyle = _window.document.createElement("link"); + copytexStyle.setAttribute("rel", "stylesheet"); + copytexStyle.setAttribute( + "href", + "chrome://Knowledge4Zotero/content/lib/css/copy-tex.css" + ); + _window.document.body.append(copytexStyle); + + const copytexScript = _window.document.createElement("script"); + copytexScript.setAttribute( + "src", + "chrome://Knowledge4Zotero/content/lib/js/copy-tex.min.js" + ); + _window.document.head.append(copytexScript); + message.content.editorInstance._knowledgeUIInitialized = true; + + if ( + this._Addon.views._texNotes.includes( + message.content.editorInstance._item.id + ) + ) { + this.onEditorEvent( + new EditorMessage("switchEditorTex", { + editorInstance: message.content.editorInstance, + params: { viewTex: true }, + }) + ); + } } else if (message.type === "enterWorkspace") { /* message.content = { @@ -482,11 +503,15 @@ class AddonEvents extends AddonBase { } else if (message.type === "switchEditorTex") { /* message.content = { - editorInstance + editorInstance, params: {viewTex: boolean} } */ const instance = message.content.editorInstance; - if (!instance._viewTex) { + let viewTex = false; + if (message.content.params && message.content.params.viewTex) { + viewTex = true; + } + if (!this._Addon.views._texNotes.includes(instance._item.id) || viewTex) { const editorElement = instance._iframeWindow.document.getElementsByClassName( "primary-editor" @@ -494,6 +519,7 @@ class AddonEvents extends AddonBase { if (!editorElement) { return; } + Zotero.debug("Knowledge4Zotero: latex view on."); const viewNode = editorElement.cloneNode(true) as HTMLElement; renderMathInElement(viewNode, { // customised options @@ -507,7 +533,6 @@ class AddonEvents extends AddonBase { // • rendering keys, e.g.: throwOnError: false, }); - instance._viewTex = true; this._Addon.views.switchEditorTexView(instance, true, viewNode); this._Addon.views.changeEditorButtonView( instance._iframeWindow.document.getElementById("knowledge-switchTex"), @@ -515,7 +540,7 @@ class AddonEvents extends AddonBase { `Editor View ${Zotero.isWin ? "Ctrl" : "⌘"}+/` ); } else { - instance._viewTex = false; + Zotero.debug("Knowledge4Zotero: latex view off."); this._Addon.views.switchEditorTexView(instance, false); this._Addon.views.changeEditorButtonView( instance._iframeWindow.document.getElementById("knowledge-switchTex"), diff --git a/src/views.ts b/src/views.ts index 55e65d1..2e51f61 100644 --- a/src/views.ts +++ b/src/views.ts @@ -5,6 +5,7 @@ class AddonViews extends AddonBase { editorIcon: object; currentOutline: OutlineType; _initIframe: any; + _texNotes: number[]; constructor(parent: Knowledge4Zotero) { super(parent); @@ -28,6 +29,7 @@ class AddonViews extends AddonBase { }; this.currentOutline = OutlineType.treeView; this._initIframe = Zotero.Promise.defer(); + this._texNotes = []; } getEditor(_document: Document) { @@ -188,15 +190,35 @@ class AddonViews extends AddonBase { "editor-core" )[0] as HTMLElement; if (showView) { + if (!this._texNotes.includes(instance._item.id)) { + this._texNotes.push(instance._item.id); + } + let oldView = instance._iframeWindow.document.getElementById("texView"); + while (oldView) { + oldView.remove(); + oldView = instance._iframeWindow.document.getElementById("texView"); + } viewNode.setAttribute("id", "texView"); viewNode.style.height = "100%"; viewNode.style.padding = "20px 30px 20px 30px"; viewNode.style.overflowY = "auto"; viewNode.removeAttribute("contentEditable"); + Array.prototype.forEach.call( + viewNode.getElementsByTagName("a"), + (e: HTMLElement) => { + e.addEventListener("click", (ev) => { + ZoteroPane.loadURI(e.getAttribute("href")); + }); + } + ); + editorCore.after(viewNode); editorCore.style.visibility = "hidden"; viewNode.scrollTop = editorCore.scrollTop; } else { + if (this._texNotes.includes(instance._item.id)) { + this._texNotes.splice(this._texNotes.indexOf(instance._item.id), 1); + } const texView = instance._iframeWindow.document.getElementById("texView"); if (texView) { editorCore.scrollTop = texView.scrollTop; @@ -243,7 +265,13 @@ class AddonViews extends AddonBase { } // @ts-ignore - editor.parentNode.scrollTo(0, editor.children[lineIndex].offsetTop); + const scrollNum = editor.children[lineIndex].offsetTop; + (editor.parentNode as HTMLElement).scrollTo(0, scrollNum); + + const texView = instance._iframeWindow.document.getElementById("texView"); + if (texView) { + texView.scrollTo(0, scrollNum); + } } addNewKnowledgeButton() {