Index: gc_core/js/ibdawg.js ================================================================== --- gc_core/js/ibdawg.js +++ gc_core/js/ibdawg.js @@ -214,15 +214,13 @@ } _suggest (sRemain, nMaxDel=0, nDeep=0, iAddr=0, sNewWord="", bAvoidLoop=false) { // returns a set of suggestions // recursive function - //show(nDeep, sNewWord + ":" + sRemain) let aSugg = new Set(); if (sRemain == "") { if (this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask) { - //show(nDeep, "___" + sNewWord + "___"); aSugg.add(sNewWord); } for (let sTail of this._getTails(iAddr)) { aSugg.add(sNewWord+sTail); } @@ -298,18 +296,16 @@ _suggestWithCrushedUselessChars (sWord, nDeep=0, iAddr=0, sNewWord="", bAvoidLoop=false) { let aSugg = new Set(); if (sWord.length == 0) { if (this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask) { - show(nDeep, "!!! " + sNewWord + " !!!"); aSugg.add(sNewWord); } return aSugg; } let cCurrent = sWord.slice(0, 1); for (let [cChar, jAddr] of this._getSimilarArcsAndCrushedChars(cCurrent, iAddr)) { - show(nDeep, cChar); aSugg.gl_update(this._suggestWithCrushedUselessChars(sWord.slice(1), nDeep+1, jAddr, sNewWord+cChar)); } return aSugg; } Index: gc_lang/fr/webext/background.js ================================================================== --- gc_lang/fr/webext/background.js +++ gc_lang/fr/webext/background.js @@ -174,28 +174,69 @@ /* Context Menu */ + +// Selected text browser.contextMenus.create({ - id: "getListOfTokens", - title: "Analyser", + id: "rightClickLxgSelectedText", + title: "Lexicographe (sélection)", contexts: ["selection"] }); browser.contextMenus.create({ - id: "parseAndSpellcheck", - title: "Corriger", + id: "rightClickGCSelectedText", + title: "Correction grammaticale (sélection)", contexts: ["selection"] }); browser.contextMenus.create({ - id: "separator1", + id: "separator_selection", type: "separator", contexts: ["selection"] }); +// Editable content +browser.contextMenus.create({ + id: "rightClickLxgEditableNode", + title: "Lexicographe (zone de texte)", + contexts: ["editable"] +}); + +browser.contextMenus.create({ + id: "rightClickGCEditableNode", + title: "Correction grammaticale (zone de texte)", + contexts: ["editable"] +}); + +browser.contextMenus.create({ + id: "separator_editable", + type: "separator", + contexts: ["editable"] +}); + +// Page +browser.contextMenus.create({ + id: "rightClickLxgPage", + title: "Lexicographe (page)", + contexts: ["page"] +}); + +browser.contextMenus.create({ + id: "rightClickGCPage", + title: "Correction grammaticale (page)", + contexts: ["page"] +}); + +browser.contextMenus.create({ + id: "separator_page", + type: "separator", + contexts: ["page"] +}); + +// Conjugueur browser.contextMenus.create({ id: "conjugueur_window", title: "Conjugueur [fenêtre]", contexts: ["all"] }); @@ -204,39 +245,62 @@ id: "conjugueur_tab", title: "Conjugueur [onglet]", contexts: ["all"] }); +// Rescan page browser.contextMenus.create({ - id: "separator2", + id: "separator_rescan", type: "separator", contexts: ["editable"] }); browser.contextMenus.create({ id: "rescanPage", title: "Rechercher à nouveau les zones de texte", contexts: ["editable"] }); + browser.contextMenus.onClicked.addListener(function (xInfo, xTab) { // xInfo = https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/contextMenus/OnClickData // xTab = https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/Tab // confusing: no way to get the node where we click?! switch (xInfo.menuItemId) { - case "parseAndSpellcheck": - parseAndSpellcheckSelectedText(xTab.id, xInfo.selectionText); + // editable node + // page + case "rightClickGCEditableNode": + case "rightClickLxgEditableNode": + case "rightClickGCPage": + case "rightClickLxgPage": + sendCommandToTab(xInfo.menuItemId, xTab.id); + break; + // selected text + case "rightClickGCSelectedText": + sendCommandToTab("rightClickGCSelectedText", xTab.id); + xGCEWorker.postMessage({ + sCommand: "parseAndSpellcheck", + dParam: {sText: xInfo.selectionText, sCountry: "FR", bDebug: false, bContext: false}, + dInfo: {iReturnPort: xTab.id} + }); break; - case "getListOfTokens": - getListOfTokensFromSelectedText(xTab.id, xInfo.selectionText); + case "rightClickLxgSelectedText": + sendCommandToTab("rightClickLxgSelectedText", xTab.id); + xGCEWorker.postMessage({ + sCommand: "getListOfTokens", + dParam: {sText: xInfo.selectionText}, + dInfo: {iReturnPort: xTab.id} + }); break; + // conjugueur case "conjugueur_window": openConjugueurWindow(); break; case "conjugueur_tab": openConjugueurTab(); break; + // rescan page case "rescanPage": let xPort = dConnx.get(xTab.id); xPort.postMessage({sActionDone: "rescanPage"}); break; default: @@ -272,32 +336,13 @@ dOptions = helpers.mapToObject(dOptions); } browser.storage.local.set({"gc_options": dOptions}); } -function parseAndSpellcheckSelectedText (iTab, sText) { - // send message to the tab - let xTabPort = dConnx.get(iTab); - xTabPort.postMessage({sActionDone: "openGCPanel", result: null, dInfo: null, bEnd: false, bError: false}); - // send command to the worker - xGCEWorker.postMessage({ - sCommand: "parseAndSpellcheck", - dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false}, - dInfo: {iReturnPort: iTab} - }); -} - -function getListOfTokensFromSelectedText (iTab, sText) { - // send message to the tab - let xTabPort = dConnx.get(iTab); - xTabPort.postMessage({sActionDone: "openLxgPanel", result: null, dInfo: null, bEnd: false, bError: false}); - // send command to the worker - xGCEWorker.postMessage({ - sCommand: "getListOfTokens", - dParam: {sText: sText}, - dInfo: {iReturnPort: iTab} - }); +function sendCommandToTab (sCommand, iTab) { + let xTabPort = dConnx.get(iTab); + xTabPort.postMessage({sActionDone: sCommand, result: null, dInfo: null, bEnd: false, bError: false}); } function openConjugueurTab () { if (bChrome) { browser.tabs.create({ Index: gc_lang/fr/webext/content_scripts/init.js ================================================================== --- gc_lang/fr/webext/content_scripts/init.js +++ gc_lang/fr/webext/content_scripts/init.js @@ -44,10 +44,24 @@ lMenu: [], oTFPanel: null, oLxgPanel: null, oGCPanel: null, + + xRightClickedNode: null, + + listenRightClick: function () { + // Node where a right click is done + // Bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=1325814 + document.addEventListener('contextmenu', function (xEvent) { + this.xRightClickedNode = xEvent.target; + }.bind(this), true); + }, + + clearRightClickedNode: function () { + this.xRightClickedNode = null; + }, createMenus: function () { let lNode = document.getElementsByTagName("textarea"); for (let xNode of lNode) { if (xNode.style.display !== "none" && xNode.style.visibility !== "hidden") { @@ -54,20 +68,30 @@ this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode)); this.nMenu += 1; } } }, + + createMenus2 () { + let lNode = document.querySelectorAll("[contenteditable]"); + for (let xNode of lNode) { + this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode)); + this.nMenu += 1; + } + }, rescanPage: function () { if (this.oTFPanel !== null) { this.oTFPanel.hide(); } if (this.oLxgPanel !== null) { this.oLxgPanel.hide(); } if (this.oGCPanel !== null) { this.oGCPanel.hide(); } for (let oMenu of this.lMenu) { oMenu.deleteNodes(); } this.lMenu.length = 0; // to clear an array + this.listenRightClick(); this.createMenus(); + this.createMenus2(); }, createTFPanel: function () { if (this.oTFPanel === null) { this.oTFPanel = new GrammalecteTextFormatter("grammalecte_tf_panel", "Formateur de texte", 760, 600, false); @@ -88,10 +112,34 @@ if (this.oGCPanel === null) { this.oGCPanel = new GrammalecteGrammarChecker("grammalecte_gc_panel", "Grammalecte", 500, 700); this.oGCPanel.insertIntoPage(); } }, + + startGCPanel: function (xNode=null) { + oGrammalecte.createGCPanel(); + oGrammalecte.oGCPanel.clear(); + oGrammalecte.oGCPanel.show(); + oGrammalecte.oGCPanel.start(xNode); + oGrammalecte.oGCPanel.startWaitIcon(); + }, + + startLxgPanel: function () { + oGrammalecte.createLxgPanel(); + oGrammalecte.oLxgPanel.clear(); + oGrammalecte.oLxgPanel.show(); + oGrammalecte.oLxgPanel.startWaitIcon(); + }, + + getPageText: function () { + let sPageText = document.body.innerText; + let nPos = sPageText.indexOf("__grammalecte_panel__"); + if (nPos >= 0) { + sPageText = sPageText.slice(0, nPos); + } + return sPageText; + }, createNode: function (sType, oAttr, oDataset=null) { try { let xNode = document.createElement(sType); Object.assign(xNode, oAttr); @@ -112,10 +160,11 @@ */ let xGrammalectePort = browser.runtime.connect({name: "content-script port"}); xGrammalectePort.onMessage.addListener(function (oMessage) { let {sActionDone, result, dInfo, bEnd, bError} = oMessage; + let sText = ""; switch (sActionDone) { case "parseAndSpellcheck": if (!bEnd) { oGrammalecte.oGCPanel.addParagraphResult(result); } else { @@ -133,25 +182,71 @@ } break; case "getSpellSuggestions": oGrammalecte.oGCPanel.oTooltip.setSpellSuggestionsFor(result.sWord, result.aSugg, dInfo.sErrorId); break; - // Design WTF: context menus are made in background, not in content-script. - // Commands from context menu received here to initialize panels - case "openGCPanel": - oGrammalecte.createGCPanel(); - oGrammalecte.oGCPanel.clear(); - oGrammalecte.oGCPanel.show(); - oGrammalecte.oGCPanel.start(); - oGrammalecte.oGCPanel.startWaitIcon(); - break; - case "openLxgPanel": - oGrammalecte.createLxgPanel(); - oGrammalecte.oLxgPanel.clear(); - oGrammalecte.oLxgPanel.show(); - oGrammalecte.oLxgPanel.startWaitIcon(); - break; + /* + Commands received from the context menu + (Context menu are initialized in background) + */ + // Grammar checker commands + case "rightClickGCEditableNode": + if (oGrammalecte.xRightClickedNode !== null) { + oGrammalecte.startGCPanel(oGrammalecte.xRightClickedNode); + sText = (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText; + xGrammalectePort.postMessage({ + sCommand: "parseAndSpellcheck", + dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false}, + dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id} + }); + } else { + oGrammalecte.startGCPanel(); + oGrammalecte.oGCPanel.addMessage("Erreur. Node introuvable… Sélectionnez le texte à corriger et relancez le correcteur via le menu contextuel."); + oGrammalecte.oGCPanel.stopWaitIcon(); + } + break; + case "rightClickGCPage": + oGrammalecte.startGCPanel(); + xGrammalectePort.postMessage({ + sCommand: "parseAndSpellcheck", + dParam: {sText: oGrammalecte.getPageText(), sCountry: "FR", bDebug: false, bContext: false}, + dInfo: {} + }); + break; + case "rightClickGCSelectedText": + oGrammalecte.startGCPanel(); + // selected text is sent to the GC worker in the background script. + break; + // Lexicographer commands + case "rightClickLxgEditableNode": + if (oGrammalecte.xRightClickedNode !== null) { + oGrammalecte.startLxgPanel(); + sText = (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.textContent; + xGrammalectePort.postMessage({ + sCommand: "getListOfTokens", + dParam: {sText: sText}, + dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id} + }); + } else { + oGrammalecte.startLxgPanel(); + oGrammalecte.oLxgPanel.addMessage("Erreur. Node introuvable… Sélectionnez le texte à analyser et relancez le lexicographe via le menu contextuel."); + oGrammalecte.oLxgPanel.stopWaitIcon(); + } + break; + case "rightClickLxgPage": + oGrammalecte.startLxgPanel(); + xGrammalectePort.postMessage({ + sCommand: "getListOfTokens", + dParam: {sText: oGrammalecte.getPageText()}, + dInfo: {} + }); + break; + case "rightClickLxgSelectedText": + oGrammalecte.startLxgPanel(); + // selected text is sent to the GC worker in the background script. + break; + // rescan page command case "rescanPage": oGrammalecte.rescanPage(); break; default: console.log("[Content script] Unknown command: " + sActionDone); @@ -160,6 +255,8 @@ /* Start */ +oGrammalecte.listenRightClick(); oGrammalecte.createMenus(); +oGrammalecte.createMenus2(); Index: gc_lang/fr/webext/content_scripts/menu.css ================================================================== --- gc_lang/fr/webext/content_scripts/menu.css +++ gc_lang/fr/webext/content_scripts/menu.css @@ -18,11 +18,11 @@ border-radius: 50%; text-align: center; cursor: pointer; box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5); z-index: 2147483640; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */ - animation: grammalecte-spin 2s ease 3; + animation: grammalecte-spin 2s ease 1; } .grammalecte_menu_main_button:hover { border: 4px solid hsla(210, 80%, 35%, .5); background-color: hsla(210, 80%, 55%, .5); animation: grammalecte-spin .5s linear infinite; Index: gc_lang/fr/webext/content_scripts/menu.js ================================================================== --- gc_lang/fr/webext/content_scripts/menu.js +++ gc_lang/fr/webext/content_scripts/menu.js @@ -3,81 +3,77 @@ "use strict"; class GrammalecteMenu { - constructor (nMenu, xTextArea) { + constructor (nMenu, xNode) { this.sMenuId = "grammalecte_menu" + nMenu; this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "}); this.xButton.onclick = () => { this.switchMenu(); }; - this.xMenu = this._createMenu(xTextArea); - this._insertAfter(this.xButton, xTextArea); - this._insertAfter(this.xMenu, xTextArea); + this.xMenu = this._createMenu(xNode); + this._insertAfter(this.xButton, xNode); + this._insertAfter(this.xMenu, xNode); } _insertAfter (xNewNode, xReferenceNode) { xReferenceNode.parentNode.insertBefore(xNewNode, xReferenceNode.nextSibling); } - _createMenu (xTextArea) { + _createMenu (xNode) { try { + let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.textContent; let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"}); + xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"})); // Text formatter - let xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"}); - xTFButton.onclick = () => { - this.switchMenu(); - oGrammalecte.createTFPanel(); - oGrammalecte.oTFPanel.start(xTextArea); - oGrammalecte.oTFPanel.show(); - }; + if (xNode.tagName == "TEXTAREA") { + let xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"}); + xTFButton.onclick = () => { + this.switchMenu(); + oGrammalecte.createTFPanel(); + oGrammalecte.oTFPanel.start(xNode); + oGrammalecte.oTFPanel.show(); + }; + xMenu.appendChild(xTFButton); + } // lexicographe let xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"}); xLxgButton.onclick = () => { - this.switchMenu(); - oGrammalecte.createLxgPanel(); - oGrammalecte.oLxgPanel.clear(); - oGrammalecte.oLxgPanel.show(); - oGrammalecte.oLxgPanel.startWaitIcon(); + this.switchMenu(); + oGrammalecte.startLxgPanel(); xGrammalectePort.postMessage({ sCommand: "getListOfTokens", - dParam: {sText: xTextArea.value}, - dInfo: {sTextAreaId: xTextArea.id} + dParam: {sText: sText}, + dInfo: {sTextAreaId: xNode.id} }); }; + xMenu.appendChild(xLxgButton); // Grammar checker let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"}); xGCButton.onclick = () => { - this.switchMenu(); - oGrammalecte.createGCPanel(); - oGrammalecte.oGCPanel.start(xTextArea); - oGrammalecte.oGCPanel.show(); - oGrammalecte.oGCPanel.startWaitIcon(); + this.switchMenu(); + oGrammalecte.startGCPanel(xNode); xGrammalectePort.postMessage({ sCommand: "parseAndSpellcheck", - dParam: {sText: xTextArea.value, sCountry: "FR", bDebug: false, bContext: false}, - dInfo: {sTextAreaId: xTextArea.id} + dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false}, + dInfo: {sTextAreaId: xNode.id} }); }; + xMenu.appendChild(xGCButton); // Conjugation tool let xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"}); let xConjButtonTab = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"}); xConjButtonTab.onclick = () => { - this.switchMenu(); - xGrammalectePort.postMessage({sCommand: "openConjugueurTab", dParam: null, dInfo: null}); + this.switchMenu(); + xGrammalectePort.postMessage({sCommand: "openConjugueurTab", dParam: null, dInfo: null}); }; let xConjButtonWin = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"}); xConjButtonWin.onclick = () => { - this.switchMenu(); - xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null}); + this.switchMenu(); + xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null}); }; xConjButton.appendChild(xConjButtonTab); xConjButton.appendChild(xConjButtonWin); - // Create - xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"})); - xMenu.appendChild(xTFButton); - xMenu.appendChild(xLxgButton); - xMenu.appendChild(xGCButton); xMenu.appendChild(xConjButton); //xMenu.appendChild(oGrammalecte.createNode("img", {scr: browser.extension.getURL("img/logo-16.png")})); // can’t work, due to content-script policy: https://bugzilla.mozilla.org/show_bug.cgi?id=1267027 xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_footer"})); return xMenu; @@ -91,9 +87,9 @@ this.xMenu.parentNode.removeChild(this.xMenu); this.xButton.parentNode.removeChild(this.xButton); } switchMenu () { - let xMenu = document.getElementById(this.sMenuId); + let xMenu = document.getElementById(this.sMenuId); xMenu.style.display = (xMenu.style.display == "block") ? "none" : "block"; } } Index: gc_lang/fr/webext/content_scripts/panel.css ================================================================== --- gc_lang/fr/webext/content_scripts/panel.css +++ gc_lang/fr/webext/content_scripts/panel.css @@ -39,10 +39,16 @@ } .grammalecte_panel_label { display: inline-block; padding: 0 10px; } +.grammalecte_panel_invisible_marker { + position: absolute; + /*visibility: hidden;*/ + font-size: 6px; + color: hsl(210, 0%, 90%); /* same color than panel_bar background */ +} .grammalecte_panel_commands { float: right; } .grammalecte_copy_button { @@ -91,10 +97,19 @@ position: absolute; min-width: 100%; height: calc(100% - 55px); /* panel height - title_bar */ overflow: auto; } + +.grammalecte_panel_message { + margin: 10px; + padding: 10px; + border-radius: 5px; + background-color: hsl(0, 50%, 40%); + color: hsl(0, 50%, 96%); + font-size: 20px; +} /* Spinner */ Index: gc_lang/fr/webext/content_scripts/panel.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel.js +++ gc_lang/fr/webext/content_scripts/panel.js @@ -19,10 +19,11 @@ } _createPanel (sTitle) { try { let xPanel = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_panel"}); + this.xPanelBar.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_panel_invisible_marker", textContent: "__grammalecte_panel__"})); this.xPanelBar.appendChild(this._createButtons()); let xTitle = oGrammalecte.createNode("div", {className: "grammalecte_panel_title"}); xTitle.appendChild(this._createLogo()); xTitle.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_panel_label", textContent: sTitle})); this.xPanelBar.appendChild(xTitle); @@ -89,10 +90,11 @@ this.xPanel.style.display = "block"; } hide () { this.xPanel.style.display = "none"; + oGrammalecte.clearRightClickedNode(); } center () { let nHeight = (this.bFlexible) ? window.innerHeight-100 : this.nHeight; this.xPanel.style = `top: 50%; left: 50%; width: ${this.nWidth}px; height: ${nHeight}px; margin-top: -${nHeight/2}px; margin-left: -${this.nWidth/2}px;`; Index: gc_lang/fr/webext/content_scripts/panel_gc.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_gc.js +++ gc_lang/fr/webext/content_scripts/panel_gc.js @@ -53,15 +53,15 @@ this.oTooltip = new GrammalecteTooltip(this.xContentNode); this.xPanelContent.appendChild(this.xContentNode); this.oTAC = new GrammalecteTextAreaControl(); } - start (xTextArea=null) { + start (xNode=null) { this.oTooltip.hide(); this.clear(); - if (xTextArea) { - this.oTAC.setTextArea(xTextArea); + if (xNode && xNode.tagName == "TEXTAREA") { + this.oTAC.setTextArea(xNode); } } clear () { while (this.xParagraphList.firstChild) { @@ -235,11 +235,11 @@ addSummary () { // todo } addMessage (sMessage) { - let xNode = oGrammalecte.createNode("div", {className: "grammalecte_gc_panel_message", textContent: sMessage}); + let xNode = oGrammalecte.createNode("div", {className: "grammalecte_panel_message", textContent: sMessage}); this.xParagraphList.appendChild(xNode); } _copyToClipboard (sText) { // recipe from https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/clipboard-helper.js @@ -448,11 +448,11 @@ this._dParagraph.set(i, sText.slice(iStart, iEnd)); i++; iStart = iEnd+1; } this._dParagraph.set(i, sText.slice(iStart)); - console.log("Paragraphs number: " + (i+1)); + //console.log("Paragraphs number: " + (i+1)); } write () { if (this._xTextArea !== null) { let sText = ""; Index: gc_lang/fr/webext/content_scripts/panel_lxg.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_lxg.js +++ gc_lang/fr/webext/content_scripts/panel_lxg.js @@ -22,12 +22,13 @@ if (this._xContentNode.textContent !== "") { this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_separator", textContent: sText})); } } - addMessage (sClass, sText) { - this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: sClass, textContent: sText})); + addMessage (sMessage) { + let xNode = oGrammalecte.createNode("div", {className: "grammalecte_panel_message", textContent: sMessage}); + this._xContentNode.appendChild(xNode); } addListOfTokens (lTokens) { try { if (lTokens) { DELETED gc_lang/fr/webext/gce_sharedworker.js Index: gc_lang/fr/webext/gce_sharedworker.js ================================================================== --- gc_lang/fr/webext/gce_sharedworker.js +++ /dev/null @@ -1,271 +0,0 @@ -/* - WORKER: - https://developer.mozilla.org/en-US/docs/Web/API/Worker - https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope - - - JavaScript sucks. - No module available in WebExtension at the moment! :( - No require, no import/export. - - In Worker, we have importScripts() which imports everything in this scope. - - In order to use the same base of code with XUL-addon for Thunderbird and SDK-addon for Firefox, - all modules have been “objectified”. And while they are still imported via “require” - in the previous extensions, they are loaded as background scripts in WebExtension sharing - the same memory space… - - When JavaScript become a modern language, “deobjectify” the modules… - - ATM, import/export are not available by default: - — Chrome 60 – behind the Experimental Web Platform flag in chrome:flags. - — Firefox 54 – behind the dom.moduleScripts.enabled setting in about:config. - — Edge 15 – behind the Experimental JavaScript Features setting in about:flags. - - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export -*/ - -"use strict"; - - -console.log("GC Engine SharedWorker [start]"); -//console.log(self); - -importScripts("grammalecte/helpers.js"); -importScripts("grammalecte/str_transform.js"); -importScripts("grammalecte/ibdawg.js"); -importScripts("grammalecte/text.js"); -importScripts("grammalecte/tokenizer.js"); -importScripts("grammalecte/fr/conj.js"); -importScripts("grammalecte/fr/mfsp.js"); -importScripts("grammalecte/fr/phonet.js"); -importScripts("grammalecte/fr/cregex.js"); -importScripts("grammalecte/fr/gc_options.js"); -importScripts("grammalecte/fr/gc_rules.js"); -importScripts("grammalecte/fr/gc_engine.js"); -importScripts("grammalecte/fr/lexicographe.js"); -importScripts("grammalecte/tests.js"); -/* - Warning. - Initialization can’t be completed at startup of the worker, - for we need the path of the extension to load data stored in JSON files. - This path is retrieved in background.js and passed with the event “init”. -*/ - - -/* - Message Event Object - https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent -*/ - -let xPort = null; - -function createResponse (sActionDone, result, dInfo, bError=false) { - return { - "sActionDone": sActionDone, - "result": result, // can be of any type - "dInfo": dInfo, - "bError": bError - }; -} - -function createErrorResult (e, sDescr="no description") { - return { - "sType": "error", - "sDescription": sDescr, - "sMessage": e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message - }; -} - -function showData (e) { - for (let sParam in e) { - console.log(sParam); - console.log(e[sParam]); - } -} - -onconnect = function (e) { - console.log("[Sharedworker] START CONNECTION"); - xPort = e.ports[0]; - - xPort.onmessage = function (e) { - console.log("[Sharedworker] ONMESSAGE"); - let {sCommand, dParam, dInfo} = e.data; - console.log(e.data); - switch (sCommand) { - case "init": - init(dParam.sExtensionPath, dParam.sOptions, dParam.sContext, dInfo); - break; - case "parse": - parse(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo); - break; - case "parseAndSpellcheck": - parseAndSpellcheck(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo); - break; - case "getOptions": - getOptions(dInfo); - break; - case "getDefaultOptions": - getDefaultOptions(dInfo); - break; - case "setOptions": - setOptions(dParam.sOptions, dInfo); - break; - case "setOption": - setOption(dParam.sOptName, dParam.bValue, dInfo); - break; - case "resetOptions": - resetOptions(dInfo); - break; - case "textToTest": - textToTest(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo); - break; - case "fullTests": - fullTests('{"nbsp":true, "esp":true, "unit":true, "num":true}', dInfo); - break; - case "getListOfTokens": - getListOfTokens(dParam.sText, dInfo); - break; - default: - console.log("Unknown command: " + sCommand); - showData(e.data); - } - } - //xPort.start(); -} - -let bInitDone = false; - -let oDict = null; -let oTokenizer = null; -let oLxg = null; -let oTest = null; - - -function init (sExtensionPath, sGCOptions="", sContext="JavaScript", dInfo={}) { - try { - if (!bInitDone) { - console.log("[Sharedworker] Loading… Extension path: " + sExtensionPath); - conj.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/conj_data.json")); - phonet.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/phonet_data.json")); - mfsp.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/mfsp_data.json")); - console.log("[Sharedworker] Modules have been initialized…"); - gc_engine.load(sContext, sExtensionPath+"grammalecte/_dictionaries"); - oDict = gc_engine.getDictionary(); - oTest = new TestGrammarChecking(gc_engine, sExtensionPath+"/grammalecte/fr/tests_data.json"); - oLxg = new Lexicographe(oDict); - if (sGCOptions !== "") { - gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions))); - } - oTokenizer = new Tokenizer("fr"); - //tests(); - bInitDone = true; - } else { - console.log("[Sharedworker] Already initialized…") - } - // we always retrieve options from the gc_engine, for setOptions filters obsolete options - xPort.postMessage(createResponse("init", gc_engine.getOptions().gl_toString(), dInfo)); - } - catch (e) { - helpers.logerror(e); - xPort.postMessage(createResponse("init", createErrorResult(e, "init failed"), dInfo, true)); - } -} - -function parse (sText, sCountry, bDebug, bContext, dInfo={}) { - let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext); - xPort.postMessage({sActionDone: "parse", result: aGrammErr, dInfo: dInfo}); -} - -function parseAndSpellcheck (sText, sCountry, bDebug, bContext, dInfo={}) { - let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext); - let aSpellErr = oTokenizer.getSpellingErrors(sText, oDict); - xPort.postMessage(createResponse("parseAndSpellcheck", {aGrammErr: aGrammErr, aSpellErr: aSpellErr}, dInfo)); -} - -function getOptions (dInfo={}) { - xPort.postMessage(createResponse("getOptions", gc_engine.getOptions().gl_toString(), dInfo)); -} - -function getDefaultOptions (dInfo={}) { - xPort.postMessage(createResponse("getDefaultOptions", gc_engine.getDefaultOptions().gl_toString(), dInfo)); -} - -function setOptions (sGCOptions, dInfo={}) { - gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions))); - xPort.postMessage(createResponse("setOptions", gc_engine.getOptions().gl_toString(), dInfo)); -} - -function setOption (sOptName, bValue, dInfo={}) { - gc_engine.setOptions(new Map([ [sOptName, bValue] ])); - xPort.postMessage(createResponse("setOption", gc_engine.getOptions().gl_toString(), dInfo)); -} - -function resetOptions (dInfo={}) { - gc_engine.resetOptions(); - xPort.postMessage(createResponse("resetOptions", gc_engine.getOptions().gl_toString(), dInfo)); -} - -function tests () { - console.log(conj.getConj("devenir", ":E", ":2s")); - console.log(mfsp.getMasForm("emmerdeuse", true)); - console.log(mfsp.getMasForm("pointilleuse", false)); - console.log(phonet.getSimil("est")); - let aRes = gc_engine.parse("Je suit..."); - for (let oErr of aRes) { - console.log(text.getReadableError(oErr)); - } -} - -function textToTest (sText, sCountry, bDebug, bContext, dInfo={}) { - if (!gc_engine || !oDict) { - xPort.postMessage(createResponse("textToTest", "# Grammar checker or dictionary not loaded.", dInfo)); - return; - } - let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext); - let sMsg = ""; - for (let oErr of aGrammErr) { - sMsg += text.getReadableError(oErr) + "\n"; - } - xPort.postMessage(createResponse("textToTest", sMsg, dInfo)); -} - -function fullTests (sGCOptions="", dInfo={}) { - if (!gc_engine || !oDict) { - xPort.postMessage(createResponse("fullTests", "# Grammar checker or dictionary not loaded.", dInfo)); - return; - } - let dMemoOptions = gc_engine.getOptions(); - if (sGCOptions) { - gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions))); - } - let sMsg = ""; - for (let sRes of oTest.testParse()) { - sMsg += sRes + "\n"; - console.log(sRes); - } - gc_engine.setOptions(dMemoOptions); - xPort.postMessage(createResponse("fullTests", sMsg, dInfo)); -} - - -// Lexicographer - -function getListOfTokens (sText, dInfo={}) { - try { - let aElem = []; - let aRes = null; - for (let oToken of oTokenizer.genTokens(sText)) { - aRes = oLxg.getInfoForToken(oToken); - if (aRes) { - aElem.push(aRes); - } - } - xPort.postMessage(createResponse("getListOfTokens", aElem, dInfo)); - } - catch (e) { - helpers.logerror(e); - xPort.postMessage(createResponse("getListOfTokens", createErrorResult(e, "no tokens"), dInfo, true)); - } -} Index: gc_lang/fr/webext/panel/main.html ================================================================== --- gc_lang/fr/webext/panel/main.html +++ gc_lang/fr/webext/panel/main.html @@ -15,13 +15,13 @@ @@ -49,11 +49,11 @@

-

AIDE

+

INTERFACE

Grammalecte affiche un bouton d’accès au menu en bas à gauche des zones de texte usuelles pour accéder aux fonctionnalités existantes.

Pour les autres zones de texte (HTML éditable), il faut sélectionner le texte et utiliser le menu contextuel.