Grammalecte  Check-in [7217592c77]

Overview
Comment:merge comdic
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7217592c77f23a9e439f41473408c523dadc5c7b57117a66d605a52efff780ea
User & Date: olr on 2019-04-03 14:18:54
Other Links: manifest | tags
Context
2019-04-03
14:34
[tb] remove extended dictionary labels check-in: 77ef752105 user: olr tags: trunk, tb
14:18
merge comdic check-in: 7217592c77 user: olr tags: trunk
13:31
[fr] mise à jour du dictionnaire check-in: 0b6aa78216 user: olr tags: trunk, fr
2019-03-15
14:08
[fx] fix merge Closed-Leaf check-in: e8375db0be user: olr tags: fx, comdic
Changes

Modified gc_core/js/lang_core/gc_engine.js from [8e4be3285b] to [65c6c687b8].

40
41
42
43
44
45
46





47
48
49
50
51
52
53
let _sAppContext = "";                                  // what software is running
let _dOptions = null;
let _dOptionsColors = null;
let _oSpellChecker = null;
let _oTokenizer = null;
let _aIgnoredRules = new Set();








var gc_engine = {

    //// Informations

    lang: "${lang}",







>
>
>
>
>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
let _sAppContext = "";                                  // what software is running
let _dOptions = null;
let _dOptionsColors = null;
let _oSpellChecker = null;
let _oTokenizer = null;
let _aIgnoredRules = new Set();


function echo (x) {
    console.log(x);
    return true;
}


var gc_engine = {

    //// Informations

    lang: "${lang}",

Modified gc_lang/fr/config.ini from [62a573c6e2] to [eb65238ea7].

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







>
|






|
>



|
>



|
>







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

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/modules-js/lexicographe.js from [50f4dc02f6] to [7979205e02].

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
            if (aRes) {
                yield aRes;
            }
        }
    }

    getListOfTokensReduc (sText, bInfo=true) {
        let aTokenList = this.getListOfTokens(sText.replace("'", "’").trim(), false);
        let iKey = 0;
        let aElem = [];



        do {
            let oToken = aTokenList[iKey];
            let sMorphLoc = '';
            let aTokenTempList = [oToken];
            if (oToken.sType == "WORD" || oToken.sType == "WORD_ELIDED"){
                let iKeyTree = iKey + 1;
                let oLocNode = this.oLocGraph[oToken.sValue.toLowerCase()];
                while (oLocNode) {
                    let oTokenNext = aTokenList[iKeyTree];
                    iKeyTree++;
                    if (oTokenNext) {
                        oLocNode = oLocNode[oTokenNext.sValue.toLowerCase()];
                    }
                    if (oLocNode && iKeyTree <= aTokenList.length) {
                        sMorphLoc = oLocNode["_:_"];
                        aTokenTempList.push(oTokenNext);
                    } else {
                        break;
                    }
                }
            }

            if (sMorphLoc) {

                let sValue = '';
                for (let oTokenWord of aTokenTempList) {
                    sValue += oTokenWord.sValue+' ';
                }
                let oTokenLocution = {
                    'nStart': aTokenTempList[0].nStart,
                    'nEnd': aTokenTempList[aTokenTempList.length-1].nEnd,







|
|

>
>
>

|



|


|
|



|









>







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
            if (aRes) {
                yield aRes;
            }
        }
    }

    getListOfTokensReduc (sText, bInfo=true) {
        let lToken = this.getListOfTokens(sText.replace("'", "’").trim(), false);
        let iToken = 0;
        let aElem = [];
        if (lToken.length == 0) {
            return aElem;
        }
        do {
            let oToken = lToken[iToken];
            let sMorphLoc = '';
            let aTokenTempList = [oToken];
            if (oToken.sType == "WORD" || oToken.sType == "WORD_ELIDED"){
                let iLocEnd = iToken + 1;
                let oLocNode = this.oLocGraph[oToken.sValue.toLowerCase()];
                while (oLocNode) {
                    let oTokenNext = lToken[iLocEnd];
                    iLocEnd++;
                    if (oTokenNext) {
                        oLocNode = oLocNode[oTokenNext.sValue.toLowerCase()];
                    }
                    if (oLocNode && iLocEnd <= lToken.length) {
                        sMorphLoc = oLocNode["_:_"];
                        aTokenTempList.push(oTokenNext);
                    } else {
                        break;
                    }
                }
            }

            if (sMorphLoc) {
                // we have a locution
                let sValue = '';
                for (let oTokenWord of aTokenTempList) {
                    sValue += oTokenWord.sValue+' ';
                }
                let oTokenLocution = {
                    'nStart': aTokenTempList[0].nStart,
                    'nEnd': aTokenTempList[aTokenTempList.length-1].nEnd,
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
                        sValue: oTokenLocution.sValue,
                        aLabel: aFormatedTag,
                        aSubElem: aSubElem
                    });
                } else {
                    aElem.push(oTokenLocution);
                }
                iKey = iKey + aTokenTempList.length;
            } else {

                if (bInfo) {
                    let aRes = this.getInfoForToken(oToken);
                    if (aRes) {
                        aElem.push(aRes);
                    }
                } else {
                    aElem.push(oToken);
                }
                iKey++;
            }
        } while (iKey < aTokenList.length);
        return aElem;
    }
}


if (typeof(exports) !== 'undefined') {
    exports.Lexicographe = Lexicographe;
}







|

>








|

|








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
                        sValue: oTokenLocution.sValue,
                        aLabel: aFormatedTag,
                        aSubElem: aSubElem
                    });
                } else {
                    aElem.push(oTokenLocution);
                }
                iToken = iToken + aTokenTempList.length;
            } else {
                // No locution, we just add information
                if (bInfo) {
                    let aRes = this.getInfoForToken(oToken);
                    if (aRes) {
                        aElem.push(aRes);
                    }
                } else {
                    aElem.push(oToken);
                }
                iToken++;
            }
        } while (iToken < lToken.length);
        return aElem;
    }
}


if (typeof(exports) !== 'undefined') {
    exports.Lexicographe = Lexicographe;
}

Modified gc_lang/fr/oxt/DictOptions/DictOptions.py from [f2057c6bbe] to [9c9fa6ae5f].

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
# BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY
# DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE
from com.sun.star.awt.MessageBoxType import INFOBOX, ERRORBOX # MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX

def MessageBox (xDocument, sMsg, sTitle, nBoxType=INFOBOX, nBoxButtons=BUTTONS_OK):
    xParentWin = xDocument.CurrentController.Frame.ContainerWindow
    ctx = uno.getComponentContext()
    xToolkit = ctx.ServiceManager.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx) 
    xMsgBox = xToolkit.createMessageBox(xParentWin, nBoxType, nBoxButtons, sTitle, sMsg)
    return xMsgBox.execute()


class DictOptions (unohelper.Base, XActionListener, XJobExecutor):

    def __init__ (self, ctx):
        self.ctx = ctx
        self.xSvMgr = self.ctx.ServiceManager
        self.xContainer = None
        self.xDialog = None
        
    def _addWidget (self, name, wtype, x, y, w, h, **kwargs):
        xWidget = self.xDialog.createInstance('com.sun.star.awt.UnoControl%sModel' % wtype)
        xWidget.Name = name
        xWidget.PositionX = x
        xWidget.PositionY = y
        xWidget.Width = w
        xWidget.Height = h







|











|







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
# BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY
# DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE
from com.sun.star.awt.MessageBoxType import INFOBOX, ERRORBOX # MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX

def MessageBox (xDocument, sMsg, sTitle, nBoxType=INFOBOX, nBoxButtons=BUTTONS_OK):
    xParentWin = xDocument.CurrentController.Frame.ContainerWindow
    ctx = uno.getComponentContext()
    xToolkit = ctx.ServiceManager.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx)
    xMsgBox = xToolkit.createMessageBox(xParentWin, nBoxType, nBoxButtons, sTitle, sMsg)
    return xMsgBox.execute()


class DictOptions (unohelper.Base, XActionListener, XJobExecutor):

    def __init__ (self, ctx):
        self.ctx = ctx
        self.xSvMgr = self.ctx.ServiceManager
        self.xContainer = None
        self.xDialog = None

    def _addWidget (self, name, wtype, x, y, w, h, **kwargs):
        xWidget = self.xDialog.createInstance('com.sun.star.awt.UnoControl%sModel' % wtype)
        xWidget.Name = name
        xWidget.PositionX = x
        xWidget.PositionY = y
        xWidget.Width = w
        xWidget.Height = h
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
        self.xDesktop = self.xSvMgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.ctx)
        self.xDocument = self.xDesktop.getCurrentComponent()
        self.xOptionNode = helpers.getConfigSetting("/org.openoffice.Lightproof_grammalecte/Other/", True)

        # dialog
        self.xDialog = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialogModel', self.ctx)
        self.xDialog.Width = 200
        self.xDialog.Height = 310
        self.xDialog.Title = self.dUI.get('title', "#title#")
        xWindowSize = helpers.getWindowSize()
        self.xDialog.PositionX = int((xWindowSize.Width / 2) - (self.xDialog.Width / 2))
        self.xDialog.PositionY = int((xWindowSize.Height / 2) - (self.xDialog.Height / 2))

        # fonts
        xFDTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
        xFDTitle.Height = 9
        xFDTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
        xFDTitle.Name = "Verdana"
        
        xFDSubTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
        xFDSubTitle.Height = 10
        xFDSubTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
        xFDSubTitle.Name = "Verdana"

        # widget
        nX = 10
        nY1 = 10
        nY2 = nY1 + 60
        nY3 = nY2 + 25
        nY4 = nY3 + 25
        nY5 = nY4 + 45
        nY6 = nY5 + 95

        nWidth = self.xDialog.Width - 20
        nHeight = 10

        # Graphspell dictionary section
        self._addWidget("graphspell_section", 'FixedLine', nX, nY1, nWidth, nHeight, Label = self.dUI.get("graphspell_section", "#err"), FontDescriptor = xFDTitle)
        self.xMainDic = self._addWidget('activate_main', 'CheckBox', nX, nY1+15, nWidth, nHeight, Label = self.dUI.get('activate_main', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088, State = True)
        self._addWidget('activate_main_descr', 'FixedText', nX+10, nY1+25, nWidth-10, nHeight*2, Label = self.dUI.get('activate_main_descr', "#err"), MultiLine = True)
        self._addWidget('spelling', 'FixedText', nX+10, nY1+45, nWidth-80, nHeight, Label = self.dUI.get('spelling', "#err"), FontDescriptor = xFDSubTitle)
        self.xInfoDicButton = self._addWidget('info_dic_button', 'Button', nX+160, nY1+45, 12, 9, Label = "‹i›")
        self.xSelClassic = self._addWidget('classic', 'RadioButton', nX+10, nY1+55, 50, nHeight, Label = self.dUI.get('classic', "#err"))
        self.xSelReform = self._addWidget('reform', 'RadioButton', nX+65, nY1+55, 55, nHeight, Label = self.dUI.get('reform', "#err"))
        self.xSelAllvars = self._addWidget('allvars', 'RadioButton', nX+120, nY1+55, 60, nHeight, Label = self.dUI.get('allvars', "#err"))
        self.xExtendedDic = self._addWidget('activate_extended', 'CheckBox', nX, nY2+15, nWidth, nHeight, Label = self.dUI.get('activate_extended', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088, Enabled = False)
        self._addWidget('activate_extended_descr', 'FixedText', nX+10, nY2+25, nWidth-10, nHeight*1, Label = self.dUI.get('activate_extended_descr', "#err"), MultiLine = True)
        self.xCommunityDic = self._addWidget('activate_community', 'CheckBox', nX, nY3+15, nWidth, nHeight, Label = self.dUI.get('activate_community', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088, Enabled = False)
        self._addWidget('activate_community_descr', 'FixedText', nX+10, nY3+25, nWidth-10, nHeight*1, Label = self.dUI.get('activate_community_descr', "#err"), MultiLine = True)
        self.xPersonalDic = self._addWidget('activate_personal', 'CheckBox', nX, nY4+15, nWidth, nHeight, Label = self.dUI.get('activate_personal', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088)
        self._addWidget('activate_personal_descr', 'FixedText', nX+10, nY4+25, nWidth-10, nHeight*1, Label = self.dUI.get('activate_personal_descr', "#err"), MultiLine = True)
        
        # Spell suggestion engine section
        self._addWidget("suggestion_section", 'FixedLine', nX, nY5, nWidth, nHeight, Label = self.dUI.get("suggestion_section", "#err"), FontDescriptor = xFDTitle)
        self.xGraphspellSugg = self._addWidget('activate_spell_sugg', 'CheckBox', nX, nY5+15, nWidth, nHeight, Label = self.dUI.get('activate_spell_sugg', "#err"))
        self._addWidget('activate_spell_sugg_descr', 'FixedText', nX, nY5+25, nWidth, nHeight*6, Label = self.dUI.get('activate_spell_sugg_descr', "#err"), MultiLine = True)

        # Restart message
        self._addWidget('restart', 'FixedText', nX, nY6, nWidth, nHeight*2, Label = self.dUI.get('restart', "#err"), FontDescriptor = xFDTitle, MultiLine = True, TextColor = 0x880000)

        # Button
        self._addWidget('apply_button', 'Button', self.xDialog.Width-115, self.xDialog.Height-20, 50, 14, Label = self.dUI.get('apply_button', "#err"), FontDescriptor = xFDTitle, TextColor = 0x005500)
        self._addWidget('cancel_button', 'Button', self.xDialog.Width-60, self.xDialog.Height-20, 50, 14, Label = self.dUI.get('cancel_button', "#err"), FontDescriptor = xFDTitle, TextColor = 0x550000)

        self._loadOptions()








|










|










|
|
<













<
<
|
|
|
|
|

|
|
|


|







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
        self.xDesktop = self.xSvMgr.createInstanceWithContext("com.sun.star.frame.Desktop", self.ctx)
        self.xDocument = self.xDesktop.getCurrentComponent()
        self.xOptionNode = helpers.getConfigSetting("/org.openoffice.Lightproof_grammalecte/Other/", True)

        # dialog
        self.xDialog = self.xSvMgr.createInstanceWithContext('com.sun.star.awt.UnoControlDialogModel', self.ctx)
        self.xDialog.Width = 200
        self.xDialog.Height = 285
        self.xDialog.Title = self.dUI.get('title', "#title#")
        xWindowSize = helpers.getWindowSize()
        self.xDialog.PositionX = int((xWindowSize.Width / 2) - (self.xDialog.Width / 2))
        self.xDialog.PositionY = int((xWindowSize.Height / 2) - (self.xDialog.Height / 2))

        # fonts
        xFDTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
        xFDTitle.Height = 9
        xFDTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
        xFDTitle.Name = "Verdana"

        xFDSubTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
        xFDSubTitle.Height = 10
        xFDSubTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
        xFDSubTitle.Name = "Verdana"

        # widget
        nX = 10
        nY1 = 10
        nY2 = nY1 + 60
        nY3 = nY2 + 25
        nY4 = nY3 + 45
        nY5 = nY4 + 95


        nWidth = self.xDialog.Width - 20
        nHeight = 10

        # Graphspell dictionary section
        self._addWidget("graphspell_section", 'FixedLine', nX, nY1, nWidth, nHeight, Label = self.dUI.get("graphspell_section", "#err"), FontDescriptor = xFDTitle)
        self.xMainDic = self._addWidget('activate_main', 'CheckBox', nX, nY1+15, nWidth, nHeight, Label = self.dUI.get('activate_main', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088, State = True)
        self._addWidget('activate_main_descr', 'FixedText', nX+10, nY1+25, nWidth-10, nHeight*2, Label = self.dUI.get('activate_main_descr', "#err"), MultiLine = True)
        self._addWidget('spelling', 'FixedText', nX+10, nY1+45, nWidth-80, nHeight, Label = self.dUI.get('spelling', "#err"), FontDescriptor = xFDSubTitle)
        self.xInfoDicButton = self._addWidget('info_dic_button', 'Button', nX+160, nY1+45, 12, 9, Label = "‹i›")
        self.xSelClassic = self._addWidget('classic', 'RadioButton', nX+10, nY1+55, 50, nHeight, Label = self.dUI.get('classic', "#err"))
        self.xSelReform = self._addWidget('reform', 'RadioButton', nX+65, nY1+55, 55, nHeight, Label = self.dUI.get('reform', "#err"))
        self.xSelAllvars = self._addWidget('allvars', 'RadioButton', nX+120, nY1+55, 60, nHeight, Label = self.dUI.get('allvars', "#err"))


        self.xCommunityDic = self._addWidget('activate_community', 'CheckBox', nX, nY2+15, nWidth, nHeight, Label = self.dUI.get('activate_community', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088, Enabled = False)
        self._addWidget('activate_community_descr', 'FixedText', nX+10, nY2+25, nWidth-10, nHeight*1, Label = self.dUI.get('activate_community_descr', "#err"), MultiLine = True)
        self.xPersonalDic = self._addWidget('activate_personal', 'CheckBox', nX, nY3+15, nWidth, nHeight, Label = self.dUI.get('activate_personal', "#err"), FontDescriptor = xFDSubTitle, TextColor = 0x000088)
        self._addWidget('activate_personal_descr', 'FixedText', nX+10, nY3+25, nWidth-10, nHeight*1, Label = self.dUI.get('activate_personal_descr', "#err"), MultiLine = True)

        # Spell suggestion engine section
        self._addWidget("suggestion_section", 'FixedLine', nX, nY4, nWidth, nHeight, Label = self.dUI.get("suggestion_section", "#err"), FontDescriptor = xFDTitle)
        self.xGraphspellSugg = self._addWidget('activate_spell_sugg', 'CheckBox', nX, nY4+15, nWidth, nHeight, Label = self.dUI.get('activate_spell_sugg', "#err"))
        self._addWidget('activate_spell_sugg_descr', 'FixedText', nX, nY4+25, nWidth, nHeight*6, Label = self.dUI.get('activate_spell_sugg_descr', "#err"), MultiLine = True)

        # Restart message
        self._addWidget('restart', 'FixedText', nX, nY5, nWidth, nHeight*2, Label = self.dUI.get('restart', "#err"), FontDescriptor = xFDTitle, MultiLine = True, TextColor = 0x880000)

        # Button
        self._addWidget('apply_button', 'Button', self.xDialog.Width-115, self.xDialog.Height-20, 50, 14, Label = self.dUI.get('apply_button', "#err"), FontDescriptor = xFDTitle, TextColor = 0x005500)
        self._addWidget('cancel_button', 'Button', self.xDialog.Width-60, self.xDialog.Height-20, 50, 14, Label = self.dUI.get('cancel_button', "#err"), FontDescriptor = xFDTitle, TextColor = 0x550000)

        self._loadOptions()

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
        self.xContainer.execute()

    # XActionListener
    def actionPerformed (self, xActionEvent):
        try:
            if xActionEvent.ActionCommand == 'Apply':
                xChild = self.xOptionNode.getByName("o_fr")
                #xChild.setPropertyValue("use_extended_dic", self.xExtendedDic.State)
                #xChild.setPropertyValue("use_community_dic", self.xCommunityDic.State)
                xChild.setPropertyValue("use_personal_dic", self.xPersonalDic.State)
                xChild.setPropertyValue("use_graphspell_sugg", self.xGraphspellSugg.State)
                sMainDicName = "classic"
                if self.xSelClassic.State:
                    sMainDicName = "classic"
                elif self.xSelReform.State:
                    sMainDicName = "reform"
                elif self.xSelAllvars.State:
                    sMainDicName = "allvars"
                xChild.setPropertyValue("main_dic_name", sMainDicName)
                self.xOptionNode.commitChanges()
                self.xContainer.endExecute()
            elif xActionEvent.ActionCommand == 'InfoDic':
                MessageBox(self.xDocument, self.dUI.get('spelling_descr', "#err"), "Orthographe du français", nBoxType=INFOBOX, nBoxButtons=BUTTONS_OK)
            else:
                self.xContainer.endExecute()
        except:
            traceback.print_exc()
    
    # XJobExecutor
    def trigger (self, args):
        try:
            dialog = DictOptions(self.ctx)
            dialog.run()
        except:
            traceback.print_exc()

    def _loadOptions (self):
        try:
            xChild = self.xOptionNode.getByName("o_fr")
            #self.xGraphspell.State = xChild.getPropertyValue("use_graphspell")
            self.xGraphspellSugg.State = xChild.getPropertyValue("use_graphspell_sugg")
            #self.xExtendedDic.State = xChild.getPropertyValue("use_extended_dic")
            #self.xCommunityDic.State = xChild.getPropertyValue("use_community_dic")
            self.xPersonalDic.State = xChild.getPropertyValue("use_personal_dic")
            sMainDicName = xChild.getPropertyValue("main_dic_name")
            if sMainDicName == "classic":
                self.xSelClassic.State = 1
            elif sMainDicName == "reform":
                self.xSelReform.State = 1







<



















|













<







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
        self.xContainer.execute()

    # XActionListener
    def actionPerformed (self, xActionEvent):
        try:
            if xActionEvent.ActionCommand == 'Apply':
                xChild = self.xOptionNode.getByName("o_fr")

                #xChild.setPropertyValue("use_community_dic", self.xCommunityDic.State)
                xChild.setPropertyValue("use_personal_dic", self.xPersonalDic.State)
                xChild.setPropertyValue("use_graphspell_sugg", self.xGraphspellSugg.State)
                sMainDicName = "classic"
                if self.xSelClassic.State:
                    sMainDicName = "classic"
                elif self.xSelReform.State:
                    sMainDicName = "reform"
                elif self.xSelAllvars.State:
                    sMainDicName = "allvars"
                xChild.setPropertyValue("main_dic_name", sMainDicName)
                self.xOptionNode.commitChanges()
                self.xContainer.endExecute()
            elif xActionEvent.ActionCommand == 'InfoDic':
                MessageBox(self.xDocument, self.dUI.get('spelling_descr', "#err"), "Orthographe du français", nBoxType=INFOBOX, nBoxButtons=BUTTONS_OK)
            else:
                self.xContainer.endExecute()
        except:
            traceback.print_exc()

    # XJobExecutor
    def trigger (self, args):
        try:
            dialog = DictOptions(self.ctx)
            dialog.run()
        except:
            traceback.print_exc()

    def _loadOptions (self):
        try:
            xChild = self.xOptionNode.getByName("o_fr")
            #self.xGraphspell.State = xChild.getPropertyValue("use_graphspell")
            self.xGraphspellSugg.State = xChild.getPropertyValue("use_graphspell_sugg")

            #self.xCommunityDic.State = xChild.getPropertyValue("use_community_dic")
            self.xPersonalDic.State = xChild.getPropertyValue("use_personal_dic")
            sMainDicName = xChild.getPropertyValue("main_dic_name")
            if sMainDicName == "classic":
                self.xSelClassic.State = 1
            elif sMainDicName == "reform":
                self.xSelReform.State = 1

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/DictOptions/do_strings.py from [9a9f6574c0] to [dfb75d0678].

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
def getUI (sLang):
    if sLang in dStrings:
        return dStrings[sLang]
    return dStrings["fr"]

dStrings = {
    "fr": {
        "title": "Grammalecte · Options orthographiques",
        
        "spelling_section": "Correcteur orthographique",
        "activate_main": "Activer le correcteur orthographique de Grammalecte",
        "activate_main_descr": "Supplante le correcteur orthographique inclus dans LibreOffice (Hunspell).",

        "suggestion_section": "Moteur de suggestion orthographique",
        "activate_spell_sugg": "Moteur de suggestion de Grammalecte",
        "activate_spell_sugg_descr": "Les suggestions orthographiques des mots non reconnus par le correcteur sont fournies par Grammalecte. Si ces suggestions ne vous satisfont pas (ou si c’est trop lent), vous pouvez désactiver cette option : les suggestions orthographiques seront alors fournies par le correcteur de LibreOffice. Mais, dans ce cas, les mots que vous avez ajoutés au dictionnaire personnel de Grammalecte ne pourront pas être inclus aux suggestions.",

        "graphspell_section": "Dictionnaires actifs",
        "activate_main": "Dictionnaire principal",
        "activate_main_descr": "Environ 83 000 entrées, 500 000 flexions.\nNi éditable, ni désactivable.",
        "spelling": "Orthographe",
        "spelling_descr": "Le dictionnaire “Classique” propose l’orthographe telle qu’elle est écrite aujourd’hui le plus couramment. C’est le dictionnaire recommandé. Il contient les graphies usuelles et classiques, certaines encore communément utilisées, d’autres désuètes.\n\nAvec le dictionnaire “Réforme 1990”, seule l’orthographe réformée est reconnue. Attendu que bon nombre de graphies réformées sont considérées comme erronées par beaucoup, ce dictionnaire est déconseillé. Les graphies passées dans l’usage sont déjà incluses dans le dictionnaire “Classique”.\n\nLe dictionnaire “Toutes variantes” contient toutes les graphies, classiques ou réformées, ainsi que d’autres plus rares encore. Ce dictionnaire est déconseillé à ceux qui ne connaissent pas très bien la langue française.",
        "allvars": "Toutes variantes",
        "classic": "Classique",
        "reform": "Réforme 1990",
        "activate_extended": "Dictionnaire étendu",
        "activate_extended_descr": "Fonctionnalité à venir",
        "activate_community": "Dictionnaire communautaire",
        "activate_community_descr": "Fonctionnalité à venir",
        "activate_personal": "Dictionnaire personnel",
        "activate_personal_descr": "Créable et éditable via l’éditeur lexical.",

        "restart": "Le changement ne prendra effet qu’après le redémarrage du logiciel.",

        "apply_button": "Appliquer",
        "cancel_button": "Annuler",
    },
    "en": {
        "title": "Grammalecte · Spelling options",
        
        "spelling_section": "Spell checker",
        "activate_main": "Activate the spell checker from Grammalecte",
        "activate_main_descr": "Overrides the spell checker included in LibreOffice (Hunspell)",

        "suggestion_section": "Spell suggestion engine",
        "activate_spell_sugg": "Suggestion engine of Grammalecte",
        "activate_spell_sugg_descr": "Spelling suggestions for words unrecognized by the spellchecker are provided by Grammalecte. If you aren’t satisfied by these suggestions (or if it’s too slow), you can disable this option: spelling suggestions will then be provided by the LibreOffice proofreader. In this case, words you have added in your Grammalecte’s custom dictionary won’t be included in suggestions.",

        "graphspell_section": "Active dictionaries",
        "activate_main": "Main dictionary",
        "activate_main_descr": "About 83 000 entries, 500 000 flexions.\nNot editable, not deactivable.",
        "spelling": "Spelling",
        "spelling_descr": "The dictionary “Classic” offers the French spelling as it is written nowadays most often. This is the recommended dictionary. It contains usual and classical spellings, some of them still widely used, others obsolete.\n\nWith the dictionary “Reform 1990”, only the reformed spelling is recognized. As many of reformed spellings are considered erroneous by many people, this dictionary is unadvised. Reformed spellings commonly used are already included in the “Classic” dictionary.\n\nThe dictionary “All variants” contains all spelling variants, classical and reformed, and some others even rarer. This dictionary is unadvised for those who don’t know very well the French language.",
        "allvars": "All variants",
        "classic": "Classic",
        "reform": "Reform 1990",
        "activate_extended": "Extended dictionary",
        "activate_extended_descr": "Feature to come.",
        "activate_community": "Community dictionary",
        "activate_community_descr": "Feature to come.",
        "activate_personal": "Personal dictionary",
        "activate_personal_descr": "Creatible and editable via the lexicon editor.",

        "restart": "The modification will be effective only after restarting the software.",

        "apply_button": "Apply",
        "cancel_button": "Cancel",
    },
}








|
















<
<












|
















<
<











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
def getUI (sLang):
    if sLang in dStrings:
        return dStrings[sLang]
    return dStrings["fr"]

dStrings = {
    "fr": {
        "title": "Grammalecte · Options orthographiques",

        "spelling_section": "Correcteur orthographique",
        "activate_main": "Activer le correcteur orthographique de Grammalecte",
        "activate_main_descr": "Supplante le correcteur orthographique inclus dans LibreOffice (Hunspell).",

        "suggestion_section": "Moteur de suggestion orthographique",
        "activate_spell_sugg": "Moteur de suggestion de Grammalecte",
        "activate_spell_sugg_descr": "Les suggestions orthographiques des mots non reconnus par le correcteur sont fournies par Grammalecte. Si ces suggestions ne vous satisfont pas (ou si c’est trop lent), vous pouvez désactiver cette option : les suggestions orthographiques seront alors fournies par le correcteur de LibreOffice. Mais, dans ce cas, les mots que vous avez ajoutés au dictionnaire personnel de Grammalecte ne pourront pas être inclus aux suggestions.",

        "graphspell_section": "Dictionnaires actifs",
        "activate_main": "Dictionnaire principal",
        "activate_main_descr": "Environ 83 000 entrées, 500 000 flexions.\nNi éditable, ni désactivable.",
        "spelling": "Orthographe",
        "spelling_descr": "Le dictionnaire “Classique” propose l’orthographe telle qu’elle est écrite aujourd’hui le plus couramment. C’est le dictionnaire recommandé. Il contient les graphies usuelles et classiques, certaines encore communément utilisées, d’autres désuètes.\n\nAvec le dictionnaire “Réforme 1990”, seule l’orthographe réformée est reconnue. Attendu que bon nombre de graphies réformées sont considérées comme erronées par beaucoup, ce dictionnaire est déconseillé. Les graphies passées dans l’usage sont déjà incluses dans le dictionnaire “Classique”.\n\nLe dictionnaire “Toutes variantes” contient toutes les graphies, classiques ou réformées, ainsi que d’autres plus rares encore. Ce dictionnaire est déconseillé à ceux qui ne connaissent pas très bien la langue française.",
        "allvars": "Toutes variantes",
        "classic": "Classique",
        "reform": "Réforme 1990",


        "activate_community": "Dictionnaire communautaire",
        "activate_community_descr": "Fonctionnalité à venir",
        "activate_personal": "Dictionnaire personnel",
        "activate_personal_descr": "Créable et éditable via l’éditeur lexical.",

        "restart": "Le changement ne prendra effet qu’après le redémarrage du logiciel.",

        "apply_button": "Appliquer",
        "cancel_button": "Annuler",
    },
    "en": {
        "title": "Grammalecte · Spelling options",

        "spelling_section": "Spell checker",
        "activate_main": "Activate the spell checker from Grammalecte",
        "activate_main_descr": "Overrides the spell checker included in LibreOffice (Hunspell)",

        "suggestion_section": "Spell suggestion engine",
        "activate_spell_sugg": "Suggestion engine of Grammalecte",
        "activate_spell_sugg_descr": "Spelling suggestions for words unrecognized by the spellchecker are provided by Grammalecte. If you aren’t satisfied by these suggestions (or if it’s too slow), you can disable this option: spelling suggestions will then be provided by the LibreOffice proofreader. In this case, words you have added in your Grammalecte’s custom dictionary won’t be included in suggestions.",

        "graphspell_section": "Active dictionaries",
        "activate_main": "Main dictionary",
        "activate_main_descr": "About 83 000 entries, 500 000 flexions.\nNot editable, not deactivable.",
        "spelling": "Spelling",
        "spelling_descr": "The dictionary “Classic” offers the French spelling as it is written nowadays most often. This is the recommended dictionary. It contains usual and classical spellings, some of them still widely used, others obsolete.\n\nWith the dictionary “Reform 1990”, only the reformed spelling is recognized. As many of reformed spellings are considered erroneous by many people, this dictionary is unadvised. Reformed spellings commonly used are already included in the “Classic” dictionary.\n\nThe dictionary “All variants” contains all spelling variants, classical and reformed, and some others even rarer. This dictionary is unadvised for those who don’t know very well the French language.",
        "allvars": "All variants",
        "classic": "Classic",
        "reform": "Reform 1990",


        "activate_community": "Community dictionary",
        "activate_community_descr": "Feature to come.",
        "activate_personal": "Personal dictionary",
        "activate_personal_descr": "Creatible and editable via the lexicon editor.",

        "restart": "The modification will be effective only after restarting the software.",

        "apply_button": "Apply",
        "cancel_button": "Cancel",
    },
}

Modified gc_lang/fr/rules.grx from [15423c7446] to [0762ca5a90].

503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
__[s>(p_MM_point)__
    MM[.] <<- ~>> "MM "
__[s>(p_Mr_Mgr_Mme_point)__
    M(?:r|gr|me) [A-ZÉ]([.])(?=\W+[a-zéèêâîïû]) @@$ <<- ~1>> *

# Patronyme réduit à une seule lettre
__[s](p_prénom_lettre_point_patronyme)__
    ([A-ZÉÈÂÎ][\w-]+)[  ][A-ZÉÈÂ]([.])[  ]([A-ZÉÈÂ][\w-]+) @@0,$,$
    <<- morph(\1, ":M[12]") and (morph(\3, ":(?:M[12]|V)") or not spell(\3)) ~2>> *
__[s>(p_prénom_lettre_point)__
    ([A-ZÉÈÂÎ][\w-]+)[  ][A-ZÉÈÂ]([.]) @@0,$
    <<- morph(\1, ":M[12]") and after("^\\W+[a-zéèêîïâ]") ~2>> _

# Patronymes composés avec Le/La/Les
__[s](p_patronyme_composé_avec_le_la_les)__







|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
__[s>(p_MM_point)__
    MM[.] <<- ~>> "MM "
__[s>(p_Mr_Mgr_Mme_point)__
    M(?:r|gr|me) [A-ZÉ]([.])(?=\W+[a-zéèêâîïû]) @@$ <<- ~1>> *

# Patronyme réduit à une seule lettre
__[s](p_prénom_lettre_point_patronyme)__
    ([A-ZÉÈÂÎ][\w-]+)[  ][A-ZÉÈÂ]([.])[  ]([A-ZÉÈÂ][\w-]+) @@0,*,$
    <<- morph(\1, ":M[12]") and (morph(\3, ":(?:M[12]|V)") or not spell(\3)) ~2>> *
__[s>(p_prénom_lettre_point)__
    ([A-ZÉÈÂÎ][\w-]+)[  ][A-ZÉÈÂ]([.]) @@0,$
    <<- morph(\1, ":M[12]") and after("^\\W+[a-zéèêîïâ]") ~2>> _

# Patronymes composés avec Le/La/Les
__[s](p_patronyme_composé_avec_le_la_les)__
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
!!
!!!! Ponctuation de fin de paragraphe                                                             !!
!!
!!

__[i>/poncfin(poncfin_règle1)__
    ({w_1}) *$  @@0
    <<- before("\\w+(?:[.]|[   ][!?]) +(?:[A-ZÉÈÎ]\\w+|[ÀÔ])") -1>> \1.|\1 !|\1 ?                   # Il semble manquer une ponctuation finale (s’il s’agit d’un titre, le point final n’est pas requis).

TEST: __poncfin__ Vraiment. Quel {{ennui}}
TEST: Internet : le nouvel eldorado
TEST: OMC-FMI : Les nouveaux maîtres du monde


!!







|







739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
!!
!!!! Ponctuation de fin de paragraphe                                                             !!
!!
!!

__[i>/poncfin(poncfin_règle1)__
    ({w_1}) *$  @@0
    <<- before("\\w+(?:\\.|[   ][!?]) +(?:[A-ZÉÈÎ]\\w+|[ÀÔ])") -1>> \1.|\1 !|\1 ?                   # Il semble manquer une ponctuation finale (s’il s’agit d’un titre, le point final n’est pas requis).

TEST: __poncfin__ Vraiment. Quel {{ennui}}
TEST: Internet : le nouvel eldorado
TEST: OMC-FMI : Les nouveaux maîtres du monde


!!

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 [5137139ec8].

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 (to be removed in 2020)
        console.log("personal dictionary migration");
        browser.storage.local.set({ "personal_dictionary": oData["oPersonalDictionary"] });
        setDictionary("personal", oData["oPersonalDictionary"]);
        browser.storage.local.remove("oPersonalDictionary");
    }
    if (oData.hasOwnProperty("personal_dictionary")) {
        setDictionary("personal", oData["personal_dictionary"]);
    }
    if (oData.hasOwnProperty("community_dictionary")) {
        setDictionary("community", oData["community_dictionary"]);
    }
}

function init () {
    if (bChrome) {
        browser.storage.local.get("gc_options", initGrammarChecker);
        browser.storage.local.get("ui_options", initUIOptions);
        browser.storage.local.get("personal_dictionary", setSpellingDictionaries);
        browser.storage.local.get("community_dictionary", 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("personal_dictionary").then(setSpellingDictionaries, showError);
    browser.storage.local.get("community_dictionary").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
335
336
337
338
339
340
341
342
343
344
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
        // 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);
            console.log(xInfo);
            console.log(xTab);
    }
});


/*
    Keyboard shortcuts
*/
browser.commands.onCommand.addListener(function (sCommand) {
    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}`);
}







>
>
>
>
>
>


















>
>
>
>
>
>
>
>
>






|
|
>
>
>




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

















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

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


















<



<
<
<
<
|
|

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
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
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
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
        // 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);
            console.log(xInfo);
            console.log(xTab);
    }
});


/*
    Keyboard shortcuts
*/
browser.commands.onCommand.addListener(function (sCommand) {
    switch (sCommand) {
        case "lexicographer":
            sendCommandToCurrentTab("shortcutLexicographer");
            break;
        case "text_formatter":
            sendCommandToCurrentTab("shortcutTextFormatter");
            break;
        case "grammar_checker":
            sendCommandToCurrentTab("shortcutGrammarChecker");
            break;
        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 sendCommandToCurrentTab (sCommand) {
    console.log(sCommand);
    if (bChrome) {
        browser.tabs.query({ currentWindow: true, active: true }, (lTabs) => {
            for (let xTab of lTabs) {
                console.log(xTab);
                browser.tabs.sendMessage(xTab.id, {sActionRequest: sCommand});
            }
        });
        return;
    }
    browser.tabs.query({ currentWindow: true, active: true }).then((lTabs) => {
        for (let xTab of lTabs) {
            console.log(xTab);
            browser.tabs.sendMessage(xTab.id, {sActionRequest: sCommand});
        }
    }, onError);
}

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/content_scripts/init.js from [f86f05b6a6] to [6e32e0cbb4].

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
                    this.nMenu += 1;
                }
            }
        }
    },

    observePage: function () {
        /*
            When a textarea is added via jascript we add the menu :)
        */
        let that = this;
        this.xObserver = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                for (let i = 0;  i < mutation.addedNodes.length;  i++){
                    if (mutation.addedNodes[i].tagName == "TEXTAREA") {
                        if (that.oOptions === null || that.oOptions.textarea) {
                            oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, mutation.addedNodes[i]));







<
|
<







99
100
101
102
103
104
105

106

107
108
109
110
111
112
113
                    this.nMenu += 1;
                }
            }
        }
    },

    observePage: function () {

        //    When a textarea is added via jascript we add the menu

        let that = this;
        this.xObserver = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                for (let i = 0;  i < mutation.addedNodes.length;  i++){
                    if (mutation.addedNodes[i].tagName == "TEXTAREA") {
                        if (that.oOptions === null || that.oOptions.textarea) {
                            oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, mutation.addedNodes[i]));
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
    Connexion to the background
*/
let xGrammalectePort = browser.runtime.connect({name: "content-script port"});

xGrammalectePort.onMessage.addListener(function (oMessage) {
    let {sActionDone, result, dInfo, bEnd, bError} = oMessage;
    let sText = "";
    switch (sActionDone) {
        case "init":
            oGrammalecte.sExtensionUrl = oMessage.sUrl;
            // Start
            oGrammalecte.listenRightClick();
            oGrammalecte.createMenus();
            oGrammalecte.observePage();







<







251
252
253
254
255
256
257

258
259
260
261
262
263
264
/*
    Connexion to the background
*/
let xGrammalectePort = browser.runtime.connect({name: "content-script port"});

xGrammalectePort.onMessage.addListener(function (oMessage) {
    let {sActionDone, result, dInfo, bEnd, bError} = oMessage;

    switch (sActionDone) {
        case "init":
            oGrammalecte.sExtensionUrl = oMessage.sUrl;
            // Start
            oGrammalecte.listenRightClick();
            oGrammalecte.createMenus();
            oGrammalecte.observePage();
289
290
291
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
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
359
360


































361
362
363
364











































        /*
            Commands received from the context menu
            (Context menu are initialized in background)
        */
        // Grammar checker commands
        case "rightClickGCEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                oGrammalecte.startGCPanel(oGrammalecte.xRightClickedNode);
                sText = (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText;
                xGrammalectePort.postMessage({
                    sCommand: "parseAndSpellcheck",
                    dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false},
                    dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id}
                });
            } else {
                oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié. Sélectionnez le texte à corriger et relancez le correcteur via le menu contextuel.");
            }
            break;
        case "rightClickGCPage":
            oGrammalecte.startGCPanel();
            xGrammalectePort.postMessage({
                sCommand: "parseAndSpellcheck",
                dParam: {sText: oGrammalecte.getPageText(), sCountry: "FR", bDebug: false, bContext: false},
                dInfo: {}
            });
            break;
        case "rightClickGCSelectedText":
            oGrammalecte.startGCPanel();
            // selected text is sent to the GC worker in the background script.
            break;
        // Lexicographer commands
        case "rightClickLxgEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                oGrammalecte.startLxgPanel();
                sText = (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText;
                xGrammalectePort.postMessage({
                    sCommand: "getListOfTokens",
                    dParam: {sText: sText},
                    dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id}
                });
            } else {
                oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié. Sélectionnez le texte à analyser et relancez le lexicographe via le menu contextuel.");
            }
            break;
        case "rightClickLxgPage":
            oGrammalecte.startLxgPanel();
            xGrammalectePort.postMessage({
                sCommand: "getListOfTokens",
                dParam: {sText: oGrammalecte.getPageText()},
                dInfo: {}
            });
            break;
        case "rightClickLxgSelectedText":
            oGrammalecte.startLxgPanel();
            // selected text is sent to the GC worker in the background script.
            break;
        // Text formatter command
        case "rightClickTFEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                if (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") {
                    oGrammalecte.startFTPanel(oGrammalecte.xRightClickedNode);
                } else {
                    oGrammalecte.showMessage("Cette zone de texte n’est pas réellement un champ de formulaire, mais un node HTML éditable. Le formateur de texte n’est pas disponible pour ce type de champ de saisie.");
                }
            } else {
                oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié.");
            }
            break;
        // rescan page command
        case "rescanPage":
            oGrammalecte.rescanPage();
            break;


































        default:
            console.log("[Content script] Unknown command: " + sActionDone);
    }
});


















































|
<
<
<
<
<
<





<
<
|
<
<
<








<
<
<
<
<
|
<





<
<
<
<
<
|








|












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




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
286
287
288
289
290
291
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
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
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
        /*
            Commands received from the context menu
            (Context menu are initialized in background)
        */
        // Grammar checker commands
        case "rightClickGCEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                parseAndSpellcheckEditableNode(oGrammalecte.xRightClickedNode);






            } else {
                oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié. Sélectionnez le texte à corriger et relancez le correcteur via le menu contextuel.");
            }
            break;
        case "rightClickGCPage":


            parseAndSpellcheckPage();



            break;
        case "rightClickGCSelectedText":
            oGrammalecte.startGCPanel();
            // selected text is sent to the GC worker in the background script.
            break;
        // Lexicographer commands
        case "rightClickLxgEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {





                lexicographerEditableNode(oGrammalecte.xRightClickedNode);

            } else {
                oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié. Sélectionnez le texte à analyser et relancez le lexicographe via le menu contextuel.");
            }
            break;
        case "rightClickLxgPage":





            lexicographerPage();
            break;
        case "rightClickLxgSelectedText":
            oGrammalecte.startLxgPanel();
            // selected text is sent to the GC worker in the background script.
            break;
        // Text formatter command
        case "rightClickTFEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                if (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA" || oGrammalecte.xRightClickedNode.tagName == "INPUT") {
                    oGrammalecte.startFTPanel(oGrammalecte.xRightClickedNode);
                } else {
                    oGrammalecte.showMessage("Cette zone de texte n’est pas réellement un champ de formulaire, mais un node HTML éditable. Le formateur de texte n’est pas disponible pour ce type de champ de saisie.");
                }
            } else {
                oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié.");
            }
            break;
        // rescan page command
        case "rescanPage":
            oGrammalecte.rescanPage();
            break;

    }
});


/*
    Other messages from background
*/
browser.runtime.onMessage.addListener(function (oMessage) {
    let {sActionRequest} = oMessage;
    let xActiveNode = document.activeElement;
    switch (sActionRequest) {
        /*
            Commands received from the keyboard (shortcuts)
        */
        case "shortcutLexicographer":
            if (xActiveNode && (xActiveNode.tagName == "TEXTAREA" || xActiveNode.tagName == "INPUT")) {
                lexicographerEditableNode(xActiveNode);
            } else {
                lexicographerPage();
            }
            break;
        case "shortcutTextFormatter":
            if (xActiveNode && (xActiveNode.tagName == "TEXTAREA" || xActiveNode.tagName == "INPUT")) {
                oGrammalecte.startFTPanel(xActiveNode);
            }
            break;
        case "shortcutGrammarChecker":
            if (xActiveNode && (xActiveNode.tagName == "TEXTAREA" || xActiveNode.tagName == "INPUT")) {
                parseAndSpellcheckEditableNode(xActiveNode);
            } else {
                parseAndSpellcheckPage();
            }
            break;
        default:
            console.log("[Content script] Unknown command: " + sActionDone);
    }
});


/*
    Actions
*/

function parseAndSpellcheckPage () {
    oGrammalecte.startGCPanel();
    xGrammalectePort.postMessage({
        sCommand: "parseAndSpellcheck",
        dParam: {sText: oGrammalecte.getPageText(), sCountry: "FR", bDebug: false, bContext: false},
        dInfo: {}
    });
}

function parseAndSpellcheckEditableNode (xNode) {
    oGrammalecte.startGCPanel(xNode);
    let sText = (xNode.tagName == "TEXTAREA" || xNode.tagName == "INPUT") ? xNode.value : xNode.innerText;
    xGrammalectePort.postMessage({
        sCommand: "parseAndSpellcheck",
        dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false},
        dInfo: {sTextAreaId: xNode.id}
    });
}

function lexicographerPage () {
    oGrammalecte.startLxgPanel();
    xGrammalectePort.postMessage({
        sCommand: "getListOfTokens",
        dParam: {sText: oGrammalecte.getPageText()},
        dInfo: {}
    });
}

function lexicographerEditableNode (xNode) {
    oGrammalecte.startLxgPanel();
    let sText = (xNode.tagName == "TEXTAREA" || xNode.tagName == "INPUT") ? xNode.value : xNode.innerText;
    xGrammalectePort.postMessage({
        sCommand: "getListOfTokens",
        dParam: {sText: sText},
        dInfo: {sTextAreaId: xNode.id}
    });
}

Modified gc_lang/fr/webext/content_scripts/panel_gc.js from [04fddfc5c0] to [d5e6934557].

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    }

    start (xNode=null) {
        this.oTooltip.hide();
        this.clear();
        if (xNode) {
            this.oNodeControl.setNode(xNode);
            if (xNode.tagName != "TEXTAREA") {
                this.addMessage("Note : cette zone de texte n’est pas un champ de formulaire “textarea” mais un node HTML éditable. Une telle zone de texte est susceptible de contenir des éléments non textuels qui seront effacés lors de la correction.");
            }
        }
    }

    clear () {
        while (this.xParagraphList.firstChild) {







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    }

    start (xNode=null) {
        this.oTooltip.hide();
        this.clear();
        if (xNode) {
            this.oNodeControl.setNode(xNode);
            if (!(xNode.tagName == "TEXTAREA" || xNode.tagName == "INPUT")) {
                this.addMessage("Note : cette zone de texte n’est pas un champ de formulaire “textarea” mais un node HTML éditable. Une telle zone de texte est susceptible de contenir des éléments non textuels qui seront effacés lors de la correction.");
            }
        }
    }

    clear () {
        while (this.xParagraphList.firstChild) {
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
        this.dParagraph = new Map();
        this.bTextArea = null;
    }

    setNode (xNode) {
        this.clear();
        this.xNode = xNode;
        this.bTextArea = (xNode.tagName == "TEXTAREA");
        this.xNode.disabled = true;
        this._loadText();
    }

    clear () {
        if (this.xNode !== null) {
            this.xNode.disabled = false;







|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
        this.dParagraph = new Map();
        this.bTextArea = null;
    }

    setNode (xNode) {
        this.clear();
        this.xNode = xNode;
        this.bTextArea = (xNode.tagName == "TEXTAREA" || xNode.tagName == "INPUT");
        this.xNode.disabled = true;
        this._loadText();
    }

    clear () {
        if (this.xNode !== null) {
            this.xNode.disabled = false;

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 [f83d1e1e3e].

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
        "content_scripts/init.js"
      ],
      "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",







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



|
<
<


|
|
<
>
|
>
>
|







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
        "content_scripts/init.js"
      ],
      "run_at": "document_idle"
    }
  ],

  "commands": {
    "lexicographer": {
      "suggested_key": { "default": "Ctrl+Shift+L" },
      "description": "Ouvre le lexicographe"
    },
    "text_formatter": {
      "suggested_key": { "default": "Ctrl+Shift+F" },
      "description": "Ouvre le formateur de texte"
    },
    "grammar_checker": {
      "suggested_key": { "default": "Ctrl+Shift+V" },
      "description": "Ouvre le correcteur grammatical"
    },
    "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",
114
115
116
117
118
119
120


121
122

123
124
125
126
127
128
129
    "grammalecte/fr/mfsp_data.json",
    "grammalecte/fr/phonet_data.json",
    "grammalecte/fr/tests_data.json",
    "img/logo-16.png"
  ],

  "permissions": [


    "activeTab",
    "contextMenus",

    "downloads",
    "storage"
  ],

  "chrome_settings_overrides": {
    "search_provider": {
      "name": "Grammalecte",







>
>


>







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    "grammalecte/fr/mfsp_data.json",
    "grammalecte/fr/phonet_data.json",
    "grammalecte/fr/tests_data.json",
    "img/logo-16.png"
  ],

  "permissions": [
    "*://localhost/*",
    "*://dic.grammalecte.net/*",
    "activeTab",
    "contextMenus",
    "cookies",
    "downloads",
    "storage"
  ],

  "chrome_settings_overrides": {
    "search_provider": {
      "name": "Grammalecte",

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



































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
   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;
}


#message_box {
    display: none;
    position: fixed;
    top: 33%;
    left: calc(50% - 325px);
}
#message {
    display: inline-block;
    padding: 5px 20px;
    width: 600px;
    background-color: hsl(0, 50%, 50%);
    color: hsl(0, 50%, 98%);
    border-style: solid;
    border-width: 3px 0 3px 3px;
    border-color: hsla(0, 50%, 40%, .5);
    border-radius: 5px 0 0 5px;
}
#message_close_button {
    display: inline-block;
    padding: 5px 10px;
    background-color: hsl(0, 50%, 40%);
    color: hsl(0, 90%, 90%);
    border-style: solid;
    border-width: 3px 3px 3px 0;
    border-color: hsla(0, 50%, 30%, .5);
    border-radius: 0 5px 5px 0;
    cursor: pointer;
}


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


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


#connect_panel {
    background-color: hsl(210, 50%, 90%);
    border-radius: 5px;
    padding: 3px 10px;
}
#submit_button {
    display: inline-block;
    padding: 1px 5px;
    background-color: hsl(210, 50%, 30%);
    color: hsl(210, 0%, 100%);
    border-radius: 3px;
    cursor: pointer;
}


.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(210, 50%, 94%);
    border-style: solid;
    border-width: 1px 1px 1px 0;
    border-color: hsl(210, 50%, 70%);
    border-radius: 0 3px 3px 0;
}

.apply {
    display: none;
    float: right;
    padding: 2px 10px;
    background: hsl(120, 50%, 30%);
    color: hsl(120, 50%, 96%);
    cursor: pointer;
    border-radius: 3px;
}


/*
    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(210, 50%, 30%);
    color: hsl(210, 50%, 100%);
    border-radius: 3px;
    text-align: center;
}

Added gc_lang/fr/webext/panel/dictionaries.html version [7b8437c981].



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<!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 id="message_box">
      <div id="message">[néant]</div><div id="message_close_button">×</div>
    </div>

    <div class="inbox">
      <h1>Grammalecte · Dictionnaires communautaires</h1>

      <div id="connect_panel">
        <form id="connect_form" method="post" enctype="multipart/form-data">
          <p>
            Non connecté.
            <label for="email">E-mail : </label> <input type="email" id="email" name="email" />
            <label for="password">Mot de passe : </label> <input type="password" id="pw" name="pw" />
            <span id="submit_button">Se connecter</span>
            |
            <a href="http://dic.grammalecte.net" target="_blank">Inscription</a>
          </p>
        </form>
        <div id="connect_info">
          <p>
            Connecté. Identifiants : <span id="login_label"> </span>, <span id="email_label"> </span>
          </p>
        </div>
      </div>

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

      <div id="apply" class="apply">Appliquer les modifications</div>
      <h2><span id="num_dic">0</span> dictionnaires disponibles</h2>
      <progress id="wait_progress" value="0"></progress>
      <table id="dictionaries_table">
      </table>
    </div> <!-- inbox -->


    <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/dic_merger.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 [185528ef06].



















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
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
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
338
339
340
341
342
343
344
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
428
429
430
431
432
433
434
435
436
437
438
439
440
441
// 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);
    }
}

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)) {
        document.getElementById(sElemId).style.display = "none";
    } else {
        console.log("HTML node named <" + sElemId + "> not found.")
    }
}

async function hashText (sText, sAlgorithm = 'SHA-256') {
    let msgBuffer = new TextEncoder('utf-8').encode(sText);
    let hashBuffer = await crypto.subtle.digest(sAlgorithm, msgBuffer);
    let hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
}


const oMessage = {
    show: function (sMessage, nDelay=10000) {
        document.getElementById("message").textContent = sMessage;
        showElement("message_box");
        window.setTimeout(this.close, nDelay);
    },

    listen: function () {
        document.getElementById("message_close_button").addEventListener("click", (xEvent) => { this.close(); });
    },

    close: function () {
        hideElement("message_box");
    }
}


const oConnect = {
    bConnected: false,

    init: function () {
        if (bChrome) {
            browser.cookies.getAll({ domain: "localhost" }, this._init.bind(this));
            return;
        }
        let xPromise = browser.cookies.getAll({ domain: "localhost" });
        xPromise.then(this._init.bind(this), showError);
    },

    _init: function (lData) {
        for (let xCookie of lData) {
            console.log(xCookie.name, xCookie.value);
            this.bConnected = true;
        }
        if (this.bConnected) {
            hideElement("connect_form");
            showElement("connect_info");
        }
        else {
            showElement("connect_form");
            hideElement("connect_info");
        }
    },

    listen: function () {
        document.getElementById("submit_button").addEventListener("click", (xEvent) => { this.connect(); });
    },

    connect: function () {
        if (!this.checkValues()) {
            oMessage.show("Les valeurs des champs du formulaire ne sont pas conformes.");
            return;
        }
        let xForm = new FormData(document.getElementById('connect_form'));
        for (let [k, v] of xForm.entries()) {
            console.log("* ", k, v);
        }
        fetch("http://localhost/connect/", {
            method: "POST", // *GET, POST, PUT, DELETE, etc.
            //mode: "cors", // no-cors, cors, *same-origin
            //cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
            headers: {
                "Accept-Charset": "utf-8"
                //"Content-Type": "multipart/form-data",  // text/plain, application/json
            },
            credentials: "omit", // include, *same-origin, omit
            body: xForm
        })
        .then((response) => {
            if (response.ok) {
                if (response.status == 204) {
                    oMessage.show("Échec d’identification. Vérifiez l’e-mail et le mot de passe envoyés…");
                    return null;
                }
                for (let param in response) {
                    console.log(param, response[param]);
                }
                console.log(response.body);
                return response.json();
            } else {
                oMessage.show("Erreur. Le serveur ne semble pas en état de répondre. Veuillez réessayer ultérieurement.");
                return null;
            }
        })
        .then((response) => {
            if (response) {
                console.log("response: ", response);
            }
        })
        .catch((e) => {
            showError(e);
        });
    },

    checkValues () {
        if (document.getElementById("email").value === "") {
            return false;
        }
        let sEmail = document.getElementById("email").value;
        if (sEmail.search(/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/) === -1) {
            return false;
        }
        return true;
    },

    showId (sLogin, sEmail) {
        document.getElementById("login_label").textContent = sLogin;
        document.getElementById("email_label").textContent = sEmail;
        hideElement("connect_form");
        showElement("connect_info");
    }
}


class Table {

    constructor (sNodeId, lColumn, sProgressBarId, sResultId="", bDeleteButtons=true, bActionButtons) {
        this.sNodeId = sNodeId;
        this.xTable = document.getElementById(sNodeId);
        this.xApply = document.getElementById("apply");
        this.nColumn = lColumn.length;
        this.lColumn = lColumn;
        this.xProgressBar = document.getElementById(sProgressBarId);
        this.xNumEntry = document.getElementById(sResultId);
        this.lEntry = [];
        this.nEntry = 0;
        this.dSelectedDictionaries = new Map();
        this.lSelectedDictionaries = [];
        this.dDict = 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._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();
    }

    init () {
        if (bChrome) {
            browser.storage.local.get("selected_dictionaries_list", this._init.bind(this));
            return;
        }
        let xPromise = browser.storage.local.get("selected_dictionaries_list");
        xPromise.then(this._init.bind(this), showError);
    }

    _init (oResult) {
        if (oResult.hasOwnProperty("selected_dictionaries_list")) {
            this.lSelectedDictionaries = oResult.selected_dictionaries_list;
            console.log(this.lSelectedDictionaries);
        }
        this.getDictionarieslist();
    }

    getDictionarieslist () {
        fetch("http://localhost/dictionaries/")
        .then((response) => {
            if (response.ok) {
                return response.json();
            } else {
                return null;
            }
        })
        .then((response) => {
            if (response) {
                this.fill(response);
                this.showSelectedDictionaries(true);
            } else {
                // todo
            }
        })
        .catch((e) => {
            showError(e);
        });
    }

    getDictionary (sId, sName) {
        console.log("get: "+sName);
        fetch("http://localhost/download/"+sName)
        .then((response) => {
            if (response.ok) {
                return response.json();
            } else {
                console.log("dictionary not loaded: " + sName);
                return null;
            }
        })
        .then((response) => {
            if (response) {
                this.selectEntry(sId, sName);
                this.dDict.set(sName, response);
                browser.storage.local.set({ "stored_dictionaries": this.dDict });
            } else {
                //
            }
        })
        .catch((e) => {
            showError(e);
        });
    }

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

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

    listen () {
        if (this.bDeleteButtons || this.bActionButtons) {
            this.xTable.addEventListener("click", (xEvent) => { this.onTableClick(xEvent); }, false);
        }
        this.xApply.addEventListener("click", (xEvent) => { this.generateCommunityDictionary(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.getDictionary(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");
        }
        showElement("apply");
    }

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

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

    showSelectedDictionaries (bUpdateTable=false) {
        this.clearSelectedDict();
        let xDicList = document.getElementById("dictionaries_list");
        if (this.dSelectedDictionaries.size === 0) {
            xDicList.textContent = "[Aucun]";
            return;
        }
        for (let [sName, nDicId] of this.dSelectedDictionaries) {
            xDicList.appendChild(this._createDictLabel(nDicId, sName));
            if (bUpdateTable) {
                document.getElementById(this.sNodeId + "_row_" + nDicId).style.backgroundColor = "hsl(210, 50%, 90%)";
            }
        }
    }

    _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.dSelectedDictionaries.delete(sLabel);
            document.getElementById(this.sNodeId+"_row_"+nDicId).style.backgroundColor = "";
            xLabel.style.display = "none";
            showElement("apply");
        });
        xLabel.appendChild(xCloseButton);
        xLabel.appendChild(createNode("div", {className: "dic_button_label", textContent: sLabel}));
        return xLabel;
    }

    generateCommunityDictionary (xEvent) {
        hideElement("apply");
        let lDict = [];
        for (let sName of this.dSelectedDictionaries.keys()) {
            lDict.push(this.dDict.get(sName));
        }
        let oDict = dic_merger.merge(lDict, "S", "fr", "Français", "fr.community", "Dictionnaire communautaire (personnalisé)", this.xProgressBar);
        console.log(oDict);
        browser.storage.local.set({ "community_dictionary": oDict });
        browser.storage.local.set({ "selected_dictionaries_list": Array.from(this.dSelectedDictionaries.keys()) });
        browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sDictionary: "community", oDict: oDict}, dInfo: {} });
    }
}

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

oDicTable.init();

oMessage.listen();

oConnect.init();
oConnect.listen();

Modified gc_lang/fr/webext/panel/lex_editor.css from [62f94b1b3b] to [0f7a2051f7].

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


/*
    Dictionary
*/
#new_dictionary_button, #delete_dictionary_button {
    margin-left: 5px;
    padding: 1px 5px;
    background-color: hsl(150, 50%, 50%);
    color: hsl(150, 0%, 100%);
    border-radius: 3px;
    cursor: pointer;
}
#delete_dictionary_button {
    background-color: hsl(0, 50%, 50%);
    color: hsl(0, 0%, 100%);
}

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

#new_dictionary_section {
    margin: 5px 0;
    padding: 5px 10px;
    background-color: hsl(210, 10%, 90%);
    border-radius: 3px;
}
#create_dictionary_button {
    padding: 1px 5px;
    background-color: hsl(120, 50%, 30%);
    color: hsl(120, 10%, 100%);
    border-radius: 3px;
    cursor: pointer;
}

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


/*

Modified gc_lang/fr/webext/panel/lex_editor.html from [66bbff43be] to [8e3bc0ab95].

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
49
50
51
52
53
54
<!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 class="dic_container">
            <select id="dic_selector">
              <option value="__personal__">__personnel__</option>
            </select>
            <div id="new_dictionary_button" title="Créer un dictionnaire partagé">+</div>
            <div id="delete_dictionary_button" title="Supprimer ce dictionnaire">−</div>
          </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 id="new_dictionary_section" style="display: none;">
          <div class="dic_container">
            <div>Nouveau dictionnaire partagé</div>
            <div>Nom : fr.x.<input type="text" id="new_dictionary_name" required> · Description : <input type="text" id="new_dictionary_description" required></div>
            <div id="create_dictionary_button">Créer</div>
          </div>
        </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>







|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
                      <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;">







|



|











<
<
<
<
<
<
<

|







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
268
269
270
271
272
273
                  <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">







|







287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

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







|



















|

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

            <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 [b98659c88b].

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

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)) {
        document.getElementById(sElemId).style.display = "none";
    } else {
        console.log("HTML node named <" + sElemId + "> not found.")
    }
}
















const oTabulations = {

    lPage: ["lexicon_page", "add_page", "search_page", "info_page"],

    showPage: function (sRequestedPage) {







|













|

|












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







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

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)) {
        document.getElementById(sElemId).style.display = "none";
    } else {
        console.log("HTML node named <" + sElemId + "> not found.")
    }
}

function switchDisplay (sElemId, sDisplay="block") {
    if (document.getElementById(sElemId)) {
        if (document.getElementById(sElemId).style.display != "none") {
            document.getElementById(sElemId).style.display = "none";
        } else {
            document.getElementById(sElemId).style.display = sDisplay;
        }
    }
}

function showMessage (sMessage) {
    console.log(sMessage);
}


const oTabulations = {

    lPage: ["lexicon_page", "add_page", "search_page", "info_page"],

    showPage: function (sRequestedPage) {
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;







>
>


>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
        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);
    }
}







|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
        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,







|









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




>
>

|
|
<
<
<
<
<
<
|
<
<
<
<
<
|

|



>



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














<
|
<
<
<










|
|








|














>



>
>
>






|

|



>

<



>
>
>
>
>
>
>
>




|







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
648
649
650
651
652
653
654
655
656
657
658
659
660
661






662





663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700

701



702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
        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: {},
    oPersonalDictionary: null,
    lCreatedDictionaries: [],
    xDicSelector: document.getElementById("dic_selector"),

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

    _loadDictionaries: function (oResult) {
        if (oResult.hasOwnProperty("shared_dictionaries")) {
            this.oDictionaries = oResult.shared_dictionaries;
        }
        if (oResult.hasOwnProperty("personal_dictionary")) {
            this.oPersonalDictionary = oResult.personal_dictionary;
            oBinaryDict.load("__personal__");
        }
        if (oResult.hasOwnProperty("created_dictionaries_list")) {
            this.lCreatedDictionaries = oResult.created_dictionaries_list;
            for (let sDicName of this.lCreatedDictionaries) {
                let xOption = createNode("option", {value: sDicName, textContent: sDicName});
                this.xDicSelector.appendChild(xOption);
            }
        }
    },

    addDictionary: function (sDicName) {
        if (!this.oDictionaries.hasOwnProperty(sDicName)) {
            let xOption = createNode("option", {value: sDicName, textContent: sDicName});
            this.xDicSelector.appendChild(xOption);
            this.xDicSelector.selectedIndex = this.xDicSelector.options.length-1;
            this.lCreatedDictionaries.push(sDicName);
            browser.storage.local.set({ "created_dictionaries_list": this.lCreatedDictionaries });
        }
    },

    deleteDictionary: function (sDicName) {
        this.saveDictionary(sDicName, null);
        if (sDicName != "__personal__") {
            let iDict = this.lCreatedDictionaries.indexOf(sDicName);
            if (iDict > -1) {
                this.lCreatedDictionaries.splice(iDict, 1);
            }
            browser.storage.local.set({ "created_dictionaries_list": this.lCreatedDictionaries });
            for (let xNode of this.xDicSelector.childNodes) {
                if (xNode.value == sDicName) {
                    this.xDicSelector.removeChild(xNode);
                }
            }
            this.xDicSelector.selectedIndex = 0;
            oBinaryDict.load("__personal__");
        }
    },

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

    saveDictionary: function (sName, oJSON) {
        if (sName == "__personal__") {
            browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sDictionary: "personal", oDict: oJSON}, dInfo: {} });
            browser.storage.local.set({ "personal_dictionary": oJSON });
        }
        else {
            this.oDictionaries[sName] = oJSON;
            if (oJSON === null) {
                delete this.oDictionaries[sName];
            }
            browser.storage.local.set({ "shared_dictionaries": this.oDictionaries });
            this.sendDictionaryOnline(oJSON);
        }
    },

    sendDictionaryOnline: function (oJSON) {
        let sJSON = "";
        try {
            sJSON = JSON.stringify(oJSON);
        }
        catch (e) {
            showError(e);
            return e.message;
        }
        console.log("Send online dictionary: " + oJSON.sDicName);
        fetch("http://localhost/receive/", {
            method: "POST", // *GET, POST, PUT, DELETE, etc.
            //mode: "cors", // no-cors, cors, *same-origin
            //cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
            credentials: "include", // include, *same-origin, omit
            headers: {
                "Content-Type": "application/json",  // text/plain, application/json
                "Content-Length": sJSON.length
            },
            redirect: "follow", // manual, *follow, error
            referrer: "no-referrer", // no-referrer, *client
            body: sJSON, // body data type must match "Content-Type" header
        })
        .then((response) => {
            if (response.ok) {
                for (let param in response) {
                    console.log(param, response[param]);
                }
                console.log(response);
                return response.json();
            } else {
                console.log("Error: dictionary not sent: " + oJSON.sDicName);
                return null;
            }
        })
        .then((response) => {
            if (response) {
                console.log(response);
            } else {
                //
            }
        })
        .catch((e) => {
            showError(e);
        });
    }
}


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

    newDictionary: function () {
        this.oIBDAWG = null;
        this.sName = document.getElementById("new_dictionary_name").value;
        this.sDescription = document.getElementById("new_dictionary_description").value;
        oDictHandler.addDictionary(this.sName);
        oLexiconTable.clear();
        this.setDictData(0, "[néant]");
        hideElement("save_button");
        document.getElementById("new_dictionary_name").value = "";
        document.getElementById("new_dictionary_description").value = "";
        hideElement("new_dictionary_section")
    },

    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);
        document.getElementById("new_dictionary_button").addEventListener("click", () => { switchDisplay("new_dictionary_section"); }, false);
        document.getElementById("delete_dictionary_button").addEventListener("click", () => { this.delete(); }, false);
        document.getElementById("create_dictionary_button").addEventListener("click", () => { this.newDictionary(); }, 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");
    },

    delete: function () {
        if (confirm("Voulez-vous effacer le dictionnaire “"+this.sName+"” ?")) {
            oLexiconTable.clear();
            this.setDictData(0, "[néant]");
            oDictHandler.deleteDictionary(this.sName);
        }
    },

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







|




833
834
835
836
837
838
839
840
841
842
843
844
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 [b83ce0fb48].

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
              <p class="option_description">Ces zones de texte sont les champs de formulaire usuels pour saisir du texte. Ils ne permettent que la saisie de texte brut, sans fioritures.</p>
          </div>
          <div class="option_section" id="ui_option_editablenode_box">
              <p><input type="checkbox" id="ui_option_editablenode" /> <label for="ui_option_editablenode">“Nodes” éditables</label></p>
              <p class="option_description">Ces zones de texte sont des sections de page web éditables. Il est fréquent que ces zones de texte apparaissent comme des “textareas” standard. Il est aussi fréquent que ces zones de texte soient couplées avec toutes sortes de logiciels (de simples scripts d’aide à la mise en page ou des applications complexes). Ces zones de texte permettent l’affichage de texte enrichi (italique, gras, hyperlien, images, etc.).</p>
          </div>
          <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">







>
>
>
>
>
>






>
>














<

|
|

|
|
|
>
>
>
|
<
<
<



|
>
>
>







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
              <p class="option_description">Ces zones de texte sont les champs de formulaire usuels pour saisir du texte. Ils ne permettent que la saisie de texte brut, sans fioritures.</p>
          </div>
          <div class="option_section" id="ui_option_editablenode_box">
              <p><input type="checkbox" id="ui_option_editablenode" /> <label for="ui_option_editablenode">“Nodes” éditables</label></p>
              <p class="option_description">Ces zones de texte sont des sections de page web éditables. Il est fréquent que ces zones de texte apparaissent comme des “textareas” standard. Il est aussi fréquent que ces zones de texte soient couplées avec toutes sortes de logiciels (de simples scripts d’aide à la mise en page ou des applications complexes). Ces zones de texte permettent l’affichage de texte enrichi (italique, gras, hyperlien, images, etc.).</p>
          </div>
          <h2>Raccourcis clavier</h2>
          <p class="shortcut">CTRL+MAJ+L</p>
          <p class="shortcut_label">Lexicographe</p>
          <p class="shortcut">CTRL+MAJ+F</p>
          <p class="shortcut_label">Formateur de texte</p>
          <p class="shortcut">CTRL+MAJ+V</p>
          <p class="shortcut_label">Correcteur grammatical</p>
          <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,

Added graphspell-js/dic_merger.js version [e44b159d9d].















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Dictionaries merger

"use strict";

if (typeof(process) !== 'undefined') {
    var dawg = require("./dawg.js");
    var ibdawg = require("./ibdawg.js");
}
else if (typeof(require) !== 'undefined') {
    var dawg = require("resource://grammalecte/graphspell/dawg.js");
    var ibdawg = require("resource://grammalecte/graphspell/ibdawg.js");
}


const dic_merger = {

    merge: function (lDict, cStemming, sLangCode, sLangName, sDicName, sDescription, xProgressBar=null) {
        // merge a list of dictionaries (given as JSON objects)
        // return a merged dictionary as JSON object.
        if (xProgressBar) {
            xProgressBar.max = lDict.length;
            xProgressBar.value = 0;
        }
        let lEntry = [];
        for (let oDict of lDict) {
            // generate words list from selected dictionaries
            if (xProgressBar) {
                xProgressBar.value += 1;
            }
            try {
                let oIBDAWG = new IBDAWG(oDict);
                for (let aRes of oIBDAWG.select()) {
                    lEntry.push(aRes);
                }
            }
            catch (e) {
                console.error(e);
            }
        }
        if (xProgressBar) {
            xProgressBar.value = xProgressBar.max;
        }
        try {
            let oDAWG = new DAWG(lEntry, cStemming, sLangCode, sLangName, sDicName, sDescription, xProgressBar);
            let oDict = oDAWG.createBinaryJSON(1);
            return oDict;
        }
        catch (e) {
            console.log("Dictionaries merger: unable to generate merged dictionary");
            console.error(e);
            return null;
        }
    }

}

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 [c16f0b3559] to [72263209a8].

27
28
29
30
31
32
33
34
35
36
37
38
    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()







|




27
28
29
30
31
32
33
34
35
36
37
38
    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 [f072b5943d] to [a83cc39c80].

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 v6.4
# 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 v6.4
# 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 [50643cf0e8] to [c862a44ad1].

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

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()
    xParser.add_argument("lang", type=str, nargs='+', help="lang project to generate (name of folder in /lang)")







>

|
|





>




>




>
|
<







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()
    xParser.add_argument("lang", type=str, nargs='+', help="lang project to generate (name of folder in /lang)")