Index: gc_core/js/helpers.js ================================================================== --- gc_core/js/helpers.js +++ gc_core/js/helpers.js @@ -72,11 +72,10 @@ // conversions objectToMap: function (obj) { let m = new Map(); for (let param in obj) { - //console.log(param + " " + obj[param]); m.set(param, obj[param]); } return m; }, Index: gc_lang/fr/build.py ================================================================== --- gc_lang/fr/build.py +++ gc_lang/fr/build.py @@ -31,11 +31,11 @@ sLang = dVars['sDefaultUILang'] for sSection, lOpt in dVars['lStructOpt']: sHTML += f'\n
\n

{dVars["dOptLabel"][sLang][sSection][0]}

\n' for lLineOpt in lOpt: for sOpt in lLineOpt: - sHTML += f'

\n' + sHTML += f'

\n' sHTML += '
\n' return sHTML def createFirefoxExtension (sLang, dVars): Index: gc_lang/fr/data/phonet_simil.txt ================================================================== --- gc_lang/fr/data/phonet_simil.txt +++ gc_lang/fr/data/phonet_simil.txt @@ -631,10 +631,11 @@ reflux reflue reflues refluent régal régals régale régale régalent reine reines renne rennes rêne rênes relai relais relaie relaies relaient relaye relayes relayent remblai remblais remblaie remblaies remblaient +remord remords renvoi renvois renvoie renvoies renvoient repaire repaires repère repères repèrent reperds reperd repli replis replie replies replient ressenti ressentis ressentit resserre resserres resserrent ressers ressert Index: gc_lang/fr/modules-js/conj.js ================================================================== --- gc_lang/fr/modules-js/conj.js +++ gc_lang/fr/modules-js/conj.js @@ -81,18 +81,18 @@ return null; } return this._lVtyp[this._dVerb[sVerb][0]]; }, - getSimil: function (sWord, sMorph, sFilter=null) { + getSimil: function (sWord, sMorph, bSubst=false) { if (!sMorph.includes(":V")) { return new Set(); } let sInfi = sMorph.slice(1, sMorph.indexOf(" ")); let tTags = this._getTags(sInfi); let aSugg = new Set(); - if (sMorph.includes(":Q") || sMorph.includes(":Y")) { + if (!bSubst) { // we suggest conjugated forms if (sMorph.includes(":V1")) { aSugg.add(sInfi); aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":3s")); aSugg.add(this._getConjWithTags(sInfi, tTags, ":Ip", ":2p")); @@ -124,13 +124,10 @@ aSugg.delete(""); // if there is only one past participle (epi inv), unreliable. if (aSugg.size === 1) { aSugg.clear(); } - if (sMorph.includes(":V1")) { - aSugg.add(sInfi); - } } return aSugg; }, _getTags: function (sVerb) { @@ -485,16 +482,19 @@ } // Initialization if (!conj.bInit && typeof(browser) !== 'undefined') { - // WebExtension (but not in Worker) + // WebExtension Standard (but not in Worker) conj.init(helpers.loadFile(browser.extension.getURL("grammalecte/fr/conj_data.json"))); +} else if (!conj.bInit && typeof(chrome) !== 'undefined') { + // WebExtension Chrome (but not in Worker) + conj.init(helpers.loadFile(chrome.extension.getURL("grammalecte/fr/conj_data.json"))); } else if (!conj.bInit && typeof(require) !== 'undefined') { // Add-on SDK and Thunderbird conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json")); -} else if ( !conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") { +} else if (!conj.bInit && typeof(self) !== 'undefined' && typeof(self.port) !== 'undefined' && typeof(self.port.on) !== "undefined") { // used within Firefox content script (conjugation panel). // can’t load JSON from here, so we do it in ui.js and send it here. self.port.on("provideConjData", function (sJSONData) { conj.init(sJSONData); }); Index: gc_lang/fr/modules-js/gce_suggestions.js ================================================================== --- gc_lang/fr/modules-js/gce_suggestions.js +++ gc_lang/fr/modules-js/gce_suggestions.js @@ -488,16 +488,16 @@ function hasSimil (sWord, sPattern=null) { return phonet.hasSimil(sWord, sPattern); } -function suggSimil (sWord, sPattern) { +function suggSimil (sWord, sPattern=null, bSubst=false) { // return list of words phonetically similar to sWord and whom POS is matching sPattern let aSugg = phonet.selectSimil(sWord, sPattern); for (let sMorph of _dAnalyses.gl_get(sWord, [])) { - for (let e of conj.getSimil(sWord, sMorph, sPattern)) { - aSugg.add(e); + for (let e of conj.getSimil(sWord, sMorph, bSubst)) { + aSugg.add(e); } } if (aSugg.size > 0) { return Array.from(aSugg).join("|"); } Index: gc_lang/fr/modules-js/phonet.js ================================================================== --- gc_lang/fr/modules-js/phonet.js +++ gc_lang/fr/modules-js/phonet.js @@ -64,11 +64,11 @@ } return []; }, selectSimil: function (sWord, sPattern) { - // return list of words phonetically similar to sWord and whom POS is matching sPattern + // return a set of words phonetically similar to sWord and whom POS is matching sPattern if (!sPattern) { return new Set(this.getSimil(sWord)); } let aSelect = new Set(); for (let sSimil of this.getSimil(sWord)) { Index: gc_lang/fr/modules/conj.py ================================================================== --- gc_lang/fr/modules/conj.py +++ gc_lang/fr/modules/conj.py @@ -53,17 +53,18 @@ if sVerb not in _dVerb: return None return _lVtyp[_dVerb[sVerb][0]] -def getSimil (sWord, sMorph, sFilter=None): +def getSimil (sWord, sMorph, bSubst=False): if ":V" not in sMorph: return set() sInfi = sMorph[1:sMorph.find(" ")] tTags = _getTags(sInfi) aSugg = set() - if ":Q" in sMorph or ":Y" in sMorph: + #if ":Q" in sMorph or ":Y" in sMorph: + if not bSubst: # we suggest conjugated forms if ":V1" in sMorph: aSugg.add(sInfi) aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":3s")) aSugg.add(_getConjWithTags(sInfi, tTags, ":Ip", ":2p")) @@ -93,12 +94,10 @@ aSugg.add(_getConjWithTags(sInfi, tTags, ":PQ", ":Q4")) aSugg.discard("") # if there is only one past participle (epi inv), unreliable. if len(aSugg) == 1: aSugg.clear() - if ":V1" in sMorph: - aSugg.add(sInfi) return aSugg def getConjSimilInfiV1 (sInfi): if sInfi not in _dVerb: Index: gc_lang/fr/modules/gce_suggestions.py ================================================================== --- gc_lang/fr/modules/gce_suggestions.py +++ gc_lang/fr/modules/gce_suggestions.py @@ -371,18 +371,17 @@ def hasSimil (sWord, sPattern=None): return phonet.hasSimil(sWord, sPattern) -def suggSimil (sWord, sPattern=None): +def suggSimil (sWord, sPattern=None, bSubst=False): "return list of words phonetically similar to sWord and whom POS is matching sPattern" # we don’t check if word exists in _dAnalyses, for it is assumed it has been done before aSugg = phonet.selectSimil(sWord, sPattern) for sMorph in _dAnalyses.get(sWord, []): - for e in conj.getSimil(sWord, sMorph, sPattern): - aSugg.add(e) - #aSugg = aSugg.union(conj.getSimil(sWord, sMorph)) + aSugg.update(conj.getSimil(sWord, sMorph, bSubst)) + break if aSugg: return "|".join(aSugg) return "" Index: gc_lang/fr/modules/phonet.py ================================================================== --- gc_lang/fr/modules/phonet.py +++ gc_lang/fr/modules/phonet.py @@ -37,14 +37,14 @@ return _lSet[_dWord[sWord]] return [] def selectSimil (sWord, sPattern): - "return list of words phonetically similar to sWord and whom POS is matching sPattern" + "return a set of words phonetically similar to sWord and whom POS is matching sPattern" if not sPattern: return set(getSimil(sWord)) aSelect = set() for sSimil in getSimil(sWord): for sMorph in _dMorph.get(sSimil, []): if re.search(sPattern, sMorph): aSelect.add(sSimil) return aSelect Index: gc_lang/fr/oxt/TextFormatter/tf_tabrep.py ================================================================== --- gc_lang/fr/oxt/TextFormatter/tf_tabrep.py +++ gc_lang/fr/oxt/TextFormatter/tf_tabrep.py @@ -370,11 +370,11 @@ ("(?<=\\b[XVICL][XVICL][XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b", "e", True, True), ("(?<=\\b[XVICL][XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b", "e", True, True), ("(?<=\\b[XVICL][XVICL])(i?[èe]me|è|ᵉ)\\b", "e", True, True), ("(?<=\\b[XVICL])(i?[èe]me|è|ᵉ)\\b", "e", True, True), ("(?<=\\b[1I])ᵉʳ\\b", "er", True, True), - ("(?<=\\b[1I])ʳᵉ\\b", "er", True, True) + ("(?<=\\b[1I])ʳᵉ\\b", "re", True, True) ], "misc2": [ ("etc(…|[.][.][.]?)", "etc.", True, True), ("(?> =suggSimil(\2, ":[NA].*:[pi]") # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. + <<- -2>> =suggSimil(\2, ":[NA].*:[pi]", True) # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. __[s](incohérences_globales2)__ ([cC]e(?:tte|t|)|[mtsMTS]a|[mM]on) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on) @@0,$ - <<- -2>> =suggSimil(\2, ":[NA].*:[si]") # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. + <<- -2>> =suggSimil(\2, ":[NA].*:[si]", True) # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. TEST: {{Ces}} {{cette}} canaille qui nous a donné tant de fil à retordre. TEST: Mon {{il}} est une merveille. __[s](incohérence_globale_au_qqch)__ ([aA]u) ({w2}) @@0,$ <<- not \2.isupper() >>> <<- morph(\2, ">(?:[cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on|parce) ", False) - -2>> =suggSimil(\2, ":[NA].*:[si]") # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. + -2>> =suggSimil(\2, ":[NA].*:[si]", True) # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. <<- __else__ and morph(\2, ">quelle ", False) ->> auquel|auxquels|auxquelles # Incohérence. Soudez les deux mots.|https://fr.wiktionary.org/wiki/auquel <<- __else__ and \2 == "combien" and morph(word(1), ":[AY]", False) -1>> ô # Incohérence probable.|https://fr.wiktionary.org/wiki/%C3%B4_combien TEST: au {{nos}} enfants. TEST: {{Au quel}} faut-il s’adresser ? @@ -2529,11 +2529,11 @@ __[s](incohérence_globale_aux_qqch)__ ([aA]ux) ({w2}) @@0,$ <<- not \2.isupper() >>> <<- morph(\2, ">(?:[cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on|parce) ", False) - -2>> =suggSimil(\2, ":[NA].*:[pi]") # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. + -2>> =suggSimil(\2, ":[NA].*:[pi]", True) # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. <<- __else__ and morph(\2, ">quelle ", False) ->> auxquels|auxquelles # Incohérence. Soudez les deux mots.|https://fr.wiktionary.org/wiki/auquel <<- __else__ and \2 == "combien" and morph(word(1), ":[AY]", False) -1>> ô # Incohérence probable.|https://fr.wiktionary.org/wiki/%C3%B4_combien TEST: ils jouent aux {{des}}. TEST: {{Aux quels}} a-t-il adressé sa requête. ? @@ -2540,12 +2540,12 @@ TEST: Des individus {{aux}} combien sensibles aux usages. __[s](incohérences_globales3)__ ([dD]es) ([cdlmst]es|[nv]os|cettes?|[mts]a|mon|je|tu|ils?|elle?|[vn]ous|on) @@0,$ - <<- -2>> =suggSimil(\2, ":[NA].*:[pi]") # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. - <<- -1>> de # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. + <<- -2>> =suggSimil(\2, ":[NA].*:[pi]", True) # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. + <<- -1>> de # Incohérence : les mots “\1” et “\2” ne devraient pas se succéder. TEST: je ne sais {{des}} {{ses}} choses. @@ -2865,29 +2865,29 @@ TEST: {{en n’}}{{envoient}} que peu. __[i]/conf(conf_malgré_le_la_les)__ malgré l(?:es? +|a +|’)({w_3}) @@$ - <<- morphex(\1, ":", ":[GNAWM]") -1>> =suggSimil(\1, ":[NA]") # Incohérence : après “malgré”, on devrait trouver un groupe nominal. + <<- morphex(\1, ":", ":[GNAWM]") -1>> =suggSimil(\1, ":[NA]", True) # Incohérence : après “malgré”, on devrait trouver un groupe nominal. TEST: malgré l’{{arrête}} qui interdisait le port __[i]/conf(conf_ma_ta_cette_verbe)__ ([mt]a|cette) +({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() - -2>> =suggSimil(\2, ":[NA]:[fe]:[si]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:[fe]:[si]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: Cette {{pèle}} est trop fragile. __[i]/conf(conf_sa_verbe)__ (sa) ({w_2}) @@0,3 <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":N.*:[fe]|:[AW]") and \2[0].islower() or \2 == "va" -1>> ça # Confusion : « \2 » est un verbe. Exemples : sa jambe, ça vient. <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and hasSimil(\2) - -2>> =suggSimil(\2, ":[NA]:[fe]:[si]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:[fe]:[si]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: {{sa}} devient difficile. TEST: il me tendit {{sa}} {{pèche}}. @@ -2898,67 +2898,67 @@ __[i]/conf(conf_du_cet_au_verbe)__ (du|cet|au) +({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and not (\2 == "sortir" and re.search(r"(?i)au", \1)) - -2>> =suggSimil(\2, ":[NA]:[me]:[si]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:[me]:[si]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: cet {{plaît}} est infectée. __[i]/conf(conf_ce_verbe)__ (ce) +(?!faire|peut)({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]:.:[si]|:V0e.*:3[sp]|>devoir") and \2[0].islower() and hasSimil(\2) - -2>> =suggSimil(\2, ":[NA]:[me]:[si]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:[me]:[si]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: {{ce}} {{rappelle}} n’en finit pas. __[i]/conf(conf_mon_verbe)__ (mon) +({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() - -2>> =suggSimil(\2, ":[NA]:.:[si]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:.:[si]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: mon {{rackette}} n’a pas porté les fruits espérés. TEST: Belle qui tient mon vit captif entre tes doigts. __[i]/conf(conf_ton_son_verbe)__ [st]on ({w_2}) @@4 <<- morph(\1, ":V.*:(?:Y|[123][sp])") and \1[0].islower() and isStart() - -1>> =suggSimil(\1, ":[NA]:[me]:[si]") # Incohérence : « \1 » est un verbe. + -1>> =suggSimil(\1, ":[NA]:[me]:[si]", True) # Incohérence : « \1 » est un verbe. TEST: ton {{recèle}} a été dévoilé __[i]/conf(conf_det_plur_verbe)__ ([dcmts]es|quelques|aux|[nv]os) +({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() and not re.search(r"(?i)^quelques? soi(?:ent|t|s)\b", \0) - -2>> =suggSimil(\2, ":[NA]:.:[pi]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:.:[pi]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: la crainte des {{attentas}} fait feu de tout bois. __[i]/conf(conf_auxdits_verbe)__ (auxdits) +({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() - -2>> =suggSimil(\2, ":[NA]:[me]:[pi]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:[me]:[pi]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: elle se rendit auxdits {{jardinais}} __[i]/conf(conf_auxdites_verbe)__ (auxdites) +({w_2}) @@0,$ <<- morphex(\2, ":V.*:(?:Y|[123][sp])", ":[NAQ]") and \2[0].islower() - -2>> =suggSimil(\2, ":[NA]:[fe]:[pi]") # Incohérence avec « \1 » : « \2 » est un verbe. + -2>> =suggSimil(\2, ":[NA]:[fe]:[pi]", True) # Incohérence avec « \1 » : « \2 » est un verbe. TEST: auxdites {{scelles}}, il ne prêta pas attention. __[i]/conf(conf_de_la_vconj)__ de la ({w_2}) @@6 <<- morphex(\1, ":[123][sp]", ":[NAQ]") - -1>> =suggSimil(\1, ":(?:[NA]:[fe]:[si])") # Incohérence : « \1 » est un verbe. + -1>> =suggSimil(\1, ":(?:[NA]:[fe]:[si])", True) # Incohérence : « \1 » est un verbe. TEST: les petits esprits de la {{pensait}} religieuse TEST: pour les insulter au sortir du seul troquet dispensateur d’oubli liquide du coin @@ -2966,78 +2966,78 @@ __[i]/conf(conf_de_le_nom_ou_vconj)__ (de le) ({w_2}) @@0,6 <<- morphex(\2, ":[NAQ].*:[me]", ":[YG]") and \2[0].islower() -1>> du # Incohérence : « \2 » est un nom ou un adjectif. - <<- morph(\2, ":[123][sp]", False) -2>> =suggSimil(\2, ":Y") # Incohérence : « \2 » est une forme verbale conjuguée. + <<- morph(\2, ":[123][sp]", False) -2>> =suggVerbInfi(\2) # Incohérence : « \2 » est une forme verbale conjuguée. TEST: {{de le}} vin ->> du TEST: il n’est pas interdit de le {{pensait}} __[i]/conf(conf_de_l_vconj)__ de l’({w_2}) @@5 - <<- morphex(\1, ":[123][sp]", ":[NAQ]") -1>> =suggSimil(\1, ":(?:[NA]:.:[si])") # Incohérence : « \1 » est une forme verbale conjuguée. + <<- morphex(\1, ":[123][sp]", ":[NAQ]") -1>> =suggSimil(\1, ":[NA]:.:[si]", True) # Incohérence : « \1 » est une forme verbale conjuguée. TEST: de l’{{entra}} __[i]/conf(conf_un_verbe)__ (?> =suggSimil(\1, ":[NAQ]:[me]:[si]") # Incohérence : « \1 » est une forme verbale conjuguée. + -1>> =suggSimil(\1, ":[NAQ]:[me]:[si]", True) # Incohérence : « \1 » est une forme verbale conjuguée. TEST: un {{maintient}} difficile. __[i]/conf(conf_de_dès_par_vconj)__ (?:d(?:e|ès)|par) ({w_2}) @@$ - <<- \1[0].islower() and morph(\1, ":V.*:[123][sp]") -1>> =suggSimil(\1, ":[NA]") # Incohérence : « \1 » est une forme verbale conjuguée. + <<- \1[0].islower() and morph(\1, ":V.*:[123][sp]") -1>> =suggSimil(\1, ":[NA]", True) # Incohérence : « \1 » est une forme verbale conjuguée. TEST: par {{bloque}} de données TEST: il s’agit de {{mette}} en évidence. __[i]/conf(conf_d_une_vconj)__ d’(?:une? +|)({w_2}) @@$ <<- \1[0].islower() and morphex(\1, ":V.*:[123][sp]", ":[GNA]") and not before(r"(?i)\b(?:plus|moins) +$") - -1>> =suggSimil(\1, ":[NA]") # Incohérence : « \1 » est une forme verbale conjuguée. + -1>> =suggSimil(\1, ":[NA]", True) # Incohérence : « \1 » est une forme verbale conjuguée. TEST: d’une {{habille}} femme TEST: plus d’un ont été traumatisés TEST: plus d’une sont parties aussi vite qu’elles étaient venues __[i]/conf(conf_il_on_pas_verbe)__ (?> =suggSimil(\1, ":(?:3s|Oo)") # Incohérence : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. + -1>> =suggSimil(\1, ":(?:3s|Oo)", False) # Incohérence : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. TEST: il {{et}} parti. __[i]/conf(conf_ils_pas_verbe)__ (?> =suggSimil(\1, ":(?:3p|Oo)") # Incohérence avec « ils » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. + -1>> =suggSimil(\1, ":(?:3p|Oo)", False) # Incohérence avec « ils » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. TEST: ils {{son}} du même bois. TEST: Ils {{étai}} partie au {{restaurent}} __[i]/conf(conf_je_pas_verbe)__ je (?!soussigné)(?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$ <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)") and morphex(word(-1), ":", ":1s", True) - -1>> =suggSimil(\1, ":(?:1s|Oo)") # Incohérence avec « je » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. + -1>> =suggSimil(\1, ":(?:1s|Oo)", False) # Incohérence avec « je » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. TEST: Je {{travail}}. __[i]/conf(conf_tu_pas_verbe)__ tu (?:l’|l(?:es?|a|eur|ui) +|[nv]ous +|)({w_2}) @@$ <<- morphex(\1, ":", ":(?:[123][sp]|O[onw]|X)") and morphex(word(-1), ":", ":(?:2s|V0e)", True) - -1>> =suggSimil(\1, ":(?:2s|Oo)") # Incohérence avec « tu » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. + -1>> =suggSimil(\1, ":(?:2s|Oo)", False) # Incohérence avec « tu » : « \1 » devrait être un verbe, un pronom objet, un adverbe de négation, etc. TEST: tu {{croix}} que tu sais quelque chose, mais tu ne sais rien. TEST: elles seules peuvent s’en sortir. @@ -3064,11 +3064,11 @@ # # Incohérence avec « très » : « \2 » n’est ni un adjectif, ni un participe passé, ni un adverbe. __[i]/conf(conf_très_verbe)__ très +(?!envie)({w_2}) @@$ - <<- morphex(\1, ":(?:Y|[123][sp])", ":[AQW]") -1>> =suggSimil(\1, ":[AW]") # Incohérence avec « très » : « \1 » n’est ni un adjectif, ni un participe passé, ni un adverbe. + <<- morphex(\1, ":(?:Y|[123][sp])", ":[AQW]") -1>> =suggSimil(\1, ":[AW]", True) # Incohérence avec « très » : « \1 » n’est ni un adjectif, ni un participe passé, ni un adverbe. TEST: Il est très {{cite}}. TEST: très {{suivit}} par ce détective TEST: il était très {{habille}} @@ -3109,11 +3109,11 @@ __[i]/conf(conf_si_vconj)__ si +({w2}) @@$ <<- morphex(\1, ":[123][sp]", ":[GNAQWMT]") and morphex(word(1), ":", ":D", True) - -1>> =suggSimil(\1, ":[AWGT]") # Incohérence avec « si » : « \1 » ne devrait pas être une forme verbale conjuguée. + -1>> =suggSimil(\1, ":[AWGT]", True) # Incohérence avec « si » : « \1 » ne devrait pas être une forme verbale conjuguée. TEST: Ces gens sont si {{prit}} par leur travail qu’ils en oublient de vivre. TEST: Ça ira mieux demain, surtout si émerge une demande forte de la part des consommateurs. @@ -3464,11 +3464,11 @@ __[s]/conf(conf_c_est3)__ ([scSC]es) (?:qu(?:lle|el?|)|comme|ce(?:t|tte|)|[nv]os|les?|eux|elles) @@0 <<- -1>> c’est # Confusion probable. Écrivez « c’est » pour dire « ceci est… ». __[s]/conf(conf_c_est4)__ ([scSC]es) ({w_1}) ({w_1}) @@0,w,$ - <<- morph(\2, ":[WX]", False) and morph(\3, ":[RD]|>pire ", False) -1>> c’est # Confusion probable. Écrivez « c’est » pour dire « ceci est… ». + <<- morph(\2, ":[WX]", ":N:.*:[pi]") and morph(\3, ":[RD]|>pire ", False) -1>> c’est # Confusion probable. Écrivez « c’est » pour dire « ceci est… ». __[i]/conf(conf_ces_ses)__ (c’est) ({w_2}) @@0,6 <<- morphex(\2, ":N.*:p", ":(?:G|W|M|A.*:[si])") -1>> ces|ses # Confusion. Exemples : c’est facile ; ces chats (désignation) ; ses chats (possession)… TEST: {{ses}} au-dessus de ses forces. TEST: {{ces}} comme la peste @@ -3475,10 +3475,11 @@ TEST: car {{ses}} d’avance perdu TEST: {{ces}} qu’il y a tant de pertes TEST: {{ces}} jamais une bonne idée. TEST: {{c’est}} {{délires}} nous ennuient TEST: En 2015, c’est Paris et son agglomération qui… +TEST: Ses pas de danse. # date / datte __[i]/conf(conf_date1)__ dates @@ -4045,44 +4046,44 @@ __[i](p_m_enfin)__ m’enfin <<- ~>> * __[i]/conf(conf_j_y_en_qqch)__ (j’(?:en +|y +|))({w_1}) @@0,$ <<- morphex(\2, ":", ":(?:[123][sp]|O[onw])") - -2>> =suggSimil(\2, ":1s") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":1s", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. __[i]/conf(conf_ne_qqch)__ (n(?:e +|’))({w_1}) @@0,$ <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)|>(?:[lmtsn]|surtout|guère|presque|même|tout|parfois|vraiment|réellement) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet. + -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet. __[i]/conf(conf_n_y_en_qqch)__ (n’(?:en|y)) ({w_1}) @@0,$ <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. __[i]/conf(conf_ne_pronom_qqch)__ (ne (?:l(?:es? +|eur +|a +|’)|[nv]ous))({w_1}) @@0,$ <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|O[onw]|X)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. __[i]/conf(conf_me_te_se_qqch)__ ([mts]e +(?:les? |la |l’|))(?!voi(?:là|ci))({w_1}) @@0,$ <<- not re.search("(?i)^se que?", \0) and morphex(\2, ":", ":(?:[123][sp]|Y|P|Oo)|>[lmts] ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet. + -2>> =suggSimil(\2, ":(?:[123][sp]|Oo|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe ou un pronom personnel objet. __[i]/conf(conf_m_t_s_y_en_qqch)__ ([mts]’(?:en|y)) (?!voilà)({w_1}) @@0,$ <<- morphex(\2, ":", ":(?:[123][sp]|Y|P|Oo)") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. __[i]/conf(conf_m_s_qqch)__ ([ms]’)({w_1}) @@0,2 <<- morphex(\2, ":", ":(?:[123][sp]|Y|P)|>(?:en|y|ils?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. __[i]/conf(conf_t_qqch)__ (t’)({w_1}) @@0,2 <<- morphex(\2, ":", ":(?:[123][sp]|Y|P)|>(?:en|y|ils?|elles?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|ce)$", \2) - -2>> =suggSimil(\2, ":(?:[123][sp]|Y)") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":(?:[123][sp]|Y)", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. __[i]/conf(conf_c_ç_qqch)__ ([cç]’)({w_1}) @@0,2 <<- morphex(\2, ":", ":[123][sp]|>(?:en|y|que?) ") and not re.search("(?i)-(?:ils?|elles?|[nv]ous|je|tu|on|dire)$", \2) - -2>> =suggSimil(\2, ":3s") # Incohérence avec « \1 » : « \2 » devrait être un verbe. + -2>> =suggSimil(\2, ":3s", False) # Incohérence avec « \1 » : « \2 » devrait être un verbe. TEST: ne l’{{oubli}} pas TEST: elle ne la {{croix}} pas TEST: ils me les {{laissés}}. TEST: ne {{pensée}} rien, jamais @@ -4742,10 +4743,11 @@ __[i](p_chili_con_carne)__ chilis? (con carne) @@$ <<- ~1>> * __[i](p_chef_d_œuvre)__ chefs?(-d’œuvre) @@$ <<- ~1>> * __[i](p_clair_comme)__ claire?s? (comme (?:de l’eau de (?:boudin|roche|source)|du (?:cristal|jus de (?:boudin|chaussettes?|chique)))) @@$ <<- ~1>> * __[i](p_commis_d_office)__ commise?s? (d’office) @@$ <<- ~1>> * __[i](p_convention)__ conventions? (récepteur|générateur) @@$ <<- ~1>> * +__[i](p_con_comme)__ con(?:ne|)s? (comme (?:un balai|une valise sans poignées?|la lune)) @@$ <<- ~1>> * __[i](p_coup_de)__ coups? (de (?:balai|bol|cœur|foudre|fil|grâce|jarnac|théâtre|coude|genou|main|p(?:atte|ied|oing|oker|ouce)|tête)|d’(?:avance|éclat|État|œil|épaule)|du sort) @@$ <<- ~1>> * __[i](p_course_contre_la_montre)__ courses? (contre la montre) @@$ <<- ~1>> * __[i](p_cousu_main)__ cousue?s? +(main) @@$ <<- ~1>> * @@ -4819,12 +4821,16 @@ <<- ~1>> * __[i](p_oiseau_de)__ oiseaux? (de (?:malheur|nuit|proie|mauvais augure)) @@$ <<- ~1>> * __[i](p_onde_de_choc)__ ondes? (de choc) @@$ <<- ~1>> * __[i](p_orge)__ orge (perlé|mondé|carré) @@$ <<- ~1>> * __[i](p_noire_comme)__ noire?s? (comme (?:la nuit|une nuit sans lune)) @@$ <<- ~1>> * -__[i](p_pièce_de)__ pièces? (de (?:théâtre|monnaie|\d+ (?:euros?|centimes?|cents?|livres? sterling|shillings?))) @@$ <<- ~1>> * __[i](p_partie_de_jambe_en_l_air)__ parties? (de jambes en l’air) @@$ <<- ~1>> * +__[i](p_papier_à_lettre)__ + papiers? (([àa]) lettres?) @@$,w + <<- \2 == "a" -2>> à # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”. + <<- ~1>> * +__[i](p_pièce_de)__ pièces? (de (?:théâtre|monnaie|\d+ (?:euros?|centimes?|cents?|livres? sterling|shillings?))) @@$ <<- ~1>> * __[i](p_porte_de)__ portes? (de (?:service|garage)) @@$ <<- ~1>> * __[i](p_poudre_aux_yeux)__ poudres? (aux yeux) @@$ <<- ~1>> * __[i](p_preuve_du_contraire)__ preuves? +(?:suffisantes? +|)(du contraire) @@$ <<- ~1>> * __[i](p_quelqu_un_d_autre)__ quelqu un (d’autre) @@$ <<- ~1>> * __[i](loc_remire_à_plat)__ @@ -4894,10 +4900,11 @@ TEST: cette fille {{a}} papa nous pourrit la vie. TEST: Les conséquences des gaz {{a}} effet de serre. TEST: devant la machine {{a}} café. TEST: Achète un moule {{a}} gaufres. TEST: Fais la mise {{a}} jour +TEST: Amenez-moi du papier {{a}} lettres. TEST: Elle mit du rouge {{a}} lèvres. TEST: on a besoin d’une remise {{a}} plat. TEST: passe-moi mon sac {{a}} dos. TEST: dans le silo {{a}} grain. TEST: sa chambre, c’est une vraie soue {{a}} cochons. @@ -5202,11 +5209,11 @@ ## Simplication des locutions verbales __[i](p_donner_sens)__ ((?:re|)donn\w+) +(sens) @@0,$ <<- morph(\1, ">(?:re|)donner ", False) ~2>> * __[i](p_faire_qqch)__ - (f[aiîeo]\w*) +(tous(?: deux| trois|) +|)(allusion|assaut|bonne figure|confiance|compliqué|chaud|débat|demi-tour|fausse route|froid|gr(?:ise mine|and cas)|h(?:alte|onte)|ma(?:chine|rche) arrière|p(?:art(?:ie(?: intégrante|)|)|eur|laisir|rofil bas)|rage|salle comble|sens|table rase|volte-face|ce que bon (?:me|te|lui|leur|nous|vous) semble) @@0,*,$ + (f[aiîeo]\w*) +(tous(?: deux| trois|) +|)(allusion|assaut|bonne figure|confiance|compliqué|chaud|débat|demi-tour|fausse route|froid|gr(?:ise mine|and cas)|h(?:alte|onte)|illusion|ma(?:chine|rche) arrière|p(?:art(?:ie(?: intégrante|)|)|eur|laisir|rofil bas)|rage|salle comble|sens|table rase|volte-face|ce que bon (?:me|te|lui|leur|nous|vous) semble) @@0,*,$ <<- morph(\1, ">faire ", False) ~2>> * <<- __also__ ~3>> * __[i](loc_mettre_à_qqch)__ (m(?:et|[iî][mst])\w*) +(([àa]) (?:jour|niveau|plat|l’écart)) @@0,$,w <<- morph(\1, ">mettre ", False) >>> @@ -5227,10 +5234,15 @@ (rest\w+) (lettre morte) @@0,$ <<- morph(\1, ">rester ", False) ~2>> * __[i](p_sembler_paraitre_être)__ (sembl\w+|par[au]\w+) +(être|avoir été) +({w_2}) @@0,w,$ <<- morph(\1, ">(?:sembler|para[îi]tre) ") and morphex(\3, ":A", ":G") ~2>> * +__[i](loc_suivre_de_près)__ + (suiv\w+) +((?:ça +|ce(?:ci|la) +|)de (pr[èé]s?|prêts?)) @@0,$,$ + <<- morph(\1, ">suivre ", False) >>> + <<- \3 != "près" -3>> près # Confusion : écrivez “près” pour dire “proche de quelque chose”.|https://fr.wiktionary.org/wiki/pr%C3%A8s + <<- ~2>> * __[i](loc_tenir_à_distance)__ (t[eiî]\w+) +(([àa]) distance) d(?:es?|u) @@0,$,w <<- morph(\1, ">tenir ", False) >>> <<- \3 == "a" -3>> à # Confusion : “a” est une conjugaison du verbe “avoir”. Pour la préposition, écrivez “à”. <<- ~2>> * @@ -5245,10 +5257,11 @@ (v[eiî]\w+) ((?:on ne sait|je ne sais) (?:pas |)(?:trop |)d’où) @@0,$ <<- morph(\1, ">venir ", False) ~2>> * TEST: il faut tenir {{contes}} des faits au lieu de nos impressions. TEST: prendre {{a}} la légère ce test serait une erreur. +TEST: on va suivre ça de {{prêt}}. TEST: il faut se tenir {{a}} distance de ces gens-là. # Autres tests contre les faux positifs TEST: pourquoi faire compliqué quand on peut faire simple @@ -5309,11 +5322,11 @@ TEST: ce que c’est : le signe évident d’une politique volontaire TEST: On aura carte blanche. TEST: La seule façon de redonner sens à des notions… TEST: Les longues tresses que j’ai pris l’habitude de porter depuis quelque temps et qu’il faut cinq heures pour parfaire. TEST: Il est pieds nus. -TEST: des dossiers secrets {{défense}} +TEST: des dossiers secrets défense # # //////////////////////////////////////// RÈGLES DE CONTRÔLE //////////////////////////////////////// # @@ -11462,31 +11475,31 @@ __[i]/inte(inte_je)__ ({w1})-je @@0 <<- morphex(\1, ":V", ":1[sśŝ]") -1>> =suggVerb(@, ":1ś") # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier. - <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":1[sśŝ]") # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier. + <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":1[sśŝ]", False) # Forme interrogative : « \1 » n’est pas un verbe à la 1ʳᵉ personne du singulier. TEST: {{Vas}}-je ->> Vais TEST: {{Prit}}-je ->> Pris TEST: {{prix}}-je le temps d’y parvenir ? Oui. __[i]/inte(inte_tu)__ ({w1})-tu @@0 <<- morphex(\1, ":V", ":[ISK].*:2s") -1>> =suggVerb(@, ":2s") # Forme interrogative. « \1 » n’est pas un verbe à la 2ᵉ personne du singulier. - <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":2s") # Forme interrogative : « \1 » n’est pas un verbe à la 2ᵉ personne du singulier. + <<- not morph(\1, ":V", False) -1>> =suggSimil(\1, ":2s", False) # Forme interrogative : « \1 » n’est pas un verbe à la 2ᵉ personne du singulier. TEST: {{Peut}}-tu ->> Peux TEST: {{peu}}-tu revenir chez moi ? __[i]/inte(inte_il_elle_on)__ ({w1})-(?:t-|)(il|elle|on) @@0,$ <<- morphex(\1, ":V", ":3s") -1>> =suggVerb(@, ":3s") # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier. <<- \1 != "t" and (not \1.endswith("oilà") or \2 != "il") and morphex(\1, ":", ":V") - -1>> =suggSimil(\1, ":3s") # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier. + -1>> =suggSimil(\1, ":3s", False) # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier. <<- not \2.endswith(("n", "N")) and morphex(\1, ":3p", ":3s") -2>> \2s # Forme interrogative : accordez “\2” avec le verbe à la 3ᵉ personne du pluriel. TEST: {{Peux}}-il ->> Peut TEST: {{Attaques}}-t-on ->> Attaque TEST: {{Prends}}-elle ->> Prend @@ -11496,11 +11509,11 @@ __[s]/inte(inte_ce)__ ({w_2})-([cs]e) @@0,$ <<- morphex(\1, ":V", ":(?:3s|V0e.*:3p)") -1>> =suggVerb(@, ":3s") # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132 - <<- morphex(\1, ":", ":V") -1>> =suggSimil(\1, ":3s") # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132 + <<- morphex(\1, ":", ":V") -1>> =suggSimil(\1, ":3s", False) # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du singulier.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132 <<- \2 == "se" -2>> ce # Forme interrogative. Confusion.|http://bdl.oqlf.gouv.qc.ca/bdl/gabarit_bdl.asp?id=4132 TEST: était-{{se}} cela, la vérité ineffable ? TEST: {{étai}}-ce notre destinée de souffrir ? TEST: étaient-{{se}} ces hommes-là qui allaient nous guider dans les montagnes ? @@ -11509,20 +11522,20 @@ __[i]/inte(inte_nous)__ ({w1})-nous @@0 <<- morphex(\1, ":V", ":(?:1p|E:2[sp])") -1>> =suggVerb(@, ":1p") # Forme interrogative ou impérative incorrecte. - <<- morphex(\1, ":", ":V|>chez ") -1>> =suggSimil(\1, ":1p") # Forme interrogative ou impérative incorrecte. + <<- morphex(\1, ":", ":V|>chez ") -1>> =suggSimil(\1, ":1p", False) # Forme interrogative ou impérative incorrecte. TEST: {{Prendront}}-nous ->> Prendrons TEST: {{Attendront}}-nous le train ->> Attendrons __[i]/inte(inte_vous)__ ({w1})-vous @@0 <<- morphex(\1, ":V", ":2p") -1>> =suggVerb(@, ":2p") # Forme interrogative ou impérative incorrecte. - <<- not morph(\1, ":V|>chez ", False) -1>> =suggSimil(\1, ":2p") # Forme interrogative ou impérative incorrecte. + <<- not morph(\1, ":V|>chez ", False) -1>> =suggSimil(\1, ":2p", False) # Forme interrogative ou impérative incorrecte. TEST: {{Attaquait}}-vous ->> Attaquiez TEST: Elle a de nombreux rendez-vous ce matin. TEST: êtes-vous là ? @@ -11530,11 +11543,11 @@ __[i]/inte(inte_ils_elles)__ ({w1})-(?:ils|elles) @@0 <<- morphex(\1, ":V", ":3p") and spell(\1) -1>> =suggVerb(@, ":3p") # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel. <<- \1 != "t" and not morph(\1, ":V", False) and spell(\1) - -1>> =suggSimil(\1, ":3p") # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel. + -1>> =suggSimil(\1, ":3p", False) # Forme interrogative : « \1 » n’est pas un verbe à la 3ᵉ personne du pluriel. TEST: {{attaquant}}-ils ->> attaquent TEST: {{prendrons}}-elles un verre avec moi ? Index: gc_lang/fr/webext/background.js ================================================================== --- gc_lang/fr/webext/background.js +++ gc_lang/fr/webext/background.js @@ -5,10 +5,18 @@ function showError (e) { console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); } +// Chrome don’t follow the W3C specification: +// https://browserext.github.io/browserext/ +let bChrome = false; +if (typeof(browser) !== "object") { + var browser = chrome; + bChrome = true; +} + /* Worker (separate thread to avoid freezing Firefox) */ let xGCEWorker = new Worker("gce_worker.js"); @@ -17,11 +25,11 @@ // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent try { let {sActionDone, result, dInfo} = e.data; switch (sActionDone) { case "init": - browser.storage.local.set({"gc_options": result}); + storeGCOptions(result); break; case "parse": case "parseAndSpellcheck": case "parseAndSpellcheck1": case "getListOfTokens": @@ -42,16 +50,19 @@ break; case "getOptions": case "getDefaultOptions": case "resetOptions": // send result to panel + storeGCOptions(result); + if (bChrome) { + e.data.result = helpers.mapToObject(e.data.result); + } browser.runtime.sendMessage(e.data); - browser.storage.local.set({"gc_options": result}); break; case "setOptions": case "setOption": - browser.storage.local.set({"gc_options": result}); + storeGCOptions(result); break; default: console.log("[background] Unknown command: " + sActionDone); console.log(e.data); } @@ -59,22 +70,27 @@ catch (e) { showError(e); } }; +function initGrammarChecker (dSavedOptions) { + let dOptions = (dSavedOptions.hasOwnProperty("gc_options")) ? dSavedOptions.gc_options : null; + xGCEWorker.postMessage({ + sCommand: "init", + dParam: {sExtensionPath: browser.extension.getURL(""), dOptions: dOptions, sContext: "Firefox"}, + dInfo: {} + }); +} function init () { + if (bChrome) { + browser.storage.local.get("gc_options", initGrammarChecker); + return; + } let xPromise = browser.storage.local.get("gc_options"); xPromise.then( - function (dSavedOptions) { - let dOptions = (dSavedOptions.hasOwnProperty("gc_options")) ? dSavedOptions.gc_options : null; - xGCEWorker.postMessage({ - sCommand: "init", - dParam: {sExtensionPath: browser.extension.getURL("."), dOptions: dOptions, sContext: "Firefox"}, - dInfo: {} - }); - }, + initGrammarChecker, function (e) { showError(e); xGCEWorker.postMessage({ sCommand: "init", dParam: {sExtensionPath: browser.extension.getURL("."), dOptions: null, sContext: "Firefox"}, @@ -247,10 +263,19 @@ /* Actions */ + +function storeGCOptions (dOptions) { + if (bChrome) { + // JS crap again. Chrome can’t store Map object. + dOptions = helpers.mapToObject(dOptions); + } + browser.storage.local.set({"gc_options": dOptions}); +} + function parseAndSpellcheckSelectedText (iTab, sText) { // send message to the tab let xTabPort = dConnx.get(iTab); xTabPort.postMessage({sActionDone: "openGCPanel", result: null, dInfo: null, bEnd: false, bError: false}); // send command to the worker @@ -272,20 +297,35 @@ dInfo: {iReturnPort: iTab} }); } function openConjugueurTab () { + if (bChrome) { + browser.tabs.create({ + url: browser.extension.getURL("panel/conjugueur.html") + }); + return; + } let xConjTab = browser.tabs.create({ url: browser.extension.getURL("panel/conjugueur.html") }); xConjTab.then(onCreated, onError); } function openConjugueurWindow () { + if (bChrome) { + browser.windows.create({ + url: browser.extension.getURL("panel/conjugueur.html"), + type: "popup", + width: 710, + height: 980 + }); + return; + } let xConjWindow = browser.windows.create({ url: browser.extension.getURL("panel/conjugueur.html"), - type: "detached_panel", + type: "popup", width: 710, height: 980 }); xConjWindow.then(onCreated, onError); } Index: gc_lang/fr/webext/content_scripts/init.js ================================================================== --- gc_lang/fr/webext/content_scripts/init.js +++ gc_lang/fr/webext/content_scripts/init.js @@ -12,23 +12,18 @@ 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); - } -} +// Chrome don’t follow the W3C specification: +// https://browserext.github.io/browserext/ +let bChrome = false; +if (typeof(browser) !== "object") { + var browser = chrome; + bChrome = true; +} + /* function loadImage (sContainerClass, sImagePath) { let xRequest = new XMLHttpRequest(); xRequest.open('GET', browser.extension.getURL("")+sImagePath, false); @@ -53,12 +48,14 @@ oGCPanel: null, createMenus: function () { let lNode = document.getElementsByTagName("textarea"); for (let xNode of lNode) { - this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode)); - this.nMenu += 1; + if (xNode.style.display !== "none" && xNode.style.visibility !== "hidden") { + this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode)); + this.nMenu += 1; + } } }, createMenus2 () { let lNode = document.querySelectorAll("[contenteditable]"); @@ -98,10 +95,24 @@ createGCPanel: function () { if (this.oGCPanel === null) { this.oGCPanel = new GrammalecteGrammarChecker("grammalecte_gc_panel", "Grammalecte", 500, 700); this.oGCPanel.insertIntoPage(); } + }, + + createNode: function (sType, oAttr, oDataset=null) { + try { + let xNode = document.createElement(sType); + Object.assign(xNode, oAttr); + if (oDataset) { + Object.assign(xNode.dataset, oDataset); + } + return xNode; + } + catch (e) { + showError(e); + } } } /* Index: gc_lang/fr/webext/content_scripts/menu.css ================================================================== --- gc_lang/fr/webext/content_scripts/menu.css +++ gc_lang/fr/webext/content_scripts/menu.css @@ -18,11 +18,11 @@ border-radius: 50%; text-align: center; cursor: pointer; box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5); z-index: 2147483640; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */ - animation: grammalecte-spin 2s ease infinite; + animation: grammalecte-spin 2s ease 3; } .grammalecte_menu_main_button:hover { border: 4px solid hsla(210, 80%, 35%, .5); background-color: hsla(210, 80%, 55%, .5); animation: grammalecte-spin .5s linear infinite; Index: gc_lang/fr/webext/content_scripts/menu.js ================================================================== --- gc_lang/fr/webext/content_scripts/menu.js +++ gc_lang/fr/webext/content_scripts/menu.js @@ -5,11 +5,11 @@ class GrammalecteMenu { constructor (nMenu, xNode) { this.sMenuId = "grammalecte_menu" + nMenu; - this.xButton = createNode("div", {className: "grammalecte_menu_main_button", textContent: " "}); + this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "}); this.xButton.onclick = () => { this.switchMenu(); }; this.xMenu = this._createMenu(xNode); this._insertAfter(this.xButton, xNode); this._insertAfter(this.xMenu, xNode); } @@ -19,25 +19,25 @@ } _createMenu (xNode) { try { let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.textContent; - let xMenu = createNode("div", {id: this.sMenuId, className: "grammalecte_menu"}); - xMenu.appendChild(createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"})); + let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"}); + xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"})); // Text formatter if (xNode.tagName == "TEXTAREA") { - let xTFButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"}); + let xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"}); xTFButton.onclick = () => { this.switchMenu(); oGrammalecte.createTFPanel(); oGrammalecte.oTFPanel.start(xNode); oGrammalecte.oTFPanel.show(); }; xMenu.appendChild(xTFButton); } // lexicographe - let xLxgButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"}); + let xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"}); xLxgButton.onclick = () => { this.switchMenu(); oGrammalecte.createLxgPanel(); oGrammalecte.oLxgPanel.clear(); oGrammalecte.oLxgPanel.show(); @@ -48,11 +48,11 @@ dInfo: {sTextAreaId: xNode.id} }); }; xMenu.appendChild(xLxgButton); // Grammar checker - let xGCButton = createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"}); + let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"}); xGCButton.onclick = () => { this.switchMenu(); oGrammalecte.createGCPanel(); oGrammalecte.oGCPanel.start(xNode); oGrammalecte.oGCPanel.show(); @@ -63,27 +63,27 @@ dInfo: {sTextAreaId: xNode.id} }); }; xMenu.appendChild(xGCButton); // Conjugation tool - let xConjButton = createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"}); - let xConjButtonTab = createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"}); + let xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"}); + let xConjButtonTab = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"}); xConjButtonTab.onclick = () => { this.switchMenu(); xGrammalectePort.postMessage({sCommand: "openConjugueurTab", dParam: null, dInfo: null}); }; - let xConjButtonWin = createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"}); + let xConjButtonWin = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"}); xConjButtonWin.onclick = () => { this.switchMenu(); xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null}); }; xConjButton.appendChild(xConjButtonTab); xConjButton.appendChild(xConjButtonWin); xMenu.appendChild(xConjButton); - //xMenu.appendChild(createNode("img", {scr: browser.extension.getURL("img/logo-16.png")})); + //xMenu.appendChild(oGrammalecte.createNode("img", {scr: browser.extension.getURL("img/logo-16.png")})); // can’t work, due to content-script policy: https://bugzilla.mozilla.org/show_bug.cgi?id=1267027 - xMenu.appendChild(createNode("div", {className: "grammalecte_menu_footer"})); + xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_footer"})); return xMenu; } catch (e) { showError(e); } Index: gc_lang/fr/webext/content_scripts/panel.css ================================================================== --- gc_lang/fr/webext/content_scripts/panel.css +++ gc_lang/fr/webext/content_scripts/panel.css @@ -94,40 +94,44 @@ overflow: auto; } /* - CSS Spinner - Double bounce - http://tobiasahlin.com/spinkit/ + Spinner */ .grammalecte_spinner { visibility: hidden; - width: 40px; - height: 40px; - position: absolute; - top: 2px; - right: 180px; -} -.grammalecte_spinner .bounce1, -.grammalecte_spinner .bounce2 { - width: 100%; - height: 100%; - border-radius: 50%; - background-color: hsl(0, 50%, 75%); - opacity: 0.6; - position: absolute; - top: 0; - left: 0; - animation: grammalecte-sk-bounce 2.0s infinite ease-in-out; -} -.grammalecte_spinner .bounce2 { - animation-delay: -1.0s; -} - -@keyframes grammalecte-sk-bounce { - 0%, 100% { - transform: scale(0.0); - } 50% { - transform: scale(1.0); + width: 20px; + height: 20px; + position: absolute; + top: 0px; + right: 200px; + background-color: hsla(210, 80%, 80%, .5); + border: 10px solid hsla(210, 80%, 60%, .5); + border-top: 10px solid hsla(210, 100%, 40%, .7); + border-bottom: 10px solid hsla(210, 100%, 40%, .7); + border-radius: 50%; + text-align: center; + cursor: pointer; + box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5); + animation: grammalecte-spin-big .5s linear infinite; +} + +@keyframes grammalecte-spin-big { + 0% { + transform: rotate(0deg) scale(1); + border-top: 10px solid hsla(210, 100%, 40%, .7); + border-bottom: 10px solid hsla(210, 100%, 40%, .7); + } + 70% { + transform: rotate(180deg) scale(.8); + border-top: 10px solid hsla(0, 100%, 40%, .7); + border-bottom: 10px solid hsla(0, 100%, 40%, .7); + box-shadow: 0 0 0 20px hsla(210, 50%, 50%, 0); + } + 100% { + transform: rotate(360deg) scale(1); + border-top: 10px solid hsla(210, 100%, 40%, .7); + border-bottom: 10px solid hsla(210, 100%, 40%, .7); + box-shadow: 0 0 0 0 hsla(210, 50%, 50%, 0); } } Index: gc_lang/fr/webext/content_scripts/panel.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel.js +++ gc_lang/fr/webext/content_scripts/panel.js @@ -9,24 +9,24 @@ constructor (sId, sTitle, nWidth, nHeight, bFlexible=true) { this.sId = sId; this.nWidth = nWidth; this.nHeight = nHeight; this.bFlexible = bFlexible; - this.xPanelBar = createNode("div", {className: "grammalecte_panel_bar"}); - this.xPanelContent = createNode("div", {className: "grammalecte_panel_content"}); + this.xPanelBar = oGrammalecte.createNode("div", {className: "grammalecte_panel_bar"}); + this.xPanelContent = oGrammalecte.createNode("div", {className: "grammalecte_panel_content"}); this.xWaitIcon = this._createWaitIcon(); this.xPanel = this._createPanel(sTitle); this.center(); } _createPanel (sTitle) { try { - let xPanel = createNode("div", {id: this.sId, className: "grammalecte_panel"}); + let xPanel = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_panel"}); this.xPanelBar.appendChild(this._createButtons()); - let xTitle = createNode("div", {className: "grammalecte_panel_title"}); + let xTitle = oGrammalecte.createNode("div", {className: "grammalecte_panel_title"}); xTitle.appendChild(this._createLogo()); - xTitle.appendChild(createNode("div", {className: "grammalecte_panel_label", textContent: sTitle})); + xTitle.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_panel_label", textContent: sTitle})); this.xPanelBar.appendChild(xTitle); xPanel.appendChild(this.xPanelBar); xPanel.appendChild(this.xPanelContent); return xPanel; } @@ -40,11 +40,11 @@ xImg.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAC8UlEQVQ4jX3TbUgTcRwH8P89ddu5u9tt082aZmpFEU4tFz0QGTUwCi0heniR9MSUIKRaD0RvIlKigsooo+iNFa0XJYuwIjEK19OcDtPElsG0ktyp591t7u7+vUh7MPX3+vf5/n8/+P0BmKJIPUUVlh2rdVVeesWlzEybqg+bFOsoylnqPmNavGFfknV2Omu2Lvja3vxAURKJib3opHizu8riLK6gjRyuKgmoSoMRFENRUqfXTzvBGK62LC2uoFkOl4RhjQ8+qWt7dPNE3sbdp+2LXbsGe9qb4rIo/BfwFy6nWQ4ThWGNDzbcfu29dMDh2nHU7CypYNLmzTda0/L5cNuzmDQi/A4Y27k6eQxLI79wS/11D0AAMNvs6XT6ojVJjJEgTbMy2BT77xBMp09KcpaWV1uc41jQoi0NdUHfjeOO9WWn7AVF7s7n986SithPJGeupBh2PCSP/xxqxAp3eq6wuUV7Wc6MSZIEhA8vHjbfOe/OcW3zmAuKy+nUzAyD2bow8ODaEROFq8AyZ5WBYdEZXGqGxZ61HJV+9HYCJRbTNA0QBA40HWunaKN5dKg/DBKxeCIe09Th/m4MJwiMSZmLEzMQAABQRuNqgu8NYX3doTcMpvCkLbtQZ2AJkrPOZG1zlnY13T+Hy9EehY90h57eqcorcZ/lctZuMzAsOjLEqwNv66/6vZcPYRBC+C3cGaBxhSet2av1BpYgTTY7k5y2JPT41slIR6Axv8R9nnOs+4Pf+2r992uOxGVJwgAAAEINfgt3BGgsESWtWas1iGDyl+CT/u7WpvxNFRc4x7qtBoZFhSFejb7z1fq9NYfjsiT+cwcQavBruCOgU4SIGo18amuoq3Js3FNlynVtH385+s53ze+t8cRkURx3yMTTRBAEQVAUXbFlf3XystJKA2NExeFBdWASDAAA+MQACCEEmqbJ0b6PMC7JwhDU8YFHV5u9NZ64LErT/oW/63tPV6uJwmKoOND78u7Fg5NhAAD4CVbzY9cwrWQrAAAAAElFTkSuQmCC"; return xImg; } _createButtons () { - let xButtonLine = createNode("div", {className: "grammalecte_panel_commands"}); + let xButtonLine = oGrammalecte.createNode("div", {className: "grammalecte_panel_commands"}); xButtonLine.appendChild(this.xWaitIcon); if (this.sId === "grammalecte_gc_panel") { xButtonLine.appendChild(this._createCopyButton()); } xButtonLine.appendChild(this._createMoveButton("stickToTop", "¯", "Coller en haut")); @@ -55,30 +55,30 @@ xButtonLine.appendChild(this._createCloseButton()); return xButtonLine; } _createWaitIcon () { - let xWaitIcon = createNode("div", {className: "grammalecte_spinner"}); - xWaitIcon.appendChild(createNode("div", {className: "bounce1"})); - xWaitIcon.appendChild(createNode("div", {className: "bounce2"})); + let xWaitIcon = oGrammalecte.createNode("div", {className: "grammalecte_spinner"}); + //xWaitIcon.appendChild(oGrammalecte.createNode("div", {className: "bounce1"})); + //xWaitIcon.appendChild(oGrammalecte.createNode("div", {className: "bounce2"})); return xWaitIcon; } _createCopyButton () { - let xButton = createNode("div", {id: "grammalecte_clipboard_button", className: "grammalecte_copy_button", textContent: "∑", title: "Copier dans le presse-papiers"}); + let xButton = oGrammalecte.createNode("div", {id: "grammalecte_clipboard_button", className: "grammalecte_copy_button", textContent: "∑", title: "Copier dans le presse-papiers"}); xButton.onclick = function () { this.copyTextToClipboard(); }.bind(this); return xButton; } _createMoveButton (sAction, sLabel, sTitle) { - let xButton = createNode("div", {className: "grammalecte_move_button", textContent: sLabel, title: sTitle}); + let xButton = oGrammalecte.createNode("div", {className: "grammalecte_move_button", textContent: sLabel, title: sTitle}); xButton.onclick = function () { this[sAction](); }.bind(this); return xButton; } _createCloseButton () { - let xButton = createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"}); + let xButton = oGrammalecte.createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"}); xButton.onclick = function () { this.hide(); }.bind(this); // better than writing “let that = this;” before the function? return xButton; } insertIntoPage () { Index: gc_lang/fr/webext/content_scripts/panel_gc.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_gc.js +++ gc_lang/fr/webext/content_scripts/panel_gc.js @@ -44,12 +44,12 @@ */ constructor (...args) { super(...args); this.aIgnoredErrors = new Set(); - this.xContentNode = createNode("div", {id: "grammalecte_gc_panel_content"}); - this.xParagraphList = createNode("div", {id: "grammalecte_paragraph_list"}); + this.xContentNode = oGrammalecte.createNode("div", {id: "grammalecte_gc_panel_content"}); + this.xParagraphList = oGrammalecte.createNode("div", {id: "grammalecte_paragraph_list"}); this.xContentNode.appendChild(this.xParagraphList); this.xPanelContent.addEventListener("click", onGrammalecteGCPanelClick, false); this.oTooltip = new GrammalecteTooltip(this.xContentNode); this.xPanelContent.appendChild(this.xContentNode); this.oTAC = new GrammalecteTextAreaControl(); @@ -76,17 +76,17 @@ } addParagraphResult (oResult) { try { if (oResult && (oResult.sParagraph.trim() !== "" || oResult.aGrammErr.length > 0 || oResult.aSpellErr.length > 0)) { - let xNodeDiv = createNode("div", {className: "grammalecte_paragraph_block"}); + let xNodeDiv = oGrammalecte.createNode("div", {className: "grammalecte_paragraph_block"}); // actions - let xActionsBar = createNode("div", {className: "grammalecte_paragraph_actions"}); - xActionsBar.appendChild(createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "Réanalyser"}, {para_num: oResult.iParaNum})); - xActionsBar.appendChild(createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", style: "font-weight: bold;"})); + let xActionsBar = oGrammalecte.createNode("div", {className: "grammalecte_paragraph_actions"}); + xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "Réanalyser"}, {para_num: oResult.iParaNum})); + xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", style: "font-weight: bold;"})); // paragraph - let xParagraph = createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum}); + let xParagraph = oGrammalecte.createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum}); xParagraph.setAttribute("spellcheck", "false"); // doesn’t seem possible to use “spellcheck” as a common attribute. xParagraph.addEventListener("keyup", function (xEvent) { this.oTAC.setParagraph(parseInt(xEvent.target.dataset.para_num), this.purgeText(xEvent.target.textContent)); this.oTAC.write(); }.bind(this) @@ -235,11 +235,11 @@ addSummary () { // todo } addMessage (sMessage) { - let xNode = createNode("div", {className: "grammalecte_gc_panel_message", textContent: sMessage}); + let xNode = oGrammalecte.createNode("div", {className: "grammalecte_gc_panel_message", textContent: sMessage}); this.xParagraphList.appendChild(xNode); } _copyToClipboard (sText) { // recipe from https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/clipboard-helper.js @@ -277,26 +277,26 @@ class GrammalecteTooltip { constructor (xContentNode) { this.sErrorId = null; - this.xTooltip = createNode("div", {id: "grammalecte_tooltip"}); - this.xTooltipArrow = createNode("img", { + this.xTooltip = oGrammalecte.createNode("div", {id: "grammalecte_tooltip"}); + this.xTooltipArrow = oGrammalecte.createNode("img", { id: "grammalecte_tooltip_arrow", src: " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwAAADsABataJCQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xNzNun2MAAAAnSURBVChTY/j//z8cq/kW/wdhZDEMSXRFWCVhGKwAmwQyHngFxf8B5fOGYfeFpYoAAAAASUVORK5CYII=", alt: "^", }); - this.xTooltipSuggBlock = createNode("div", {id: "grammalecte_tooltip_sugg_block"}); - let xMessageBlock = createNode("div", {id: "grammalecte_tooltip_message_block"}); - xMessageBlock.appendChild(createNode("p", {id: "grammalecte_tooltip_rule_id"})); - xMessageBlock.appendChild(createNode("p", {id: "grammalecte_tooltip_message", textContent: "Erreur."})); - let xActions = xMessageBlock.appendChild(createNode("div", {id: "grammalecte_tooltip_actions"})); - xActions.appendChild(createNode("div", {id: "grammalecte_tooltip_ignore", textContent: "Ignorer"})); - xActions.appendChild(createNode("div", {id: "grammalecte_tooltip_url", textContent: "Voulez-vous en savoir plus ?…"}, {url: ""})); + this.xTooltipSuggBlock = oGrammalecte.createNode("div", {id: "grammalecte_tooltip_sugg_block"}); + let xMessageBlock = oGrammalecte.createNode("div", {id: "grammalecte_tooltip_message_block"}); + xMessageBlock.appendChild(oGrammalecte.createNode("p", {id: "grammalecte_tooltip_rule_id"})); + xMessageBlock.appendChild(oGrammalecte.createNode("p", {id: "grammalecte_tooltip_message", textContent: "Erreur."})); + let xActions = xMessageBlock.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_actions"})); + xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_ignore", textContent: "Ignorer"})); + xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_url", textContent: "Voulez-vous en savoir plus ?…"}, {url: ""})); xMessageBlock.appendChild(xActions); this.xTooltip.appendChild(xMessageBlock); - this.xTooltip.appendChild(createNode("div", {id: "grammalecte_tooltip_sugg_title", textContent: "SUGGESTIONS :"})); + this.xTooltip.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_tooltip_sugg_title", textContent: "SUGGESTIONS :"})); this.xTooltip.appendChild(this.xTooltipSuggBlock); xContentNode.appendChild(this.xTooltip); xContentNode.appendChild(this.xTooltipArrow); } Index: gc_lang/fr/webext/content_scripts/panel_lxg.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_lxg.js +++ gc_lang/fr/webext/content_scripts/panel_lxg.js @@ -5,11 +5,11 @@ class GrammalecteLexicographer extends GrammalectePanel { constructor (...args) { super(...args); this._nCount = 0; - this._xContentNode = createNode("div", {id: "grammalecte_lxg_panel_content"}); + this._xContentNode = oGrammalecte.createNode("div", {id: "grammalecte_lxg_panel_content"}); this.xPanelContent.appendChild(this._xContentNode); } clear () { this._nCount = 0; @@ -18,24 +18,24 @@ } } addSeparator (sText) { if (this._xContentNode.textContent !== "") { - this._xContentNode.appendChild(createNode("div", {className: "grammalecte_lxg_separator", textContent: sText})); + this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_separator", textContent: sText})); } } addMessage (sClass, sText) { - this._xContentNode.appendChild(createNode("div", {className: sClass, textContent: sText})); + this._xContentNode.appendChild(oGrammalecte.createNode("div", {className: sClass, textContent: sText})); } addListOfTokens (lTokens) { try { if (lTokens) { this._nCount += 1; - let xNodeDiv = createNode("div", {className: "grammalecte_lxg_list_of_tokens"}); - xNodeDiv.appendChild(createNode("div", {className: "grammalecte_lxg_list_num", textContent: this._nCount})); + let xNodeDiv = oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_of_tokens"}); + xNodeDiv.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_list_num", textContent: this._nCount})); for (let oToken of lTokens) { xNodeDiv.appendChild(this._createTokenNode(oToken)); } this._xContentNode.appendChild(xNodeDiv); } @@ -44,19 +44,19 @@ showError(e); } } _createTokenNode (oToken) { - let xTokenNode = createNode("div", {className: "grammalecte_lxg_token_block"}); - xTokenNode.appendChild(createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue})); - xTokenNode.appendChild(createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"})); + let xTokenNode = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"}); + xTokenNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue})); + xTokenNode.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"})); if (oToken.aLabel.length === 1) { xTokenNode.appendChild(document.createTextNode(oToken.aLabel[0])); } else { - let xTokenList = createNode("div", {className: "grammalecte_lxg_morph_list"}); + let xTokenList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"}); for (let sLabel of oToken.aLabel) { - xTokenList.appendChild(createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel})); + xTokenList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel})); } xTokenNode.appendChild(xTokenList); } return xTokenNode; } Index: gc_lang/fr/webext/content_scripts/panel_tf.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_tf.js +++ gc_lang/fr/webext/content_scripts/panel_tf.js @@ -15,12 +15,12 @@ _createTextFormatter () { let xTFNode = document.createElement("div"); try { // Options - let xOptions = createNode("div", {id: "grammalecte_tf_options"}); - let xColumn1 = createNode("div", {className: "grammalecte_tf_column"}); + let xOptions = oGrammalecte.createNode("div", {id: "grammalecte_tf_options"}); + let xColumn1 = oGrammalecte.createNode("div", {className: "grammalecte_tf_column"}); let xSSP = this._createFieldset("group_ssp", true, "Espaces surnuméraires"); xSSP.appendChild(this._createBlockOption("o_start_of_paragraph", true, "En début de paragraphe")); xSSP.appendChild(this._createBlockOption("o_end_of_paragraph", true, "En fin de paragraphe")); xSSP.appendChild(this._createBlockOption("o_between_words", true, "Entre les mots")); xSSP.appendChild(this._createBlockOption("o_before_punctuation", true, "Avant les points (.), les virgules (,)")); @@ -36,11 +36,11 @@ xNBSP.appendChild(this._createBlockOption("o_nbsp_before_symbol", true, "Avant % ‰ € $ £ ¥ ˚C")); xNBSP.appendChild(this._createBlockOption("o_nbsp_within_numbers", true, "À l’intérieur des nombres")); xNBSP.appendChild(this._createBlockOption("o_nbsp_before_units", true, "Avant les unités de mesure")); let xDelete = this._createFieldset("group_delete", true, "Suppressions"); xDelete.appendChild(this._createBlockOption("o_erase_non_breaking_hyphens", true, "Tirets conditionnels")); - let xColumn2 = createNode("div", {className: "grammalecte_tf_column"}); + let xColumn2 = oGrammalecte.createNode("div", {className: "grammalecte_tf_column"}); let xTypo = this._createFieldset("group_typo", true, "Signes typographiques"); xTypo.appendChild(this._createBlockOption("o_ts_apostrophe", true, "Apostrophe (’)")); xTypo.appendChild(this._createBlockOption("o_ts_ellipsis", true, "Points de suspension (…)")); xTypo.appendChild(this._createBlockOption("o_ts_dash_middle", true, "Tirets d’incise :")); xTypo.appendChild(this._createRadioBoxHyphens("o_ts_m_dash_middle", "o_ts_n_dash_middle", false)); @@ -68,20 +68,20 @@ xColumn2.appendChild(xMisc); xColumn2.appendChild(xStruct); xOptions.appendChild(xColumn1); xOptions.appendChild(xColumn2); // Actions - let xActions = createNode("div", {id: "grammalecte_tf_actions"}); - let xDefaultButton = createNode("div", {id: "grammalecte_tf_reset", textContent: "Par défaut", className: "grammalecte_tf_button"}); + let xActions = oGrammalecte.createNode("div", {id: "grammalecte_tf_actions"}); + let xDefaultButton = oGrammalecte.createNode("div", {id: "grammalecte_tf_reset", textContent: "Par défaut", className: "grammalecte_tf_button"}); xDefaultButton.addEventListener("click", () => { this.reset(); }); - let xApplyButton = createNode("div", {id: "grammalecte_tf_apply", textContent: "Appliquer", className: "grammalecte_tf_button"}); + let xApplyButton = oGrammalecte.createNode("div", {id: "grammalecte_tf_apply", textContent: "Appliquer", className: "grammalecte_tf_button"}); xApplyButton.addEventListener("click", () => { this.saveOptions(); this.apply(); }); xActions.appendChild(xDefaultButton); - xActions.appendChild(createNode("progress", {id: "grammalecte_tf_progressbar"})); - xActions.appendChild(createNode("span", {id: "grammalecte_tf_time_res", textContent: "…"})); + xActions.appendChild(oGrammalecte.createNode("progress", {id: "grammalecte_tf_progressbar"})); + xActions.appendChild(oGrammalecte.createNode("span", {id: "grammalecte_tf_time_res", textContent: "…"})); xActions.appendChild(xApplyButton); - //xActions.appendChild(createNode("div", {id: "grammalecte_infomsg", textContent: "blabla"})); + //xActions.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_infomsg", textContent: "blabla"})); // create result xTFNode.appendChild(xOptions); xTFNode.appendChild(xActions); } catch (e) { @@ -90,50 +90,50 @@ return xTFNode; } // Common options _createFieldset (sId, bDefault, sLabel) { - let xFieldset = createNode("div", {id: sId, className: "grammalecte_tf_groupblock"}); - let xGroupOption = createNode("div", {id: "o_"+sId, className: "grammalecte_tf_option grammalecte_tf_option_title_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: ""}); + let xFieldset = oGrammalecte.createNode("div", {id: sId, className: "grammalecte_tf_groupblock"}); + let xGroupOption = oGrammalecte.createNode("div", {id: "o_"+sId, className: "grammalecte_tf_option grammalecte_tf_option_title_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: ""}); xGroupOption.addEventListener("click", (xEvent) => { this.switchOption(xEvent.target.id); this.switchGroup(xEvent.target.id); }); xFieldset.appendChild(xGroupOption); return xFieldset; } _createBlockOption (sId, bDefault, sLabel) { - let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"}); + let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"}); xLine.appendChild(this._createOption(sId, bDefault, sLabel)); - xLine.appendChild(createNode("div", {id: "res_"+sId, className: "grammalecte_tf_result", textContent: "·"})); + xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+sId, className: "grammalecte_tf_result", textContent: "·"})); return xLine; } _createOption (sId, bDefault, sLabel, sLinkedOptionsId="") { - let xOption = createNode("div", {id: sId, className: "grammalecte_tf_option grammalecte_tf_option_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: sLinkedOptionsId}); + let xOption = oGrammalecte.createNode("div", {id: sId, className: "grammalecte_tf_option grammalecte_tf_option_off", textContent: sLabel}, {selected: "false", default: bDefault, linked_ids: sLinkedOptionsId}); xOption.addEventListener("click", (xEvent) => { this.switchOption(xEvent.target.id); }); return xOption; } // Hyphens _createRadioBoxHyphens (sIdEmDash, sIdEnDash, bDefaultEmDash) { - let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"}); + let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"}); xLine.appendChild(this._createOption(sIdEmDash, bDefaultEmDash, "cadratin (—)", sIdEnDash)); xLine.appendChild(this._createOption(sIdEnDash, !bDefaultEmDash, "demi-cadratin (—)", sIdEmDash)); return xLine; } // Ligatures _createRadioBoxLigatures () { - let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"}); + let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"}); xLine.appendChild(this._createOption("o_ts_ligature", true, "Ligatures")); xLine.appendChild(this._createOption("o_ts_ligature_do", false, "faire", "o_ts_ligature_undo")); xLine.appendChild(this._createOption("o_ts_ligature_undo", true, "défaire", "o_ts_ligature_do")); - xLine.appendChild(createNode("div", {id: "res_"+"o_ts_ligature", className: "grammalecte_tf_result", textContent: "·"})); + xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ts_ligature", className: "grammalecte_tf_result", textContent: "·"})); return xLine; } _createLigaturesSelection () { - let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"}); + let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"}); xLine.appendChild(this._createOption("o_ts_ligature_ff", true, "ff")); xLine.appendChild(this._createOption("o_ts_ligature_fi", true, "fi")); xLine.appendChild(this._createOption("o_ts_ligature_ffi", true, "ffi")); xLine.appendChild(this._createOption("o_ts_ligature_fl", true, "fl")); xLine.appendChild(this._createOption("o_ts_ligature_ffl", true, "ffl")); @@ -142,32 +142,36 @@ return xLine; } // Apostrophes _createSingleLetterOptions () { - let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"}); + let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_indent"}); xLine.appendChild(this._createOption("o_ma_1letter_lowercase", false, "lettres isolées (j’ n’ m’ t’ s’ c’ d’ l’)")); xLine.appendChild(this._createOption("o_ma_1letter_uppercase", false, "Maj.")); return xLine; } // Ordinals _createOrdinalOptions () { - let xLine = createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"}); + let xLine = oGrammalecte.createNode("div", {className: "grammalecte_tf_blockopt grammalecte_tf_underline"}); xLine.appendChild(this._createOption("o_ordinals_no_exponant", true, "Ordinaux (15e, XXIe…)")); xLine.appendChild(this._createOption("o_ordinals_exponant", true, "e → ᵉ")); - xLine.appendChild(createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"})); + xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"})); return xLine; } /* Actions */ start (xTextArea) { this.xTextArea = xTextArea; - let xPromise = browser.storage.local.get("tf_options"); - xPromise.then(this.setOptions.bind(this), this.reset.bind(this)); + if (bChrome) { + browser.storage.local.get("tf_options", this.setOptions.bind(this)); + } else { + let xPromise = browser.storage.local.get("tf_options"); + xPromise.then(this.setOptions.bind(this), this.reset.bind(this)); + } } switchGroup (sOptName) { if (document.getElementById(sOptName).dataset.selected == "true") { document.getElementById(sOptName.slice(2)).style.opacity = 1; Index: gc_lang/fr/webext/manifest.json ================================================================== --- gc_lang/fr/webext/manifest.json +++ gc_lang/fr/webext/manifest.json @@ -9,10 +9,12 @@ "id": "French-GC@grammalecte.net", "strict_min_version": "57.0" } }, + "minimum_chrome_version": "61", + "author": "Olivier R.", "homepage_url": "https://grammalecte.net", "description": "Correcteur grammatical pour le français.", "default_locale": "fr", @@ -31,10 +33,11 @@ "browser_style": false }, "background": { "scripts": [ + "grammalecte/helpers.js", "background.js" ] }, "content_scripts": [ @@ -90,17 +93,17 @@ ], "commands": { "conjugueur_tab": { "suggested_key": { - "default": "Ctrl+Shift+F6" + "default": "Ctrl+Shift+6" }, "description": "Ouvre le conjugueur dans un onglet" }, "conjugueur_window": { "suggested_key": { - "default": "Ctrl+Shift+F7" + "default": "Ctrl+Shift+7" }, "description": "Ouvre le conjugueur dans une fenêtre" } }, @@ -121,10 +124,12 @@ "chrome_settings_overrides": { "search_provider": { "name": "Grammalecte", "search_url": "https://www.dicollecte.org/dictionary.php?prj=fr&lemma={searchTerms}", - "keyword": "disc", - "favicon_url": "https://www.dicollecte.org/favicon.ico" + "keyword": "gram", + "favicon_url": "https://www.dicollecte.org/favicon.ico", + "encoding": "UTF-8", + "is_default": false } } } Index: gc_lang/fr/webext/panel/main.css ================================================================== --- gc_lang/fr/webext/panel/main.css +++ gc_lang/fr/webext/panel/main.css @@ -122,11 +122,11 @@ overflow: auto; } #page h1 { margin: 0 0 10px 0; color: hsl(210, 50%, 50%); - font: bold 30px 'Yanone Kaffeesatz', "Liberation Sans Narrow", sans-serif; + font: bold 30px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif; } /* Home @@ -158,11 +158,11 @@ #help_page { display: none; padding: 20px; } #help_page h2 { - font: bold 20px 'Yanone Kaffeesatz', "Liberation Sans Narrow", sans-serif; + font: bold 20px 'Yanone Kaffeesatz', "Oswald", "Liberation Sans Narrow", sans-serif; color: hsl(210, 50%, 50%); } #help_page .shortcut { margin-top: 10px; font-weight: bold; Index: gc_lang/fr/webext/panel/main.html ================================================================== --- gc_lang/fr/webext/panel/main.html +++ gc_lang/fr/webext/panel/main.html @@ -57,13 +57,13 @@

Pour les autres zones de texte (HTML éditable), il faut sélectionner le texte et utiliser le menu contextuel.

Raccourcis clavier

-

CTRL+MAJ+F6

+

CTRL+MAJ+6

Conjugueur (dans un onglet)

-

CTRL+MAJ+F7

+

CTRL+MAJ+7

Conjugueur (dans une fenêtre)

Index: gc_lang/fr/webext/panel/main.js ================================================================== --- gc_lang/fr/webext/panel/main.js +++ gc_lang/fr/webext/panel/main.js @@ -5,10 +5,18 @@ function showError (e) { console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); } +// Chrome don’t follow the W3C specification: +// https://browserext.github.io/browserext/ +let bChrome = false; +if (typeof(browser) !== "object") { + var browser = chrome; + bChrome = true; +} + /* Events */ window.addEventListener( @@ -123,27 +131,38 @@ function showTestResult (sText) { document.getElementById("tests_result").textContent = sText; } + function setGCOptionsFromStorage () { + if (bChrome) { + browser.storage.local.get("gc_options", _setGCOptions); + return; + } let xPromise = browser.storage.local.get("gc_options"); - xPromise.then( - function (dSavedOptions) { - if (dSavedOptions.hasOwnProperty("gc_options")) { - setGCOptions(dSavedOptions.gc_options); - } - }, - function (e) { - showError(e); - } - ); + xPromise.then(_setGCOptions, showError); +} + +function _setGCOptions (dSavedOptions) { + if (dSavedOptions.hasOwnProperty("gc_options")) { + setGCOptions(dSavedOptions.gc_options); + } } function setGCOptions (dOptions) { + // dOptions is supposed to be a Map + if (bChrome) { + // JS crap again. Chrome can’t store/send Map object. + let m = new Map(); + for (let param in dOptions) { + m.set(param, dOptions[param]); + } + dOptions = m; + } for (let [sOpt, bVal] of dOptions) { if (document.getElementById("option_"+sOpt)) { document.getElementById("option_"+sOpt).checked = bVal; } } }