Grammalecte  Changes On Branch ef6ea473b6bd59c7

Changes In Branch comdic Through [ef6ea473b6] Excluding Merge-Ins

This is equivalent to a diff from 889cc645d6 to ef6ea473b6

2019-01-28
22:17
[fx] get dictionaries list, download dictionaries check-in: a0890eba14 user: olr tags: fx, comdic
2019-01-23
16:03
[graphspell] new date format for consistency with the DB check-in: ef6ea473b6 user: olr tags: graphspell, comdic
2019-01-22
10:12
[build][fx] Firefox Nightly has a new installation folder check-in: 3fc5e58719 user: olr tags: build, fx, comdic
2019-01-10
08:19
[fr] faux positif check-in: 5e334a2cb3 user: olr tags: trunk, fr
2019-01-09
17:22
merge trunk check-in: 096875de48 user: olr tags: comdic
17:18
[fr] màj dictionnaire, [graphspell][fx][tb][lo] new field description for dictionaries check-in: 889cc645d6 user: olr tags: trunk, fr, tb, fx, lo, graphspell
2019-01-08
13:55
[fr] màj: à court/moyen/long terme check-in: e476704b50 user: olr tags: trunk, fr

Modified gc_lang/fr/config.ini from [aee238173d] to [f13ee44744].

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
description = Correcteur grammatical pour le français.
extras = README_fr.txt
logo = logo.png

# main dictionary
lexicon_src = lexicons/French.lex
dic_filenames = fr-allvars,fr-classic,fr-reform

dic_name = Français,Français (Classique/Moderne),Français (Réforme 1990)
dic_filter = ,[*CMPX]$,[*RPX]$
dic_default_filename_py = fr-allvars
dic_default_filename_js = fr-allvars
# extended dictionary
lexicon_extended_src = lexicons/French.extended.lex
dic_extended_filename = fr.extended
dic_extended_name = Français - dictionnaire étendu

# community dictionary
lexicon_community_src = lexicons/French.community.lex
dic_community_filename = fr.community
dic_community_name = Français - dictionnaire communautaire

# personal dictionary
lexicon_personal_src = lexicons/French.personal.lex
dic_personal_filename = fr.personal
dic_personal_name = Français - dictionnaire personnel

# Finite state automaton compression: 1, 2 (experimental) or 3 (experimental)
fsa_method = 1
# stemming method: S for suffixes only, A for prefixes and suffixes
stemming_method = S

# LibreOffice
unopkg = C:/Program Files/LibreOffice/program/unopkg.com
oxt_version = 7.0
oxt_identifier = French.linguistic.resources.from.Dicollecte.by.OlivierR

# Firefox
fx_identifier = French-GC@grammalecte.net
fx_name = Grammalecte [fr]

win_fx_dev_path = C:\Program Files\Firefox Developer Edition\firefox.exe
win_fx_nightly_path = C:\Program Files\Nightly\firefox.exe
linux_fx_dev_path = /usr/bin/firefox
linux_fx_nightly_path = /usr/bin/firefox

# Thunderbird
tb_identifier = French-GC-TB@grammalecte.net
tb_name = Grammalecte [fr]
win_tb_path = C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe







>
|






|
>



|
>



|
>















|







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
description = Correcteur grammatical pour le français.
extras = README_fr.txt
logo = logo.png

# main dictionary
lexicon_src = lexicons/French.lex
dic_filenames = fr-allvars,fr-classic,fr-reform
dic_name = fr-allvars,fr-classic,fr-reform
dic_description = Français (Toutes variantes),Français (Classique),Français (Réforme 1990)
dic_filter = ,[*CMPX]$,[*RPX]$
dic_default_filename_py = fr-allvars
dic_default_filename_js = fr-allvars
# extended dictionary
lexicon_extended_src = lexicons/French.extended.lex
dic_extended_filename = fr.extended
dic_extended_name = fr.extended
dic_extended_description = Français - dictionnaire étendu
# community dictionary
lexicon_community_src = lexicons/French.community.lex
dic_community_filename = fr.community
dic_community_name = fr.community
dic_community_description = Français - dictionnaire communautaire
# personal dictionary
lexicon_personal_src = lexicons/French.personal.lex
dic_personal_filename = fr.personal
dic_personal_name = fr.personal
dic_personal_description = Français - dictionnaire personnel
# Finite state automaton compression: 1, 2 (experimental) or 3 (experimental)
fsa_method = 1
# stemming method: S for suffixes only, A for prefixes and suffixes
stemming_method = S

# LibreOffice
unopkg = C:/Program Files/LibreOffice/program/unopkg.com
oxt_version = 7.0
oxt_identifier = French.linguistic.resources.from.Dicollecte.by.OlivierR

# Firefox
fx_identifier = French-GC@grammalecte.net
fx_name = Grammalecte [fr]

win_fx_dev_path = C:\Program Files\Firefox Developer Edition\firefox.exe
win_fx_nightly_path = C:\Program Files\Firefox Nightly\firefox.exe
linux_fx_dev_path = /usr/bin/firefox
linux_fx_nightly_path = /usr/bin/firefox

# Thunderbird
tb_identifier = French-GC-TB@grammalecte.net
tb_name = Grammalecte [fr]
win_tb_path = C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe

Modified gc_lang/fr/dictionnaire/genfrdic.py from [321fa8c26f] to [fef905a8c3].

522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
                hDst.write(oFlex.__str__(oStatsLex))

    def writeGrammarCheckerLexicon (self, spfDst, version):
        echo(' * Lexique simplifié >> [ {} ] '.format(spfDst))
        with open(spfDst[:-4]+".lex", 'w', encoding='utf-8', newline="\n") as hDst:
            hDst.write(MPLHEADER)
            hDst.write("# Lexique simplifié pour Grammalecte v{}\n# Licence : MPL v2.0\n\n".format(version))
            hDst.write("## LangCode: fr\n")
            hDst.write("## LangName: Français\n")
            hDst.write("## DicName: fr.commun\n")
            hDst.write("## Description: Français commun (toutes variantes)\n")
            hDst.write("## Author: Olivier R.\n\n")
            hDst.write(Flexion.simpleHeader())
            for oFlex in self.lFlexions:
                hDst.write(oFlex.getGrammarCheckerRepr())

    def createFiles (self, spDst, lDictVars, nMode, bSimplified):
        sDicName = PREFIX_DICT_PATH + self.sVersion
        spDic = spDst + '/' + sDicName







<
<
<
<
<







522
523
524
525
526
527
528





529
530
531
532
533
534
535
                hDst.write(oFlex.__str__(oStatsLex))

    def writeGrammarCheckerLexicon (self, spfDst, version):
        echo(' * Lexique simplifié >> [ {} ] '.format(spfDst))
        with open(spfDst[:-4]+".lex", 'w', encoding='utf-8', newline="\n") as hDst:
            hDst.write(MPLHEADER)
            hDst.write("# Lexique simplifié pour Grammalecte v{}\n# Licence : MPL v2.0\n\n".format(version))





            hDst.write(Flexion.simpleHeader())
            for oFlex in self.lFlexions:
                hDst.write(oFlex.getGrammarCheckerRepr())

    def createFiles (self, spDst, lDictVars, nMode, bSimplified):
        sDicName = PREFIX_DICT_PATH + self.sVersion
        spDic = spDst + '/' + sDicName

Modified gc_lang/fr/oxt/DictOptions/LexiconEditor.py from [30177fb38e] to [4e150dc058].

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
    @_waitPointer
    def saveLexicon (self):
        xGridDataModel = self.xGridModelLex.GridDataModel
        lEntry = []
        for i in range(xGridDataModel.RowCount):
            lEntry.append(xGridDataModel.getRowData(i))
        if lEntry:
            oDAWG = dawg.DAWG(lEntry, "S", "fr", "Français", "fr.personal")
            self.oPersonalDicJSON = oDAWG.getBinaryAsJSON()
            self.xOptionNode.setPropertyValue("personal_dic", json.dumps(self.oPersonalDicJSON, ensure_ascii=False))
            self.xSettingNode.commitChanges()
            self.xNumDic.Label = str(self.oPersonalDicJSON["nEntry"])
            self.xDateDic.Label = self.oPersonalDicJSON["sDate"]
        else:
            self.xOptionNode.setPropertyValue("personal_dic", "")







|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
    @_waitPointer
    def saveLexicon (self):
        xGridDataModel = self.xGridModelLex.GridDataModel
        lEntry = []
        for i in range(xGridDataModel.RowCount):
            lEntry.append(xGridDataModel.getRowData(i))
        if lEntry:
            oDAWG = dawg.DAWG(lEntry, "S", "fr", "Français", "fr.personal", "Dictionnaire personnel")
            self.oPersonalDicJSON = oDAWG.getBinaryAsJSON()
            self.xOptionNode.setPropertyValue("personal_dic", json.dumps(self.oPersonalDicJSON, ensure_ascii=False))
            self.xSettingNode.commitChanges()
            self.xNumDic.Label = str(self.oPersonalDicJSON["nEntry"])
            self.xDateDic.Label = self.oPersonalDicJSON["sDate"]
        else:
            self.xOptionNode.setPropertyValue("personal_dic", "")

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.aff from [a9c2422fab] to [5be819083a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “CLASSIQUE” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 09-01-2019 à 18:08
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “CLASSIQUE” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 11-01-2019 à 17:14
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-moderne.aff from [cf1eb7064c] to [93c2cdd8ee].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “MODERNE” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 09-01-2019 à 18:08
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “MODERNE” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 11-01-2019 à 17:14
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.aff from [b9b9132d08] to [84824df4fa].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “RÉFORME 1990” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 09-01-2019 à 18:08
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “RÉFORME 1990” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 11-01-2019 à 17:14
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-toutesvariantes.aff from [b23332b58c] to [3297933a4a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “TOUTES VARIANTES” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 09-01-2019 à 18:08
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “TOUTES VARIANTES” v7.0
# par Olivier R. -- licence MPL 2.0
# Généré le 11-01-2019 à 17:14
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

WORDCHARS -’'1234567890.

Modified gc_lang/fr/tb/content/lex_editor.js from [0814cc49a1] to [52568b3e47].

474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
        document.getElementById("import_button").addEventListener("click", () => { this.import(); }, false);
    },

    build: function () {
        let xProgressNode = document.getElementById("wait_progress");
        let lEntry = oLexiconTable.getEntries();
        if (lEntry.length > 0) {
            let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "fr.personal", xProgressNode);
            let oJSON = oDAWG.createBinaryJSON(1);
            oFileHandler.saveFile("fr.personal.json", JSON.stringify(oJSON));
            this.oIBDAWG = new IBDAWG(oJSON);
            this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
            //browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sType: "personal", oDict: oJSON}, dInfo: {} });
            enableElement("export_button");
        } else {







|







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
        document.getElementById("import_button").addEventListener("click", () => { this.import(); }, false);
    },

    build: function () {
        let xProgressNode = document.getElementById("wait_progress");
        let lEntry = oLexiconTable.getEntries();
        if (lEntry.length > 0) {
            let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "fr.personal", "Dictionnaire personnel", xProgressNode);
            let oJSON = oDAWG.createBinaryJSON(1);
            oFileHandler.saveFile("fr.personal.json", JSON.stringify(oJSON));
            this.oIBDAWG = new IBDAWG(oJSON);
            this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
            //browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sType: "personal", oDict: oJSON}, dInfo: {} });
            enableElement("export_button");
        } else {

Modified gc_lang/fr/webext/background.js from [52ec35f9bc] to [8000393b2f].

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
180
181
    xGCEWorker.postMessage({
        sCommand: "setDictionaryOnOff",
        dParam: { sDictionary: sDictionary, bActivate: bActivate },
        dInfo: {}
    });
}

function initSCOptions (dSavedOptions) {
    if (!dSavedOptions.hasOwnProperty("sc_options")) {
        browser.storage.local.set({"sc_options": {
            extended: true,
            community: true,
            personal: true
        }});
        setDictionaryOnOff("extended", true);
        setDictionaryOnOff("community", true);
        setDictionaryOnOff("personal", true);
    } else {
        let dOptions = dSavedOptions.sc_options;
        setDictionaryOnOff("extended", dOptions["extended"]);
        setDictionaryOnOff("community", dOptions["community"]);
        setDictionaryOnOff("personal", dOptions["personal"]);
    }
}

function setDictionary (sDictionary, oDictionary) {
    xGCEWorker.postMessage({
        sCommand: "setDictionary",
        dParam: { sDictionary: sDictionary, oDict: oDictionary },
        dInfo: {}
    });
}

function setSpellingDictionary (dSavedDictionary) {
    if (dSavedDictionary.hasOwnProperty("oExtendedDictionary")) {



        setDictionary("extended", dSavedDictionary["oExtendedDictionary"]);

    }
    if (dSavedDictionary.hasOwnProperty("oCommunityDictionary")) {

        setDictionary("community", dSavedDictionary["oCommunityDictionary"]);
    }
    if (dSavedDictionary.hasOwnProperty("oPersonalDictionary")) {
        setDictionary("personal", dSavedDictionary["oPersonalDictionary"]);

    }
}

function init () {
    if (bChrome) {
        browser.storage.local.get("gc_options", initGrammarChecker);
        browser.storage.local.get("ui_options", initUIOptions);
        browser.storage.local.get("oExtendedDictionary", setSpellingDictionary);
        browser.storage.local.get("oCommunityDictionary", setSpellingDictionary);
        browser.storage.local.get("oPersonalDictionary", setSpellingDictionary);
        browser.storage.local.get("sc_options", initSCOptions);
        return;
    }
    browser.storage.local.get("gc_options").then(initGrammarChecker, showError);
    browser.storage.local.get("ui_options").then(initUIOptions, showError);
    browser.storage.local.get("oExtendedDictionary").then(setSpellingDictionary, showError);
    browser.storage.local.get("oCommunityDictionary").then(setSpellingDictionary, showError);
    browser.storage.local.get("oPersonalDictionary").then(setSpellingDictionary, showError);
    browser.storage.local.get("sc_options").then(initSCOptions, showError);
}

init();


browser.runtime.onInstalled.addListener(function (oDetails) {







|
|





<



<
<
|
|











|
|
>
>
>
|
>

|
>
|
|
|
|
>







|
<
|





|
<
|







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
180
181
182
    xGCEWorker.postMessage({
        sCommand: "setDictionaryOnOff",
        dParam: { sDictionary: sDictionary, bActivate: bActivate },
        dInfo: {}
    });
}

function initSCOptions (oData) {
    if (!oData.hasOwnProperty("sc_options")) {
        browser.storage.local.set({"sc_options": {
            extended: true,
            community: true,
            personal: true
        }});

        setDictionaryOnOff("community", true);
        setDictionaryOnOff("personal", true);
    } else {


        setDictionaryOnOff("community", oData.sc_options["community"]);
        setDictionaryOnOff("personal", oData.sc_options["personal"]);
    }
}

function setDictionary (sDictionary, oDictionary) {
    xGCEWorker.postMessage({
        sCommand: "setDictionary",
        dParam: { sDictionary: sDictionary, oDict: oDictionary },
        dInfo: {}
    });
}

function setSpellingDictionaries (oData) {
    if (oData.hasOwnProperty("oPersonalDictionary")) {
        // deprecated
        console.log("personal dictionary migration");
        browser.storage.local.set({ "dictionaries": { "__personal__": oData["oPersonalDictionary"] } });
        setDictionary("personal", oData["oPersonalDictionary"]);
        browser.storage.local.remove("oPersonalDictionary");
    }
    if (oData.hasOwnProperty("dictionaries")) {
        if (oData.dictionaries.hasOwnProperty("__personal__")) {
            setDictionary("personal", oData.dictionaries["__personal__"]);
        }
        if (oData.dictionaries.hasOwnProperty("__community__")) {
            setDictionary("personal", oData.dictionaries["__community__"]);
        }
    }
}

function init () {
    if (bChrome) {
        browser.storage.local.get("gc_options", initGrammarChecker);
        browser.storage.local.get("ui_options", initUIOptions);
        browser.storage.local.get("dictionaries", setSpellingDictionaries);

        browser.storage.local.get("oPersonalDictionary", setSpellingDictionaries); // deprecated
        browser.storage.local.get("sc_options", initSCOptions);
        return;
    }
    browser.storage.local.get("gc_options").then(initGrammarChecker, showError);
    browser.storage.local.get("ui_options").then(initUIOptions, showError);
    browser.storage.local.get("dictionaries").then(setSpellingDictionaries, showError);

    browser.storage.local.get("oPersonalDictionary").then(setSpellingDictionaries, showError); // deprecated
    browser.storage.local.get("sc_options").then(initSCOptions, showError);
}

init();


browser.runtime.onInstalled.addListener(function (oDetails) {
213
214
215
216
217
218
219









220
221
222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
        case "setDictionary":
        case "setDictionaryOnOff":
            xGCEWorker.postMessage(oRequest);
            break;
        case "openURL":
            browser.tabs.create({url: dParam.sURL});
            break;









        default:
            console.log("[background] Unknown command: " + sCommand);
            console.log(oRequest);
    }
    //sendResponse({response: "response from background script"});
}

browser.runtime.onMessage.addListener(handleMessage);


function handleConnexion (xPort) {

    let iPortId = xPort.sender.tab.id; // identifier for the port: each port can be found at dConnx[iPortId]
    dConnx.set(iPortId, xPort);
    xPort.onMessage.addListener(function (oRequest) {
        let {sCommand, dParam, dInfo} = oRequest;
        switch (sCommand) {
            case "parse":
            case "parseAndSpellcheck":







>
>
>
>
>
>
>
>
>











>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
        case "setDictionary":
        case "setDictionaryOnOff":
            xGCEWorker.postMessage(oRequest);
            break;
        case "openURL":
            browser.tabs.create({url: dParam.sURL});
            break;
        case "openConjugueurTab":
            openConjugueurTab();
            break;
        case "openLexiconEditor":
            openLexiconEditor(dParam["dictionary"]);
            break;
        case "openDictionaries":
            openDictionaries();
            break;
        default:
            console.log("[background] Unknown command: " + sCommand);
            console.log(oRequest);
    }
    //sendResponse({response: "response from background script"});
}

browser.runtime.onMessage.addListener(handleMessage);


function handleConnexion (xPort) {
    // Messages from tabs
    let iPortId = xPort.sender.tab.id; // identifier for the port: each port can be found at dConnx[iPortId]
    dConnx.set(iPortId, xPort);
    xPort.onMessage.addListener(function (oRequest) {
        let {sCommand, dParam, dInfo} = oRequest;
        switch (sCommand) {
            case "parse":
            case "parseAndSpellcheck":
275
276
277
278
279
280
281
282
283
284


285
286
287
288
289
290
291
browser.contextMenus.create({ id: "rightClickLxgEditableNode",  title: "Lexicographe (zone de texte)",              contexts: ["editable"] });
browser.contextMenus.create({ id: "rightClickGCEditableNode",   title: "Correction grammaticale (zone de texte)",   contexts: ["editable"] });
browser.contextMenus.create({ id: "separator_editable",         type: "separator",                                  contexts: ["editable"] });
// Page
browser.contextMenus.create({ id: "rightClickLxgPage",          title: "Lexicographe (page)",                       contexts: ["all"] }); // on all parts, due to unwanted selection
browser.contextMenus.create({ id: "rightClickGCPage",           title: "Correction grammaticale (page)",            contexts: ["all"] });
browser.contextMenus.create({ id: "separator_page",             type: "separator",                                  contexts: ["all"] });
// Conjugueur
browser.contextMenus.create({ id: "conjugueur_window",          title: "Conjugueur [fenêtre]",                      contexts: ["all"] });
browser.contextMenus.create({ id: "conjugueur_tab",             title: "Conjugueur [onglet]",                       contexts: ["all"] });


// Rescan page
browser.contextMenus.create({ id: "separator_rescan",           type: "separator",                                  contexts: ["editable"] });
browser.contextMenus.create({ id: "rescanPage",                 title: "Rechercher à nouveau les zones de texte",   contexts: ["editable"] });


browser.contextMenus.onClicked.addListener(function (xInfo, xTab) {
    // xInfo = https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/contextMenus/OnClickData







|


>
>







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
browser.contextMenus.create({ id: "rightClickLxgEditableNode",  title: "Lexicographe (zone de texte)",              contexts: ["editable"] });
browser.contextMenus.create({ id: "rightClickGCEditableNode",   title: "Correction grammaticale (zone de texte)",   contexts: ["editable"] });
browser.contextMenus.create({ id: "separator_editable",         type: "separator",                                  contexts: ["editable"] });
// Page
browser.contextMenus.create({ id: "rightClickLxgPage",          title: "Lexicographe (page)",                       contexts: ["all"] }); // on all parts, due to unwanted selection
browser.contextMenus.create({ id: "rightClickGCPage",           title: "Correction grammaticale (page)",            contexts: ["all"] });
browser.contextMenus.create({ id: "separator_page",             type: "separator",                                  contexts: ["all"] });
// Tools
browser.contextMenus.create({ id: "conjugueur_window",          title: "Conjugueur [fenêtre]",                      contexts: ["all"] });
browser.contextMenus.create({ id: "conjugueur_tab",             title: "Conjugueur [onglet]",                       contexts: ["all"] });
browser.contextMenus.create({ id: "dictionaries",               title: "Dictionnaires",                             contexts: ["all"] });
browser.contextMenus.create({ id: "lexicon_editor",             title: "Éditeur lexical",                           contexts: ["all"] });
// Rescan page
browser.contextMenus.create({ id: "separator_rescan",           type: "separator",                                  contexts: ["editable"] });
browser.contextMenus.create({ id: "rescanPage",                 title: "Rechercher à nouveau les zones de texte",   contexts: ["editable"] });


browser.contextMenus.onClicked.addListener(function (xInfo, xTab) {
    // xInfo = https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/contextMenus/OnClickData
321
322
323
324
325
326
327






328
329
330
331
332
333
334
        // conjugueur
        case "conjugueur_window":
            openConjugueurWindow();
            break;
        case "conjugueur_tab":
            openConjugueurTab();
            break;






        // rescan page
        case "rescanPage":
            let xPort = dConnx.get(xTab.id);
            xPort.postMessage({sActionDone: "rescanPage"});
            break;
        default:
            console.log("[Background] Unknown menu id: " + xInfo.menuItemId);







>
>
>
>
>
>







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
        // conjugueur
        case "conjugueur_window":
            openConjugueurWindow();
            break;
        case "conjugueur_tab":
            openConjugueurTab();
            break;
        case "lexicon_editor":
            openLexiconEditor();
            break;
        case "dictionaries":
            openDictionaries();
            break;
        // rescan page
        case "rescanPage":
            let xPort = dConnx.get(xTab.id);
            xPort.postMessage({sActionDone: "rescanPage"});
            break;
        default:
            console.log("[Background] Unknown menu id: " + xInfo.menuItemId);
345
346
347
348
349
350
351
352
353



354
355
356
357
















358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

376
377
378





379

















380
381
382
383
384
385








386
387
388

389
390
391
392

393
394
395
396
397
398








399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
    switch (sCommand) {
        case "conjugueur_tab":
            openConjugueurTab();
            break;
        case "conjugueur_window":
            openConjugueurWindow();
            break;
        case "lex_editor":
            openLexEditor();



            break;
    }
});


















/*
    Actions
*/

function storeGCOptions (dOptions) {
    if (dOptions instanceof Map) {
        dOptions = helpers.mapToObject(dOptions);
    }
    browser.storage.local.set({"gc_options": dOptions});
}

function sendCommandToTab (sCommand, iTab) {
    let xTabPort = dConnx.get(iTab);
    xTabPort.postMessage({sActionDone: sCommand, result: null, dInfo: null, bEnd: false, bError: false});
}

function openLexEditor () {

    if (bChrome) {
        browser.tabs.create({
            url: browser.extension.getURL("panel/lex_editor.html")





        });

















        return;
    }
    let xLexEditor = browser.tabs.create({
        url: browser.extension.getURL("panel/lex_editor.html")
    });
    xLexEditor.then(onCreated, onError);








}

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: "popup",
        width: 710,
        height: 980
    });
    xConjWindow.then(onCreated, onError);
}


function onCreated (xWindowInfo) {
    //console.log(`Created window: ${xWindowInfo.id}`);
}

function onError (error) {
    console.log(`Error: ${error}`);
}







|
|
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















|
>
|
|
|
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
>
>
>
>
>



>
|
|
|
<
>
|
|
|
|
|
|
>
>
>
>
>
>
>
>


















<



<
<
<
<
|
|

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

495
496
497




498
499
500
    switch (sCommand) {
        case "conjugueur_tab":
            openConjugueurTab();
            break;
        case "conjugueur_window":
            openConjugueurWindow();
            break;
        case "lexicon_editor":
            openLexiconEditor();
            break;
        case "dictionaries":
            openDictionaries();
            break;
    }
});


/*
    Tabs
*/
let nTabLexiconEditor = null;
let nTabDictionaries = null;
let nTabConjugueur = null;

browser.tabs.onRemoved.addListener(function (nTabId, xRemoveInfo) {
    switch (nTabId) {
        case nTabLexiconEditor: nTabLexiconEditor = null; break;
        case nTabDictionaries:  nTabDictionaries = null; break;
        case nTabConjugueur:    nTabConjugueur = null; break;
    }
});


/*
    Actions
*/

function storeGCOptions (dOptions) {
    if (dOptions instanceof Map) {
        dOptions = helpers.mapToObject(dOptions);
    }
    browser.storage.local.set({"gc_options": dOptions});
}

function sendCommandToTab (sCommand, iTab) {
    let xTabPort = dConnx.get(iTab);
    xTabPort.postMessage({sActionDone: sCommand, result: null, dInfo: null, bEnd: false, bError: false});
}

function openLexiconEditor (sName="__personal__") {
    if (nTabLexiconEditor === null) {
        if (bChrome) {
            browser.tabs.create({
                url: browser.extension.getURL("panel/lex_editor.html")
            }, onLexiconEditorOpened);
            return;
        }
        let xLexEditor = browser.tabs.create({
            url: browser.extension.getURL("panel/lex_editor.html")
        });
        xLexEditor.then(onLexiconEditorOpened, onError);
    }
    else {
        browser.tabs.update(nTabLexiconEditor, {active: true});
    }
}

function onLexiconEditorOpened (xTab) {
    nTabLexiconEditor = xTab.id;
}

function openDictionaries () {
    if (nTabDictionaries === null) {
        if (bChrome) {
            browser.tabs.create({
                url: browser.extension.getURL("panel/dictionaries.html")
            }, onDictionariesOpened);
            return;
        }
        let xLexEditor = browser.tabs.create({
            url: browser.extension.getURL("panel/dictionaries.html")
        });
        xLexEditor.then(onDictionariesOpened, onError);
    }
    else {
        browser.tabs.update(nTabDictionaries, {active: true});
    }
}

function onDictionariesOpened (xTab) {
    nTabDictionaries = xTab.id;
}

function openConjugueurTab () {
    if (nTabDictionaries === null) {
        if (bChrome) {
            browser.tabs.create({
                url: browser.extension.getURL("panel/conjugueur.html")

            }, onConjugueurOpened);
            return;
        }
        let xConjTab = browser.tabs.create({
            url: browser.extension.getURL("panel/conjugueur.html")
        });
        xConjTab.then(onConjugueurOpened, onError);
    }
    else {
        browser.tabs.update(nTabConjugueur, {active: true});
    }
}

function onConjugueurOpened (xTab) {
    nTabConjugueur = xTab.id;
}

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: "popup",
        width: 710,
        height: 980
    });

}






function onError (e) {
    console.error(e);
}

Modified gc_lang/fr/webext/gce_worker.js from [f9f8b2256b] to [08f4a4604e].

316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
        return;
    }
    //console.log("setDictionary", sDictionary);
    switch (sDictionary) {
        case "main":
            oSpellChecker.setMainDictionary(oDict);
            break;
        case "extended":
            oSpellChecker.setExtendedDictionary(oDict);
            break;
        case "community":
            oSpellChecker.setCommunityDictionary(oDict);
            break;
        case "personal":
            oSpellChecker.setPersonalDictionary(oDict);
            break;
        default:
            console.log("[worker] setDictionary: Unknown dictionary <"+sDictionary+">");
    }
    postMessage(createResponse("setDictionary", true, dInfo, true));
}

function setDictionaryOnOff (sDictionary, bActivate, dInfo) {
    if (!oSpellChecker) {
        postMessage(createResponse("setDictionary", "# Error. SpellChecker not loaded.", dInfo, true));
        return;
    }
    //console.log("setDictionaryOnOff", sDictionary, bActivate);
    switch (sDictionary) {
        case "extended":
            if (bActivate) {
                oSpellChecker.activateExtendedDictionary();
            } else {
                oSpellChecker.deactivateExtendedDictionary();
            }
            break;
        case "community":
            if (bActivate) {
                oSpellChecker.activateCommunityDictionary();
            } else {
                oSpellChecker.deactivateCommunityDictionary();
            }
            break;







<
<
<



















<
<
<
<
<
<
<







316
317
318
319
320
321
322



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341







342
343
344
345
346
347
348
        return;
    }
    //console.log("setDictionary", sDictionary);
    switch (sDictionary) {
        case "main":
            oSpellChecker.setMainDictionary(oDict);
            break;



        case "community":
            oSpellChecker.setCommunityDictionary(oDict);
            break;
        case "personal":
            oSpellChecker.setPersonalDictionary(oDict);
            break;
        default:
            console.log("[worker] setDictionary: Unknown dictionary <"+sDictionary+">");
    }
    postMessage(createResponse("setDictionary", true, dInfo, true));
}

function setDictionaryOnOff (sDictionary, bActivate, dInfo) {
    if (!oSpellChecker) {
        postMessage(createResponse("setDictionary", "# Error. SpellChecker not loaded.", dInfo, true));
        return;
    }
    //console.log("setDictionaryOnOff", sDictionary, bActivate);
    switch (sDictionary) {







        case "community":
            if (bActivate) {
                oSpellChecker.activateCommunityDictionary();
            } else {
                oSpellChecker.deactivateCommunityDictionary();
            }
            break;

Modified gc_lang/fr/webext/manifest.json from [756d794e19] to [928cff8b51].

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
      ],
      "run_at": "document_idle"
    }
  ],

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

      },


      "description": "Ouvre l’éditeur lexical"
    }
  },

  "web_accessible_resources": [
    "content_scripts/panel.css",
    "content_scripts/panel_tf.css",
    "content_scripts/panel_gc.css",







|
<
<



|
<
<


|
|
<
>
|
>
>
|







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
      ],
      "run_at": "document_idle"
    }
  ],

  "commands": {
    "conjugueur_tab": {
      "suggested_key": { "default": "Ctrl+Shift+6" },


      "description": "Ouvre le conjugueur dans un onglet"
    },
    "conjugueur_window": {
      "suggested_key": { "default": "Ctrl+Shift+7" },


      "description": "Ouvre le conjugueur dans une fenêtre"
    },
    "lexicon_editor": {
      "suggested_key": { "default": "Ctrl+Shift+8" },

      "description": "Ouvre l’éditeur lexical"
    },
    "dictionaries": {
      "suggested_key": { "default": "Ctrl+Shift+9" },
      "description": "Ouvre le gestionnaire de dictionnaires communautaires"
    }
  },

  "web_accessible_resources": [
    "content_scripts/panel.css",
    "content_scripts/panel_tf.css",
    "content_scripts/panel_gc.css",

Added gc_lang/fr/webext/panel/dictionaries.css version [bafc0510cd].





































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
/*
   CSS Document
   White
   Design par Olivier R.
*/

* { margin: 0; padding: 0; }
img { border: none; }


/* Generic classes */

.fleft { float: left; }
.fright { float: right; }
.center { text-align: center; }
.right { text-align: right; }
.left { text-align: left; }
.justify { text-align: justify; }
.hidden { display: none; }
.clearer { clear: both; font-size: 0; height: 0; }

body {
    background: hsl(0, 0%, 100%) url(../img/lines.png);
    font: normal 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
    color: #505050;
}

.inbox {
    width: 800px;
    margin: 20px auto 10px auto;
    padding: 10px 30px 30px 30px;
    background: hsl(0, 0%, 100%);
    border: 2px solid hsl(210, 0%, 90%);
    border-radius: 20px;
}

h1 {
    margin: 5px 0 5px 0;
    color: hsl(210, 50%, 50%);
    font: bold 30px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
    text-align: center;
}
h2 {
    margin: 10px 0 2px 0;
    color: hsl(0, 50%, 50%);
    font: bold 20px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}


/*
    Main buttons
*/

ul {
    margin-left: 30px;
}

input[type=text].large {
    display: inline-block;
    width: 250px;
    padding: 5px 10px;
    border: 2px solid hsl(0, 0%, 80%);
    border-radius: 3px;
    height: 24px;
    background: transparent;
    font: normal 20px Tahoma, "Ubuntu Condensed";
    color: hsl(0, 0%, 20%);
}

input[type=text].medium {
    display: inline-block;
    width: 175px;
    padding: 2px 5px;
    border: 2px solid hsl(0, 0%, 80%);
    border-radius: 3px;
    height: 20px;
    background: transparent;
    font: normal 18px Tahoma, "Ubuntu Condensed";
    color: hsl(0, 0%, 20%);
}

input[placeholder] {
    color: hsl(0, 0%, 50%);
}


.dic_button {
    margin: 2px;
    display: inline-block;
}
.dic_button_close {
    display: inline-block;
    padding: 1px 5px;
    background-color: hsl(0, 50%, 50%);
    color: hsl(0, 90%, 90%);
    border-style: solid;
    border-width: 1px 0 1px 1px;
    border-color: hsl(0, 50%, 45%);
    border-radius: 3px 0 0 3px;
    cursor: pointer;
}
.dic_button_label {
    display: inline-block;
    padding: 1px 10px;
    background-color: hsl(120, 50%, 94%);
    border-style: solid;
    border-width: 1px 1px 1px 0;
    border-color: hsl(120, 50%, 70%);
    border-radius: 0 3px 3px 0;
}


/*
    Table
*/
#wait_progress {
    width: 100%;
    height: 4px;
}

table {
    border: 1px solid hsl(210, 10%, 50%);
    width: 100%;
    font-size: 14px;
}
th {
    padding: 5px 10px;
    border-left: 1px solid hsl(210, 10%, 90%);
    text-align: left;
}
td {
    padding: 0 10px;
    vertical-align: top;
}
.delete_entry {
    cursor: pointer;
    font-weight: bold;
    color: hsl(0, 100%, 50%);
}
.select_entry {
    cursor: pointer;
    background-color: hsl(120, 50%, 30%);
    color: hsl(120, 50%, 100%);
    border-radius: 3px;
    text-align: center;
}

Added gc_lang/fr/webext/panel/dictionaries.html version [30e1db6643].





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<!DOCTYPE HTML>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="dictionaries.css" />
    <title>Grammalecte · Dictionnaires communautaires</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  </head>

  <body>

    <div class="inbox">

      <h1>Dictionnaires communautaires</h1>

        <h2>Dictionnaires sélectionnés</h2>
        <p id="dictionaries_list">[Aucun]<p>

        <h2><span id="num_dic">0</span> dictionnaires disponibles</h2>
        <progress id="wait_progress" value="0"></progress>
        <table id="dictionaries_table">
        </table>

    </div>


    <script src="../grammalecte/graphspell/helpers.js"></script>
    <script src="../grammalecte/graphspell/char_player.js"></script>
    <script src="../grammalecte/graphspell/str_transform.js"></script>
    <script src="../grammalecte/graphspell/ibdawg.js"></script>
    <script src="../grammalecte/graphspell/spellchecker.js"></script>
    <script src="dictionaries.js"></script>
  </body>

</html>

Added gc_lang/fr/webext/panel/dictionaries.js version [85a136186d].



















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// JavaScript

"use strict";


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


/*
    Common functions
*/

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);
        if (oDataset) {
            Object.assign(xNode.dataset, oDataset);
        }
        return xNode;
    }
    catch (e) {
        showError(e);
    }
}



class Table {

    constructor (sNodeId, lColumn, sProgressBarId, sResultId="", bDeleteButtons=true, bActionButtons) {
        this.sNodeId = sNodeId;
        this.xTable = document.getElementById(sNodeId);
        this.nColumn = lColumn.length;
        this.lColumn = lColumn;
        this.xProgressBar = document.getElementById(sProgressBarId);
        this.xNumEntry = document.getElementById(sResultId);
        this.iEntryIndex = 0;
        this.lEntry = [];
        this.nEntry = 0;
        this.aSelectedDict = new Map();
        this.bDeleteButtons = bDeleteButtons;
        this.bActionButtons = bActionButtons;
        this._createHeader();
        this.listen();
    }

    _createHeader () {
        let xRowNode = createNode("tr");
        if (this.bDeleteButtons) {
            xRowNode.appendChild(createNode("th", { textContent: "·", width: "12px" }));
        }
        for (let sColumn of this.lColumn) {
            xRowNode.appendChild(createNode("th", { textContent: sColumn }));
        }
        this.xTable.appendChild(xRowNode);
    }

    clear () {
        while (this.xTable.firstChild) {
            this.xTable.removeChild(this.xTable.firstChild);
        }
        this.lEntry = [];
        this.nEntry = 0;
        this.iEntryIndex = 0;
        this._createHeader();
        this.showEntryNumber();
    }

    fill (lFlex) {
        this.clear();
        if (lFlex.length > 0) {
            this.xProgressBar.max = lFlex.length;
            this.xProgressBar.value = 1;
            for (let lData of lFlex) {
                this._addRow(lData);
                this.xProgressBar.value += 1;
            }
            this.xProgressBar.value = this.xProgressBar.max;
        }
        this.lEntry = lFlex;
        this.nEntry = lFlex.length;
        this.showEntryNumber();
    }

    addEntries (lFlex) {
        this.lEntry.push(...lFlex);
        for (let lData of lFlex) {
            this._addRow(lData);
        }
        this.nEntry += lFlex.length;
        this.showEntryNumber();
    }

    showEntryNumber () {
        if (this.xNumEntry) {
            this.xNumEntry.textContent = this.nEntry;
        }
    }

    _addRow (lData) {
        let xRowNode = createNode("tr", { id: this.sNodeId + "_row_" + this.iEntryIndex });
        if (this.bDeleteButtons) {
            xRowNode.appendChild(createNode("td", { textContent: "×", className: "delete_entry", title: "Effacer cette entrée" }, { id_entry: this.iEntryIndex }));
        }
        let [nDicId, sName, sOwner, nEntry, sDescription, ...data] = lData;
        xRowNode.appendChild(createNode("td", { textContent: nDicId }));
        xRowNode.appendChild(createNode("td", { textContent: sName }));
        xRowNode.appendChild(createNode("td", { textContent: sOwner }));
        xRowNode.appendChild(createNode("td", { textContent: nEntry }));
        xRowNode.appendChild(createNode("td", { textContent: sDescription }));
        if (this.bActionButtons) {
            xRowNode.appendChild(createNode("td", { textContent: "+", className: "select_entry", title: "Sélectionner/Désélectionner cette entrée" }, { id_entry: this.iEntryIndex, dict_name: sName }));
        }
        this.xTable.appendChild(xRowNode);
        this.iEntryIndex += 1;
    }

    listen () {
        if (this.bDeleteButtons || this.bActionButtons) {
            this.xTable.addEventListener("click", (xEvent) => { this.onTableClick(xEvent); }, false);
        }
    }

    onTableClick (xEvent) {
        try {
            let xElem = xEvent.target;
            if (xElem.className) {
                switch (xElem.className) {
                    case "delete_entry": this.deleteRow(xElem.dataset.id_entry, xElem.dataset.dict_name); break;
                    case "select_entry": this.selectEntry(xElem.dataset.id_entry, xElem.dataset.dict_name); break;
                }
            }
        }
        catch (e) {
            showError(e);
        }
    }

    deleteRow (iEntry) {
        this.lEntry[parseInt(iEntry)] = null;
        if (document.getElementById(this.sNodeId + "_row_" + iEntry)) {
            document.getElementById(this.sNodeId + "_row_" + iEntry).style.display = "none";
        }
        this.nEntry -= 1;
        this.showEntryNumber();
        if (this.sNodeId == "lexicon_table") {
            showElement("save_button", "inline-block");
        }
    }

    selectEntry (nEntryId, sDicName) {
        let sRowId = this.sNodeId + "_row_" + nEntryId;
        if (!this.aSelectedDict.has(sDicName)) {
            this.aSelectedDict.set(sDicName, nEntryId);
            document.getElementById(sRowId).style.backgroundColor = "hsl(120, 50%, 90%)";
        }
        else {
            this.aSelectedDict.delete(sDicName);
            document.getElementById(sRowId).style.backgroundColor = "";
        }
        this.showSelectedDict();
    }

    clearSelectedDict () {
        let xDicList = document.getElementById("dictionaries_list");
        while (xDicList.firstChild) {
            xDicList.removeChild(xDicList.firstChild);
        }
    }

    showSelectedDict () {
        this.clearSelectedDict();
        let xDicList = document.getElementById("dictionaries_list");
        if (this.aSelectedDict.size === 0) {
            xDicList.textContent = "[Aucun]";
            return;
        }
        for (let [sName, nDicId] of this.aSelectedDict) {
            xDicList.appendChild(this.createDictLabel(nDicId, sName));
        }
    }

    createDictLabel (nDicId, sLabel) {
        let xLabel = createNode("div", {className: "dic_button"});
        let xCloseButton = createNode("div", {className: "dic_button_close", textContent: "×"}, {id_entry: nDicId});
        xCloseButton.addEventListener("click", () => {
            this.aSelectedDict.delete(sLabel);
            document.getElementById(this.sNodeId+"_row_"+nDicId).style.backgroundColor = "";
            xLabel.style.display = "none";
        });
        xLabel.appendChild(xCloseButton);
        xLabel.appendChild(createNode("div", {className: "dic_button_label", textContent: sLabel}));
        return xLabel;
    }
}


const oDicTable = new Table("dictionaries_table", ["Id", "Nom", "par", "Entrées", "Description"], "wait_progress", "num_dic", false, true);

oDicTable.fill([
    [1, "Ambre", "Inconnu", "240", "Univers des Princes d’Ambre (de Roger Zelazny)"],
    [2, "Malaz", "Inconnu", "2340", "Univers du Livre des Martyrs (de Steven Erikson)"],
    [3, "Poudlard", "Inconnu", "1440", "Univers d’Harry Potter (de J. K. Rowlings)"],
    [4, "Dune", "Inconnu", "2359", "Univers de Dune (de Frank Herbert)"],
    [5, "StarWars", "Inconnu", "4359", "Univers de Star Wars (de George Lucas)"]
]);

Modified gc_lang/fr/webext/panel/lex_editor.css from [62f94b1b3b] to [3c7fbe9e7a].

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
    font: bold 20px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}
h3 {
    margin: 3px 0 2px 0;
    color: hsl(210, 50%, 50%);
    font: bold 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}






details {
    font-size: 11px;
    font-variant: small-caps;
    color: hsl(210, 50%, 50%);
    cursor: pointer;
}
details > * {
    font-size: 12px;
    font-variant: normal;
    color: hsl(210, 0%, 0%);
    cursor: auto;
}
details.inline {
    padding: 3px;
    width: 260px;
}



/*
    Main buttons
*/
#buttons {
    padding: 10px 0;
    justify-content: center;
}
.main_button {
    margin: 0 5px;
    width: 100px;
    padding: 10px 20px;
    background-color: hsl(210, 10%, 95%);
    border-radius: 5px;
    text-align: center;
    cursor: pointer;
}
#lexicon_button {







>
>
>
>
>


















>










|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    font: bold 20px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}
h3 {
    margin: 3px 0 2px 0;
    color: hsl(210, 50%, 50%);
    font: bold 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}

#dic_selector {
    color: hsl(210, 50%, 50%);
    font: bold 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}

details {
    font-size: 11px;
    font-variant: small-caps;
    color: hsl(210, 50%, 50%);
    cursor: pointer;
}
details > * {
    font-size: 12px;
    font-variant: normal;
    color: hsl(210, 0%, 0%);
    cursor: auto;
}
details.inline {
    padding: 3px;
    width: 260px;
}



/*
    Main buttons
*/
#buttons {
    padding: 10px 0;
    justify-content: center;
}
.main_button {
    margin: 0 5px;
    min-width: 100px;
    padding: 10px 20px;
    background-color: hsl(210, 10%, 95%);
    border-radius: 5px;
    text-align: center;
    cursor: pointer;
}
#lexicon_button {
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
    background-color: hsl(150, 60%, 40%);
    color: hsl(150, 60%, 90%);
    box-shadow: 0 0 2px hsl(150, 60%, 50%);
}


#lexicon_page {
    
}


/*
    Search page
*/
#search_page {







|







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    background-color: hsl(150, 60%, 40%);
    color: hsl(150, 60%, 90%);
    box-shadow: 0 0 2px hsl(150, 60%, 50%);
}


#lexicon_page {

}


/*
    Search page
*/
#search_page {
292
293
294
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
    width: 500px;
}


/*
    Dictionary
*/
#save_button, #export_button, #import_button {
    display: none;
    float: right;
    padding: 2px 10px;
    background-color: hsl(150, 50%, 50%);
    color: hsl(150, 0%, 100%);
    border-radius: 3px;
    cursor: pointer;
}
#export_button, #import_button {
    display: block;
    margin-left: 5px;


    background-color: hsl(210, 50%, 50%);
    color: hsl(210, 0%, 100%);


}

#wait_progress {
    width: 100%;
    height: 4px;
}


/*







|

|
|








>
>


>
>

>







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
    width: 500px;
}


/*
    Dictionary
*/
#save_button {
    display: none;
    margin-left: 5px;
    padding: 1px 5px;
    background-color: hsl(150, 50%, 50%);
    color: hsl(150, 0%, 100%);
    border-radius: 3px;
    cursor: pointer;
}
#export_button, #import_button {
    display: block;
    margin-left: 5px;
    float: right;
    padding: 2px 10px;
    background-color: hsl(210, 50%, 50%);
    color: hsl(210, 0%, 100%);
    border-radius: 3px;
    cursor: pointer;
}

#wait_progress {
    width: 100%;
    height: 4px;
}


/*

Modified gc_lang/fr/webext/panel/lex_editor.html from [66bbff43be] to [18a9eff11b].

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
<!DOCTYPE HTML>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="lex_editor.css" />
    <title>Grammalecte · Éditeur lexical</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  </head>
  
  <body>

    <div class="inbox">

      <h1>Éditeur lexical</h1>

      <div class="big_block">
        <div class="dic_container">
          <div><h3>Dictionnaire personnel</h3></div>






          <div>Enregistré le : <span id="dic_save_date">—</span></div>
          <div><span id="dic_num_entries">0</span> entrées</div>
          <!--<div id="import_button" class="fright">Importer</div>-->
          <div class="fright">
            <input type="file" id="import_input" accept=".json" style="display: none;">
            <label id="import_button" for="import_input">Importer</label>
          </div>
          <div id="export_button" class="fright">Exporter</div>



        </div>
        <progress id="wait_progress" value="0"></progress>
      </div>

      <div id="buttons" class="container">
        <div id="lexicon_button" class="main_button">Lexique</div>


        <div id="add_button" class="main_button">Ajout</div>
        <div id="search_button" class="main_button">Recherche</div>
        <div id="info_button" class="main_button">Informations</div>
      </div>

      <div id="add_page">
        <div class="columns">







|








|
>
>
>
>
>
>
|

<
|



|
>
>






|
>
>







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
<!DOCTYPE HTML>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="lex_editor.css" />
    <title>Grammalecte · Éditeur lexical</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  </head>

  <body>

    <div class="inbox">

      <h1>Éditeur lexical</h1>

      <div class="big_block">
        <div class="dic_container">
          <div><h3>Dictionnaire</h3></div>
          <div>
            <select id="dic_selector">
              <option value="__personal__">personnel</option>
              <option value="__community__">communautaire</option>
            </select>
          </div>
          <div>[<span id="dic_save_date">—</span>]</div>
          <div><span id="dic_num_entries">0</span> entrées</div>

          <div>
            <input type="file" id="import_input" accept=".json" style="display: none;">
            <label id="import_button" for="import_input">Importer</label>
          </div>
          <div id="export_button">Exporter</div>
        </div>
        <div class="dic_container">

        </div>
        <progress id="wait_progress" value="0"></progress>
      </div>

      <div id="buttons" class="container">
        <div id="lexicon_button" class="main_button">
          Lexique · <span id="num_entries">0</span> entrées <span id="save_button">Enregistrer</span>
        </div>
        <div id="add_button" class="main_button">Ajout</div>
        <div id="search_button" class="main_button">Recherche</div>
        <div id="info_button" class="main_button">Informations</div>
      </div>

      <div id="add_page">
        <div class="columns">
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
                      <details class="inline">
                        <div class="container">
                          <div class="examples_true">Je suis venu.<br/>Je suis parti.</div>
                          <div class="examples_false">J’ai venu.<br/>J’ai parti.</div>
                        </div>
                      </details>
                    </div>
                      
                    <div class="space_container">
                      <div>
                        <input type="checkbox" id="up_v_aa" value="a" /><label for="up_v_aa"> avoir</label>
                      </div>
                      <details class="inline">
                        <div class="container">
                          <div class="examples_true">J’ai mangé.<br/>J’ai prié.</div>







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
                      <details class="inline">
                        <div class="container">
                          <div class="examples_true">Je suis venu.<br/>Je suis parti.</div>
                          <div class="examples_false">J’ai venu.<br/>J’ai parti.</div>
                        </div>
                      </details>
                    </div>

                    <div class="space_container">
                      <div>
                        <input type="checkbox" id="up_v_aa" value="a" /><label for="up_v_aa"> avoir</label>
                      </div>
                      <details class="inline">
                        <div class="container">
                          <div class="examples_true">J’ai mangé.<br/>J’ai prié.</div>
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
                  <p><input type="text" id="flexion" name="flexion" class="large" maxlength="20" value="" pattern="^[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ._-]+$" placeholder="flexion" /></p>
                  <h3>Étiquettes</h3>
                  <p><input type="text" id="tags" name="tags" class="large" maxlength="20" value="" pattern="^:[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ:._-]+$" placeholder="étiquettes" /></p>
                </div>
              </div>
            </div>
          </div> <!-- #new_word_generator -->
          
          <div id="generated_words">
            <h2>Mots générés</h2>
            <table id="generated_words_table">
              
            </table>
            <div id="buttonline">
              <div id="add_to_lexicon">Ajouter au lexique</div>
            </div>
          </div> <!-- #generated_words -->
        </div> <!-- .columns -->
      </div> <!-- #add_page -->


      <div id="lexicon_page">
        <h2>Votre lexique</h2>
        <div class="big_block">
          <div id="save_button" class="fright">
            Enregistrer
          </div>
          <p>Nombre d’entrées : <span id="num_entries">0</span>.</p>
        </div>

        <table id="lexicon_table">
              
        </table>
      </div> <!-- #lexicon_page -->


      <div id="search_page">
        <div class="columns">
          <div style="margin-right: 20px;">







|



|











<
<
<
<
<
<
<

|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258







259
260
261
262
263
264
265
266
267
                  <p><input type="text" id="flexion" name="flexion" class="large" maxlength="20" value="" pattern="^[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ._-]+$" placeholder="flexion" /></p>
                  <h3>Étiquettes</h3>
                  <p><input type="text" id="tags" name="tags" class="large" maxlength="20" value="" pattern="^:[a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ:._-]+$" placeholder="étiquettes" /></p>
                </div>
              </div>
            </div>
          </div> <!-- #new_word_generator -->

          <div id="generated_words">
            <h2>Mots générés</h2>
            <table id="generated_words_table">

            </table>
            <div id="buttonline">
              <div id="add_to_lexicon">Ajouter au lexique</div>
            </div>
          </div> <!-- #generated_words -->
        </div> <!-- .columns -->
      </div> <!-- #add_page -->


      <div id="lexicon_page">
        <h2>Votre lexique</h2>







        <table id="lexicon_table">

        </table>
      </div> <!-- #lexicon_page -->


      <div id="search_page">
        <div class="columns">
          <div style="margin-right: 20px;">
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

            <p style="margin-top: 50px;">La recherche par expressions régulières peut générer un nombre gigantesque de résultats. Seules les 2000 premières occurrences trouvées seront affichées. La recherche peut être longue, parce tout le graphe de mots, qui contient 500 000 flexions, sera parcouru si besoin.</p>
          </div>

          <div>
            <h2>Résultats</h2>
            <table id="search_table">
                  
            </table>
          </div>
        </div>
      </div> <!-- #search_page -->


      <div id="info_page">







|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295

            <p style="margin-top: 50px;">La recherche par expressions régulières peut générer un nombre gigantesque de résultats. Seules les 2000 premières occurrences trouvées seront affichées. La recherche peut être longue, parce tout le graphe de mots, qui contient 500 000 flexions, sera parcouru si besoin.</p>
          </div>

          <div>
            <h2>Résultats</h2>
            <table id="search_table">

            </table>
          </div>
        </div>
      </div> <!-- #search_page -->


      <div id="info_page">
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
334
335
336
337

            <h3>Étiquettes rares</h3>
            <p>Il est déconseillé d’utiliser la catégorie ‹Autre› pour générer autre chose que des noms, des adjectifs, des noms propres, des verbes et des adverbes. Il n’y a aucune garantie que les étiquettes pour les autres catégories, notamment les mots grammaticaux, ne changeront pas.</p>
          </div>

          <div>
            <table id="tags_table">
              
            </table>
          </div>
        </div>
      </div> <!-- #info_page -->

    </div>


    <script src="../grammalecte/graphspell/helpers.js"></script>
    <script src="../grammalecte/graphspell/char_player.js"></script>
    <script src="../grammalecte/graphspell/str_transform.js"></script>
    <script src="../grammalecte/graphspell/dawg.js"></script>
    <script src="../grammalecte/graphspell/ibdawg.js"></script>
    <script src="../grammalecte/graphspell/spellchecker.js"></script>
    <script src="../grammalecte/fr/conj.js"></script>
    <script src="../grammalecte/fr/conj_generator.js"></script>
    <script src="../grammalecte/fr/lexicographe.js"></script>
    <script src="lex_editor.js"></script>
  </body>
  
</html>







|



















|

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

            <h3>Étiquettes rares</h3>
            <p>Il est déconseillé d’utiliser la catégorie ‹Autre› pour générer autre chose que des noms, des adjectifs, des noms propres, des verbes et des adverbes. Il n’y a aucune garantie que les étiquettes pour les autres catégories, notamment les mots grammaticaux, ne changeront pas.</p>
          </div>

          <div>
            <table id="tags_table">

            </table>
          </div>
        </div>
      </div> <!-- #info_page -->

    </div>


    <script src="../grammalecte/graphspell/helpers.js"></script>
    <script src="../grammalecte/graphspell/char_player.js"></script>
    <script src="../grammalecte/graphspell/str_transform.js"></script>
    <script src="../grammalecte/graphspell/dawg.js"></script>
    <script src="../grammalecte/graphspell/ibdawg.js"></script>
    <script src="../grammalecte/graphspell/spellchecker.js"></script>
    <script src="../grammalecte/fr/conj.js"></script>
    <script src="../grammalecte/fr/conj_generator.js"></script>
    <script src="../grammalecte/fr/lexicographe.js"></script>
    <script src="lex_editor.js"></script>
  </body>

</html>

Modified gc_lang/fr/webext/panel/lex_editor.js from [1df07baa4c] to [380093a31f].

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
        return xNode;
    }
    catch (e) {
        showError(e);
    }
}

function showElement (sElemId) {
    if (document.getElementById(sElemId)) {
        document.getElementById(sElemId).style.display = "block";
    } else {
        console.log("HTML node named <" + sElemId + "> not found.")
    }
}

function hideElement (sElemId) {
    if (document.getElementById(sElemId)) {







|

|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
        return xNode;
    }
    catch (e) {
        showError(e);
    }
}

function showElement (sElemId, sDisplay="block") {
    if (document.getElementById(sElemId)) {
        document.getElementById(sElemId).style.display = sDisplay;
    } else {
        console.log("HTML node named <" + sElemId + "> not found.")
    }
}

function hideElement (sElemId) {
    if (document.getElementById(sElemId)) {
123
124
125
126
127
128
129


130
131

132
133
134
135
136
137
138
        this.xTable.appendChild(xRowNode);
    }

    clear () {
        while (this.xTable.firstChild) {
            this.xTable.removeChild(this.xTable.firstChild);
        }


        this.iEntryIndex = 0;
        this._createHeader();

    }

    fill (lFlex) {
        this.clear();
        if (lFlex.length > 0) {
            this.xProgressBar.max = lFlex.length;
            this.xProgressBar.value = 1;







>
>


>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
        this.xTable.appendChild(xRowNode);
    }

    clear () {
        while (this.xTable.firstChild) {
            this.xTable.removeChild(this.xTable.firstChild);
        }
        this.lEntry = [];
        this.nEntry = 0;
        this.iEntryIndex = 0;
        this._createHeader();
        this.showEntryNumber();
    }

    fill (lFlex) {
        this.clear();
        if (lFlex.length > 0) {
            this.xProgressBar.max = lFlex.length;
            this.xProgressBar.value = 1;
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
        this.lEntry[parseInt(iEntry)] = null;
        if (document.getElementById(this.sNodeId + "_row_" + iEntry)) {
            document.getElementById(this.sNodeId + "_row_" + iEntry).style.display = "none";
        }
        this.nEntry -= 1;
        this.showEntryNumber();
        if (this.sNodeId == "lexicon_table") {
            showElement("save_button");
        }
    }

    getEntries () {
        return this.lEntry.filter((e) => e !== null);
    }
}







|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
        this.lEntry[parseInt(iEntry)] = null;
        if (document.getElementById(this.sNodeId + "_row_" + iEntry)) {
            document.getElementById(this.sNodeId + "_row_" + iEntry).style.display = "none";
        }
        this.nEntry -= 1;
        this.showEntryNumber();
        if (this.sNodeId == "lexicon_table") {
            showElement("save_button", "inline-block");
        }
    }

    getEntries () {
        return this.lEntry.filter((e) => e !== null);
    }
}
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510





511





512

513













514















515
516
517
518
519

520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
        try {
            oLexiconTable.addEntries(this.createFlexLemmaTagArray());
            oGenWordsTable.clear();
            document.getElementById("lemma").value = "";
            document.getElementById("lemma").focus();
            this.hideAllSections();
            hideElement("editor");
            showElement("save_button");
            this.clear();
            this.cMainTag = "";
        }
        catch (e) {
            showError(e);
        }
    }
}


const oBinaryDict = {

    oIBDAWG: null,

    load: function () {
        if (bChrome) {
            browser.storage.local.get("oPersonalDictionary", this._load.bind(this));
            return;
        }
        let xPromise = browser.storage.local.get("oPersonalDictionary");
        xPromise.then(this._load.bind(this), showError);
    },

    _load: function (oResult) {
        if (!oResult.hasOwnProperty("oPersonalDictionary")) {





            hideElement("export_button");





            return;

        }













        let oJSON = oResult.oPersonalDictionary;















        if (oJSON) {
            this.__load(oJSON);
        } else {
            oLexiconTable.clear();
            this.setDictData(0, "[néant]");

        }
    },

    __load: function (oJSON) {
        try {
            this.oIBDAWG = new IBDAWG(oJSON);
        }
        catch (e) {
            console.error(e);
            this.setDictData(0, "#Erreur. Voir la console.");
            return;
        }
        let lEntry = [];
        for (let aRes of this.oIBDAWG.select()) {
            lEntry.push(aRes);
        }
        oLexiconTable.fill(lEntry);
        this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
    },

    save: function (oJSON) {
        browser.storage.local.set({ "oPersonalDictionary": oJSON });
        browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sDictionary: "personal", oDict: oJSON}, dInfo: {} });
    },

    import: function () {
        let xInput = document.getElementById("import_input");
        let xFile = xInput.files[0];
        let xURL = URL.createObjectURL(xFile);
        let sJSON = helpers.loadFile(xURL);
        if (sJSON) {
            try {
                let oJSON = JSON.parse(sJSON);
                this.__load(oJSON);
                this.save(oJSON);
            }
            catch (e) {
                console.error(e);
                this.setDictData(0, "#Erreur. Voir la console.");
                return;
            }
        } else {
            this.setDictData(0, "[néant]");
            this.save(null);
        }
    },

    setDictData: function (nEntries, sDate) {
        document.getElementById("dic_num_entries").textContent = nEntries;
        document.getElementById("dic_save_date").textContent = sDate;
        if (nEntries == 0) {
            hideElement("export_button");
        } else {
            showElement("export_button");
        }
    },

    listen: function () {

        document.getElementById("save_button").addEventListener("click", () => { this.build(); }, false);
        document.getElementById("export_button").addEventListener("click", () => { this.export(); }, false);
        document.getElementById("import_input").addEventListener("change", () => { this.import(); }, false);
    },

    build: function () {
        let xProgressNode = document.getElementById("wait_progress");
        let lEntry = oLexiconTable.getEntries();
        if (lEntry.length > 0) {
            let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "fr.personal", xProgressNode);
            let oJSON = oDAWG.createBinaryJSON(1);
            this.save(oJSON);
            this.oIBDAWG = new IBDAWG(oJSON);
            this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
        } else {

            this.setDictData(0, "[néant]");
            this.save(null);
        }
        hideElement("save_button");
    },

    export: function () {
        let xBlob = new Blob([ JSON.stringify(this.oIBDAWG.getJSON()) ], {type: 'application/json'});
        let sURL = URL.createObjectURL(xBlob);
        browser.downloads.download({ filename: "fr.personal.json", url: sURL, saveAs: true });
    }
}


const oSearch = {

    oSpellChecker: null,







|









|
<
<
|

|

|


|
|


|
|
>
>
>
>
>
|
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|



>



|














<
|
<
<
<










|
|








|














>









|

|



>

<







|







481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498


499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

579



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
        try {
            oLexiconTable.addEntries(this.createFlexLemmaTagArray());
            oGenWordsTable.clear();
            document.getElementById("lemma").value = "";
            document.getElementById("lemma").focus();
            this.hideAllSections();
            hideElement("editor");
            showElement("save_button", "inline-block");
            this.clear();
            this.cMainTag = "";
        }
        catch (e) {
            showError(e);
        }
    }
}

const oDictHandler = {


    oDictionaries: null,

    loadDictionaries: function () {
        if (bChrome) {
            browser.storage.local.get("dictionaries", this._loadDictionaries.bind(this));
            return;
        }
        let xPromise = browser.storage.local.get("dictionaries");
        xPromise.then(this._loadDictionaries.bind(this), showError);
    },

    _loadDictionaries: function (oResult) {
        if (!oResult.hasOwnProperty("dictionaries")) {
            return;
        }
        this.oDictionaries = oResult.dictionaries;
        oBinaryDict.load("__personal__");
    },

    getDictionary: function (sName) {
        if (this.oDictionaries  &&  this.oDictionaries.hasOwnProperty(sName)) {
            //console.log(this.oDictionaries[sName]);
            return this.oDictionaries[sName];
        }
        return null;
    },

    saveDictionary: function (sName, oJSON) {
        this.oDictionaries[sName] = oJSON;
        if (sName == "__personal__") {
            browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sDictionary: "personal", oDict: oJSON}, dInfo: {} });
        }
        else if (sName == "__community__") {
            browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sDictionary: "community", oDict: oJSON}, dInfo: {} });
        }
        else {
            // TODO: merge sub-dictionaries
        }
        this.storeDictionaries();
    },

    storeDictionaries: function () {
        browser.storage.local.set({ "dictionaries": this.oDictionaries });
    }
}

const oBinaryDict = {

    oIBDAWG: null,
    sName: "",
    sDescription: "",

    load: function (sName) {
        console.log("lexicon editor, load: " + sName);
        this.sName = sName;
        let oJSON = oDictHandler.getDictionary(sName);
        if (oJSON) {
            this.parseDict(oJSON);
        } else {
            oLexiconTable.clear();
            this.setDictData(0, "[néant]");
            hideElement("save_button");
        }
    },

    parseDict: function (oJSON) {
        try {
            this.oIBDAWG = new IBDAWG(oJSON);
        }
        catch (e) {
            console.error(e);
            this.setDictData(0, "#Erreur. Voir la console.");
            return;
        }
        let lEntry = [];
        for (let aRes of this.oIBDAWG.select()) {
            lEntry.push(aRes);
        }
        oLexiconTable.fill(lEntry);
        this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);

        hideElement("save_button");



    },

    import: function () {
        let xInput = document.getElementById("import_input");
        let xFile = xInput.files[0];
        let xURL = URL.createObjectURL(xFile);
        let sJSON = helpers.loadFile(xURL);
        if (sJSON) {
            try {
                let oJSON = JSON.parse(sJSON);
                this.parseDict(oJSON);
                oDictHandler.saveDictionary(this.sName, oJSON);
            }
            catch (e) {
                console.error(e);
                this.setDictData(0, "#Erreur. Voir la console.");
                return;
            }
        } else {
            this.setDictData(0, "[néant]");
            oDictHandler.saveDictionary(this.sName, null);
        }
    },

    setDictData: function (nEntries, sDate) {
        document.getElementById("dic_num_entries").textContent = nEntries;
        document.getElementById("dic_save_date").textContent = sDate;
        if (nEntries == 0) {
            hideElement("export_button");
        } else {
            showElement("export_button");
        }
    },

    listen: function () {
        document.getElementById("dic_selector").addEventListener("change", () => {this.load(document.getElementById("dic_selector").value)}, false);
        document.getElementById("save_button").addEventListener("click", () => { this.build(); }, false);
        document.getElementById("export_button").addEventListener("click", () => { this.export(); }, false);
        document.getElementById("import_input").addEventListener("change", () => { this.import(); }, false);
    },

    build: function () {
        let xProgressNode = document.getElementById("wait_progress");
        let lEntry = oLexiconTable.getEntries();
        if (lEntry.length > 0) {
            let oDAWG = new DAWG(lEntry, "S", "fr", "Français", this.sName, this.sDescription, xProgressNode);
            let oJSON = oDAWG.createBinaryJSON(1);
            oDictHandler.saveDictionary(this.sName, oJSON);
            this.oIBDAWG = new IBDAWG(oJSON);
            this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
        } else {
            oDictHandler.saveDictionary(this.sName, null);
            this.setDictData(0, "[néant]");

        }
        hideElement("save_button");
    },

    export: function () {
        let xBlob = new Blob([ JSON.stringify(this.oIBDAWG.getJSON()) ], {type: 'application/json'});
        let sURL = URL.createObjectURL(xBlob);
        browser.downloads.download({ filename: "fr."+this.sName+".json", url: sURL, saveAs: true });
    }
}


const oSearch = {

    oSpellChecker: null,
662
663
664
665
666
667
668
669
670
671
672
673
const oLexiconTable = new Table("lexicon_table", ["Flexions", "Lemmes", "Étiquettes"], "wait_progress", "num_entries");
const oSearchTable = new Table("search_table", ["Flexions", "Lemmes", "Étiquettes"], "wait_progress", "search_num_entries", false);
const oTagsTable = new Table("tags_table", ["Étiquette", "Signification"], "wait_progress", "", false);


oTagsInfo.load();
oSearch.load();
oBinaryDict.load();
oBinaryDict.listen();
oGenerator.listen();
oTabulations.listen();
oSearch.listen();







|




700
701
702
703
704
705
706
707
708
709
710
711
const oLexiconTable = new Table("lexicon_table", ["Flexions", "Lemmes", "Étiquettes"], "wait_progress", "num_entries");
const oSearchTable = new Table("search_table", ["Flexions", "Lemmes", "Étiquettes"], "wait_progress", "search_num_entries", false);
const oTagsTable = new Table("tags_table", ["Étiquette", "Signification"], "wait_progress", "", false);


oTagsInfo.load();
oSearch.load();
oDictHandler.loadDictionaries();
oBinaryDict.listen();
oGenerator.listen();
oTabulations.listen();
oSearch.listen();

Modified gc_lang/fr/webext/panel/main.css from [85a3951146] to [2045c317c1].

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    height: 500px;
    font-family: "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}
body {
    width: 450px;
    height: 500px;
}
/* 
    Maximal height of a panel in WebExtention seems to be 500px.
    When going over this limit, a scrollbar appears which destructs the
    horizontal balance of elements.
    --> vertical scrolling is done with overflow in #page.
        #page must have the same height than body.
*/








|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    height: 500px;
    font-family: "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
}
body {
    width: 450px;
    height: 500px;
}
/*
    Maximal height of a panel in WebExtention seems to be 500px.
    When going over this limit, a scrollbar appears which destructs the
    horizontal balance of elements.
    --> vertical scrolling is done with overflow in #page.
        #page must have the same height than body.
*/

243
244
245
246
247
248
249



















250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269




270
271
272
273
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289


290
291
292
293
294
295
296
    padding: 5px 10px;
    border-radius: 3px;
    font-size: 16px;
    text-align: center;
    cursor: pointer;
}





















/*
    Spell checking options
*/
#sc_options_page {
    display: none;
    padding: 20px;
}
.dictionaries_info {
    margin: 10px 0;
    padding: 10px;
    border-radius: 3px;
    background-color: hsl(0, 50%, 40%);
    color: hsl(0, 10%, 96%);
}
#sc_options_page h2 {
    margin-top: 20px;
    font: normal 22px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif;
    color: hsl(210, 50%, 50%);
}





/*
    Options
*/
.option_section {

    padding: 10px;
    margin-top: 10px;
    border-radius: 5px;
    background-color: hsl(210, 20%, 96%);
}
.option_section label {
    font-size: 16px;
    line-height: 20px;
    color: hsl(210, 20%, 50%);
    font-weight: bold;
}
.option_description {
    padding: 0 0 0 20px;
    color: hsl(0, 0%, 0%);
    font-size: 12px;


}


/*
  Test page
*/
#test_page {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















>
>
>
>
|
<
<
<
|
>
|
<
<
|
<
<
<
<
|
<
<
<
<
|
|
>
>







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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
305
306
307
308
309
    padding: 5px 10px;
    border-radius: 3px;
    font-size: 16px;
    text-align: center;
    cursor: pointer;
}


.option_section {
    padding: 10px;
    margin-top: 10px;
    border-radius: 5px;
    background-color: hsl(210, 20%, 96%);
}
.option_section label {
    font-size: 16px;
    line-height: 20px;
    color: hsl(210, 20%, 50%);
    font-weight: bold;
}
.option_description {
    padding: 0 0 0 20px;
    color: hsl(0, 0%, 0%);
    font-size: 12px;
}


/*
    Spell checking options
*/
#sc_options_page {
    display: none;
    padding: 20px;
}
.dictionaries_info {
    margin: 10px 0;
    padding: 10px;
    border-radius: 3px;
    background-color: hsl(0, 50%, 40%);
    color: hsl(0, 10%, 96%);
}
#sc_options_page h2 {
    margin-top: 20px;
    font: normal 22px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif;
    color: hsl(210, 50%, 50%);
}
.button_row {
    display: flex;
    flex-direction: row-reverse;
    padding: 5px 0 0 0;
}



.dic_button {
    margin-left: 10px;
    padding: 2px 10px;


    background-color: hsl(210, 50%, 50%);




    color: hsl(210, 10%, 96%);




    cursor: pointer;
    font-size: 14px;
    font-variant-caps: small-caps;
    border-radius: 3px;
}


/*
  Test page
*/
#test_page {
370
371
372
373
374
375
376
377
378
379
380
381
382
    animation: sk-bounce 2.0s infinite ease-in-out;
}
.double-bounce2 {
    animation-delay: -1.0s;
}

@keyframes sk-bounce {
    0%, 100% { 
        transform: scale(0.0);
    } 50% { 
        transform: scale(1.0);
    }
}







|

|



383
384
385
386
387
388
389
390
391
392
393
394
395
    animation: sk-bounce 2.0s infinite ease-in-out;
}
.double-bounce2 {
    animation-delay: -1.0s;
}

@keyframes sk-bounce {
    0%, 100% {
        transform: scale(0.0);
    } 50% {
        transform: scale(1.0);
    }
}

Modified gc_lang/fr/webext/panel/main.html from [c94c7f3f57] to [05a014ebfd].

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
          <h2>Raccourcis clavier</h2>
          <p class="shortcut">CTRL+MAJ+6</p>
          <p class="shortcut_label">Conjugueur (dans un onglet)</p>
          <p class="shortcut">CTRL+MAJ+7</p>
          <p class="shortcut_label">Conjugueur (dans une fenêtre)</p>
          <p class="shortcut">CTRL+MAJ+8</p>
          <p class="shortcut_label">Éditeur lexical</p>


        </section> <!-- #ui_options_page -->

        <section id="gc_options_page" class="page">
          <h1>OPTIONS GRAMMATICALES</h1>
          <div id="grammar_options">
            ${webextOptionsHTML}
          </div>
          <div id="default_options_button" class="button blue center">Options par défaut</div>
        </section> <!-- #gc_options_page -->

        <section id="sc_options_page" class="page">
          <h1>OPTIONS ORTHOGRAPHIQUES</h1>
          <div id="hunspell_options">
            <h2>DICTIONNAIRES DE GRAMMALECTE</h2>
            <p class="dictionaries_info">Ces dictionnaires ne sont utilisés que lors de l’analyse grammaticale.</p>
            <div class="option_section" id="main_dic_box">
                <p><input type="checkbox" id="main_dic" data-dictionary="personal" checked disabled="disabled" /> <label for="main_dic">Dictionnaire principal</label></p>
                <p class="option_description">Environ 83 000 entrées, 500 000 flexions.<br/>Ni éditable, ni désactivable.</p>
            </div>
            <div class="option_section" id="extended_dic_box" style="opacity: .33;">
                <p><input type="checkbox" id="extended_dic" data-dictionary="personal" disabled="disabled" /> <label for="extended_dic">Dictionnaire étendu</label></p>
                <p class="option_description">Fonctionnalité à venir.</p>



            </div>
            <div class="option_section" id="community_dic_box" style="opacity: .33;">
                <p><input type="checkbox" id="community_dic" data-dictionary="personal" disabled="disabled" /> <label for="community_dic">Dictionnaire communautaire</label></p>
                <p class="option_description">Fonctionnalité à venir.</p>
            </div>
            <div class="option_section" id="personal_dic_box">
                <p><input type="checkbox" id="personal_dic" data-dictionary="personal" /> <label for="personal_dic">Dictionnaire personnel</label></p>
                <p class="option_description">Ce dictionnaire est créé et édité via l’éditeur lexical.</p>



            </div>
          </div>

          <div id="hunspell_options" style="display: none; opacity: .25">
            <h2>DICTIONNAIRES HUNSPELL</h2>
            <p class="dictionaries_info">Les dictionnaires Hunspell ne sont utilisées que pour la correction orthographique proposée par Firefox (soulignement rouge).<br/><br/>Section inactive.<br/>Le système d’extension <i>WebExtension</i> ne propose pas encore d’interface de programmation pour le correcteur orthographique.</p>
            <div class="option_section" id="fr-FR-modern_box">







>
>














<

|
|

|
|
|
>
>
>
|
<
<
<



|
>
>
>







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
          <h2>Raccourcis clavier</h2>
          <p class="shortcut">CTRL+MAJ+6</p>
          <p class="shortcut_label">Conjugueur (dans un onglet)</p>
          <p class="shortcut">CTRL+MAJ+7</p>
          <p class="shortcut_label">Conjugueur (dans une fenêtre)</p>
          <p class="shortcut">CTRL+MAJ+8</p>
          <p class="shortcut_label">Éditeur lexical</p>
          <p class="shortcut">CTRL+MAJ+9</p>
          <p class="shortcut_label">Dictionnaires communautaires</p>
        </section> <!-- #ui_options_page -->

        <section id="gc_options_page" class="page">
          <h1>OPTIONS GRAMMATICALES</h1>
          <div id="grammar_options">
            ${webextOptionsHTML}
          </div>
          <div id="default_options_button" class="button blue center">Options par défaut</div>
        </section> <!-- #gc_options_page -->

        <section id="sc_options_page" class="page">
          <h1>OPTIONS ORTHOGRAPHIQUES</h1>
          <div id="hunspell_options">
            <h2>DICTIONNAIRES DE GRAMMALECTE</h2>

            <div class="option_section" id="main_dic_box">
                <p><input type="checkbox" id="main_dic" data-dictionary="main" checked disabled="disabled" /> <label for="main_dic">Dictionnaire principal</label></p>
                <p class="option_description">Environ 83 000 entrées, 500 000 flexions.<br/>Ni éditable, ni désactivable.<br/>Ce dictionnaire est créé à partir du dictionnaire orthographique pour Firefox et LibreOffice, conçu sur le <a id="link_grammalecte" class="link" data-url="http://grammalecte.net/home.php?prj=fr">site de Grammalecte</a>.</p>
            </div>
            <div class="option_section" id="community_dic_box">
                <p><input type="checkbox" id="community_dic" data-dictionary="community" /> <label for="community_dic">Dictionnaire communautaire</label></p>
                <p class="option_description">Ce dictionnaire est créé et édité via l’éditeur lexical et est sauvegardé sur un serveur en ligne accessible à tous les membres.</p>
                <div class="button_row">
                  <div class="dic_button" id="dic_community_button">Éditer</div>
                  <div class="dic_button" id="dictionaries_button">Dictionnaires en ligne</div>
                </div>



            </div>
            <div class="option_section" id="personal_dic_box">
                <p><input type="checkbox" id="personal_dic" data-dictionary="personal" /> <label for="personal_dic">Dictionnaire personnel</label></p>
                <p class="option_description">Ce dictionnaire est créé et édité via l’éditeur lexical et n’est pas partagé.</p>
                <div class="button_row">
                  <div class="dic_button" id="dic_personal_button">Éditer</div>
                </div>
            </div>
          </div>

          <div id="hunspell_options" style="display: none; opacity: .25">
            <h2>DICTIONNAIRES HUNSPELL</h2>
            <p class="dictionaries_info">Les dictionnaires Hunspell ne sont utilisées que pour la correction orthographique proposée par Firefox (soulignement rouge).<br/><br/>Section inactive.<br/>Le système d’extension <i>WebExtension</i> ne propose pas encore d’interface de programmation pour le correcteur orthographique.</p>
            <div class="option_section" id="fr-FR-modern_box">

Modified gc_lang/fr/webext/panel/main.js from [d7a3e529e8] to [5094773a1c].

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
            else if (xElem.id.startsWith("ui_option_")) {
                storeUIOptions();
            }
            else if (xElem.id.startsWith("link_")) {
                browser.tabs.create({url: xElem.dataset.url});
            }
            else if (xElem.id == "conj_button") {

                openConjugueurTab();
























            }
        } else if (xElem.className.startsWith("select")) {
            showPage(xElem.dataset.page);
        }/* else if (xElem.tagName === "A") {
            openURL(xElem.getAttribute("href"));
        }*/
    },
    false
);


/* 
    Message sender
    and response handling
*/
function handleResponse (oResponse) {
    console.log(`[Panel] received:`);
    console.log(oResponse);
}

function handleError (error) {
    console.log(`[Panel] Error:`);
    console.log(error);
}

function sendMessageAndWaitResponse (oData) {
    let xPromise = browser.runtime.sendMessage(oData);
    xPromise.then(handleResponse, handleError);  
}


/*
    Messages received
*/
function handleMessage (oMessage, xSender, sendResponse) {







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|















|







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
            else if (xElem.id.startsWith("ui_option_")) {
                storeUIOptions();
            }
            else if (xElem.id.startsWith("link_")) {
                browser.tabs.create({url: xElem.dataset.url});
            }
            else if (xElem.id == "conj_button") {
                browser.runtime.sendMessage({
                    sCommand: "openConjugueurTab",
                    dParam: {},
                    dInfo: {}
                });
            }
            else if (xElem.id == "dictionaries_button") {
                browser.runtime.sendMessage({
                    sCommand: "openDictionaries",
                    dParam: { "dictionary": "__community__"},
                    dInfo: {}
                });
            }
            else if (xElem.id == "dic_community_button") {
                browser.runtime.sendMessage({
                    sCommand: "openLexiconEditor",
                    dParam: { "dictionary": "__community__"},
                    dInfo: {}
                });
            }
            else if (xElem.id == "dic_personal_button") {
                browser.runtime.sendMessage({
                    sCommand: "openLexiconEditor",
                    dParam: { "dictionary": "__personal__"},
                    dInfo: {}
                });
            }
        } else if (xElem.className.startsWith("select")) {
            showPage(xElem.dataset.page);
        }/* else if (xElem.tagName === "A") {
            openURL(xElem.getAttribute("href"));
        }*/
    },
    false
);


/*
    Message sender
    and response handling
*/
function handleResponse (oResponse) {
    console.log(`[Panel] received:`);
    console.log(oResponse);
}

function handleError (error) {
    console.log(`[Panel] Error:`);
    console.log(error);
}

function sendMessageAndWaitResponse (oData) {
    let xPromise = browser.runtime.sendMessage(oData);
    xPromise.then(handleResponse, handleError);
}


/*
    Messages received
*/
function handleMessage (oMessage, xSender, sendResponse) {
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
}


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

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 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);
}


/*
    UI options
*/
function displayUIOptionsLoadedFromStorage () {
    if (bChrome) {
        browser.storage.local.get("ui_options", displayUIOptions);







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







179
180
181
182
183
184
185


























186
187
188
189
190
191
192
}


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




























/*
    UI options
*/
function displayUIOptionsLoadedFromStorage () {
    if (bChrome) {
        browser.storage.local.get("ui_options", displayUIOptions);
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

function displaySCOptions (dOptions) {
    if (!dOptions.hasOwnProperty("sc_options")) {
        console.log("no sc options found");
        return;
    }
    dOptions = dOptions.sc_options;
    //document.getElementById("extended_dic").checked = dOptions.extended_dic;
    //document.getElementById("community_dic").checked = dOptions.community_dic;
    document.getElementById("personal_dic").checked = dOptions.personal;
}

function storeSCOptions () {
    browser.storage.local.set({"sc_options": {
        extended: false,
        community: false,
        personal: document.getElementById("personal_dic").checked
    }});
}


/*
    GC options







|
|






|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

function displaySCOptions (dOptions) {
    if (!dOptions.hasOwnProperty("sc_options")) {
        console.log("no sc options found");
        return;
    }
    dOptions = dOptions.sc_options;
    //document.getElementById("extended_dic").checked = dOptions.extended;
    document.getElementById("community_dic").checked = dOptions.community;
    document.getElementById("personal_dic").checked = dOptions.personal;
}

function storeSCOptions () {
    browser.storage.local.set({"sc_options": {
        extended: false,
        community: document.getElementById("community_dic").checked,
        personal: document.getElementById("personal_dic").checked
    }});
}


/*
    GC options

Modified graphspell-js/dawg.js from [8cf9f1314b] to [f4d9319997].

416
417
418
419
420
421
422

423
424
425
426
427
428
429
430

    _getDate () {
        let oDate = new Date();
        let sMonth = (oDate.getMonth() + 1).toString().padStart(2, "0"); // Month+1: Because JS always sucks somehow.
        let sDay = (oDate.getDate()).toString().padStart(2, "0");
        let sHours = (oDate.getHours()).toString().padStart(2, "0");
        let sMinutes = (oDate.getMinutes()).toString().padStart(2, "0");

        return `${oDate.getFullYear()}-${sMonth}-${sDay}, ${sHours}:${sMinutes}`;
    }
}


const oNodeCounter = {
    nNextId: 0,








>
|







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

    _getDate () {
        let oDate = new Date();
        let sMonth = (oDate.getMonth() + 1).toString().padStart(2, "0"); // Month+1: Because JS always sucks somehow.
        let sDay = (oDate.getDate()).toString().padStart(2, "0");
        let sHours = (oDate.getHours()).toString().padStart(2, "0");
        let sMinutes = (oDate.getMinutes()).toString().padStart(2, "0");
        let sSeconds = (oDate.getSeconds()).toString().padStart(2, "0");
        return `${oDate.getFullYear()}-${sMonth}-${sDay} ${sHours}:${sMinutes}:${sSeconds}`;
    }
}


const oNodeCounter = {
    nNextId: 0,

Modified graphspell/dawg.py from [70e7a3c81c] to [0043f035e5].

18
19
20
21
22
23
24


25
26
27
28
29

30
31
32




33
34



35
36
37
38
39
40
41
import re
import traceback

from . import str_transform as st
from .progressbar import ProgressBar





def readFile (spf):
    "generator: read file <spf> and return for each line a list of elements separated by a tabulation."
    print(" < Read lexicon: " + spf)
    if os.path.isfile(spf):

        with open(spf, "r", encoding="utf-8") as hSrc:
            for sLine in hSrc:
                sLine = sLine.strip()




                if sLine and not sLine.startswith("#"):
                    yield sLine.split("\t")



    else:
        raise OSError("# Error. File not found or not loadable: " + spf)



class DAWG:
    """DIRECT ACYCLIC WORD GRAPH"""







>
>





>



>
>
>
>
|

>
>
>







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
import re
import traceback

from . import str_transform as st
from .progressbar import ProgressBar



dLexiconData = {}

def readFile (spf):
    "generator: read file <spf> and return for each line a list of elements separated by a tabulation."
    print(" < Read lexicon: " + spf)
    if os.path.isfile(spf):
        dLexiconData.clear()
        with open(spf, "r", encoding="utf-8") as hSrc:
            for sLine in hSrc:
                sLine = sLine.strip()
                if sLine.startswith("##") :
                    m = re.match("## *(\\w+) *:(.*)$", sLine)
                    if m:
                        dLexiconData[m.group(1)] = m.group(2).strip()
                elif sLine and not sLine.startswith("#"):
                    yield sLine.split("\t")
        if dLexiconData:
            print("Data from dictionary:")
            print(dLexiconData)
    else:
        raise OSError("# Error. File not found or not loadable: " + spf)



class DAWG:
    """DIRECT ACYCLIC WORD GRAPH"""
118
119
120
121
122
123
124





125
126
127
128
129
130
131
                        + [ (dTag[tag]+nChar+nAff, dTagOccur[tag]) for tag in dTag ] )

        self.sFileName = src  if type(src) is str  else "[None]"
        self.sLangCode = sLangCode
        self.sLangName = sLangName
        self.sDicName = sDicName
        self.sDescription = sDescription





        self.nEntry = len(lWord)
        self.aPreviousEntry = []
        DawgNode.resetNextId()
        self.oRoot = DawgNode()
        self.lUncheckedNodes = []  # list of nodes that have not been checked for duplication.
        self.lMinimizedNodes = {}  # list of unique nodes that have been checked for duplication.
        self.lSortedNodes = []     # version 2 and 3







>
>
>
>
>







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
                        + [ (dTag[tag]+nChar+nAff, dTagOccur[tag]) for tag in dTag ] )

        self.sFileName = src  if type(src) is str  else "[None]"
        self.sLangCode = sLangCode
        self.sLangName = sLangName
        self.sDicName = sDicName
        self.sDescription = sDescription
        if dLexiconData:
            self.sLangCode = dLexiconData.get("LangCode", self.sLangCode)
            self.sLangName = dLexiconData.get("LangName", self.sLangName)
            self.sDicName = dLexiconData.get("DicName", self.sDicName)
            self.sDescription = dLexiconData.get("Description", self.sDescription)
        self.nEntry = len(lWord)
        self.aPreviousEntry = []
        DawgNode.resetNextId()
        self.oRoot = DawgNode()
        self.lUncheckedNodes = []  # list of nodes that have not been checked for duplication.
        self.lMinimizedNodes = {}  # list of unique nodes that have been checked for duplication.
        self.lSortedNodes = []     # version 2 and 3
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
                hDst.write(self.oRoot.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
                for oNode in self.lSortedNodes:
                    hDst.write(oNode.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
        if bDebug:
            self._writeNodes(sPathFile, nCompressionMethod)

    def _getDate (self):
        return time.strftime("%Y.%m.%d, %H:%M")

    def _writeNodes (self, sPathFile, nCompressionMethod):
        "for debugging only"
        print(" > Write nodes")
        with open(sPathFile+".nodes."+str(nCompressionMethod)+".txt", 'w', encoding='utf-8', newline="\n") as hDst:
            if nCompressionMethod == 1:
                hDst.write(self.oRoot.getTxtRepr1(self.nBytesArc, self.lArcVal)+"\n")







|







556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
                hDst.write(self.oRoot.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
                for oNode in self.lSortedNodes:
                    hDst.write(oNode.convToBytes3(self.nBytesArc, self.nBytesNodeAddress, self.nBytesOffset))
        if bDebug:
            self._writeNodes(sPathFile, nCompressionMethod)

    def _getDate (self):
        return time.strftime("%Y-%m-%d %H:%M:%S")

    def _writeNodes (self, sPathFile, nCompressionMethod):
        "for debugging only"
        print(" > Write nodes")
        with open(sPathFile+".nodes."+str(nCompressionMethod)+".txt", 'w', encoding='utf-8', newline="\n") as hDst:
            if nCompressionMethod == 1:
                hDst.write(self.oRoot.getTxtRepr1(self.nBytesArc, self.lArcVal)+"\n")

Modified lex_build.py from [346704203c] to [72263209a8].

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
#!python3

# Lexicon builder

import argparse
from distutils import dir_util

import graphspell.dawg as fsa
from graphspell.ibdawg import IBDAWG


def build (spfSrc, sLangCode, sLangName, sfDict, bJSON=False, sDicName="", sFilter="", cStemmingMethod="S", nCompressMethod=1):
    "transform a text lexicon as a binary indexable dictionary"
    oDAWG = fsa.DAWG(spfSrc, cStemmingMethod, sLangCode, sLangName, sDicName, sFilter)
    dir_util.mkpath("graphspell/_dictionaries")
    oDAWG.writeInfo("graphspell/_dictionaries/" + sfDict + ".info.txt")
    oDAWG.writeBinary("graphspell/_dictionaries/" + sfDict + ".bdic", int(nCompressMethod))
    if bJSON:
        dir_util.mkpath("graphspell-js/_dictionaries")
        oDic = IBDAWG(sfDict + ".bdic")
        oDic.writeAsJSObject("graphspell-js/_dictionaries/" + sfDict + ".json", bBinaryDictAsHexString=True)


def main ():
    xParser = argparse.ArgumentParser()
    xParser.add_argument("src_lexicon", type=str, help="path and file name of the source lexicon")
    xParser.add_argument("lang_code", type=str, help="language code")
    xParser.add_argument("lang_name", type=str, help="language name")
    xParser.add_argument("dic_filename", type=str, help="dictionary file name (without extension)")
    xParser.add_argument("-js", "--json", help="Build dictionary in JSON", action="store_true")
    xParser.add_argument("-s", "--stemming", help="stemming method: S=suffixes, A=affixes, N=no stemming", type=str, choices=["S", "A", "N"], default="S")
    xParser.add_argument("-c", "--compress", help="compression method: 1, 2 (beta), 3, (beta)", type=int, choices=[1, 2, 3], default=1)
    xArgs = xParser.parse_args()
    build(xArgs.src_lexicon, xArgs.lang_code, xArgs.lang_name, xArgs.dic_filename, xArgs.json)
    

if __name__ == '__main__':
    main()











|

|




















|



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
#!python3

# Lexicon builder

import argparse
from distutils import dir_util

import graphspell.dawg as fsa
from graphspell.ibdawg import IBDAWG


def build (spfSrc, sLangCode, sLangName, sfDict, bJSON=False, sDicName="", sDescription="", sFilter="", cStemmingMethod="S", nCompressMethod=1):
    "transform a text lexicon as a binary indexable dictionary"
    oDAWG = fsa.DAWG(spfSrc, cStemmingMethod, sLangCode, sLangName, sDicName, sDescription, sFilter)
    dir_util.mkpath("graphspell/_dictionaries")
    oDAWG.writeInfo("graphspell/_dictionaries/" + sfDict + ".info.txt")
    oDAWG.writeBinary("graphspell/_dictionaries/" + sfDict + ".bdic", int(nCompressMethod))
    if bJSON:
        dir_util.mkpath("graphspell-js/_dictionaries")
        oDic = IBDAWG(sfDict + ".bdic")
        oDic.writeAsJSObject("graphspell-js/_dictionaries/" + sfDict + ".json", bBinaryDictAsHexString=True)


def main ():
    xParser = argparse.ArgumentParser()
    xParser.add_argument("src_lexicon", type=str, help="path and file name of the source lexicon")
    xParser.add_argument("lang_code", type=str, help="language code")
    xParser.add_argument("lang_name", type=str, help="language name")
    xParser.add_argument("dic_filename", type=str, help="dictionary file name (without extension)")
    xParser.add_argument("-js", "--json", help="Build dictionary in JSON", action="store_true")
    xParser.add_argument("-s", "--stemming", help="stemming method: S=suffixes, A=affixes, N=no stemming", type=str, choices=["S", "A", "N"], default="S")
    xParser.add_argument("-c", "--compress", help="compression method: 1, 2 (beta), 3, (beta)", type=int, choices=[1, 2, 3], default=1)
    xArgs = xParser.parse_args()
    build(xArgs.src_lexicon, xArgs.lang_code, xArgs.lang_name, xArgs.dic_filename, xArgs.json)


if __name__ == '__main__':
    main()

Modified lexicons/French.lex from [b69ae271b0] to [af55bd82c0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Lexique simplifié pour Grammalecte v7.0
# Licence : MPL v2.0

## LangCode: fr
## LangName: Français
## DicName: fr.commun
## Description: Français commun (toutes variantes)
## Author: Olivier R.

# :POS ;LEX ~SEM =FQ /DIC
de	de	:G:D:e:i/*
de	de	:G:R:Rv/*
et	et	:G:Cc/*
à	à	:G:R:Rv/*
des	des	:G:D:e:p/*
du	du	:G:D:m:s/*







<
<
<
<
<
<







1
2
3
4
5
6
7






8
9
10
11
12
13
14
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Lexique simplifié pour Grammalecte v7.0
# Licence : MPL v2.0







# :POS ;LEX ~SEM =FQ /DIC
de	de	:G:D:e:i/*
de	de	:G:R:Rv/*
et	et	:G:Cc/*
à	à	:G:R:Rv/*
des	des	:G:D:e:p/*
du	du	:G:D:m:s/*

Modified make.py from [7a5afc5f1b] to [67b200350b].

346
347
348
349
350
351
352

353
354
355
356
357
358
359
360

361
362
363
364

365
366
367
368

369
370
371
372
373
374
375
376

def buildDictionary (dVars, sType, bJavaScript=False):
    "build binary dictionary for Graphspell from lexicons"
    if sType == "main":
        spfLexSrc = dVars['lexicon_src']
        lSfDictDst = dVars['dic_filenames'].split(",")
        lDicName = dVars['dic_name'].split(",")

        lFilter = dVars['dic_filter'].split(",")
        for sfDictDst, sDicName, sFilter in zip(lSfDictDst, lDicName, lFilter):
            lex_build.build(spfLexSrc, dVars['lang'], dVars['lang_name'], sfDictDst, bJavaScript, sDicName, sFilter, dVars['stemming_method'], int(dVars['fsa_method']))
    else:
        if sType == "extended":
            spfLexSrc = dVars['lexicon_extended_src']
            sfDictDst = dVars['dic_extended_filename']
            sDicName = dVars['dic_extended_name']

        elif sType == "community":
            spfLexSrc = dVars['lexicon_community_src']
            sfDictDst = dVars['dic_community_filename']
            sDicName = dVars['dic_community_name']

        elif sType == "personal":
            spfLexSrc = dVars['lexicon_personal_src']
            sfDictDst = dVars['dic_personal_filename']
            sDicName = dVars['dic_personal_name']

        lex_build.build(spfLexSrc, dVars['lang'], dVars['lang_name'], sfDictDst, bJavaScript, sDicName, "", dVars['stemming_method'], int(dVars['fsa_method']))



def main ():
    "build Grammalecte with requested options"
    print("Python: " + sys.version)
    xParser = argparse.ArgumentParser()







>

|
|





>




>




>
|







346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

def buildDictionary (dVars, sType, bJavaScript=False):
    "build binary dictionary for Graphspell from lexicons"
    if sType == "main":
        spfLexSrc = dVars['lexicon_src']
        lSfDictDst = dVars['dic_filenames'].split(",")
        lDicName = dVars['dic_name'].split(",")
        lDescription = dVars['dic_description'].split(",")
        lFilter = dVars['dic_filter'].split(",")
        for sfDictDst, sDicName, sDescription, sFilter in zip(lSfDictDst, lDicName, lDescription, lFilter):
            lex_build.build(spfLexSrc, dVars['lang'], dVars['lang_name'], sfDictDst, bJavaScript, sDicName, sDescription, sFilter, dVars['stemming_method'], int(dVars['fsa_method']))
    else:
        if sType == "extended":
            spfLexSrc = dVars['lexicon_extended_src']
            sfDictDst = dVars['dic_extended_filename']
            sDicName = dVars['dic_extended_name']
            sDescription = dVars['dic_extended_description']
        elif sType == "community":
            spfLexSrc = dVars['lexicon_community_src']
            sfDictDst = dVars['dic_community_filename']
            sDicName = dVars['dic_community_name']
            sDescription = dVars['dic_community_description']
        elif sType == "personal":
            spfLexSrc = dVars['lexicon_personal_src']
            sfDictDst = dVars['dic_personal_filename']
            sDicName = dVars['dic_personal_name']
            sDescription = dVars['dic_personal_description']
        lex_build.build(spfLexSrc, dVars['lang'], dVars['lang_name'], sfDictDst, bJavaScript, sDicName, sDescription, "", dVars['stemming_method'], int(dVars['fsa_method']))



def main ():
    "build Grammalecte with requested options"
    print("Python: " + sys.version)
    xParser = argparse.ArgumentParser()