Grammalecte  Check-in [d25e2ed843]

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | webext3
Files: files | file ages | folders
SHA3-256: d25e2ed84318d554b60ac63f2db73ca9518e6c773461fcc2e49a215a140febc7
User & Date: olr on 2017-10-10 14:30:43
Other Links: branch diff | manifest | tags
Context
2017-10-10
14:32
[fx] WebExt: only one cycle of animation check-in: 377c798a39 user: olr tags: fx, webext3
14:30
merge trunk check-in: d25e2ed843 user: olr tags: webext3
13:40
[fr][js] suggestion des graphies similaires check-in: 6ff5d2733a user: olr tags: trunk, fr
2017-09-22
09:31
[fx] button and menu for editable content check-in: e6dcf47f18 user: olr tags: webext3
Changes

Modified gc_core/js/helpers.js from [f725b5eed7] to [b352512c63].

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
70
71
72
73
74
75
76

77
78
79
80
81
82
83







-







        }
    },

    // conversions
    objectToMap: function (obj) {
        let m = new Map();
        for (let param in obj) {
            //console.log(param + " " + obj[param]);
            m.set(param, obj[param]);
        }
        return m;
    },

    mapToObject: function (m) {
        let obj = {};

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

29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+







def _createOptionsForWebExtension (dVars):
    sHTML = ""
    sLang = dVars['sDefaultUILang']
    for sSection, lOpt in dVars['lStructOpt']:
        sHTML += f'\n<div id="subsection_{sSection}" class="opt_subsection">\n  <h2 data-l10n-id="option_{sSection}">{dVars["dOptLabel"][sLang][sSection][0]}</h2>\n'
        for lLineOpt in lOpt:
            for sOpt in lLineOpt:
                sHTML += f'  <p><input type="checkbox" id="option_{sOpt}" data-option="{sOpt}"/><label id="option_label_{sOpt}" for="option_{sOpt}" data-l10n-id="option_{sOpt}">{dVars["dOptLabel"][sLang][sOpt][0]}</label></p>\n'
                sHTML += f'  <p><input type="checkbox" id="option_{sOpt}" class="gc_option" data-option="{sOpt}"/><label id="option_label_{sOpt}" for="option_{sOpt}" data-l10n-id="option_{sOpt}">{dVars["dOptLabel"][sLang][sOpt][0]}</label></p>\n'
        sHTML += '</div>\n'
    return sHTML


def createFirefoxExtension (sLang, dVars):
    "create extension for Firefox"
    print("Building extension for Firefox")

Modified gc_lang/fr/data/phonet_simil.txt from [b43ee621d4] to [f34a08f94e].

629
630
631
632
633
634
635

636
637
638
639
640
641
642
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643







+







recueil recueils recueille recueilles recueillent
recul reculs recule recules reculent
reflux reflue reflues refluent
régal régals régale régale régalent
reine reines renne rennes rêne rênes
relai relais relaie relaies relaient relaye relayes relayent
remblai remblais remblaie remblaies remblaient
remord remords
renvoi renvois renvoie renvoies renvoient
repaire repaires repère repères repèrent reperds reperd
repli replis replie replies replient
ressenti ressentis ressentit
resserre resserres resserrent ressers ressert
ressors ressort ressorts
résidant résident résidents

Modified gc_lang/fr/modules-js/conj.js from [fdb0ca6eac] to [20daa8dfaa].

79
80
81
82
83
84
85
86

87
88
89
90
91
92
93

94
95
96
97
98
99
100
79
80
81
82
83
84
85

86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+






-
+







        // returns raw informations about sVerb
        if (!this._dVerb.hasOwnProperty(sVerb)) {
            return null;
        }
        return this._lVtyp[this._dVerb[sVerb][0]];
    },

    getSimil: function (sWord, sMorph, sFilter=null) {
    getSimil: function (sWord, sMorph, bSubst=false) {
        if (!sMorph.includes(":V")) {
            return new Set();
        }
        let sInfi = sMorph.slice(1, sMorph.indexOf(" "));
        let tTags = this._getTags(sInfi);
        let aSugg = new Set();
        if (sMorph.includes(":Q") || sMorph.includes(":Y")) {
        if (!bSubst) {
            // we suggest conjugated forms
            if (sMorph.includes(":V1")) {
                aSugg.add(sInfi);
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":3s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":2p"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Iq", ":1s"));
                aSugg.add(this._getConjWithTags(sInfi, tTags, ":Iq", ":3s"));
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
122
123
124
125
126
127
128



129
130
131
132
133
134
135







-
-
-







            aSugg.add(this._getConjWithTags(sInfi, tTags, ":PQ", ":Q3"));
            aSugg.add(this._getConjWithTags(sInfi, tTags, ":PQ", ":Q4"));
            aSugg.delete("");
            // if there is only one past participle (epi inv), unreliable.
            if (aSugg.size === 1) {
                aSugg.clear();
            }
            if (sMorph.includes(":V1")) {
                aSugg.add(sInfi);
            }
        }
        return aSugg;
    },

    _getTags: function (sVerb) {
        // returns tuple of tags (usable with functions _getConjWithTags and _hasConjWithTags)
        if (!this._dVerb.hasOwnProperty(sVerb)) {
483
484
485
486
487
488
489
490

491



492
493
494
495

496
497
498
499
500
501
502
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502







-
+

+
+
+



-
+







        return (this.dConj.get(":PQ").get(":Q4")) ? this.dConj.get(":PQ").get(":Q4") : this.dConj.get(":PQ").get(":Q1");
    }
}


// Initialization
if (!conj.bInit && typeof(browser) !== 'undefined') {
    // WebExtension (but not in Worker)
    // WebExtension Standard (but not in Worker)
    conj.init(helpers.loadFile(browser.extension.getURL("grammalecte/fr/conj_data.json")));
} else if (!conj.bInit && typeof(chrome) !== 'undefined') {
    // WebExtension Chrome (but not in Worker)
    conj.init(helpers.loadFile(chrome.extension.getURL("grammalecte/fr/conj_data.json")));
} else if (!conj.bInit && typeof(require) !== 'undefined') {
    // Add-on SDK and Thunderbird
    conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
} else if ( !conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") {
} else if (!conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") {
    // used within Firefox content script (conjugation panel).
    // can’t load JSON from here, so we do it in ui.js and send it here.
    self.port.on("provideConjData", function (sJSONData) {
        conj.init(sJSONData);
    });    
} else if (conj.bInit){
    console.log("Module conj déjà initialisé");

Modified gc_lang/fr/modules-js/gce_suggestions.js from [0d3c06e52f] to [a844f36535].

486
487
488
489
490
491
492
493

494
495
496
497
498


499
500
501
502
503
504
505
486
487
488
489
490
491
492

493
494
495
496


497
498
499
500
501
502
503
504
505







-
+



-
-
+
+







    return "";
}

function hasSimil (sWord, sPattern=null) {
    return phonet.hasSimil(sWord, sPattern);
}

function suggSimil (sWord, sPattern) {
function suggSimil (sWord, sPattern=null, bSubst=false) {
    // return list of words phonetically similar to sWord and whom POS is matching sPattern
    let aSugg = phonet.selectSimil(sWord, sPattern);
    for (let sMorph of _dAnalyses.gl_get(sWord, [])) {
        for (let e of conj.getSimil(sWord, sMorph, sPattern)) {
            aSugg.add(e); 
        for (let e of conj.getSimil(sWord, sMorph, bSubst)) {
            aSugg.add(e);
        }
    }
    if (aSugg.size > 0) {
        return Array.from(aSugg).join("|");
    }
    return "";
}

Modified gc_lang/fr/modules-js/phonet.js from [b4e35b2c18] to [409fa52cbe].

62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76







-
+







                return this._lSet[this._dWord.get(sWord)];
            }
        }
        return [];
    },

    selectSimil: function (sWord, sPattern) {
        // return list of words phonetically similar to sWord and whom POS is matching sPattern
        // return a set of words phonetically similar to sWord and whom POS is matching sPattern
        if (!sPattern) {
            return new Set(this.getSimil(sWord));
        }
        let aSelect = new Set();
        for (let sSimil of this.getSimil(sWord)) {
            for (let sMorph of this._dMorph.gl_get(sSimil, [])) {
                if (sMorph.search(sPattern) >= 0) {

Modified gc_lang/fr/modules/conj.py from [ec8e754549] to [99ba236032].

51
52
53
54
55
56
57
58

59
60
61
62
63
64


65
66
67
68
69
70
71
51
52
53
54
55
56
57

58
59
60
61
62
63

64
65
66
67
68
69
70
71
72







-
+





-
+
+







def getVtyp (sVerb):
    "returns raw informations about sVerb"
    if sVerb not in _dVerb:
        return None
    return _lVtyp[_dVerb[sVerb][0]]


def getSimil (sWord, sMorph, sFilter=None):
def getSimil (sWord, sMorph, bSubst=False):
    if ":V" not in sMorph:
        return set()
    sInfi = sMorph[1:sMorph.find(" ")]
    tTags = _getTags(sInfi)
    aSugg = set()
    if ":Q" in sMorph or ":Y" in sMorph:
    #if ":Q" in sMorph or ":Y" in sMorph:
    if not bSubst:
        # we suggest conjugated forms
        if ":V1" in sMorph:
            aSugg.add(sInfi)
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":1s"))
            aSugg.add(_getConjWithTags(sInfi, tTags, ":Iq", ":3s"))
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
92
93
94
95
96
97
98


99
100
101
102
103
104
105







-
-







        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q2"))
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q3"))
        aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4"))
        aSugg.discard("")
        # if there is only one past participle (epi inv), unreliable.
        if len(aSugg) == 1:
            aSugg.clear()
        if ":V1" in sMorph:
            aSugg.add(sInfi)
    return aSugg


def getConjSimilInfiV1 (sInfi):
    if sInfi not in _dVerb:
        return set()
    tTags = _getTags(sInfi)

Modified gc_lang/fr/modules/gce_suggestions.py from [e839f7efe5] to [37d0c398ac].

369
370
371
372
373
374
375
376

377
378
379
380
381
382


383
384
385
386
387
388
389
390
369
370
371
372
373
374
375

376
377
378
379
380


381
382

383
384
385
386
387
388
389







-
+




-
-
+
+
-







    return ""


def hasSimil (sWord, sPattern=None):
    return phonet.hasSimil(sWord, sPattern)


def suggSimil (sWord, sPattern=None):
def suggSimil (sWord, sPattern=None, bSubst=False):
    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
    # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before
    aSugg = phonet.selectSimil(sWord, sPattern)
    for sMorph in _dAnalyses.get(sWord, []):
        for e in conj.getSimil(sWord, sMorph, sPattern):
            aSugg.add(e)
        aSugg.update(conj.getSimil(sWord, sMorph, bSubst))
        break
        #aSugg = aSugg.union(conj.getSimil(sWord, sMorph))
    if aSugg:
        return "|".join(aSugg)
    return ""


def suggCeOrCet (sWord):
    if re.match("(?i)[aeéèêiouyâîï]", sWord):

Modified gc_lang/fr/modules/phonet.py from [d03956eafb] to [cc107e0763].

35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50







-
+








        sWord = sWord.lower()
        if sWord in _dWord:
            return _lSet[_dWord[sWord]]
    return []


def selectSimil (sWord, sPattern):
    "return list of words phonetically similar to sWord and whom POS is matching sPattern"
    "return a set of words phonetically similar to sWord and whom POS is matching sPattern"
    if not sPattern:
        return set(getSimil(sWord))
    aSelect = set()
    for sSimil in getSimil(sWord):
        for sMorph in _dMorph.get(sSimil, []):
            if re.search(sPattern, sMorph):
                aSelect.add(sSimil)
    return aSelect

Modified gc_lang/fr/oxt/TextFormatter/tf_tabrep.py from [89da85a6c2] to [63ab70d6b7].

368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382







-
+







                    ("(?<=\\b[0-9][0-9])(i?[èe]me|è|ᵉ)\\b",                     "e",    True, False),
                    ("(?<=\\b[0-9])(i?[èe]me|è|ᵉ)\\b",                          "e",    True, False),
                    ("(?<=\\b[XVICL][XVICL][XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b",   "e",    True, True),
                    ("(?<=\\b[XVICL][XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b",          "e",    True, True),
                    ("(?<=\\b[XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b",                 "e",    True, True),
                    ("(?<=\\b[XVICL])(i?[èe]me|è|ᵉ)\\b",                        "e",    True, True),
                    ("(?<=\\b[1I])ᵉʳ\\b",                                       "er",   True, True),
                    ("(?<=\\b[1I])ʳᵉ\\b",                                       "er",   True, True)
                    ("(?<=\\b[1I])ʳᵉ\\b",                                       "re",   True, True)
    ],
    "misc2": [
                    ("etc(…|[.][.][.]?)",                       "etc.",         True,   True),
                    ("(?<!,) etc[.]",                           ", etc.",       True,   True)
    ],
    "misc3": [
                    ("[ -]t[’'](?=il\\b|elle|on\\b)",           "-t-",          True,   True),

Modified gc_lang/fr/rules.grx from [27c994bd63] to [56d33d66c8].

2501
2502
2503
2504
2505
2506
2507
2508

2509
2510
2511

2512
2513
2514
2515
2516
2517
2518
2519
2520
2521

2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534

2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546


2547
2548
2549
2550
2551
2552
2553
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510

2511
2512
2513
2514
2515
2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544


2545
2546
2547
2548
2549
2550
2551
2552
2553







-
+


-
+









-
+












-
+










-
-
+
+








TEST: Ce que tu ne fais {{pas jamais}}.


### incohérences globales (attention à la casse du 2e mot, car beaucoup de sigles peuvent tromper)
__[s](incohérences_globales1)__
    ([clmtsCLMTS]es|[nvNV]os) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on)  @@0,$
    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]")         # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]", True)                                                   # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
__[s](incohérences_globales2)__
    ([cC]e(?:tte|t|)|[mtsMTS]a|[mM]on) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on)  @@0,$
    <<- -2>> =suggSimil(\2, ":[NA].*:[si]")         # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- -2>> =suggSimil(\2, ":[NA].*:[si]", True)                                                   # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.

TEST: {{Ces}} {{cette}} canaille qui nous a donné tant de fil à retordre.
TEST: Mon {{il}} est une merveille.


__[s](incohérence_globale_au_qqch)__
    ([aA]u) ({w2})  @@0,$
    <<- not \2.isupper() >>>
    <<- morph(\2, ">(?:[cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on|parce) ", False)
    -2>> =suggSimil(\2, ":[NA].*:[si]")                                                             # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    -2>> =suggSimil(\2, ":[NA].*:[si]", True)                                                       # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- __else__ and morph(\2, ">quelle ", False) ->> auquel|auxquels|auxquelles                    # Incohérence. Soudez les deux mots.|https://fr.wiktionary.org/wiki/auquel
    <<- __else__ and \2 == "combien" and morph(word(1), ":[AY]", False) -1>> ô                      # Incohérence probable.|https://fr.wiktionary.org/wiki/%C3%B4_combien

TEST: au {{nos}} enfants.
TEST: {{Au quel}} faut-il s’adresser ?
TEST: Au MES, rien de nouveau.


__[s](incohérence_globale_aux_qqch)__
    ([aA]ux) ({w2})  @@0,$
    <<- not \2.isupper() >>>
    <<- morph(\2, ">(?:[cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on|parce) ", False)
    -2>> =suggSimil(\2, ":[NA].*:[pi]")                                                             # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    -2>> =suggSimil(\2, ":[NA].*:[pi]", True)                                                       # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- __else__ and morph(\2, ">quelle ", False) ->> auxquels|auxquelles                           # Incohérence. Soudez les deux mots.|https://fr.wiktionary.org/wiki/auquel
    <<- __else__ and \2 == "combien" and morph(word(1), ":[AY]", False) -1>> ô                      # Incohérence probable.|https://fr.wiktionary.org/wiki/%C3%B4_combien

TEST: ils jouent aux {{des}}.
TEST: {{Aux quels}} a-t-il adressé sa requête. ?
TEST: Des individus {{aux}} combien sensibles aux usages.


__[s](incohérences_globales3)__
    ([dD]es) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on)  @@0,$
    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]")         # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- -1>> de                                     # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- -2>> =suggSimil(\2, ":[NA].*:[pi]", True)                                                   # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.
    <<- -1>> de                                                                                     # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder.

TEST: je ne sais {{des}} {{ses}} choses.



!!
!!
2863
2864
2865
2866
2867
2868
2869
2870

2871
2872
2873
2874
2875
2876
2877
2878

2879
2880
2881
2882
2883
2884
2885
2886
2887
2888

2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903

2904
2905
2906
2907
2908
2909
2910
2911

2912
2913
2914
2915
2916
2917
2918
2919

2920
2921
2922
2923
2924
2925
2926
2927
2928

2929
2930
2931
2932
2933
2934
2935
2936

2937
2938
2939
2940
2941
2942
2943
2944

2945
2946
2947
2948
2949
2950
2951
2952

2953
2954
2955
2956
2957
2958
2959

2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
2979

2980
2981
2982
2983
2984
2985
2986
2987

2988
2989
2990
2991
2992
2993
2994

2995
2996
2997
2998
2999
3000
3001
3002
3003

3004
3005
3006
3007
3008
3009
3010
3011
3012
3013

3014
3015
3016
3017
3018
3019
3020
3021

3022
3023
3024
3025
3026
3027
3028
3029
3030

3031
3032
3033
3034
3035
3036
3037
3038

3039
3040
3041
3042
3043
3044
3045
2863
2864
2865
2866
2867
2868
2869

2870
2871
2872
2873
2874
2875
2876
2877

2878
2879
2880
2881
2882
2883
2884
2885
2886
2887

2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902

2903
2904
2905
2906
2907
2908
2909
2910

2911
2912
2913
2914
2915
2916
2917
2918

2919
2920
2921
2922
2923
2924
2925
2926
2927

2928
2929
2930
2931
2932
2933
2934
2935

2936
2937
2938
2939
2940
2941
2942
2943

2944
2945
2946
2947
2948
2949
2950
2951

2952
2953
2954
2955
2956
2957
2958

2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970

2971
2972
2973
2974
2975
2976
2977
2978

2979
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990
2991
2992
2993

2994
2995
2996
2997
2998
2999
3000
3001
3002

3003
3004
3005
3006
3007
3008
3009
3010
3011
3012

3013
3014
3015
3016
3017
3018
3019
3020

3021
3022
3023
3024
3025
3026
3027
3028
3029

3030
3031
3032
3033
3034
3035
3036
3037

3038
3039
3040
3041
3042
3043
3044
3045







-
+







-
+









-
+














-
+







-
+







-
+








-
+







-
+







-
+







-
+






-
+











-
+







-
+







-
+






-
+








-
+









-
+







-
+








-
+







-
+








TEST: {{en t’}}ait donné tant.                          ->> "t’en "
TEST: {{en n’}}{{envoient}} que peu.


__[i]/conf(conf_malgré_le_la_les)__
    malgré l(?:es? +|a +|’)({w_3})  @@$
    <<- morphex(\1, ":", ":[GNAWM]") -1>> =suggSimil(\1, ":[NA]")                                   # Incohérence : après “malgré”, on devrait trouver un groupe nominal.
    <<- morphex(\1, ":", ":[GNAWM]") -1>> =suggSimil(\1, ":[NA]", True)                             # Incohérence : après “malgré”, on devrait trouver un groupe nominal.

TEST: malgré l’{{arrête}} qui interdisait le port 


__[i]/conf(conf_ma_ta_cette_verbe)__
    ([mt]a|cette) +({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: Cette {{pèle}} est trop fragile.


__[i]/conf(conf_sa_verbe)__
    (sa) ({w_2})  @@0,3
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":N.*:[fe]|:[AW]") and \2[0].islower() or \2 == "va"
    -1>> ça                                                                                         # Confusion : « \2 » est un verbe. Exemples : sa jambe, ça vient.
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and hasSimil(\2)
    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:[fe]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: {{sa}} devient difficile.
TEST: il me tendit {{sa}} {{pèche}}.


__[s]/conf(conf_sa_fin)__
    (sa) *$  @@0  <<- -1>> ça                           # Confusion probable : “sa” est un déterminant féminin singulier. Pour l’équivalent de “cela” ou “ceci”, écrivez :

TEST: Je prends {{sa}}…


__[i]/conf(conf_du_cet_au_verbe)__
    (du|cet|au) +({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and not (\2 == "sortir" and re.search(r"(?i)au", \1))
    -2>> =suggSimil(\2, ":[NA]:[me]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:[me]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: cet {{plaît}} est infectée.


__[i]/conf(conf_ce_verbe)__
    (ce) +(?!faire|peut)({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]:.:[si]|:V0e.*:3[sp]|>devoir") and \2[0].islower() and hasSimil(\2)
    -2>> =suggSimil(\2, ":[NA]:[me]:[si]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:[me]:[si]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: {{ce}} {{rappelle}} n’en finit pas.


__[i]/conf(conf_mon_verbe)__
    (mon) +({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
    -2>> =suggSimil(\2, ":[NA]:.:[si]")                                                             # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:.:[si]", True)                                                       # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: mon {{rackette}} n’a pas porté les fruits espérés.
TEST: Belle qui tient mon vit captif entre tes doigts.


__[i]/conf(conf_ton_son_verbe)__
    [st]on ({w_2})  @@4
    <<- morph(\1, ":V.*:(?:Y|[123][sp])") and \1[0].islower() and isStart()
    -1>> =suggSimil(\1, ":[NA]:[me]:[si]")                                                          # Incohérence : « \1 » est un verbe.
    -1>> =suggSimil(\1, ":[NA]:[me]:[si]", True)                                                    # Incohérence : « \1 » est un verbe.

TEST: ton {{recèle}} a été dévoilé


__[i]/conf(conf_det_plur_verbe)__
    ([dcmts]es|quelques|aux|[nv]os) +({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and not re.search(r"(?i)^quelques? soi(?:ent|t|s)\b", \0)
    -2>> =suggSimil(\2, ":[NA]:.:[pi]")                                                             # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:.:[pi]", True)                                                       # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: la crainte des {{attentas}} fait feu de tout bois.


__[i]/conf(conf_auxdits_verbe)__
    (auxdits) +({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
    -2>> =suggSimil(\2, ":[NA]:[me]:[pi]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:[me]:[pi]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: elle se rendit auxdits {{jardinais}}


__[i]/conf(conf_auxdites_verbe)__
    (auxdites) +({w_2})  @@0,$
    <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower()
    -2>> =suggSimil(\2, ":[NA]:[fe]:[pi]")                                                          # Incohérence avec « \1 » : « \2 » est un verbe.
    -2>> =suggSimil(\2, ":[NA]:[fe]:[pi]", True)                                                    # Incohérence avec « \1 » : « \2 » est un verbe.

TEST: auxdites {{scelles}}, il ne prêta pas attention.


__[i]/conf(conf_de_la_vconj)__  de la ({w_2})  @@6
    <<- morphex(\1, ":[123][sp]", ":[NAQ]")
    -1>> =suggSimil(\1, ":(?:[NA]:[fe]:[si])")                                                      # Incohérence : « \1 » est un verbe.
    -1>> =suggSimil(\1, ":(?:[NA]:[fe]:[si])", True)                                                # Incohérence : « \1 » est un verbe.

TEST: les petits esprits de la {{pensait}} religieuse


TEST: pour les insulter au sortir du seul troquet dispensateur d’oubli liquide du coin
TEST: ce peut être un matériau à part entière pour alimenter discussions et délibérations.


__[i]/conf(conf_de_le_nom_ou_vconj)__
    (de le) ({w_2})  @@0,6
    <<- morphex(\2, ":[NAQ].*:[me]", ":[YG]") and \2[0].islower() -1>> du                           # Incohérence : « \2 » est un nom ou un adjectif.
    <<- morph(\2, ":[123][sp]", False) -2>> =suggSimil(\2, ":Y")                                    # Incohérence : « \2 » est une forme verbale conjuguée.
    <<- morph(\2, ":[123][sp]", False) -2>> =suggVerbInfi(\2)                                       # Incohérence : « \2 » est une forme verbale conjuguée.

TEST: {{de le}} vin                                           ->> du
TEST: il n’est pas interdit de le {{pensait}}


__[i]/conf(conf_de_l_vconj)__
    de l’({w_2})  @@5
    <<- morphex(\1, ":[123][sp]", ":[NAQ]") -1>> =suggSimil(\1, ":(?:[NA]:.:[si])")                 # Incohérence : « \1 » est une forme verbale conjuguée.
    <<- morphex(\1, ":[123][sp]", ":[NAQ]") -1>> =suggSimil(\1, ":[NA]:.:[si]", True)               # Incohérence : « \1 » est une forme verbale conjuguée.

TEST: de l’{{entra}}


__[i]/conf(conf_un_verbe)__
    (?<!’)un ({w_2})  @@3
    <<- morph(\1, ":(?:Y|[123][sp])") and not before("(?i)(?:dont|sauf|un à) +$")
    -1>> =suggSimil(\1, ":[NAQ]:[me]:[si]")                                                         # Incohérence : « \1 » est une forme verbale conjuguée.
    -1>> =suggSimil(\1, ":[NAQ]:[me]:[si]", True)                                                   # Incohérence : « \1 » est une forme verbale conjuguée.

TEST: un {{maintient}} difficile.


__[i]/conf(conf_de_dès_par_vconj)__
    (?:d(?:e|ès)|par) ({w_2})  @@$
    <<- \1[0].islower() and morph(\1, ":V.*:[123][sp]") -1>> =suggSimil(\1, ":[NA]")                # Incohérence : « \1 » est une forme verbale conjuguée.
    <<- \1[0].islower() and morph(\1, ":V.*:[123][sp]") -1>> =suggSimil(\1, ":[NA]", True)          # Incohérence : « \1 » est une forme verbale conjuguée.

TEST: par {{bloque}} de données
TEST: il s’agit de {{mette}} en évidence.


__[i]/conf(conf_d_une_vconj)__
    d’(?:une? +|)({w_2})  @@$
    <<- \1[0].islower() and morphex(\1, ":V.*:[123][sp]", ":[GNA]") and not before(r"(?i)\b(?:plus|moins) +$")
    -1>> =suggSimil(\1, ":[NA]")    # Incohérence : « \1 » est une forme verbale conjuguée.
    -1>> =suggSimil(\1, ":[NA]", True)                                                              # Incohérence : « \1 » est une forme verbale conjuguée.

TEST: d’une {{habille}} femme
TEST: plus d’un ont été traumatisés
TEST: plus d’une sont parties aussi vite qu’elles étaient venues


__[i]/conf(conf_il_on_pas_verbe)__
    (?<!t’)(?:il|on) (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
    <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)|ou ") and morphex(word(-1), ":", ":3s", True)
    -1>> =suggSimil(\1, ":(?:3s|Oo)")                                                               # Incohérence : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
    -1>> =suggSimil(\1, ":(?:3s|Oo)", False)                                                        # Incohérence : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.

TEST: il {{et}} parti.


__[i]/conf(conf_ils_pas_verbe)__
    (?<!t’)ils (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
    <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)|ou ") and morphex(word(-1), ":", ":3p", True)
    -1>> =suggSimil(\1, ":(?:3p|Oo)")                                                               # Incohérence avec « ils » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
    -1>> =suggSimil(\1, ":(?:3p|Oo)", False)                                                        # Incohérence avec « ils » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.

TEST: ils {{son}} du même bois.
TEST: Ils {{étai}} partie au {{restaurent}}


__[i]/conf(conf_je_pas_verbe)__
    je (?!soussigné)(?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
    <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)") and morphex(word(-1), ":", ":1s", True)
    -1>> =suggSimil(\1, ":(?:1s|Oo)")                                                               # Incohérence avec « je » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
    -1>> =suggSimil(\1, ":(?:1s|Oo)", False)                                                        # Incohérence avec « je » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.

TEST: Je {{travail}}.


__[i]/conf(conf_tu_pas_verbe)__
    tu (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$
    <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)") and morphex(word(-1), ":", ":(?:2s|V0e)", True)
    -1>> =suggSimil(\1, ":(?:2s|Oo)")                                                               # Incohérence avec « tu » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.
    -1>> =suggSimil(\1, ":(?:2s|Oo)", False)                                                        # Incohérence avec « tu » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc.

TEST: tu {{croix}} que tu sais quelque chose, mais tu ne sais rien.


TEST: elles seules peuvent s’en sortir.
TEST: elle seule peut y arriver
TEST: elle seules les femmes la font craquer
3062
3063
3064
3065
3066
3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
3062
3063
3064
3065
3066
3067
3068

3069
3070
3071
3072
3073
3074
3075
3076







-
+







#    très +(bien|\w+ent) +({w2})  @@w,$
#    <<- morph(\1, ":W", False) and morphex(\2, ":[123][sp]", ":[GAQW]") -2>> _
#    # Incohérence avec « très » : « \2 » n’est ni un adjectif, ni un participe passé, ni un adverbe.

 
__[i]/conf(conf_très_verbe)__
    très +(?!envie)({w_2})  @@$
    <<- morphex(\1, ":(?:Y|[123][sp])", ":[AQW]") -1>> =suggSimil(\1, ":[AW]")                      # Incohérence avec « très » : « \1 » n’est ni un adjectif, ni un participe passé, ni un adverbe.
    <<- morphex(\1, ":(?:Y|[123][sp])", ":[AQW]") -1>> =suggSimil(\1, ":[AW]", True)                # Incohérence avec « très » : « \1 » n’est ni un adjectif, ni un participe passé, ni un adverbe.

TEST: Il est très {{cite}}.
TEST: très {{suivit}} par ce détective
TEST: il était très {{habille}}


__[i]/conf(conf_trop_vconj)__
3107
3108
3109
3110
3111
3112
3113
3114

3115
3116
3117
3118
3119
3120
3121
3107
3108
3109
3110
3111
3112
3113

3114
3115
3116
3117
3118
3119
3120
3121







-
+








TEST: Toutes les blagues qu’on fera sur {{entreront}} dans l’histoire !


__[i]/conf(conf_si_vconj)__
    si +({w2})  @@$
    <<- morphex(\1, ":[123][sp]", ":[GNAQWMT]") and morphex(word(1), ":", ":D", True)
    -1>> =suggSimil(\1, ":[AWGT]")                                                                  # Incohérence avec « si » : « \1 » ne devrait pas être une forme verbale conjuguée.
    -1>> =suggSimil(\1, ":[AWGT]", True)                                                            # Incohérence avec « si » : « \1 » ne devrait pas être une forme verbale conjuguée.

TEST: Ces gens sont si {{prit}} par leur travail qu’ils en oublient de vivre.
TEST: Ça ira mieux demain, surtout si émerge une demande forte de la part des consommateurs.


__[i]/conf(conf_de_plus_en_plus_verbe)__
    de plus en plus +({w_2})  @@$
3462
3463
3464
3465
3466
3467
3468
3469

3470
3471
3472
3473
3474
3475
3476
3477
3478
3479

3480
3481
3482
3483
3484
3485
3486
3462
3463
3464
3465
3466
3467
3468

3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487







-
+










+







    ([scSC]es) [ld]’(?![A-Z])  @@0
    <<- -1>> c’est                                                                          # Confusion. Écrivez « c’est » pour dire « ceci est… ».
__[s]/conf(conf_c_est3)__
    ([scSC]es) (?:qu(?:lle|el?|)|comme|ce(?:t|tte|)|[nv]os|les?|eux|elles)  @@0
    <<- -1>> c’est                                                                          # Confusion probable. Écrivez « c’est » pour dire « ceci est… ».
__[s]/conf(conf_c_est4)__
    ([scSC]es) ({w_1}) ({w_1}) @@0,w,$
    <<- morph(\2, ":[WX]", False) and morph(\3, ":[RD]|>pire ", False) -1>> c’est           # Confusion probable. Écrivez « c’est » pour dire « ceci est… ».
    <<- morph(\2, ":[WX]", ":N:.*:[pi]") and morph(\3, ":[RD]|>pire ", False) -1>> c’est           # Confusion probable. Écrivez « c’est » pour dire « ceci est… ».
__[i]/conf(conf_ces_ses)__
    (c’est) ({w_2})  @@0,6 <<- morphex(\2, ":N.*:p", ":(?:G|W|M|A.*:[si])") -1>> ces|ses    # Confusion. Exemples : c’est facile ; ces chats (désignation) ; ses chats (possession)…

TEST: {{ses}} au-dessus de ses forces.
TEST: {{ces}} comme la peste
TEST: car {{ses}} d’avance perdu
TEST: {{ces}} qu’il y a tant de pertes
TEST: {{ces}} jamais une bonne idée.
TEST: {{c’est}} {{délires}} nous ennuient
TEST: En 2015, c’est Paris et son agglomération qui…
TEST: Ses pas de danse.


# date / datte
__[i]/conf(conf_date1)__
    dates
    <<- after("(?i)^ +(?:fra[iî]ches|dénoyautées|fourrées|sèches|séchées|cultivées|produites|muscade|medjool|Hamraya|deglet[ -]nour|kenta|allig|khouat)")
    or before(r"(?i)\b(?:confiture|crème|gâteau|mélasse|noyau|pâte|recette|sirop)[sx]? de +$|\b(?:moelleux|gateau|fondant|cake)[sx]? aux +$")
4043
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054

4055
4056
4057
4058

4059
4060
4061
4062

4063
4064
4065
4066
4067

4068
4069
4070
4071

4072
4073
4074
4075

4076
4077
4078
4079

4080
4081
4082
4083

4084
4085
4086
4087
4088
4089
4090
4044
4045
4046
4047
4048
4049
4050

4051
4052
4053
4054

4055
4056
4057
4058

4059
4060
4061
4062

4063
4064
4065
4066
4067

4068
4069
4070
4071

4072
4073
4074
4075

4076
4077
4078
4079

4080
4081
4082
4083

4084
4085
4086
4087
4088
4089
4090
4091







-
+



-
+



-
+



-
+




-
+



-
+



-
+



-
+



-
+







!!
!!
__[i](p_m_enfin)__      m’enfin <<- ~>> *

__[i]/conf(conf_j_y_en_qqch)__
    (j’(?:en +|y +|))({w_1})  @@0,$
    <<- morphex(\2, ":", ":(?:[123][sp]|O[onw])")
    -2>> =suggSimil(\2, ":1s")                                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":1s", False)                                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe.
__[i]/conf(conf_ne_qqch)__
    (n(?:e +|’))({w_1})  @@0,$
    <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)|>(?:[lmtsn]|surtout|guère|presque|même|tout|parfois|vraiment|réellement) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)")                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)", False)                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
__[i]/conf(conf_n_y_en_qqch)__
    (n’(?:en|y)) ({w_1})  @@0,$
    <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
__[i]/conf(conf_ne_pronom_qqch)__
    (ne (?:l(?:es? +|eur +|a +|’)|[nv]ous))({w_1})  @@0,$
    <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
__[i]/conf(conf_me_te_se_qqch)__
    ([mts]e +(?:les? |la |l’|))(?!voi(?:là|ci))({w_1})  @@0,$
    <<- not re.search("(?i)^se que?", \0)
    and morphex(\2, ":", ":(?:[123][sp]|Y|P|Oo)|>[lmts] ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)")                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)", False)                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet.
__[i]/conf(conf_m_t_s_y_en_qqch)__
    ([mts]’(?:en|y)) (?!voilà)({w_1})  @@0,$
    <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|Oo)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
__[i]/conf(conf_m_s_qqch)__
    ([ms]’)({w_1})  @@0,2
    <<- morphex(\2, ":", ":(?:[123][sp]|Y|P)|>(?:en|y|ils?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
__[i]/conf(conf_t_qqch)__
    (t’)({w_1})  @@0,2
    <<- morphex(\2, ":", ":(?:[123][sp]|Y|P)|>(?:en|y|ils?|elles?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2)
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)")                                                         # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False)                                                  # Incohérence avec « \1 » : « \2 » devrait être un verbe.
__[i]/conf(conf_c_ç_qqch)__
    ([cç]’)({w_1})  @@0,2
    <<- morphex(\2, ":", ":[123][sp]|>(?:en|y|que?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|dire)$", \2)
    -2>> =suggSimil(\2, ":3s")                                                                      # Incohérence avec « \1 » : « \2 » devrait être un verbe.
    -2>> =suggSimil(\2, ":3s", False)                                                               # Incohérence avec « \1 » : « \2 » devrait être un verbe.

TEST: ne l’{{oubli}} pas
TEST: elle ne la {{croix}} pas
TEST: ils me les {{laissés}}.
TEST: ne {{pensée}} rien, jamais
TEST: n’en {{laissée}} que des miettes
TEST: s’y {{intéressé}}
4740
4741
4742
4743
4744
4745
4746

4747
4748
4749
4750
4751
4752
4753
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755







+







__[i](p_chambre_de)__                   chambres? (d’(?:agriculture|hôtes?)|de (?:commerce|compensation|décompression|dégrisement)) @@$ <<- ~1>> *
__[i](p_chemin_de_traverse)__           chemins? (de traverse) @@$ <<- ~1>> *
__[i](p_chili_con_carne)__              chilis? (con carne) @@$ <<- ~1>> *
__[i](p_chef_d_œuvre)__                 chefs?(-d’œuvre) @@$ <<- ~1>> *
__[i](p_clair_comme)__                  claire?s? (comme (?:de l’eau de (?:boudin|roche|source)|du (?:cristal|jus de (?:boudin|chaussettes?|chique)))) @@$ <<- ~1>> *
__[i](p_commis_d_office)__              commise?s? (d’office) @@$ <<- ~1>> *
__[i](p_convention)__                   conventions? (récepteur|générateur) @@$ <<- ~1>> *
__[i](p_con_comme)__                    con(?:ne|)s? (comme (?:un balai|une valise sans poignées?|la lune)) @@$ <<- ~1>> *
__[i](p_coup_de)__
    coups? (de (?:balai|bol|cœur|foudre|fil|grâce|jarnac|théâtre|coude|genou|main|p(?:atte|ied|oing|oker|ouce)|tête)|d’(?:avance|éclat|État|œil|épaule)|du sort) @@$
    <<- ~1>> *
__[i](p_course_contre_la_montre)__      courses? (contre la montre) @@$ <<- ~1>> *
__[i](p_cousu_main)__                   cousue?s? +(main) @@$ <<- ~1>> *
__[i](p_cout_de_revient)__              (?:co[uû]t|prix) (de revient) @@$ <<- ~1>> *
__[i](loc_crayon_à_qqch)__
4817
4818
4819
4820
4821
4822
4823
4824
4825





4826
4827
4828
4829
4830
4831
4832
4819
4820
4821
4822
4823
4824
4825

4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838







-

+
+
+
+
+







    numéro (un|deux|trois|quatre|cinq|six|sept|huit|neuf|dix(?:-sept|-huit|-neuf|)|onze|douze|treize|quatorze|quinze|seize|vingt|trente|quarante|cinquante|soixante(?:-dix|)|quatre-vingt(?:-dix|)|cent|mille|\d+) @@$
    <<- before(r"\b[lL]a +$") =>> define(\0, [">numéro :N:f:s"])
    <<- ~1>> *
__[i](p_oiseau_de)__                    oiseaux? (de (?:malheur|nuit|proie|mauvais augure)) @@$ <<- ~1>> * 
__[i](p_onde_de_choc)__                 ondes? (de choc) @@$ <<- ~1>> *
__[i](p_orge)__                         orge (perlé|mondé|carré) @@$ <<- ~1>> *
__[i](p_noire_comme)__                  noire?s? (comme (?:la nuit|une nuit sans lune)) @@$ <<- ~1>> *
__[i](p_pièce_de)__                     pièces? (de (?:théâtre|monnaie|\d+ (?:euros?|centimes?|cents?|livres? sterling|shillings?))) @@$ <<- ~1>> *
__[i](p_partie_de_jambe_en_l_air)__     parties? (de jambes en l’air) @@$ <<- ~1>> *
__[i](p_papier_à_lettre)__
    papiers? (([àa]) lettres?) @@$,w
    <<- \2 == "a" -2>> à                        # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”.
    <<- ~1>> *
__[i](p_pièce_de)__                     pièces? (de (?:théâtre|monnaie|\d+ (?:euros?|centimes?|cents?|livres? sterling|shillings?))) @@$ <<- ~1>> *
__[i](p_porte_de)__                     portes? (de (?:service|garage)) @@$ <<- ~1>> *
__[i](p_poudre_aux_yeux)__              poudres? (aux yeux) @@$ <<- ~1>> *
__[i](p_preuve_du_contraire)__          preuves? +(?:suffisantes? +|)(du contraire) @@$ <<- ~1>> *
__[i](p_quelqu_un_d_autre)__            quelqu un (d’autre) @@$ <<- ~1>> *
__[i](loc_remire_à_plat)__
    remise?s? (([àa]) plat) @@$,w
    <<- \2 == "a" -2>> à                        # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”.
4892
4893
4894
4895
4896
4897
4898

4899
4900
4901
4902
4903
4904
4905
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912







+







TEST: Elle a mis du fard {{a}} paupières.
TEST: ce fils {{a}} papa est d’un ennui mortel.
TEST: cette fille {{a}} papa nous pourrit la vie.
TEST: Les conséquences des gaz {{a}} effet de serre.
TEST: devant la machine {{a}} café.
TEST: Achète un moule {{a}} gaufres.
TEST: Fais la mise {{a}} jour
TEST: Amenez-moi du papier {{a}} lettres.
TEST: Elle mit du rouge {{a}} lèvres.
TEST: on a besoin d’une remise {{a}} plat.
TEST: passe-moi mon sac {{a}} dos.
TEST: dans le silo {{a}} grain.
TEST: sa chambre, c’est une vraie soue {{a}} cochons.
TEST: Un tueur {{a}} gages ne s’y prendrait jamais comme ça.
TEST: Ce n’est que du vernis {{a}} ongles.
5200
5201
5202
5203
5204
5205
5206
5207

5208
5209
5210
5211
5212
5213
5214
5207
5208
5209
5210
5211
5212
5213

5214
5215
5216
5217
5218
5219
5220
5221







-
+









## Simplication des locutions verbales
__[i](p_donner_sens)__
    ((?:re|)donn\w+) +(sens) @@0,$
    <<- morph(\1, ">(?:re|)donner ", False) ~2>> *
__[i](p_faire_qqch)__
    (f[aiîeo]\w*) +(tous(?: deux| trois|) +|)(allusion|assaut|bonne figure|confiance|compliqué|chaud|débat|demi-tour|fausse route|froid|gr(?:ise mine|and cas)|h(?:alte|onte)|ma(?:chine|rche) arrière|p(?:art(?:ie(?: intégrante|)|)|eur|laisir|rofil bas)|rage|salle comble|sens|table rase|volte-face|ce que bon (?:me|te|lui|leur|nous|vous) semble) @@0,*,$
    (f[aiîeo]\w*) +(tous(?: deux| trois|) +|)(allusion|assaut|bonne figure|confiance|compliqué|chaud|débat|demi-tour|fausse route|froid|gr(?:ise mine|and cas)|h(?:alte|onte)|illusion|ma(?:chine|rche) arrière|p(?:art(?:ie(?: intégrante|)|)|eur|laisir|rofil bas)|rage|salle comble|sens|table rase|volte-face|ce que bon (?:me|te|lui|leur|nous|vous) semble) @@0,*,$
    <<- morph(\1, ">faire ", False) ~2>> *
    <<- __also__ ~3>> *
__[i](loc_mettre_à_qqch)__
    (m(?:et|[iî][mst])\w*) +(([àa]) (?:jour|niveau|plat|l’écart)) @@0,$,w
    <<- morph(\1, ">mettre ", False) >>>
    <<- \3 == "a" -3>> à                        # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”.
    <<- ~2>> *
5225
5226
5227
5228
5229
5230
5231





5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249

5250
5251
5252
5253
5254
5255
5256
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269







+
+
+
+
+


















+







    <<- morph(\1, ">prendre ", False) ~2>> *
__[i](p_rester_lettre_morte)__
    (rest\w+) (lettre morte) @@0,$
    <<- morph(\1, ">rester ", False) ~2>> *
__[i](p_sembler_paraitre_être)__
    (sembl\w+|par[au]\w+) +(être|avoir été) +({w_2}) @@0,w,$
    <<- morph(\1, ">(?:sembler|para[îi]tre) ") and morphex(\3, ":A", ":G") ~2>> *
__[i](loc_suivre_de_près)__
    (suiv\w+) +((?:ça +|ce(?:ci|la) +|)de (pr[èé]s?|prêts?)) @@0,$,$
    <<- morph(\1, ">suivre ", False) >>>
    <<- \3 != "près" -3>> près                  # Confusion : écrivez “près” pour dire “proche de quelque chose”.|https://fr.wiktionary.org/wiki/pr%C3%A8s
    <<- ~2>> *
__[i](loc_tenir_à_distance)__
    (t[eiî]\w+) +(([àa]) distance) d(?:es?|u) @@0,$,w
    <<- morph(\1, ">tenir ", False) >>>
    <<- \3 == "a" -3>> à                        # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”.
    <<- ~2>> *
__[i](loc_tenir_compte)__
    (t[eiî]\w+) +(co(?:mp?|n)tes?) d(?:es?|u) @@0,w
    <<- \2 != "compte" -2>> compte              # Dans cette locution, écrivez “compte” au singulier.|https://fr.wiktionary.org/wiki/tenir_compte
    <<- morph(\1, ">tenir ", False) ~2>> *
__[i](p_trier_sur_le_volet)__
    (tri\w+) (sur le volet) @@0,$
    <<- morph(\1, ">trier ", False) ~2>> *
__[i](p_venir)__
    (v[eiî]\w+) ((?:on ne sait|je ne sais) (?:pas |)(?:trop |)d’où) @@0,$
    <<- morph(\1, ">venir ", False) ~2>> *

TEST: il faut tenir {{contes}} des faits au lieu de nos impressions.
TEST: prendre {{a}} la légère ce test serait une erreur.
TEST: on va suivre ça de {{prêt}}.
TEST: il faut se tenir {{a}} distance de ces gens-là.


# Autres tests contre les faux positifs
TEST: pourquoi faire compliqué quand on peut faire simple
TEST: Pour ceux et celles qui étaient présents à la cérémonie
TEST: les pires vilénies suite au mauvais vote du peuple
5307
5308
5309
5310
5311
5312
5313
5314

5315
5316
5317
5318
5319
5320
5321
5320
5321
5322
5323
5324
5325
5326

5327
5328
5329
5330
5331
5332
5333
5334







-
+







TEST: comme le signe évident d’une politique volontaire
TEST: c’était le signe évident d’une politique volontaire
TEST: ce que c’est : le signe évident d’une politique volontaire
TEST: On aura carte blanche.
TEST: La seule façon de redonner sens à des notions…
TEST: Les longues tresses que j’ai pris l’habitude de porter depuis quelque temps et qu’il faut cinq heures pour parfaire.
TEST: Il est pieds nus.
TEST: des dossiers secrets {{défense}}
TEST: des dossiers secrets défense


#
# //////////////////////////////////////// RÈGLES DE CONTRÔLE ////////////////////////////////////////
#


11460
11461
11462
11463
11464
11465
11466
11467

11468
11469
11470
11471
11472
11473
11474
11475
11476
11477

11478
11479
11480
11481
11482
11483
11484
11485
11486
11487

11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501

11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514

11515
11516
11517
11518
11519
11520
11521
11522
11523

11524
11525
11526
11527
11528
11529
11530
11531
11532
11533
11534
11535

11536
11537
11538
11539
11540
11541
11542
11473
11474
11475
11476
11477
11478
11479

11480
11481
11482
11483
11484
11485
11486
11487
11488
11489

11490
11491
11492
11493
11494
11495
11496
11497
11498
11499

11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513

11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526

11527
11528
11529
11530
11531
11532
11533
11534
11535

11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547

11548
11549
11550
11551
11552
11553
11554
11555







-
+









-
+









-
+













-
+












-
+








-
+











-
+







TEST: Veuillez vous instruire avant de contester ces mesures.
TEST: C’était elle qui avait pris le contrôle.


__[i]/inte(inte_je)__
    ({w1})-je  @@0
    <<- morphex(\1, ":V", ":1[sśŝ]") -1>> =suggVerb(@, ":1ś")                                       # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier.
    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":1[sśŝ]")                                   # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier.
    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":1[sśŝ]", False)                            # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier.

TEST: {{Vas}}-je                                            ->> Vais
TEST: {{Prit}}-je                                           ->> Pris
TEST: {{prix}}-je le temps d’y parvenir ? Oui.


__[i]/inte(inte_tu)__
    ({w1})-tu  @@0
    <<- morphex(\1, ":V", ":[ISK].*:2s") -1>> =suggVerb(@, ":2s")                                   # Forme interrogative. « \1 » n’est pas un verbe à la 2ᵉ personne du singulier.
    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":2s")                                       # Forme interrogative : « \1 » n’est pas un verbe à la 2ᵉ personne du singulier.
    <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":2s", False)                                # Forme interrogative : « \1 » n’est pas un verbe à la 2ᵉ personne du singulier.

TEST: {{Peut}}-tu                                           ->> Peux
TEST: {{peu}}-tu revenir chez moi ?


__[i]/inte(inte_il_elle_on)__
    ({w1})-(?:t-|)(il|elle|on)  @@0,$
    <<- morphex(\1, ":V", ":3s") -1>> =suggVerb(@, ":3s")                                           # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.
    <<- \1 != "t" and (not \1.endswith("oilà") or \2 != "il") and morphex(\1, ":", ":V")
    -1>> =suggSimil(\1, ":3s")                                                                      # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.
    -1>> =suggSimil(\1, ":3s", False)                                                               # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.
    <<- not \2.endswith(("n", "N")) and morphex(\1, ":3p", ":3s") -2>> \2s                          # Forme interrogative : accordez “\2” avec le verbe à la 3ᵉ personne du pluriel.

TEST: {{Peux}}-il                                           ->> Peut
TEST: {{Attaques}}-t-on                                     ->> Attaque
TEST: {{Prends}}-elle                                       ->> Prend
TEST: {{Menthe}}-t-elle souvent ?
TEST: {{viennent}}-{{il}} demain ?
TEST: Le moteur choisi convient-il ?


__[s]/inte(inte_ce)__
    ({w_2})-([cs]e)  @@0,$
    <<- morphex(\1, ":V", ":(?:3s|V0e.*:3p)") -1>> =suggVerb(@, ":3s")      # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
    <<- morphex(\1, ":", ":V") -1>> =suggSimil(\1, ":3s")                   # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
    <<- morphex(\1, ":", ":V") -1>> =suggSimil(\1, ":3s", False)            # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132
    <<- \2 == "se" -2>> ce                                                  # Forme interrogative. Confusion.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132

TEST: était-{{se}} cela, la vérité ineffable ?
TEST: {{étai}}-ce notre destinée de souffrir ?
TEST: étaient-{{se}} ces hommes-là qui allaient nous guider dans les montagnes ?
TEST: Était-ce des femmes de ce pays ?
TEST: Eh ! dit Athos, ne sont-ce pas des braconniers qu’on arrête là-bas ?


__[i]/inte(inte_nous)__
    ({w1})-nous  @@0
    <<- morphex(\1, ":V", ":(?:1p|E:2[sp])") -1>> =suggVerb(@, ":1p")                               # Forme interrogative ou impérative incorrecte.
    <<- morphex(\1, ":", ":V|>chez ") -1>> =suggSimil(\1, ":1p")                                    # Forme interrogative ou impérative incorrecte.
    <<- morphex(\1, ":", ":V|>chez ") -1>> =suggSimil(\1, ":1p", False)                             # Forme interrogative ou impérative incorrecte.

TEST: {{Prendront}}-nous                                    ->> Prendrons
TEST: {{Attendront}}-nous le train                          ->> Attendrons


__[i]/inte(inte_vous)__
    ({w1})-vous  @@0
    <<- morphex(\1, ":V", ":2p") -1>> =suggVerb(@, ":2p")                                           # Forme interrogative ou impérative incorrecte.
    <<- not morph(\1, ":V|>chez ", False) -1>> =suggSimil(\1, ":2p")                                # Forme interrogative ou impérative incorrecte.
    <<- not morph(\1, ":V|>chez ", False) -1>> =suggSimil(\1, ":2p", False)                         # Forme interrogative ou impérative incorrecte.

TEST: {{Attaquait}}-vous                                    ->> Attaquiez
TEST: Elle a de nombreux rendez-vous ce matin.
TEST: êtes-vous là ?


__[i]/inte(inte_ils_elles)__
    ({w1})-(?:ils|elles)  @@0
    <<- morphex(\1, ":V", ":3p") and spell(\1)
    -1>> =suggVerb(@, ":3p")                                                                        # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel.
    <<- \1 != "t" and not morph(\1, ":V", False) and spell(\1)
    -1>> =suggSimil(\1, ":3p")                                                                      # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel.
    -1>> =suggSimil(\1, ":3p", False)                                                               # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel.

TEST: {{attaquant}}-ils                                     ->> attaquent
TEST: {{prendrons}}-elles un verre avec moi ?



!!!! Verbe auxiliaire                                                                               

Modified gc_lang/fr/webext/background.js from [cd0a23cfe8] to [006072374b].

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
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









+
+
+
+
+
+
+
+












-
+







// Background 

"use strict";


function showError (e) {
    console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
}

// Chrome don’t follow the W3C specification:
// https://browserext.github.io/browserext/
let bChrome = false;
if (typeof(browser) !== "object") {
    var browser = chrome;
    bChrome = true;
}


/*
    Worker (separate thread to avoid freezing Firefox)
*/
let xGCEWorker = new Worker("gce_worker.js");

xGCEWorker.onmessage = function (e) {
    // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
    try {
        let {sActionDone, result, dInfo} = e.data;
        switch (sActionDone) {
            case "init":
                browser.storage.local.set({"gc_options": result});
                storeGCOptions(result);
                break;
            case "parse":
            case "parseAndSpellcheck":
            case "parseAndSpellcheck1":
            case "getListOfTokens":
            case "getSpellSuggestions":
                // send result to content script
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
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
96
97
98







+
+
+
+

-



-
+











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







                // send result to panel
                browser.runtime.sendMessage(e.data);
                break;
            case "getOptions":
            case "getDefaultOptions":
            case "resetOptions":
                // send result to panel
                storeGCOptions(result);
                if (bChrome) {
                    e.data.result = helpers.mapToObject(e.data.result);
                }
                browser.runtime.sendMessage(e.data);
                browser.storage.local.set({"gc_options": result});
                break;
            case "setOptions":
            case "setOption":
                browser.storage.local.set({"gc_options": result});
                storeGCOptions(result);
                break;
            default:
                console.log("[background] Unknown command: " + sActionDone);
                console.log(e.data);
        }
    }
    catch (e) {
        showError(e);
    }
};


function init () {
function initGrammarChecker (dSavedOptions) {
    let xPromise = browser.storage.local.get("gc_options");
    xPromise.then(
        function (dSavedOptions) {
            let dOptions = (dSavedOptions.hasOwnProperty("gc_options")) ? dSavedOptions.gc_options : null;
            xGCEWorker.postMessage({
                sCommand: "init",
                dParam: {sExtensionPath: browser.extension.getURL("."), dOptions: dOptions, sContext: "Firefox"},
                dInfo: {}
            });
        },
    let dOptions = (dSavedOptions.hasOwnProperty("gc_options")) ? dSavedOptions.gc_options : null;
    xGCEWorker.postMessage({
        sCommand: "init",
        dParam: {sExtensionPath: browser.extension.getURL(""), dOptions: dOptions, sContext: "Firefox"},
        dInfo: {}
    });
}

function init () {
    if (bChrome) {
        browser.storage.local.get("gc_options", initGrammarChecker);
        return;
    }
    let xPromise = browser.storage.local.get("gc_options");
    xPromise.then(
        initGrammarChecker,
        function (e) {
            showError(e);
            xGCEWorker.postMessage({
                sCommand: "init",
                dParam: {sExtensionPath: browser.extension.getURL("."), dOptions: null, sContext: "Firefox"},
                dInfo: {}
            });
245
246
247
248
249
250
251









252
253
254
255
256
257
258
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283







+
+
+
+
+
+
+
+
+







    }
});


/*
    Actions
*/

function storeGCOptions (dOptions) {
    if (bChrome) {
        // JS crap again. Chrome can’t store Map object.
        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",
270
271
272
273
274
275
276






277
278
279
280
281
282
283









284
285
286

287
288
289
290
291
292
293
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333







+
+
+
+
+
+







+
+
+
+
+
+
+
+
+


-
+







        sCommand: "getListOfTokens",
        dParam: {sText: sText},
        dInfo: {iReturnPort: iTab}
    });
}

function openConjugueurTab () {
    if (bChrome) {
        browser.tabs.create({
            url: browser.extension.getURL("panel/conjugueur.html")
        });
        return;
    }
    let xConjTab = browser.tabs.create({
        url: browser.extension.getURL("panel/conjugueur.html")
    });
    xConjTab.then(onCreated, onError);
}

function openConjugueurWindow () {
    if (bChrome) {
        browser.windows.create({
            url: browser.extension.getURL("panel/conjugueur.html"),
            type: "popup",
            width: 710,
            height: 980
        });
        return;
    }
    let xConjWindow = browser.windows.create({
        url: browser.extension.getURL("panel/conjugueur.html"),
        type: "detached_panel",
        type: "popup",
        width: 710,
        height: 980
    });
    xConjWindow.then(onCreated, onError);
}


Modified gc_lang/fr/webext/content_scripts/init.js from [fb82906f86] to [3e98d11aad].

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
10
11
12
13
14
15
16




17
18
19
20









21
22
23
24
25
26
27
28
29
30
31







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







"use strict";


function showError (e) {
    console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
}

function createNode (sType, oAttr, oDataset=null) {
    try {
        let xNode = document.createElement(sType);
        Object.assign(xNode, oAttr);
// Chrome don’t follow the W3C specification:
// https://browserext.github.io/browserext/
let bChrome = false;
if (typeof(browser) !== "object") {
        if (oDataset) {
            Object.assign(xNode.dataset, oDataset);
        }
        return xNode;
    }
    catch (e) {
        showError(e);
    }
}
    var browser = chrome;
    bChrome = true;
}


/*
function loadImage (sContainerClass, sImagePath) {
    let xRequest = new XMLHttpRequest();
    xRequest.open('GET', browser.extension.getURL("")+sImagePath, false);
    xRequest.responseType = "arraybuffer";
    xRequest.send();
51
52
53
54
55
56
57

58
59



60
61
62
63
64
65
66
46
47
48
49
50
51
52
53


54
55
56
57
58
59
60
61
62
63







+
-
-
+
+
+







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

    createMenus: function () {
        let lNode = document.getElementsByTagName("textarea");
        for (let xNode of lNode) {
            if (xNode.style.display !== "none" && xNode.style.visibility !== "hidden") {
            this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
            this.nMenu += 1;
                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));
96
97
98
99
100
101
102














103
104
105
106
107
108
109
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







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







    },

    createGCPanel: function () {
        if (this.oGCPanel === null) {
            this.oGCPanel = new GrammalecteGrammarChecker("grammalecte_gc_panel", "Grammalecte", 500, 700);
            this.oGCPanel.insertIntoPage();
        }
    },

    createNode: function (sType, oAttr, oDataset=null) {
        try {
            let xNode = document.createElement(sType);
            Object.assign(xNode, oAttr);
            if (oDataset) {
                Object.assign(xNode.dataset, oDataset);
            }
            return xNode;
        }
        catch (e) {
            showError(e);
        }
    }
}


/*
    Connexion to the background
*/

Modified gc_lang/fr/webext/content_scripts/menu.css from [1ab8e5ddf4] to [7a8360406b].

16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30







-
+







    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;
    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 infinite;
    animation: grammalecte-spin 2s ease 3;
}
.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;
}

Modified gc_lang/fr/webext/content_scripts/menu.js from [13d950308a] to [296905930b].

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
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









-
+













-
-
+
+


-
+









-
+














-
+














-
-
+
+




-
+







-
+

-
+







// JavaScript

"use strict";


class GrammalecteMenu {

    constructor (nMenu, xNode) {
        this.sMenuId = "grammalecte_menu" + nMenu;
        this.xButton = createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
        this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
        this.xButton.onclick = () => { this.switchMenu(); };
        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 (xNode) {
        try {
            let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.textContent;
            let xMenu = createNode("div", {id: this.sMenuId, className: "grammalecte_menu"});
            xMenu.appendChild(createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
            let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"});
            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
            // Text formatter
            if (xNode.tagName == "TEXTAREA") {
                let xTFButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"});
                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 = createNode("div", {className: "grammalecte_menu_item", textContent: "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();
                xGrammalectePort.postMessage({
                    sCommand: "getListOfTokens",
                    dParam: {sText: sText},
                    dInfo: {sTextAreaId: xNode.id}
                });
            };
            xMenu.appendChild(xLxgButton);
            // Grammar checker
            let xGCButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"});
            let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"});
            xGCButton.onclick = () => {
                this.switchMenu();
                oGrammalecte.createGCPanel();
                oGrammalecte.oGCPanel.start(xNode);
                oGrammalecte.oGCPanel.show();
                oGrammalecte.oGCPanel.startWaitIcon();
                xGrammalectePort.postMessage({
                    sCommand: "parseAndSpellcheck",
                    dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false},
                    dInfo: {sTextAreaId: xNode.id}
                });
            };
            xMenu.appendChild(xGCButton);
            // Conjugation tool
            let xConjButton = createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"});
            let xConjButtonTab = createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"});
            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});
            };
            let xConjButtonWin = createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"});
            let xConjButtonWin = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"});
            xConjButtonWin.onclick = () => {
                this.switchMenu();
                xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null});
            };
            xConjButton.appendChild(xConjButtonTab);
            xConjButton.appendChild(xConjButtonWin);
            xMenu.appendChild(xConjButton);
            //xMenu.appendChild(createNode("img", {scr: browser.extension.getURL("img/logo-16.png")}));
            //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(createNode("div", {className: "grammalecte_menu_footer"}));
            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_footer"}));
            return xMenu;
        }
        catch (e) {
            showError(e);
        }
    }

Modified gc_lang/fr/webext/content_scripts/panel.css from [42670977b4] to [16626ac74c].

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
128
129
130
131











132
133
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
128
129
130
131
132
133
134
135
136
137







-
+
-
-



-
-
+
+

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

-
-
-
-
-
-
+
+
+
+

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


    min-width: 100%;
    height: calc(100% - 55px); /* panel height - title_bar */
    overflow: auto;
}


/*
    CSS Spinner
    Spinner
    Double bounce
    http://tobiasahlin.com/spinkit/
*/
.grammalecte_spinner {
    visibility: hidden;
    width: 40px;
    height: 40px;
    width: 20px;
    height: 20px;
    position: absolute;
    top: 2px;
    right: 180px;
    top: 0px;
    right: 200px;
}
.grammalecte_spinner .bounce1,
.grammalecte_spinner .bounce2 {
    width: 100%;
    height: 100%;
    background-color: hsla(210, 80%, 80%, .5);
    border: 10px solid hsla(210, 80%, 60%, .5);
    border-top: 10px solid hsla(210, 100%, 40%, .7);
    border-bottom: 10px solid hsla(210, 100%, 40%, .7);
    border-radius: 50%;
    background-color: hsl(0, 50%, 75%);
    opacity: 0.6;
    position: absolute;
    top: 0;
    left: 0;
    animation: grammalecte-sk-bounce 2.0s infinite ease-in-out;
    text-align: center;
    cursor: pointer;
    box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5);
    animation: grammalecte-spin-big .5s linear infinite;
}
.grammalecte_spinner .bounce2 {
    animation-delay: -1.0s;
}


@keyframes grammalecte-spin-big {
    0% {
        transform: rotate(0deg) scale(1);
        border-top: 10px solid hsla(210, 100%, 40%, .7);
        border-bottom: 10px solid hsla(210, 100%, 40%, .7);
    }
@keyframes grammalecte-sk-bounce {
    0%, 100% { 
        transform: scale(0.0);
    } 50% { 
        transform: scale(1.0);
    70% {
        transform: rotate(180deg) scale(.8);
        border-top: 10px solid hsla(0, 100%, 40%, .7);
        border-bottom: 10px solid hsla(0, 100%, 40%, .7);
        box-shadow: 0 0 0 20px hsla(210, 50%, 50%, 0);
    }
    100% {
        transform: rotate(360deg) scale(1);
        border-top: 10px solid hsla(210, 100%, 40%, .7);
        border-bottom: 10px solid hsla(210, 100%, 40%, .7);
        box-shadow: 0 0 0 0 hsla(210, 50%, 50%, 0);
    }
}

Modified gc_lang/fr/webext/content_scripts/panel.js from [48d95d0550] to [8cea12fb98].

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
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













-
-
+
+







-
+

-
+

-
+

















-
+














-
-
-
+
+
+




-
+





-
+





-
+







// JavaScript
// Panel creator

"use strict";


class GrammalectePanel {

    constructor (sId, sTitle, nWidth, nHeight, bFlexible=true) {
        this.sId = sId;
        this.nWidth = nWidth;
        this.nHeight = nHeight;
        this.bFlexible = bFlexible;
        this.xPanelBar = createNode("div", {className: "grammalecte_panel_bar"});
        this.xPanelContent = createNode("div", {className: "grammalecte_panel_content"});
        this.xPanelBar = oGrammalecte.createNode("div", {className: "grammalecte_panel_bar"});
        this.xPanelContent = oGrammalecte.createNode("div", {className: "grammalecte_panel_content"});
        this.xWaitIcon = this._createWaitIcon();
        this.xPanel = this._createPanel(sTitle);
        this.center();
    }

    _createPanel (sTitle) {
        try {
            let xPanel = createNode("div", {id: this.sId, className: "grammalecte_panel"});
            let xPanel = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_panel"});
            this.xPanelBar.appendChild(this._createButtons());
            let xTitle = createNode("div", {className: "grammalecte_panel_title"});
            let xTitle = oGrammalecte.createNode("div", {className: "grammalecte_panel_title"});
            xTitle.appendChild(this._createLogo());
            xTitle.appendChild(createNode("div", {className: "grammalecte_panel_label", textContent: sTitle}));
            xTitle.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_panel_label", textContent: sTitle}));
            this.xPanelBar.appendChild(xTitle);
            xPanel.appendChild(this.xPanelBar);
            xPanel.appendChild(this.xPanelContent);
            return xPanel;
        }
        catch (e) {
            showError(e);
        }
    }

    _createLogo () {
        let xImg = document.createElement("img");
        xImg.src = "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";
        return xImg;
    }

    _createButtons () {
        let xButtonLine = createNode("div", {className: "grammalecte_panel_commands"});
        let xButtonLine = oGrammalecte.createNode("div", {className: "grammalecte_panel_commands"});
        xButtonLine.appendChild(this.xWaitIcon);
        if (this.sId === "grammalecte_gc_panel") {
            xButtonLine.appendChild(this._createCopyButton());
        }
        xButtonLine.appendChild(this._createMoveButton("stickToTop", "¯", "Coller en haut"));
        xButtonLine.appendChild(this._createMoveButton("stickToLeft", "«", "Coller à gauche"));
        xButtonLine.appendChild(this._createMoveButton("center", "•", "Centrer"));
        xButtonLine.appendChild(this._createMoveButton("stickToRight", "»", "Coller à droite"));
        xButtonLine.appendChild(this._createMoveButton("stickToBottom", "_", "Coller en bas"));
        xButtonLine.appendChild(this._createCloseButton());
        return xButtonLine;
    }

    _createWaitIcon () {
        let xWaitIcon = createNode("div", {className: "grammalecte_spinner"});
        xWaitIcon.appendChild(createNode("div", {className: "bounce1"}));
        xWaitIcon.appendChild(createNode("div", {className: "bounce2"}));
        let xWaitIcon = oGrammalecte.createNode("div", {className: "grammalecte_spinner"});
        //xWaitIcon.appendChild(oGrammalecte.createNode("div", {className: "bounce1"}));
        //xWaitIcon.appendChild(oGrammalecte.createNode("div", {className: "bounce2"}));
        return xWaitIcon;
    }

    _createCopyButton () {
        let xButton = createNode("div", {id: "grammalecte_clipboard_button", className: "grammalecte_copy_button", textContent: "∑", title: "Copier dans le presse-papiers"});
        let xButton = oGrammalecte.createNode("div", {id: "grammalecte_clipboard_button", className: "grammalecte_copy_button", textContent: "∑", title: "Copier dans le presse-papiers"});
        xButton.onclick = function () { this.copyTextToClipboard(); }.bind(this);
        return xButton;
    }

    _createMoveButton (sAction, sLabel, sTitle) {
        let xButton = createNode("div", {className: "grammalecte_move_button", textContent: sLabel, title: sTitle});
        let xButton = oGrammalecte.createNode("div", {className: "grammalecte_move_button", textContent: sLabel, title: sTitle});
        xButton.onclick = function () { this[sAction](); }.bind(this);
        return xButton;
    }

    _createCloseButton () {
        let xButton = createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"});
        let xButton = oGrammalecte.createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"});
        xButton.onclick = function () { this.hide(); }.bind(this);  // better than writing “let that = this;” before the function?
        return xButton;
    }

    insertIntoPage () {
        document.body.appendChild(this.xPanel);
    }

Modified gc_lang/fr/webext/content_scripts/panel_gc.js from [7e48ad2a90] to [b14363b80e].

42
43
44
45
46
47
48
49
50


51
52
53
54
55
56
57
42
43
44
45
46
47
48


49
50
51
52
53
54
55
56
57







-
-
+
+







            grammalecte_error{Id}     : [paragraph number]-[error_number]
            grammalecte_sugg{Id}      : [paragraph number]-[error_number]--[suggestion_number]
    */

    constructor (...args) {
        super(...args);
        this.aIgnoredErrors = new Set();
        this.xContentNode = createNode("div", {id: "grammalecte_gc_panel_content"});
        this.xParagraphList = createNode("div", {id: "grammalecte_paragraph_list"});
        this.xContentNode = oGrammalecte.createNode("div", {id: "grammalecte_gc_panel_content"});
        this.xParagraphList = oGrammalecte.createNode("div", {id: "grammalecte_paragraph_list"});
        this.xContentNode.appendChild(this.xParagraphList);
        this.xPanelContent.addEventListener("click", onGrammalecteGCPanelClick, false);
        this.oTooltip = new GrammalecteTooltip(this.xContentNode);
        this.xPanelContent.appendChild(this.xContentNode);
        this.oTAC = new GrammalecteTextAreaControl();
    }

74
75
76
77
78
79
80
81

82
83
84
85



86
87

88
89
90
91
92
93
94
74
75
76
77
78
79
80

81
82



83
84
85
86

87
88
89
90
91
92
93
94







-
+

-
-
-
+
+
+

-
+







        this.xPanel.style.display = "none";
        this.oTAC.clear();
    }

    addParagraphResult (oResult) {
        try {
            if (oResult && (oResult.sParagraph.trim() !== "" || oResult.aGrammErr.length > 0 || oResult.aSpellErr.length > 0)) {
                let xNodeDiv = createNode("div", {className: "grammalecte_paragraph_block"});
                let xNodeDiv = oGrammalecte.createNode("div", {className: "grammalecte_paragraph_block"});
                // actions
                let xActionsBar = createNode("div", {className: "grammalecte_paragraph_actions"});
                xActionsBar.appendChild(createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "Réanalyser"}, {para_num: oResult.iParaNum}));
                xActionsBar.appendChild(createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", style: "font-weight: bold;"}));
                let xActionsBar = oGrammalecte.createNode("div", {className: "grammalecte_paragraph_actions"});
                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "Réanalyser"}, {para_num: oResult.iParaNum}));
                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", style: "font-weight: bold;"}));
                // paragraph
                let xParagraph = createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum});
                let xParagraph = oGrammalecte.createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum});
                xParagraph.setAttribute("spellcheck", "false"); // doesn’t seem possible to use “spellcheck” as a common attribute.
                xParagraph.addEventListener("keyup", function (xEvent) {
                    this.oTAC.setParagraph(parseInt(xEvent.target.dataset.para_num), this.purgeText(xEvent.target.textContent));
                    this.oTAC.write();
                }.bind(this)
                , true);
                this._tagParagraph(xParagraph, oResult.sParagraph, oResult.iParaNum, oResult.aGrammErr, oResult.aSpellErr);
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247







-
+







    }

    addSummary () {
        // todo
    }

    addMessage (sMessage) {
        let xNode = createNode("div", {className: "grammalecte_gc_panel_message", textContent: sMessage});
        let xNode = oGrammalecte.createNode("div", {className: "grammalecte_gc_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
        function setClipboardData (xEvent) {
            document.removeEventListener("copy", setClipboardData, true);
275
276
277
278
279
280
281
282
283


284
285
286
287
288
289
290
291
292
293
294







295
296
297

298
299
300
301
302
303
304
275
276
277
278
279
280
281


282
283
284
285
286
287







288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304







-
-
+
+




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


-
+







}


class GrammalecteTooltip {

    constructor (xContentNode) {
        this.sErrorId = null;
        this.xTooltip = createNode("div", {id: "grammalecte_tooltip"});
        this.xTooltipArrow = createNode("img", {
        this.xTooltip = oGrammalecte.createNode("div", {id: "grammalecte_tooltip"});
        this.xTooltipArrow = oGrammalecte.createNode("img", {
            id: "grammalecte_tooltip_arrow",
            src: " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwAAADsABataJCQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xNzNun2MAAAAnSURBVChTY/j//z8cq/kW/wdhZDEMSXRFWCVhGKwAmwQyHngFxf8B5fOGYfeFpYoAAAAASUVORK5CYII=",
            alt: "^",
        });
        this.xTooltipSuggBlock = createNode("div", {id: "grammalecte_tooltip_sugg_block"});
        let xMessageBlock = createNode("div", {id: "grammalecte_tooltip_message_block"});
        xMessageBlock.appendChild(createNode("p", {id: "grammalecte_tooltip_rule_id"}));
        xMessageBlock.appendChild(createNode("p", {id: "grammalecte_tooltip_message", textContent: "Erreur."}));
        let xActions = xMessageBlock.appendChild(createNode("div", {id: "grammalecte_tooltip_actions"}));
        xActions.appendChild(createNode("div", {id: "grammalecte_tooltip_ignore", textContent: "Ignorer"}));
        xActions.appendChild(createNode("div", {id: "grammalecte_tooltip_url", textContent: "Voulez-vous en savoir plus ?…"}, {url: ""}));
        this.xTooltipSuggBlock = oGrammalecte.createNode("div", {id: "grammalecte_tooltip_sugg_block"});
        let xMessageBlock = oGrammalecte.createNode("div", {id: "grammalecte_tooltip_message_block"});
        xMessageBlock.appendChild(oGrammalecte.createNode("p", {id: "grammalecte_tooltip_rule_id"}));
        xMessageBlock.appendChild(oGrammalecte.createNode("p", {id: "grammalecte_tooltip_message", textContent: "Erreur."}));
        let xActions = xMessageBlock.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_actions"}));
        xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_ignore", textContent: "Ignorer"}));
        xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_url", textContent: "Voulez-vous en savoir plus ?…"}, {url: ""}));
        xMessageBlock.appendChild(xActions);
        this.xTooltip.appendChild(xMessageBlock);
        this.xTooltip.appendChild(createNode("div", {id: "grammalecte_tooltip_sugg_title", textContent: "SUGGESTIONS :"}));
        this.xTooltip.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_sugg_title", textContent: "SUGGESTIONS :"}));
        this.xTooltip.appendChild(this.xTooltipSuggBlock);
        xContentNode.appendChild(this.xTooltip);
        xContentNode.appendChild(this.xTooltipArrow);
    }

    show (sNodeErrorId) {  // err
        try {

Modified gc_lang/fr/webext/content_scripts/panel_lxg.js from [dcf9b1545d] to [eb959206ea].

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
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









-
+












-
+




-
+






-
-
+
+












-
-
-
+
+
+



-
+

-
+












// JavaScript

"use strict";

class GrammalecteLexicographer extends GrammalectePanel {

    constructor (...args) {
        super(...args);
        this._nCount = 0;
        this._xContentNode = createNode("div", {id: "grammalecte_lxg_panel_content"});
        this._xContentNode = oGrammalecte.createNode("div", {id: "grammalecte_lxg_panel_content"});
        this.xPanelContent.appendChild(this._xContentNode);
    }

    clear () {
        this._nCount = 0;
        while (this._xContentNode.firstChild) {
            this._xContentNode.removeChild(this._xContentNode.firstChild);
        }
    }

    addSeparator (sText) {
        if (this._xContentNode.textContent !== "") {
            this._xContentNode.appendChild(createNode("div", {className: "grammalecte_lxg_separator", textContent: sText}));
            this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_separator", textContent: sText}));
        }
    }

    addMessage (sClass, sText) {
        this._xContentNode.appendChild(createNode("div", {className: sClass, textContent: sText}));
        this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: sClass, textContent: sText}));
    }

    addListOfTokens (lTokens) {
        try {
            if (lTokens) {
                this._nCount += 1;
                let xNodeDiv = createNode("div", {className: "grammalecte_lxg_list_of_tokens"});
                xNodeDiv.appendChild(createNode("div", {className: "grammalecte_lxg_list_num", textContent: this._nCount}));
                let xNodeDiv = oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_of_tokens"});
                xNodeDiv.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_num", textContent: this._nCount}));
                for (let oToken of lTokens) {
                    xNodeDiv.appendChild(this._createTokenNode(oToken));
                }
                this._xContentNode.appendChild(xNodeDiv);
            }
        }
        catch (e) {
            showError(e);
        }
    }

    _createTokenNode (oToken) {
        let xTokenNode = createNode("div", {className: "grammalecte_lxg_token_block"});
        xTokenNode.appendChild(createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
        xTokenNode.appendChild(createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
        let xTokenNode = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"});
        xTokenNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue}));
        xTokenNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"}));
        if (oToken.aLabel.length === 1) {
            xTokenNode.appendChild(document.createTextNode(oToken.aLabel[0]));
        } else {
            let xTokenList = createNode("div", {className: "grammalecte_lxg_morph_list"});
            let xTokenList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"});
            for (let sLabel of oToken.aLabel) {
                xTokenList.appendChild(createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
                xTokenList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel}));
            }
            xTokenNode.appendChild(xTokenList);
        }
        return xTokenNode;
    }

    setHidden (sClass, bHidden) {
        for (let xNode of document.getElementsByClassName(sClass)) {
            xNode.hidden = bHidden;
        }
    }
}

Modified gc_lang/fr/webext/content_scripts/panel_tf.js from [ee3e21ae91] to [4e9190557a].

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
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







-
-
+
+



















-
+







        this.xTextArea = null;
    }

    _createTextFormatter () {
        let xTFNode = document.createElement("div");
        try {
            // Options
            let xOptions = createNode("div", {id: "grammalecte_tf_options"});
            let xColumn1 = createNode("div", {className: "grammalecte_tf_column"});
            let xOptions = oGrammalecte.createNode("div", {id: "grammalecte_tf_options"});
            let xColumn1 = oGrammalecte.createNode("div", {className: "grammalecte_tf_column"});
            let xSSP = this._createFieldset("group_ssp", true, "Espaces surnuméraires");
            xSSP.appendChild(this._createBlockOption("o_start_of_paragraph", true, "En début de paragraphe"));
            xSSP.appendChild(this._createBlockOption("o_end_of_paragraph", true, "En fin de paragraphe"));
            xSSP.appendChild(this._createBlockOption("o_between_words", true, "Entre les mots"));
            xSSP.appendChild(this._createBlockOption("o_before_punctuation", true, "Avant les points (.), les virgules (,)"));
            xSSP.appendChild(this._createBlockOption("o_within_parenthesis", true, "À l’intérieur des parenthèses"));
            xSSP.appendChild(this._createBlockOption("o_within_square_brackets", true, "À l’intérieur des crochets"));
            xSSP.appendChild(this._createBlockOption("o_within_quotation_marks", true, "À l’intérieur des guillemets “ et ”"));
            let xSpace = this._createFieldset("group_space", true, "Espaces manquants");
            xSpace.appendChild(this._createBlockOption("o_add_space_after_punctuation", true, "Après , ; : ? ! . …"));
            xSpace.appendChild(this._createBlockOption("o_add_space_around_hyphens", true, "Autour des tirets d’incise"));
            let xNBSP = this._createFieldset("group_nbsp", true, "Espaces insécables");
            xNBSP.appendChild(this._createBlockOption("o_nbsp_before_punctuation", true, "Avant : ; ? et !"));
            xNBSP.appendChild(this._createBlockOption("o_nbsp_within_quotation_marks", true, "Avec les guillemets « et »"));
            xNBSP.appendChild(this._createBlockOption("o_nbsp_before_symbol", true, "Avant % ‰ € $ £ ¥ ˚C"));
            xNBSP.appendChild(this._createBlockOption("o_nbsp_within_numbers", true, "À l’intérieur des nombres"));
            xNBSP.appendChild(this._createBlockOption("o_nbsp_before_units", true, "Avant les unités de mesure"));
            let xDelete = this._createFieldset("group_delete", true, "Suppressions");
            xDelete.appendChild(this._createBlockOption("o_erase_non_breaking_hyphens", true, "Tirets conditionnels"));
            let xColumn2 = createNode("div", {className: "grammalecte_tf_column"});
            let xColumn2 = oGrammalecte.createNode("div", {className: "grammalecte_tf_column"});
            let xTypo = this._createFieldset("group_typo", true, "Signes typographiques");
            xTypo.appendChild(this._createBlockOption("o_ts_apostrophe", true, "Apostrophe (’)"));
            xTypo.appendChild(this._createBlockOption("o_ts_ellipsis", true, "Points de suspension (…)"));
            xTypo.appendChild(this._createBlockOption("o_ts_dash_middle", true, "Tirets d’incise :"));
            xTypo.appendChild(this._createRadioBoxHyphens("o_ts_m_dash_middle", "o_ts_n_dash_middle", false));
            xTypo.appendChild(this._createBlockOption("o_ts_dash_start", true, "Tirets en début de paragraphe :"));
            xTypo.appendChild(this._createRadioBoxHyphens("o_ts_m_dash_start", "o_ts_n_dash_start", true));
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
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
128
129

130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155

156
157
158

159
160
161
162
163
164
165
166



167
168



169
170
171
172
173
174
175
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
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
128

129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154

155
156
157

158
159
160
161
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
177
178
179







-
-
+
+

-
+


-
-
+
+

-
+












-
-
+
+






-
+

-
+




-
+






-
+







-
+



-
+




-
+












-
+







-
+


-
+








+
+
+
-
-
+
+
+







            xColumn1.appendChild(xDelete);
            xColumn2.appendChild(xTypo);
            xColumn2.appendChild(xMisc);
            xColumn2.appendChild(xStruct);
            xOptions.appendChild(xColumn1);
            xOptions.appendChild(xColumn2);
            // Actions
            let xActions = createNode("div", {id: "grammalecte_tf_actions"});
            let xDefaultButton = createNode("div", {id: "grammalecte_tf_reset", textContent: "Par défaut", className: "grammalecte_tf_button"});
            let xActions = oGrammalecte.createNode("div", {id: "grammalecte_tf_actions"});
            let xDefaultButton = oGrammalecte.createNode("div", {id: "grammalecte_tf_reset", textContent: "Par défaut", className: "grammalecte_tf_button"});
            xDefaultButton.addEventListener("click", () => { this.reset(); });
            let xApplyButton = createNode("div", {id: "grammalecte_tf_apply", textContent: "Appliquer", className: "grammalecte_tf_button"});
            let xApplyButton = oGrammalecte.createNode("div", {id: "grammalecte_tf_apply", textContent: "Appliquer", className: "grammalecte_tf_button"});
            xApplyButton.addEventListener("click", () => { this.saveOptions(); this.apply(); });
            xActions.appendChild(xDefaultButton);
            xActions.appendChild(createNode("progress", {id: "grammalecte_tf_progressbar"}));
            xActions.appendChild(createNode("span", {id: "grammalecte_tf_time_res", textContent: "…"}));
            xActions.appendChild(oGrammalecte.createNode("progress", {id: "grammalecte_tf_progressbar"}));
            xActions.appendChild(oGrammalecte.createNode("span", {id: "grammalecte_tf_time_res", textContent: "…"}));
            xActions.appendChild(xApplyButton);
            //xActions.appendChild(createNode("div", {id: "grammalecte_infomsg", textContent: "blabla"}));
            //xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_infomsg", textContent: "blabla"}));
            // create result
            xTFNode.appendChild(xOptions);
            xTFNode.appendChild(xActions);
        }
        catch (e) {
            showError(e);
        }
        return xTFNode;
    }

    // Common options
    _createFieldset (sId, bDefault, sLabel) {
        let xFieldset = createNode("div", {id: sId, className: "grammalecte_tf_groupblock"});
        let xGroupOption = createNode("div", {id: "o_"+sId, className: "grammalecte_tf_option grammalecte_tf_option_title_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: ""});
        let xFieldset = oGrammalecte.createNode("div", {id: sId, className: "grammalecte_tf_groupblock"});
        let xGroupOption = oGrammalecte.createNode("div", {id: "o_"+sId, className: "grammalecte_tf_option grammalecte_tf_option_title_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: ""});
        xGroupOption.addEventListener("click", (xEvent) => { this.switchOption(xEvent.target.id); this.switchGroup(xEvent.target.id); });
        xFieldset.appendChild(xGroupOption);
        return xFieldset;
    }

    _createBlockOption (sId, bDefault, sLabel) {
        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
        xLine.appendChild(this._createOption(sId, bDefault, sLabel));
        xLine.appendChild(createNode("div", {id: "res_"+sId, className: "grammalecte_tf_result", textContent: "·"}));
        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+sId, className: "grammalecte_tf_result", textContent: "·"}));
        return xLine;
    }

    _createOption (sId, bDefault, sLabel, sLinkedOptionsId="") {
        let xOption = createNode("div", {id: sId, className: "grammalecte_tf_option grammalecte_tf_option_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: sLinkedOptionsId});
        let xOption = oGrammalecte.createNode("div", {id: sId, className: "grammalecte_tf_option grammalecte_tf_option_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: sLinkedOptionsId});
        xOption.addEventListener("click", (xEvent) => { this.switchOption(xEvent.target.id); });
        return xOption;
    }

    // Hyphens
    _createRadioBoxHyphens (sIdEmDash, sIdEnDash, bDefaultEmDash) {
        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
        xLine.appendChild(this._createOption(sIdEmDash, bDefaultEmDash, "cadratin (—)", sIdEnDash));
        xLine.appendChild(this._createOption(sIdEnDash, !bDefaultEmDash, "demi-cadratin (—)", sIdEmDash));
        return xLine;
    }

    // Ligatures
    _createRadioBoxLigatures () {
        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
        xLine.appendChild(this._createOption("o_ts_ligature", true, "Ligatures"));
        xLine.appendChild(this._createOption("o_ts_ligature_do", false, "faire", "o_ts_ligature_undo"));
        xLine.appendChild(this._createOption("o_ts_ligature_undo", true, "défaire", "o_ts_ligature_do"));
        xLine.appendChild(createNode("div", {id: "res_"+"o_ts_ligature", className: "grammalecte_tf_result", textContent: "·"}));
        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ts_ligature", className: "grammalecte_tf_result", textContent: "·"}));
        return xLine;
    }

    _createLigaturesSelection () {
        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
        xLine.appendChild(this._createOption("o_ts_ligature_ff", true, "ff"));
        xLine.appendChild(this._createOption("o_ts_ligature_fi", true, "fi"));
        xLine.appendChild(this._createOption("o_ts_ligature_ffi", true, "ffi"));
        xLine.appendChild(this._createOption("o_ts_ligature_fl", true, "fl"));
        xLine.appendChild(this._createOption("o_ts_ligature_ffl", true, "ffl"));
        xLine.appendChild(this._createOption("o_ts_ligature_ft", true, "ft"));
        xLine.appendChild(this._createOption("o_ts_ligature_st", false, "st"));
        return xLine;
    }

    // Apostrophes
    _createSingleLetterOptions () {
        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"});
        xLine.appendChild(this._createOption("o_ma_1letter_lowercase", false, "lettres isolées (j’ n’ m’ t’ s’ c’ d’ l’)"));
        xLine.appendChild(this._createOption("o_ma_1letter_uppercase", false, "Maj."));
        return xLine;
    }

    // Ordinals
    _createOrdinalOptions () {
        let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
        let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"});
        xLine.appendChild(this._createOption("o_ordinals_no_exponant", true, "Ordinaux (15e, XXIe…)"));
        xLine.appendChild(this._createOption("o_ordinals_exponant", true, "e → ᵉ"));
        xLine.appendChild(createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"}));
        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"}));
        return xLine;
    }
    
    /*
        Actions
    */
    start (xTextArea) {
        this.xTextArea = xTextArea;
        if (bChrome) {
            browser.storage.local.get("tf_options", this.setOptions.bind(this));
        } else {
        let xPromise = browser.storage.local.get("tf_options");
        xPromise.then(this.setOptions.bind(this), this.reset.bind(this));
            let xPromise = browser.storage.local.get("tf_options");
            xPromise.then(this.setOptions.bind(this), this.reset.bind(this));
        }
    }

    switchGroup (sOptName) {
        if (document.getElementById(sOptName).dataset.selected == "true") {
            document.getElementById(sOptName.slice(2)).style.opacity = 1;
        } else {
            document.getElementById(sOptName.slice(2)).style.opacity = 0.3;

Modified gc_lang/fr/webext/manifest.json from [7d6295f445] to [bbea6aa8bb].

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


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













+
+







{
  "manifest_version": 2,
  "name": "Grammalecte [fr]",
  "short_name": "Grammalecte [fr]",
  "version": "0.6.0",

  "applications": {
    "gecko": {
      "id": "French-GC@grammalecte.net",
      "strict_min_version": "57.0"
    }
  },

  "minimum_chrome_version": "61",

  "author": "Olivier R.",
  "homepage_url": "https://grammalecte.net",
  "description": "Correcteur grammatical pour le français.",

  "default_locale": "fr",

  "icons": { "16": "img/logo-16.png",
29
30
31
32
33
34
35

36
37
38
39
40
41
42
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45







+







    "default_popup": "panel/main.html",
    "default_title": "Grammalecte [fr]",
    "browser_style": false
  },

  "background": {
    "scripts": [
      "grammalecte/helpers.js",
      "background.js"
    ]
  },

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
88
89
90
91
92
93
94
95

96
97
98
99
100
101

102
103
104
105
106
107
108
91
92
93
94
95
96
97

98
99
100
101
102
103

104
105
106
107
108
109
110
111







-
+





-
+







      "run_at": "document_idle"
    }
  ],

  "commands": {
    "conjugueur_tab": {
      "suggested_key": {
        "default": "Ctrl+Shift+F6"
        "default": "Ctrl+Shift+6"
      },
      "description": "Ouvre le conjugueur dans un onglet"
    },
    "conjugueur_window": {
      "suggested_key": {
        "default": "Ctrl+Shift+F7"
        "default": "Ctrl+Shift+7"
      },
      "description": "Ouvre le conjugueur dans une fenêtre"
    }
  },

  "web_accessible_resources": [
    "grammalecte/_dictionaries/French.json",
119
120
121
122
123
124
125
126
127




128
129
130
122
123
124
125
126
127
128


129
130
131
132
133
134
135







-
-
+
+
+
+



    "storage"
  ],

  "chrome_settings_overrides": {
    "search_provider": {
      "name": "Grammalecte",
      "search_url": "https://www.dicollecte.org/dictionary.php?prj=fr&lemma={searchTerms}",
      "keyword": "disc",
      "favicon_url": "https://www.dicollecte.org/favicon.ico"
      "keyword": "gram",
      "favicon_url": "https://www.dicollecte.org/favicon.ico",
      "encoding": "UTF-8",
      "is_default": false
    }
  }
}

Modified gc_lang/fr/webext/panel/main.css from [e691764c17] to [4ea20bf8f5].

120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134







-
+







    min-width: calc(100% - 51px);
    height: 500px;
    overflow: auto;
}
#page h1 {
    margin: 0 0 10px 0;
    color: hsl(210, 50%, 50%);
    font: bold 30px 'Yanone Kaffeesatz', "Liberation Sans Narrow", sans-serif;
    font: bold 30px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif;
}


/*
    Home
*/
#home_page {
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170







-
+







    Help
*/
#help_page {
    display: none;
    padding: 20px;
}
#help_page h2 {
    font: bold 20px 'Yanone Kaffeesatz', "Liberation Sans Narrow", sans-serif;
    font: bold 20px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif;
    color: hsl(210, 50%, 50%);
}
#help_page .shortcut {
    margin-top: 10px;
    font-weight: bold;
    font-size: 13px;
}

Modified gc_lang/fr/webext/panel/main.html from [718e696348] to [fac2fe84b3].

55
56
57
58
59
60
61
62

63
64

65
66
67
68
69
70
71
55
56
57
58
59
60
61

62
63

64
65
66
67
68
69
70
71







-
+

-
+







          <div id="help_section">
            <p>Grammalecte affiche un bouton d’accès au menu en bas à gauche des zones de texte usuelles pour accéder aux fonctionnalités existantes.</p>
            <p class="right"><img src="../img/menu_button1.png" title="bouton du menu" /></p>
            <p class="right"><img src="../img/menu_button2.png" title="menu" /></p>
            <p>Pour les autres zones de texte (HTML éditable), il faut sélectionner le texte et utiliser le menu contextuel.</p>
            <p class="right"><img src="../img/contextmenu.png" title="menu contextuel sur sélection" /></p>
            <h2>Raccourcis clavier</h2>
            <p class="shortcut">CTRL+MAJ+F6</p>
            <p class="shortcut">CTRL+MAJ+6</p>
            <p class="shortcut_label">Conjugueur (dans un onglet)</p>
            <p class="shortcut">CTRL+MAJ+F7</p>
            <p class="shortcut">CTRL+MAJ+7</p>
            <p class="shortcut_label">Conjugueur (dans une fenêtre)</p>
          </div>
        </section> <!-- #help_page -->

        <section id="gc_options_page" class="page">
          <h1>OPTIONS GRAMMATICALES</h1>
          <div id="grammar_options">

Modified gc_lang/fr/webext/panel/main.js from [405aefbae4] to [4bafd8a9dd].

1
2
3
4
5
6
7
8
9








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









+
+
+
+
+
+
+
+







// Main panel

"use strict";


function showError (e) {
    console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
}

// Chrome don’t follow the W3C specification:
// https://browserext.github.io/browserext/
let bChrome = false;
if (typeof(browser) !== "object") {
    var browser = chrome;
    bChrome = true;
}


/*
    Events
*/
window.addEventListener(
    "click",
    function (xEvent) {
121
122
123
124
125
126
127
128

129




130
131
132
133
134
135







136
137
138
139

140
141
142
143











144
145
146
147
148
149
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143





144
145
146
147
148
149
150




151




152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168








+

+
+
+
+

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






    }
}


function showTestResult (sText) {
    document.getElementById("tests_result").textContent = sText;
}


function setGCOptionsFromStorage () {
    if (bChrome) {
        browser.storage.local.get("gc_options", _setGCOptions);
        return;
    }
    let xPromise = browser.storage.local.get("gc_options");
    xPromise.then(
        function (dSavedOptions) {
            if (dSavedOptions.hasOwnProperty("gc_options")) {
                setGCOptions(dSavedOptions.gc_options);
            }
    xPromise.then(_setGCOptions, showError);
}

function _setGCOptions (dSavedOptions) {
    if (dSavedOptions.hasOwnProperty("gc_options")) {
        setGCOptions(dSavedOptions.gc_options);
    }
        },
        function (e) {
            showError(e);
        }
}
    );
}

function setGCOptions (dOptions) {

function setGCOptions (dOptions) {
    // dOptions is supposed to be a Map
    if (bChrome) {
        // JS crap again. Chrome can’t store/send Map object.
        let m = new Map();
        for (let param in dOptions) {
            m.set(param, dOptions[param]);
        }
        dOptions = m;
    }
    for (let [sOpt, bVal] of dOptions) {
        if (document.getElementById("option_"+sOpt)) {
            document.getElementById("option_"+sOpt).checked = bVal;
        }
    }
}