Grammalecte  Changes On Branch ff2b908b6718fa68

Changes In Branch comunicate Excluding Merge-Ins

This is equivalent to a diff from 9b6a855c65 to ff2b908b67

2020-03-10
08:56
[fx] cancel code cosmetics Leaf check-in: ff2b908b67 user: olr tags: comunicate, fx
08:43
[fx] cancel code cosmetics check-in: bcfa44ecc9 user: olr tags: comunicate, fx
2018-11-07
09:04
[fr] nr: confusion date/datte, des/dès/dés check-in: 2528e7df7c user: olr tags: fr, trunk
2018-11-06
23:42
Added the possibility to web page script open gcpanel or lexicographe check-in: 5c25db680b user: IllusionPerdu tags: comunicate
18:33
[fr] nr: confusions diverses check-in: 9b6a855c65 user: olr tags: fr, trunk
2018-11-05
21:29
[fr] nr: à vau-l’eau, confusion pécher/pêcher, golf/golfe, cœur/chœur check-in: 7ac6a5159e user: olr tags: fr, trunk

Added gc_lang/fr/webext/content_scripts/event.js version [072a12ec6a].

            1  +// Injected script into web page
            2  +
            3  +"use strict";
            4  +
            5  +
            6  +function uniqueID () {
            7  +    let nMin = Math.ceil(0);
            8  +    let nMax = Math.floor(9999999);
            9  +    return Date.now().toString(36) + "-" + (Math.floor(Math.random() * (nMax - nMin)) + nMin).toString(36);
           10  +}
           11  +
           12  +// ! Ecoute des messages venant du content-script
           13  +let sBrowserURL;
           14  +document.addEventListener("GrammalecteToPage", function respListener (event) {
           15  +    //console.log(event);
           16  +    let oData = JSON.parse(event.detail);
           17  +    // Message envoyer dès que le script est injecté
           18  +    if (typeof oData.init !== "undefined") {
           19  +        sBrowserURL = oData.init;
           20  +    }
           21  +    if (typeof oData.tiny !== "undefined") {
           22  +        //console.log('Detect Tiny', oData.tiny);
           23  +        TinyIDInPage(oData.tiny);
           24  +    }
           25  +    //console.log("GrammalecteToPage", oData);
           26  +});
           27  +
           28  +// ! Permet d'envoyer des message vers le content script
           29  +// Retourne un identifiant unique au cas ou si besoin
           30  +// La ID unique peut être util si on permet d'intérogé grammalecte sans zone
           31  +function sendToGrammalecte (oDataAction) {
           32  +    let oDataToSend = oDataAction;
           33  +    if (typeof oDataToSend.sActionId === "undefined") {
           34  +        oDataToSend.sActionId = uniqueID();
           35  +    }
           36  +    if (oDataAction.elm) {
           37  +        if (!oDataAction.elm.id) {
           38  +            oDataAction.elm.id = uniqueID();
           39  +        }
           40  +        oDataToSend.elm = oDataAction.elm.id;
           41  +    }
           42  +    //console.log('oDataToSend', oDataToSend);
           43  +    let eventGrammalecte = new CustomEvent("GrammalecteEvent", { detail: JSON.stringify(oDataToSend) });
           44  +    document.dispatchEvent(eventGrammalecte);
           45  +    return oDataToSend.sActionId;
           46  +}
           47  +
           48  +// ! Envoie de l’information que l'injection est bien faite ;)
           49  +// (peut être lu aussi bien par la page web que le content script)
           50  +var customAPILoaded = new CustomEvent("GLInjectedScriptIsReady");
           51  +document.dispatchEvent(customAPILoaded);
           52  +
           53  +// Gros Hack : Auto add a button in tinymce ;)
           54  +
           55  +// Page to test v4 https://www.quackit.com/html/html_editors/tinymce_editor.cfm
           56  +// https://www.responsivefilemanager.com/demo.php
           57  +
           58  +// Page to test v3 http://www.imathas.com/editordemo/demo.html
           59  +
           60  +function TinyOnEditor (event, editor=null) {
           61  +    let xEditorAdd = editor || event.editor;
           62  +    //console.log(xEditorAdd);
           63  +    if (typeof xEditorAdd.settings.Grammalecte === "undefined") {
           64  +        let aBtn;
           65  +        let cPlugSep;
           66  +        let bIsAdded = false;
           67  +        if (tinyMCE.majorVersion >= 4) {
           68  +            cPlugSep = " ";
           69  +            aBtn = ["toolbar3", "toolbar2", "toolbar1", "toolbar"];
           70  +        } else if (tinyMCE.majorVersion >= 3) {
           71  +            cPlugSep = ",";
           72  +            aBtn = ["theme_advanced_buttons3", "theme_advanced_buttons2", "theme_advanced_buttons1", "theme_advanced_buttons1_add_before"];
           73  +        }
           74  +
           75  +        let sBtn;
           76  +        let iBtn = 0;
           77  +        for (sBtn of aBtn) {
           78  +            if (!bIsAdded && (typeof xEditorAdd.settings[sBtn] !== "undefined" || iBtn == aBtn.length)) {
           79  +                bIsAdded = true;
           80  +                if (typeof xEditorAdd.settings[sBtn] !== "undefined" && xEditorAdd.settings[sBtn] !== "") {
           81  +                    xEditorAdd.settings[sBtn] = (xEditorAdd.settings[sBtn] + cPlugSep + "Grammalecte").trim();
           82  +                } else {
           83  +                    let m = /(.*)([0-9])/.exec(sBtn);
           84  +                    if (m.length === 3 && parseInt(m[2]) > 1 && xEditorAdd.settings[sBtn] === "") {
           85  +                        sBtn = m[1] + (parseInt(m[2]) - 1);
           86  +                        xEditorAdd.settings[sBtn] = (xEditorAdd.settings[sBtn] + cPlugSep + "Grammalecte").trim();
           87  +                    } else {
           88  +                        xEditorAdd.settings[sBtn] = "Grammalecte";
           89  +                    }
           90  +                }
           91  +            }
           92  +            iBtn++;
           93  +        }
           94  +        if (!bIsAdded) {
           95  +            //Valeur par defaut
           96  +            xEditorAdd.settings[sBtn] =
           97  +                "undo redo | styleselect | bold italic | alignleft" +
           98  +                " aligncenter alignright alignjustify | " +
           99  +                " bullist numlist outdent indent | link image" +
          100  +                " Grammalecte";
          101  +        }
          102  +        xEditorAdd.settings["Grammalecte"] = true;
          103  +    }
          104  +
          105  +    xEditorAdd.addButton("Grammalecte", {
          106  +        text: "",
          107  +        icon: false,
          108  +        image: sBrowserURL + "img/logo-16.png",
          109  +        //"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAC8UlEQVQ4jX3TbUgTcRwH8P89ddu5u9tt082aZmpFEU4tFz0QGTUwCi0heniR9MSUIKRaD0RvIlKigsooo+iNFa0XJYuwIjEK19OcDtPElsG0ktyp591t7u7+vUh7MPX3+vf5/n8/+P0BmKJIPUUVlh2rdVVeesWlzEybqg+bFOsoylnqPmNavGFfknV2Omu2Lvja3vxAURKJib3opHizu8riLK6gjRyuKgmoSoMRFENRUqfXTzvBGK62LC2uoFkOl4RhjQ8+qWt7dPNE3sbdp+2LXbsGe9qb4rIo/BfwFy6nWQ4ThWGNDzbcfu29dMDh2nHU7CypYNLmzTda0/L5cNuzmDQi/A4Y27k6eQxLI79wS/11D0AAMNvs6XT6ojVJjJEgTbMy2BT77xBMp09KcpaWV1uc41jQoi0NdUHfjeOO9WWn7AVF7s7n986SithPJGeupBh2PCSP/xxqxAp3eq6wuUV7Wc6MSZIEhA8vHjbfOe/OcW3zmAuKy+nUzAyD2bow8ODaEROFq8AyZ5WBYdEZXGqGxZ61HJV+9HYCJRbTNA0QBA40HWunaKN5dKg/DBKxeCIe09Th/m4MJwiMSZmLEzMQAABQRuNqgu8NYX3doTcMpvCkLbtQZ2AJkrPOZG1zlnY13T+Hy9EehY90h57eqcorcZ/lctZuMzAsOjLEqwNv66/6vZcPYRBC+C3cGaBxhSet2av1BpYgTTY7k5y2JPT41slIR6Axv8R9nnOs+4Pf+2r992uOxGVJwgAAAEINfgt3BGgsESWtWas1iGDyl+CT/u7WpvxNFRc4x7qtBoZFhSFejb7z1fq9NYfjsiT+cwcQavBruCOgU4SIGo18amuoq3Js3FNlynVtH385+s53ze+t8cRkURx3yMTTRBAEQVAUXbFlf3XystJKA2NExeFBdWASDAAA+MQACCEEmqbJ0b6PMC7JwhDU8YFHV5u9NZ64LErT/oW/63tPV6uJwmKoOND78u7Fg5NhAAD4CVbzY9cwrWQrAAAAAElFTkSuQmCC",
          110  +        onclick: function (e) {
          111  +            //console.log(xEditorAdd.getContent());
          112  +            //console.log(xEditorAdd.getBody().innerText);
          113  +            let sText = xEditorAdd.getBody().innerText;
          114  +            let iframeElement;
          115  +            if (typeof xEditorAdd.iframeElement !== "undefined" && typeof xEditorAdd.iframeElement.id !== "undefined") {
          116  +                iframeElement = xEditorAdd.iframeElement.id;
          117  +            } else if (typeof xEditorAdd.editorId !== "undefined") {
          118  +                iframeElement = xEditorAdd.editorId + "_ifr";
          119  +            }
          120  +            sendToGrammalecte({ sTextToParse: sText, iframe: iframeElement });
          121  +        }
          122  +    });
          123  +}
          124  +
          125  +function TinyInPage () {
          126  +    for (let i = tinyMCE.editors.length - 1;  i > -1;  i--) {
          127  +        let sTinyId = tinyMCE.editors[i].id;
          128  +        if (typeof tinyMCE.editors[i].settings.Grammalecte === "undefined") {
          129  +            TinyIDInPage(sTinyId);
          130  +        }
          131  +    }
          132  +}
          133  +
          134  +function TinyIDInPage (sTinyId) {
          135  +    if (tinyMCE.majorVersion >= 4) {
          136  +        tinyMCE.EditorManager.execCommand("mceFocus", true, sTinyId);
          137  +        tinyMCE.EditorManager.execCommand("mceRemoveEditor", true, sTinyId);
          138  +        tinyMCE.EditorManager.execCommand("mceAddEditor", false, sTinyId);
          139  +    } else if (tinyMCE.majorVersion >= 3) {
          140  +        tinyMCE.execCommand("mceFocus", false, sTinyId);
          141  +        tinyMCE.execCommand("mceRemoveControl", true, sTinyId);
          142  +        tinyMCE.execCommand("mceAddControl", false, sTinyId);
          143  +    }
          144  +}
          145  +
          146  +if (typeof tinyMCE !== "undefined" && tinyMCE.majorVersion && tinyMCE.majorVersion >= 3 && tinyMCE.majorVersion <= 5) {
          147  +    //console.log("Have TinyMCE");
          148  +    if (tinyMCE.majorVersion >= 4) {
          149  +        tinyMCE.on("AddEditor", TinyOnEditor);
          150  +    } else if (tinyMCE.majorVersion >= 3) {
          151  +        tinyMCE.onAddEditor.add(TinyOnEditor);
          152  +    }
          153  +    try {
          154  +        TinyInPage();
          155  +    } catch (e) {
          156  +        console.error(e);
          157  +    }
          158  +}
          159  +
          160  +/* // ! In the webpage script :
          161  +document.addEventListener('GLInjectedScriptIsReady', function() {
          162  +    // Le gestionnaire d'évènement est prêt!
          163  +    // La page web peut effectuer des actions
          164  +    ...
          165  +});
          166  +...
          167  +// Pour demander une correction sur le texte
          168  +sendToGrammalecte({"sTextToParse": "salut comment ca vaa?"});
          169  +// Pour demander une correction sur un élément html
          170  +sendToGrammalecte({"sTextToParse": true, "elm": elementHTML});
          171  +// Pour avoir le lexicographe sur un texte
          172  +sendToGrammalecte({"sTextForLexicographer": "salut comment ca vaa?"});
          173  +// Pour avoir le lexicographe sur un élément html
          174  +sendToGrammalecte({"sTextForLexicographer": true, "elm": elementHTML});
          175  +*/

Modified gc_lang/fr/webext/content_scripts/init.js from [31953bf9da] to [ed619d9108].

     9      9       Not possible to load content from within the extension:
    10     10       https://bugzilla.mozilla.org/show_bug.cgi?id=1267027
    11     11       No SharedWorker, no images allowed for now…
    12     12   */
    13     13   
    14     14   "use strict";
    15     15   
    16         -
    17     16   function showError (e) {
           17  +    // console can’t display error objects from content scripts
    18     18       console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
    19     19   }
    20     20   
    21     21   // Chrome don’t follow the W3C specification:
    22     22   // https://browserext.github.io/browserext/
    23     23   let bChrome = false;
    24     24   if (typeof(browser) !== "object") {
    25     25       var browser = chrome;
    26     26       bChrome = true;
    27     27   }
    28         -
    29     28   
    30     29   /*
    31     30   function loadImage (sContainerClass, sImagePath) {
    32     31       let xRequest = new XMLHttpRequest();
    33     32       xRequest.open('GET', browser.extension.getURL("")+sImagePath, false);
    34     33       xRequest.responseType = "arraybuffer";
    35     34       xRequest.send();
................................................................................
    38     37       img.src = (URL || webkitURL).createObjectURL(blobTxt); // webkitURL is obsolete: https://bugs.webkit.org/show_bug.cgi?id=167518
    39     38       Array.filter(document.getElementsByClassName(sContainerClass), function (oElem) {
    40     39           oElem.appendChild(img);
    41     40       });
    42     41   }
    43     42   */
    44     43   
           44  +let oTinyAdd = {};
    45     45   
    46     46   const oGrammalecte = {
    47         -
    48     47       nMenu: 0,
    49     48       lMenu: [],
    50     49   
    51     50       oTFPanel: null,
    52     51       oLxgPanel: null,
    53     52       oGCPanel: null,
    54     53   
................................................................................
   100     99           }
   101    100       },
   102    101   
   103    102       observePage: function () {
   104    103           /*
   105    104               When a textarea is added via jascript we add the menu :)
   106    105           */
          106  +        function NodeTinyMCE (xNode) {
          107  +            let parentNode = xNode.parentNode; //mutation.target
          108  +            if (
          109  +                typeof xNode !== "undefined" &&
          110  +                typeof xNode.id !== "undefined" &&
          111  +                typeof oTinyAdd[xNode.id] === "undefined" &&
          112  +                (parentNode.classList.contains("mce-edit-area") || parentNode.classList.contains("mceIframeContainer"))
          113  +            ) {
          114  +                //console.log(oTinyAdd, xNode, parentNode, parentNode.classList);
          115  +                oTinyAdd[xNode.id] = true;
          116  +                sendToWebpage({ tiny: xNode.id.replace("_ifr", "") });
          117  +            }
          118  +        }
   107    119           this.xObserver = new MutationObserver(function (mutations) {
   108    120               mutations.forEach(function (mutation) {
   109         -                for (let i = 0;  i < mutation.addedNodes.length;  i++){
   110         -                    if (mutation.addedNodes[i].tagName == "TEXTAREA") {
   111         -                        oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, mutation.addedNodes[i]));
          121  +                for (let i = 0;  i < mutation.addedNodes.length;  i++) {
          122  +                    let MutationNode = mutation.addedNodes[i];
          123  +                    let tagName = MutationNode.tagName;
          124  +
          125  +                    if (tagName == "TEXTAREA") {
          126  +                        oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, MutationNode));
          127  +                        oGrammalecte.nMenu += 1;
          128  +                    } else if (tagName == "IFRAME") {
          129  +                        NodeTinyMCE(MutationNode);
          130  +                    } else if ((tagName == "DIV" || tagName == "SPAN") && MutationNode.hasAttribute && MutationNode.hasAttribute("contenteditable")) {
          131  +                        oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, MutationNode));
   112    132                           oGrammalecte.nMenu += 1;
   113         -                    } else if (mutation.addedNodes[i].getElementsByTagName) {
   114         -                        for (let xNode of mutation.addedNodes[i].getElementsByTagName("textarea")) {
          133  +                    } else if (MutationNode.getElementsByTagName) {
          134  +                        for (let xNode of MutationNode.getElementsByTagName("textarea")) {
   115    135                               oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
   116    136                               oGrammalecte.nMenu += 1;
          137  +                        }
          138  +                        for (let xNode of MutationNode.getElementsByTagName("div")) {
          139  +                            if (xNode.hasAttribute && xNode.hasAttribute("contenteditable")){
          140  +                                oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
          141  +                                oGrammalecte.nMenu += 1;
          142  +                            }
          143  +                        }
          144  +                        for (let xNode of MutationNode.getElementsByTagName("span")) {
          145  +                            if (xNode.hasAttribute && xNode.hasAttribute("contenteditable")){
          146  +                                oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
          147  +                                oGrammalecte.nMenu += 1;
          148  +                            }
          149  +                        }
          150  +                        for (let xNode of MutationNode.getElementsByTagName("iframe")) {
          151  +                            NodeTinyMCE(xNode);
   117    152                           }
   118    153                       }
   119    154                   }
   120    155               });
   121    156           });
   122    157           this.xObserver.observe(document.body, {
   123    158               childList: true,
................................................................................
   351    386           case "rescanPage":
   352    387               oGrammalecte.rescanPage();
   353    388               break;
   354    389           default:
   355    390               console.log("[Content script] Unknown command: " + sActionDone);
   356    391       }
   357    392   });
          393  +
          394  +
          395  +/*
          396  +    Communicate webpage script <=> WebExtension
          397  +    La méthode d’injection de ce script est importante !
          398  +
          399  +    Pour que la page web puisse envoyer des infos au background
          400  +    Page web => Script injecté => Content script => Background
          401  +    Pour la réponse, ce sont les mêmes étapes en sens inverse.
          402  +*/
          403  +let xScriptNode = document.createElement("script");
          404  +xScriptNode.src = browser.extension.getURL("content_scripts/event.js");
          405  +document.documentElement.appendChild(xScriptNode);
          406  +
          407  +let nMin = Math.ceil(0);
          408  +let nMax = Math.floor(9999999);
          409  +function uniqueID () {
          410  +    return Date.now().toString(36) + "-" + (Math.floor(Math.random() * (nMax - nMin)) + nMin).toString(36);
          411  +}
          412  +
          413  +// ! Écoute des messages venant du script injecté
          414  +document.addEventListener("GrammalecteEvent", function (event) {
          415  +    let oActionFromPage = JSON.parse(event.detail);
          416  +    //console.log(event);
          417  +    let sText = false;
          418  +    let dInfo = {};
          419  +    let xNodeToParse = null;
          420  +
          421  +    if (oActionFromPage.iframe) {
          422  +        xNodeToParse = document.getElementById(oActionFromPage.iframe).contentWindow.document.body;
          423  +    }
          424  +    if (oActionFromPage.elm) {
          425  +        xNodeToParse = document.getElementById(oActionFromPage.elm);
          426  +        sText = xNodeToParse.tagName == "TEXTAREA" ? xNodeToParse.value : xNodeToParse.innerText;
          427  +        dInfo = { sTextAreaId: xNodeToParse.id };
          428  +    }
          429  +    if (oActionFromPage.sTextToParse) {
          430  +        oGrammalecte.startGCPanel(xNodeToParse);
          431  +        xGrammalectePort.postMessage({
          432  +            sCommand: "parseAndSpellcheck",
          433  +            dParam: { sText: sText || oActionFromPage.sTextToParse, sCountry: "FR", bDebug: false, bContext: false },
          434  +            dInfo: dInfo
          435  +        });
          436  +    }
          437  +    if (oActionFromPage.sTextForLexicographer) {
          438  +        oGrammalecte.startLxgPanel();
          439  +        xGrammalectePort.postMessage({
          440  +            sCommand: "getListOfTokens",
          441  +            dParam: { sText: sText || oActionFromPage.sTextForLexicographer },
          442  +            dInfo: dInfo
          443  +        });
          444  +    }
          445  +});
          446  +
          447  +let bInjectedScriptReady = false;
          448  +let lBufferMsg = [];
          449  +
          450  +// ! Permet d’envoyer des messages vers le script injecté
          451  +// (peut aussi être lu par un script sur la page web)
          452  +function sendToWebpage (oDataAction) {
          453  +    let oDataToSend = oDataAction;
          454  +    if (typeof oDataToSend.sActionId === "undefined") {
          455  +        oDataToSend.sActionId = uniqueID();
          456  +    }
          457  +    if (oDataAction.elm) {
          458  +        if (!oDataAction.elm.id) {
          459  +            oDataAction.elm.id = uniqueID();
          460  +        }
          461  +        oDataToSend.elm = oDataAction.elm.id;
          462  +    }
          463  +
          464  +    if (!bInjectedScriptReady) {
          465  +        lBufferMsg.push(oDataToSend);
          466  +    } else {
          467  +        //console.log('sendToWebpage', oDataToSend);
          468  +        let eventGrammalecte = new CustomEvent("GrammalecteToPage", { detail: JSON.stringify(oDataToSend) });
          469  +        document.dispatchEvent(eventGrammalecte);
          470  +    }
          471  +
          472  +    return oDataToSend.sActionId;
          473  +}
          474  +
          475  +// ! Les messages ne peuvent être envoyés qu’après l’injection du script
          476  +document.addEventListener("GLInjectedScriptIsReady", function () {
          477  +    //console.log("GLInjectedScriptIsReady EXT");
          478  +    bInjectedScriptReady = true;
          479  +    if (lBufferMsg.length > 0) {
          480  +        for (const oDataToSend of lBufferMsg) {
          481  +            let eventGrammalecte = new CustomEvent("GrammalecteToPage", { detail: JSON.stringify(oDataToSend) });
          482  +            document.dispatchEvent(eventGrammalecte);
          483  +        }
          484  +    }
          485  +});
          486  +
          487  +sendToWebpage({ init: browser.extension.getURL("") });

Modified gc_lang/fr/webext/manifest.json from [756d794e19] to [6f106795b7].

   110    110       "grammalecte/graphspell/_dictionaries/fr-allvars.json",
   111    111       "grammalecte/graphspell/_dictionaries/fr-classic.json",
   112    112       "grammalecte/graphspell/_dictionaries/fr-reform.json",
   113    113       "grammalecte/fr/conj_data.json",
   114    114       "grammalecte/fr/mfsp_data.json",
   115    115       "grammalecte/fr/phonet_data.json",
   116    116       "grammalecte/fr/tests_data.json",
          117  +    "content_scripts/event.js",
   117    118       "img/logo-16.png"
   118    119     ],
   119    120   
   120    121     "permissions": [
   121    122       "activeTab",
   122    123       "contextMenus",
   123    124       "downloads",