Grammalecte  Changes On Branch 29423db53a79922a

Changes In Branch FixWebext Through [29423db53a] Excluding Merge-Ins

This is equivalent to a diff from a6d823b2a6 to 29423db53a

2017-10-28
10:04
[fx] NFC normalization Closed-Leaf check-in: c8646cd128 user: olr tags: fx, FixWebext
09:47
[doc] update build.md check-in: 29423db53a user: olr tags: doc, FixWebext
09:19
Ajustement de la condition dans le MutationObserver check-in: 40768b2313 user: IllusionPerdu tags: FixWebext
00:16
Ajout de MutationObserver, ajout dans le css et isolation du xNode du menu (tester uniquement sur Chrome check-in: c422898599 user: IllusionPerdu tags: fx, FixWebext
2017-10-27
21:46
[fr] phonet_simil: handicap/handicape check-in: 00a95e2427 user: olr tags: trunk, fr
20:41
[fx] use a debug profile for Firefox check-in: a6d823b2a6 user: olr tags: trunk, fx
19:32
[fx][bug] retrieving text content from node check-in: e1ac68ef1a user: olr tags: trunk, fx

Modified doc/build.md from [28ea36b703] to [a9bb1bbf94].

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18









-
+
+








# How to build Grammalecte

## Required ##

* Python 3.6
* Firefox Nightly
* NodeJS
  * npm
  * jpm
  * jpm : https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm
  * web-ext : https://developer.mozilla.org/fr/Add-ons/WebExtensions/Getting_started_with_web-ext
* Thunderbird


## Commands ##

**Build a language**

Modified gc_lang/fr/build.py from [e6bfac7235] to [d4197caf3b].

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# Builder for French language

import os
import zipfile
from distutils import dir_util, file_util

import helpers


def build (sLang, dVars, spLangPack):
    "complementary build launched from make.py"
    createFirefoxExtension(sLang, dVars)
    #createFirefoxExtension(sLang, dVars)
    createWebExtension(sLang, dVars)
    createThunderbirdExtension(sLang, dVars, spLangPack)


def createWebExtension (sLang, dVars):
    "create Web-extension"
    print("Building WebExtension")

Modified gc_lang/fr/webext/content_scripts/init.js from [08d2b10057] to [8fdfb151d0].

47
48
49
50
51
52
53


54
55
56
57
58
59
60
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62







+
+







    oTFPanel: null,
    oLxgPanel: null,
    oGCPanel: null,

    oMessageBox: null,

    xRightClickedNode: null,

    xObserver: 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);
87
88
89
90
91
92
93

























94
95
96
97
98
99
100
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







                for (let xNode of document.querySelectorAll("[contenteditable]")) {
                    this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
                    this.nMenu += 1;
                }
            }
        }
    },

    observePage: function () {
        /*
            When a textarea is added via jascript we add the menu :)
        */
        this.xObserver = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                for (let i = 0;  i < mutation.addedNodes.length;  i++){
                    if (mutation.addedNodes[i].tagName == "TEXTAREA") {
                        oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, mutation.addedNodes[i]));
                        oGrammalecte.nMenu += 1;
                    } else if (mutation.addedNodes[i].getElementsByTagName) {
                        for (let xNode of mutation.addedNodes[i].getElementsByTagName("textarea")) {
                            oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
                            oGrammalecte.nMenu += 1;
                        }
                    }
                }
            });
        });
        this.xObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    },

    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();
294
295
296
297
298
299
300

321
322
323
324
325
326
327
328







+


/*
    Start
*/
oGrammalecte.listenRightClick();
oGrammalecte.createMenus();
oGrammalecte.observePage();

Modified gc_lang/fr/webext/content_scripts/menu.css from [2b784470a7] to [6ef7f32071].

1
2
3
4
5
6
7
8
9
10

11
12
13
14


15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20
21
22










+


-
-
+
+







/*
    CSS
    Button and menu for Grammalecte
*/

/*
    Button
*/
.grammalecte_menu_main_button {
    position: absolute;
    box-sizing: border-box;
    display: none;
    margin: -8px 0 0 -8px;
    width: 8px;
    height: 8px;
    width: 16px;
    height: 16px;
    background-color: hsla(210, 80%, 80%, .5);
    border: 4px solid hsla(210, 80%, 60%, .5);
    border-top: 4px solid hsla(210, 100%, 40%, .7);
    border-bottom: 4px solid hsla(210, 100%, 40%, .7);
    border-radius: 50%;
    text-align: center;
    cursor: pointer;
59
60
61
62
63
64
65








66
67
68
69
70
71
72
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81







+
+
+
+
+
+
+
+







    margin-left: -10px;
    border-radius: 5px;
    border: 3px solid hsl(210, 50%, 30%);
    box-shadow: 0px 0px 2px hsla(210, 10%, 10%, .5);
    background-color: hsl(210, 50%, 30%);
    font-family: "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
    z-index: 2147483640; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */
    text-align: left;
}

.grammalecte_menu > div {
    line-height: 21px;
}
.grammalecte_menu > div.grammalecte_menu_close_button {
    line-height: 18px;
}

.grammalecte_menu_close_button {
    float: right;
    margin: 2px 2px 0 0;
    padding: 1px 5px;
    border-radius: 2px;

Modified gc_lang/fr/webext/content_scripts/menu.js from [2428c12fef] to [687c841278].

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16













17
18
19

20

21
22
23
24


25
26
27

28
29

30
31




32

33
34
35
36




37
38
39
40

41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59


60
61
62
63
64
65
66
67
68

69
70
71
72


73
74
75
76
77
78
79
1
2
3
4
5
6
7
8
9
10
11
12
13




14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33


34
35
36
37

38
39

40
41
42
43
44
45
46

47
48
49
50

51
52
53
54
55
56
57

58
59
60
61
62

63
64
65
66
67
68
69
70
71

72
73
74


75
76
77
78
79
80
81
82
83


84
85
86


87
88
89
90
91
92
93
94
95








+




-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

+


-
-
+
+


-
+

-
+


+
+
+
+
-
+



-
+
+
+
+



-
+




-
+








-



-
-
+
+







-
-
+


-
-
+
+







// JavaScript

"use strict";


class GrammalecteMenu {

    constructor (nMenu, xNode) {
        this.xNode = xNode;
        this.sMenuId = "grammalecte_menu" + nMenu;
        this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
        this.xButton.onclick = () => { this.switchMenu(); };
        this.xButton.style.zIndex = (xNode.style.zIndex.search(/^[0-9]+$/) !== -1) ? (parseInt(xNode.style.zIndex) + 1).toString() : xNode.style.zIndex;
        this.xMenu = this._createMenu(xNode);
        this._insertAfter(this.xButton, xNode);
        this._insertAfter(this.xMenu, xNode);
        this._createListenersOnReferenceNode(xNode);
        this.xMenu = this._createMenu();

        let xStyle = window.getComputedStyle(this.xNode);
        let nMarginTop = -1 * (8 + parseInt(xStyle.marginBottom.replace('px', ''), 10));

        let xNodeInsertAfter = this.xNode;
        if (document.location.host == "twitter.com" && this.xNode.classList.contains('rich-editor')) {
            xNodeInsertAfter = this.xNode.parentNode;
        }

        this._insertAfter(this.xButton, xNodeInsertAfter, nMarginTop);
        this._insertAfter(this.xMenu, xNodeInsertAfter, nMarginTop + 8);
        this._createListeners();
    }

    _insertAfter (xNewNode, xReferenceNode) {
    _insertAfter (xNewNode, xReferenceNode, nMarginTop) {
        xReferenceNode.parentNode.insertBefore(xNewNode, xReferenceNode.nextSibling);
        xNewNode.style.marginTop = nMarginTop + "px";
    }

    _createListenersOnReferenceNode (xNode) {
        xNode.addEventListener('focus', (e) => {
    _createListeners () {
        this.xNode.addEventListener('focus', (e) => {
            this.xButton.style.display = "block";
        });
        xNode.addEventListener('blur', (e) => {
        /*this.xNode.addEventListener('blur', (e) => {
            window.setTimeout(() => {this.xButton.style.display = "none";}, 300);
        });
        });*/
    }

    _getText () {
        return (this.xNode.tagName == "TEXTAREA") ? this.xNode.value : this.xNode.innerText;
    }

    _createMenu (xNode) {
    _createMenu () {
        try {
            let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"});
            let xCloseButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_close_button", textContent: "×"} );
            xCloseButton.onclick = () => { this.switchMenu(); }
            xCloseButton.onclick = () => {
                this.xButton.style.display = "none";
                this.switchMenu();
            }
            xMenu.appendChild(xCloseButton);
            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
            // Text formatter
            if (xNode.tagName == "TEXTAREA") {
            if (this.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.start(this.xNode);
                    oGrammalecte.oTFPanel.show();
                };
                xMenu.appendChild(xTFButton);
            }
            // lexicographe
            let xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"});
            xLxgButton.onclick = () => {
                this.switchMenu();
                let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.innerText;
                oGrammalecte.startLxgPanel();
                xGrammalectePort.postMessage({
                    sCommand: "getListOfTokens",
                    dParam: {sText: sText},
                    dInfo: {sTextAreaId: xNode.id}
                    dParam: {sText: this._getText()},
                    dInfo: {sTextAreaId: this.xNode.id}
                });
            };
            xMenu.appendChild(xLxgButton);
            // Grammar checker
            let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"});
            xGCButton.onclick = () => {
                this.switchMenu();
                let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.innerText;
                oGrammalecte.startGCPanel(xNode);
                oGrammalecte.startGCPanel(this.xNode);
                xGrammalectePort.postMessage({
                    sCommand: "parseAndSpellcheck",
                    dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false},
                    dInfo: {sTextAreaId: xNode.id}
                    dParam: {sText: this._getText(), sCountry: "FR", bDebug: false, bContext: false},
                    dInfo: {sTextAreaId: this.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 = () => {

Modified make.py from [1769780386] to [ccd63c6d40].

284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298







-
+







    xParser.add_argument("-bb", "--build_data_before", help="launch build_data.py (only part 1: before dictionary building)", action="store_true")
    xParser.add_argument("-ba", "--build_data_after", help="launch build_data.py (only part 2: before dictionary building)", action="store_true")
    xParser.add_argument("-d", "--dict", help="generate FSA dictionary", action="store_true")
    xParser.add_argument("-t", "--tests", help="run unit tests", action="store_true")
    xParser.add_argument("-p", "--perf", help="run performance tests", action="store_true")
    xParser.add_argument("-pm", "--perf_memo", help="run performance tests and store results in perf_memo.txt", action="store_true")
    xParser.add_argument("-js", "--javascript", help="JavaScript build for Firefox", action="store_true")
    xParser.add_argument("-fx", "--firefox", help="Launch Firefox Developper for Adden-SDK testing", action="store_true")
    xParser.add_argument("-fx", "--firefox", help="Launch Firefox Nightly for WebExtension testing", action="store_true")
    xParser.add_argument("-we", "--web_ext", help="Launch Firefox Nightly for WebExtension testing", action="store_true")
    xParser.add_argument("-tb", "--thunderbird", help="Launch Thunderbird", action="store_true")
    xParser.add_argument("-i", "--install", help="install the extension in Writer (path of unopkg must be set in config.ini)", action="store_true")
    xArgs = xParser.parse_args()

    if xArgs.build_data:
        xArgs.build_data_before = True
345
346
347
348
349
350
351
352


353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368
369
370
345
346
347
348
349
350
351

352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368
369
370
371







-
+
+




-
+













                        xTestSuite = unittest.TestLoader().loadTestsFromModule(tests)
                        unittest.TextTestRunner().run(xTestSuite)
                    if xArgs.perf or xArgs.perf_memo:
                        hDst = open("./gc_lang/"+sLang+"/perf_memo.txt", "a", encoding="utf-8", newline="\n")  if xArgs.perf_memo  else None
                        tests.perf(sVersion, hDst)

            # Firefox
            if xArgs.firefox:
            if False:
                # obsolete
                with helpers.cd("_build/xpi/"+sLang):
                    spfFirefox = dVars['win_fx_dev_path']  if platform.system() == "Windows"  else dVars['linux_fx_dev_path']
                    os.system('jpm run -b "' + spfFirefox + '"')

            if xArgs.web_ext:
            if xArgs.web_ext or xArgs.firefox:
                with helpers.cd("_build/webext/"+sLang):
                    spfFirefox = dVars['win_fx_nightly_path']  if platform.system() == "Windows"  else dVars['linux_fx_nightly_path']
                    os.system(r'web-ext run --firefox="' + spfFirefox + '" --browser-console --firefox-profile=debug')            

            # Thunderbird
            if xArgs.thunderbird:
                os.system("thunderbird -jsconsole -P debug")
        else:
            print("Folder not found: gc_lang/"+sLang)


if __name__ == '__main__':
    main()