Index: gc_lang/fr/build.py
==================================================================
--- gc_lang/fr/build.py
+++ gc_lang/fr/build.py
@@ -6,14 +6,15 @@
from distutils import dir_util, file_util
import helpers
-def build (sLang, dVars, spLangPack):
+def build (sLang, dVars):
"complementary build launched from make.py"
createWebExtension(sLang, dVars)
- createThunderbirdExtension(sLang, dVars, spLangPack)
+ createThunderbirdExtension(sLang, dVars)
+ createMailExtension(sLang, dVars)
createNodeJSPackage(sLang)
def createWebExtension (sLang, dVars):
"create Web-extension"
@@ -38,27 +39,40 @@
sHTML += f'
\n'
sHTML += '\n'
return sHTML
-def createThunderbirdExtension (sLang, dVars, spLangPack):
- "create extension for Thunderbird"
+def createMailExtension (sLang, dVars):
+ "create extension for Thunderbird (as MailExtension)"
+ print("Building extension for Thunderbird (MailExtension)")
+ spfZip = "_build/" + dVars['tb_identifier'] + "-v" + dVars['version'] + '.mailext.xpi'
+ hZip = zipfile.ZipFile(spfZip, mode='w', compression=zipfile.ZIP_DEFLATED)
+ _copyGrammalecteJSPackageInZipFile(hZip, sLang)
+ for spf in ["LICENSE.txt", "LICENSE.fr.txt"]:
+ hZip.write(spf)
+ dVars = _createOptionsForThunderbird(dVars)
+ helpers.addFolderToZipAndFileFile(hZip, "gc_lang/"+sLang+"/mailext", "", dVars, True)
+ hZip.close()
+ spExtension = dVars['win_tb_debug_extension_path'] if platform.system() == "Windows" else dVars['linux_tb_debug_extension_path']
+ file_util.copy_file(spfZip, spExtension + "/" + dVars['tb_identifier']+ ".xpi") # Filename for TB is just
+ spExtension = dVars['win_tb_beta_extension_path'] if platform.system() == "Windows" else dVars['linux_tb_beta_extension_path']
+ file_util.copy_file(spfZip, spExtension + "/" + dVars['tb_identifier']+ ".xpi") # Filename for TB is just
+
+
+def createThunderbirdExtension (sLang, dVars):
+ "create extension for Thunderbird (as XUL addon)"
print("Building extension for Thunderbird")
- sExtensionName = dVars['tb_identifier'] + "-v" + dVars['version'] + '.xpi'
- spfZip = "_build/" + sExtensionName
+ spfZip = "_build/" + dVars['tb_identifier'] + "-v" + dVars['version'] + '.xpi'
hZip = zipfile.ZipFile(spfZip, mode='w', compression=zipfile.ZIP_DEFLATED)
- _copyGrammalecteJSPackageInZipFile(hZip, spLangPack)
+ _copyGrammalecteJSPackageInZipFile(hZip, sLang)
for spf in ["LICENSE.txt", "LICENSE.fr.txt"]:
hZip.write(spf)
dVars = _createOptionsForThunderbird(dVars)
helpers.addFolderToZipAndFileFile(hZip, "gc_lang/"+sLang+"/tb", "", dVars, True)
hZip.close()
- spDebugProfile = dVars['win_tb_debug_extension_path'] if platform.system() == "Windows" else dVars['linux_tb_debug_extension_path']
- helpers.unzip(spfZip, spDebugProfile)
- spfBetaExtension = dVars['win_tb_beta_extension_filepath'] if platform.system() == "Windows" else dVars['linux_tb_beta_extension_filepath']
- #helpers.unzip(spfZip, spBetaProfile)
- file_util.copy_file(spfZip, spfBetaExtension)
+ #spDebugProfile = dVars['win_tb_debug_extension_path'] if platform.system() == "Windows" else dVars['linux_tb_debug_extension_path']
+ #helpers.unzip(spfZip, spDebugProfile)
def _createOptionsForThunderbird (dVars):
dVars['sXULTabs'] = ""
dVars['sXULTabPanels'] = ""
@@ -74,24 +88,24 @@
for sLang in dVars['dOptLabel'].keys():
dVars['gc_options_labels_'+sLang] = "\n".join( [ "' for sOpt in dVars['dOptLabel'][sLang] ] )
return dVars
-def _copyGrammalecteJSPackageInZipFile (hZip, spLangPack, sAddPath=""):
+def _copyGrammalecteJSPackageInZipFile (hZip, sLang, sAddPath=""):
for sf in os.listdir("grammalecte-js"):
if not os.path.isdir("grammalecte-js/"+sf):
- hZip.write("grammalecte-js/"+sf, sAddPath+"grammalecte-js/"+sf)
+ hZip.write("grammalecte-js/"+sf, sAddPath+"grammalecte/"+sf)
for sf in os.listdir("grammalecte-js/graphspell"):
if not os.path.isdir("grammalecte-js/graphspell/"+sf):
- hZip.write("grammalecte-js/graphspell/"+sf, sAddPath+"grammalecte-js/graphspell/"+sf)
+ hZip.write("grammalecte-js/graphspell/"+sf, sAddPath+"grammalecte/graphspell/"+sf)
for sf in os.listdir("grammalecte-js/graphspell/_dictionaries"):
if not os.path.isdir("grammalecte-js/graphspell/_dictionaries/"+sf):
- hZip.write("grammalecte-js/graphspell/_dictionaries/"+sf, sAddPath+"grammalecte-js/graphspell/_dictionaries/"+sf)
- for sf in os.listdir(spLangPack):
- if not os.path.isdir(spLangPack+"/"+sf):
- hZip.write(spLangPack+"/"+sf, sAddPath+spLangPack+"/"+sf)
+ hZip.write("grammalecte-js/graphspell/_dictionaries/"+sf, sAddPath+"grammalecte/graphspell/_dictionaries/"+sf)
+ for sf in os.listdir("grammalecte-js/"+sLang):
+ if not os.path.isdir("grammalecte-js/"+sLang+"/"+sf):
+ hZip.write("grammalecte-js/"+sLang+"/"+sf, sAddPath+"grammalecte/"+sLang+"/"+sf)
def createNodeJSPackage (sLang):
helpers.createCleanFolder("_build/nodejs/"+sLang)
dir_util.copy_tree("gc_lang/"+sLang+"/nodejs/", "_build/nodejs/"+sLang)
dir_util.copy_tree("grammalecte-js", "_build/nodejs/"+sLang+"/core/grammalecte")
Index: gc_lang/fr/config.ini
==================================================================
--- gc_lang/fr/config.ini
+++ gc_lang/fr/config.ini
@@ -4,15 +4,15 @@
locales = fr_FR fr_BE fr_CA fr_CH fr_LU fr_BF fr_BJ fr_CD fr_CI fr_CM fr_MA fr_ML fr_MU fr_NE fr_RE fr_SN fr_TG
country_default = FR
name = Grammalecte
implname = grammalecte
# always use 3 numbers for version: x.y.z
-version = 1.5.0
+version = 1.6.0
author = Olivier R.
provider = Grammalecte.net
link = https://grammalecte.net
-description = Correcteur grammatical pour le français.
+description = Correcteur grammatical, orthographique et typographique pour le français.
extras = README_fr.txt
logo = logo.png
# main dictionary
lexicon_src = lexicons/French.lex
@@ -37,11 +37,11 @@
# stemming method: S for suffixes only, A for prefixes and suffixes
stemming_method = S
# LibreOffice
unopkg = C:/Program Files/LibreOffice/program/unopkg.com
-oxt_version = 6.5
+oxt_version = 6.5.1
oxt_identifier = French.linguistic.resources.from.Dicollecte.by.OlivierR
oxt_update_info_URL = https://grammalecte.net/grammalecte/oxt/grammalecte.update.xml
# Firefox
fx_identifier = French-GC@grammalecte.net
@@ -54,18 +54,17 @@
# Thunderbird
tb_identifier = French-GC-TB@grammalecte.net
tb_name = Grammalecte [fr]
win_tb_path = C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe
-#win_tb_beta_path = C:\Program Files (x86)\Mozilla Thunderbird (Beta)\thunderbird.exe
-win_tb_beta_path = C:\Program Files (x86)\Mozilla Thunderbird (Beta)\thunderbird.exe
+win_tb_beta_path = C:\Program Files\Thunderbird Daily\thunderbird.exe
linux_tb_path = /usr/bin/thunderbird
linux_tb_beta_path = /usr/bin/thunderbird
-win_tb_debug_extension_path = D:\_temp\tb-debug.profile\extensions\French-GC-TB@grammalecte.net
-linux_tb_debug_extension_path = ~/tb-debug.profile/extensions/French-GC-TB@grammalecte.net
-win_tb_beta_extension_filepath = D:\_temp\tb-beta.profile\extensions\French-GC-TB@grammalecte.net.xpi
-linux_tb_beta_extension_filepath = ~/tb-beta.profile/extensions/French-GC-TB@grammalecte.net.xpi
+win_tb_debug_extension_path = D:\_temp\tb-debug.profile\extensions
+linux_tb_debug_extension_path = ~/tb-debug.profile/extensions
+win_tb_beta_extension_path = D:\_temp\tb-beta.profile\extensions
+linux_tb_beta_extension_path = ~/tb-beta.profile/extensions
# Set Thunderbird folder in your PATH variable
# Create a local profile:
# thunderbird -CreateProfile "debug _build\tb-debug.profile"
# Or you can use the GUI with:
# thunderbird -P
ADDED gc_lang/fr/mailext/README.txt
Index: gc_lang/fr/mailext/README.txt
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/README.txt
@@ -0,0 +1,14 @@
+
+= GRAMMALECTE =
+
+French grammar checker
+By Olivier R. (olivier /at/ grammalecte /dot/ net)
+
+Website: https://grammalecte.net/
+
+License: GPL 3 -- http://www.gnu.org/copyleft/gpl.html
+
+Grammalecte for Firefox is a derivative tool born from the version
+for LibreOffice written in Python.
+
+Written in JavaScript ES6/ES7.
ADDED gc_lang/fr/mailext/background.js
Index: gc_lang/fr/mailext/background.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/background.js
@@ -0,0 +1,202 @@
+// Background
+
+"use strict";
+
+// Draft for later
+
+const oWorkerHandler = {
+ xGCEWorker: null,
+
+ nLastTimeWorkerResponse: 0, // milliseconds since 1970-01-01
+
+ oTask: {},
+
+ start: function () {
+ this.xGCEWorker = new Worker("gce_worker.js");
+ this.xGCEWorker.onmessage = function (e) {
+ // Messages received from the Worker
+ // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
+ try {
+ this.nLastTimeWorkerResponse = Date.now();
+ let {sActionDone, result, dInfo, bEnd, bError} = e.data;
+ if (bError) {
+ console.log(result);
+ console.log(dInfo);
+ return;
+ }
+ switch (sActionDone) {
+ case "init":
+ storeGCOptions(result);
+ break;
+ case "parse":
+ case "parseAndSpellcheck":
+ case "parseAndSpellcheck1":
+ case "parseFull":
+ case "getListOfTokens":
+ case "getSpellSuggestions":
+ case "getVerb":
+ // send result to content script
+ if (typeof(dInfo.iReturnPort) === "number") {
+ let xPort = dConnx.get(dInfo.iReturnPort);
+ xPort.postMessage(e.data);
+ } else {
+ console.log("[background] don’t know where to send results");
+ console.log(e.data);
+ }
+ break;
+ case "textToTest":
+ case "fullTests":
+ // send result to panel
+ browser.runtime.sendMessage(e.data);
+ break;
+ case "getOptions":
+ case "getDefaultOptions":
+ case "resetOptions":
+ // send result to panel
+ storeGCOptions(result);
+ browser.runtime.sendMessage(e.data);
+ break;
+ case "setOptions":
+ case "setOption":
+ storeGCOptions(result);
+ break;
+ case "setDictionary":
+ case "setDictionaryOnOff":
+ //console.log("[background] " + sActionDone + ": " + result);
+ break;
+ default:
+ console.log("[background] Unknown command: " + sActionDone);
+ console.log(e.data);
+ }
+ }
+ catch (error) {
+ showError(error);
+ console.log(e.data);
+ }
+ };
+ },
+
+ getTimeSinceLastResponse: function () {
+ // result in seconds
+ return Math.floor((Date.now() - this.nLastTimeWorkerResponse) / 1000);
+ },
+
+ restart: function (nDelay=5) {
+ if (this.getTimeSinceLastResponse() <= nDelay) {
+ console.log("Worker not restarted. Worked ", nDelay, " seconds ago.");
+ return false;
+ }
+ if (this.xGCEWorker) {
+ this.xGCEWorker.terminate();
+ }
+ this.start();
+ oInitHandler.initGrammarChecker();
+ sendCommandToAllTabs("workerRestarted");
+ console.log("Worker restarted.");
+ return true;
+ },
+
+ addTask: function () {
+ //
+ },
+
+ closeTask: function () {
+ //
+ }
+}
+
+
+const oInitHandler = {
+
+ initUIOptions: function () {
+ browser.storage.local.get("ui_options").then(this._initUIOptions, showError);
+ browser.storage.local.get("autorefresh_option").then(this._initUIOptions, showError);
+ },
+
+ initGrammarChecker: function () {
+ browser.storage.local.get("gc_options").then(this._initGrammarChecker, showError);
+ browser.storage.local.get("personal_dictionary").then(this._setSpellingDictionaries, showError);
+ browser.storage.local.get("community_dictionary").then(this._setSpellingDictionaries, showError);
+ browser.storage.local.get("sc_options").then(this._initSCOptions, showError);
+ },
+
+ _initUIOptions: function (oSavedOptions) {
+ if (!oSavedOptions.hasOwnProperty("ui_options")) {
+ browser.storage.local.set({"ui_options": {
+ textarea: true,
+ editablenode: true
+ }});
+ }
+ if (!oSavedOptions.hasOwnProperty("autorefresh_option")) {
+ browser.storage.local.set({"autorefresh_option": true});
+ }
+ },
+
+ _initGrammarChecker: function (oSavedOptions) {
+ try {
+ let dOptions = (oSavedOptions.hasOwnProperty("gc_options")) ? oSavedOptions.gc_options : null;
+ if (dOptions !== null && Object.getOwnPropertyNames(dOptions).length == 0) {
+ console.log("# Error: the saved options was an empty object.");
+ dOptions = null;
+ }
+ oWorkerHandler.xGCEWorker.postMessage({
+ sCommand: "init",
+ dParam: {sExtensionPath: browser.extension.getURL(""), dOptions: dOptions, sContext: "Firefox"},
+ dInfo: {}
+ });
+ }
+ catch (e) {
+ console.log("initGrammarChecker failed");
+ showError(e);
+ }
+ },
+
+ _setSpellingDictionaries: function (oData) {
+ if (oData.hasOwnProperty("community_dictionary")) {
+ oWorkerHandler.xGCEWorker.postMessage({ sCommand: "setDictionary", dParam: { sDictionary: "community", oDict: oData["community_dictionary"] }, dInfo: {} });
+ }
+ if (oData.hasOwnProperty("personal_dictionary")) {
+ oWorkerHandler.xGCEWorker.postMessage({ sCommand: "setDictionary", dParam: { sDictionary: "personal", oDict: oData["personal_dictionary"] }, dInfo: {} });
+ }
+ },
+
+ _initSCOptions: function (oData) {
+ if (!oData.hasOwnProperty("sc_options")) {
+ browser.storage.local.set({"sc_options": {
+ community: true,
+ personal: true
+ }});
+ oWorkerHandler.xGCEWorker.postMessage({ sCommand: "setDictionaryOnOff", dParam: { sDictionary: "community", bActivate: true }, dInfo: {} });
+ oWorkerHandler.xGCEWorker.postMessage({ sCommand: "setDictionaryOnOff", dParam: { sDictionary: "personal", bActivate: true }, dInfo: {} });
+ } else {
+ oWorkerHandler.xGCEWorker.postMessage({ sCommand: "setDictionaryOnOff", dParam: { sDictionary: "community", bActivate: oData.sc_options["community"] }, dInfo: {} });
+ oWorkerHandler.xGCEWorker.postMessage({ sCommand: "setDictionaryOnOff", dParam: { sDictionary: "personal", bActivate: oData.sc_options["personal"] }, dInfo: {} });
+ }
+ }
+}
+
+// start the Worker for the GC
+oWorkerHandler.start();
+
+// init the options stuff and start the GC
+oInitHandler.initUIOptions();
+oInitHandler.initGrammarChecker();
+
+
+
+/*
+ Actions
+*/
+
+function storeGCOptions (dOptions) {
+ if (dOptions instanceof Map) {
+ dOptions = helpers.mapToObject(dOptions);
+ }
+ browser.storage.local.set({"gc_options": dOptions});
+}
+
+
+function showError (e) {
+ console.error(e);
+ //console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
+}
ADDED gc_lang/fr/mailext/chrome.manifest
Index: gc_lang/fr/mailext/chrome.manifest
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/chrome.manifest
@@ -0,0 +1,9 @@
+# https://developer.mozilla.org/en-US/docs/Chrome_Registration
+content grammarchecker content/
+content promiseworker ./worker/
+resource grammalecte ./grammalecte/
+locale grammarchecker fr locale/fr/
+locale grammarchecker en locale/en/
+skin grammarchecker classic/1.0 skin/
+overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://grammarchecker/content/overlay.xul
+style chrome://messenger/content/customizeToolbar.xul chrome://grammarchecker/content/overlay.css
ADDED gc_lang/fr/mailext/content/about.css
Index: gc_lang/fr/mailext/content/about.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/about.css
@@ -0,0 +1,46 @@
+/* CSS */
+
+.descr {
+ font-size: 18px;
+ font-weight: bold;
+ text-align: center;
+}
+
+.stdlabel {
+ font-size: 16px;
+ text-align: center;
+}
+
+#website {
+ font-size: 16px;
+ font-weight: bold;
+ color: hsl(210, 50%, 50%);
+ text-align: center;
+ cursor: pointer;
+}
+
+#contrib {
+ font-size: 16px;
+ text-align: center;
+ color: hsl(210, 50%, 50%);
+ cursor: pointer;
+}
+
+
+/*
+ TB Next: fix dialogheaders
+*/
+dialogheader {
+ -moz-binding: url("chrome://messenger/content/generalBindings.xml#dialogheader");
+ margin: 0 5px 5px;
+ border: 1px solid ThreeDDarkShadow;
+ padding: 5px 8px;
+ background-color: Highlight;
+ color: HighlightText;
+}
+
+.dialogheader-title {
+ margin: 0 !important;
+ font-size: larger;
+ font-weight: bold;
+}
ADDED gc_lang/fr/mailext/content/about.js
Index: gc_lang/fr/mailext/content/about.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/about.js
@@ -0,0 +1,35 @@
+// JavaScript
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+//const Cu = Components.utils;
+
+
+function openInBrowserURL (sURL) {
+ // method found in S3.Google.Translator
+ try {
+ openURL(sURL);
+ // Works in overlay.js, but not here… Seems there is no documentation available about this feature on Mozilla.org
+ }
+ catch (e) {
+ console.error(e);
+ //Cu.reportError(e);
+ }
+}
+
+function openInTabURL (sURL) {
+ // method found in S3.Google.Translator
+ try {
+ let xWM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+ let xWin = xWM.getMostRecentWindow("mail:3pane");
+ let xTabmail = xWin.document.getElementById('tabmail');
+ xWin.focus();
+ if (xTabmail) {
+ xTabmail.openTab('contentTab', { contentPage: sURL });
+ }
+ }
+ catch (e) {
+ console.error(e);
+ //Cu.reportError(e);
+ }
+}
ADDED gc_lang/fr/mailext/content/about.xul
Index: gc_lang/fr/mailext/content/about.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/about.xul
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/conjugueur.css
Index: gc_lang/fr/mailext/content/conjugueur.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/conjugueur.css
@@ -0,0 +1,48 @@
+/* CSS */
+
+#verb {
+ width: 200px;
+}
+
+#verb_title {
+ font-size: 24px;
+ font-weight: bold;
+ text-align: center;
+ color: hsl(210, 50%, 50%);
+}
+
+#info {
+ font-size: 16px;
+ text-align: center;
+ vertical-align: bottom;
+}
+
+
+.groupbox {
+ margin-left: 5px;
+ margin-bottom: 5px;
+ width: 275px;
+ border: 1px solid hsl(0, 0%, 90%);
+ border-radius: 5px;
+}
+
+#smallnote {
+ font-size: 10px;
+ width: 250px;
+}
+
+.sub_header {
+ color: hsl(0, 50%, 50%);
+ font-size: 16px;
+ font-weight: bold;
+ border-bottom: 1px solid hsl(0, 0%, 80%);
+}
+
+label.temps {
+ color: hsl(210, 50%, 50%);
+ font-size: 13px;
+ font-weight: bold;
+}
+label.cj {
+ font-size: 11px;
+}
ADDED gc_lang/fr/mailext/content/conjugueur.js
Index: gc_lang/fr/mailext/content/conjugueur.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/conjugueur.js
@@ -0,0 +1,218 @@
+// JavaScript
+
+//const Cu = Components.utils;
+//const { require } = Cu.import("resource://gre/modules/commonjs/toolkit/require.js", {});
+//const conj = require("resource://grammalecte/fr/conj.js");
+
+
+let oConj = {
+ init: function () {
+ console.log("Init conjugueur");
+ try {
+ // button
+ document.getElementById('conjugate').addEventListener("click", (xEvent) => {
+ this.getVerbAndConjugate();
+ });
+ // text field
+ document.getElementById('verb').addEventListener("change", (xEvent) => {
+ this.getVerbAndConjugate();
+ });
+ // options
+ document.getElementById('oneg').addEventListener("click", (xEvent) => {
+ this._displayResults();
+ });
+ document.getElementById('opro').addEventListener("click", (xEvent) => {
+ this._displayResults();
+ });
+ document.getElementById('oint').addEventListener("click", (xEvent) => {
+ this._displayResults();
+ });
+ document.getElementById('ofem').addEventListener("click", (xEvent) => {
+ this._displayResults();
+ });
+ document.getElementById('otco').addEventListener("click", (xEvent) => {
+ this._displayResults();
+ });
+ }
+ catch (e) {
+ console.error(e);
+ }
+ this.conjugate("être");
+ },
+
+ oVerb: null,
+
+ getVerbAndConjugate: function () {
+ this.conjugate(document.getElementById('verb').value);
+ },
+
+ conjugate: function (sVerb) {
+ try {
+ document.getElementById('oneg').checked = false;
+ document.getElementById('opro').checked = false;
+ document.getElementById('oint').checked = false;
+ document.getElementById('otco').checked = false;
+ document.getElementById('ofem').checked = false;
+ document.getElementById('smallnote').hidden = true;
+
+ // request analyzing
+ sVerb = sVerb.trim().toLowerCase().replace(/’/g, "'").replace(/ +/g, " ");
+ if (sVerb) {
+ if (sVerb.startsWith("ne pas ")) {
+ document.getElementById('oneg').checked = true;
+ sVerb = sVerb.slice(7);
+ }
+ if (sVerb.startsWith("se ")) {
+ document.getElementById('opro').checked = true;
+ sVerb = sVerb.slice(3);
+ } else if (sVerb.startsWith("s'")) {
+ document.getElementById('opro').checked = true;
+ sVerb = sVerb.slice(2);
+ }
+ if (sVerb.endsWith("?")) {
+ document.getElementById('oint').checked = true;
+ sVerb = sVerb.slice(0,-1).trim();
+ }
+
+ if (!conj.isVerb(sVerb)) {
+ document.getElementById('verb').style = "color: #BB4411;";
+ } else {
+ document.getElementById('verb_title').textContent = sVerb;
+ document.getElementById('verb').style = "color: #999999;";
+ document.getElementById('verb').value = "";
+ this.oVerb = new Verb(sVerb);
+ document.getElementById('info').textContent = this.oVerb.sInfo;
+ document.getElementById('opro').label = this.oVerb.sProLabel;
+ if (this.oVerb.bUncomplete) {
+ document.getElementById('opro').checked = false;
+ document.getElementById('opro').disabled = true;
+ document.getElementById('opro').style = "color: #CCC;";
+ document.getElementById('otco').checked = false;
+ document.getElementById('otco').disabled = true;
+ document.getElementById('otco').style = "color: #CCC;";
+ document.getElementById('smallnote').hidden = false;
+ } else {
+ document.getElementById('otco').disabled = false;
+ document.getElementById('otco').style = "color: #000;";
+ if (this.oVerb.nPronominable == 0) {
+ document.getElementById('opro').checked = false;
+ document.getElementById('opro').disabled = false;
+ document.getElementById('opro').style = "color: #000;";
+ } else if (this.oVerb.nPronominable == 1) {
+ document.getElementById('opro').checked = true;
+ document.getElementById('opro').disabled = true;
+ document.getElementById('opro').style = "color: #CCC;";
+ } else { // -1 or 1 or error
+ document.getElementById('opro').checked = false;
+ document.getElementById('opro').disabled = true;
+ document.getElementById('opro').style = "color: #CCC;";
+ }
+ document.getElementById('smallnote').hidden = true;
+ }
+ this._displayResults();
+ }
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+
+ _displayResults: function () {
+ if (this.oVerb === null) {
+ return;
+ }
+ try {
+ let bPro = document.getElementById('opro').checked;
+ let bNeg = document.getElementById('oneg').checked;
+ let bTCo = document.getElementById('otco').checked;
+ let bInt = document.getElementById('oint').checked;
+ let bFem = document.getElementById('ofem').checked;
+ let oConjTable = this.oVerb.createConjTable(bPro, bNeg, bTCo, bInt, bFem);
+ document.getElementById('verb').Text = "";
+ // infinitif
+ document.getElementById('infi').textContent = oConjTable["infi"] || " "; // something or nbsp
+ // participe présent
+ document.getElementById('ppre').textContent = oConjTable["ppre"] || " ";
+ // participes passés
+ document.getElementById('ppas1').textContent = oConjTable["ppas1"] || " ";
+ document.getElementById('ppas2').textContent = oConjTable["ppas2"] || " ";
+ document.getElementById('ppas3').textContent = oConjTable["ppas3"] || " ";
+ document.getElementById('ppas4').textContent = oConjTable["ppas4"] || " ";
+ // impératif
+ document.getElementById('impe_temps').textContent = oConjTable["t_impe"] || " ";
+ document.getElementById('impe1').textContent = oConjTable["impe1"] || " ";
+ document.getElementById('impe2').textContent = oConjTable["impe2"] || " ";
+ document.getElementById('impe3').textContent = oConjTable["impe3"] || " ";
+ // présent
+ document.getElementById('ipre_temps').textContent = oConjTable["t_ipre"] || " ";
+ document.getElementById('ipre1').textContent = oConjTable["ipre1"] || " ";
+ document.getElementById('ipre2').textContent = oConjTable["ipre2"] || " ";
+ document.getElementById('ipre3').textContent = oConjTable["ipre3"] || " ";
+ document.getElementById('ipre4').textContent = oConjTable["ipre4"] || " ";
+ document.getElementById('ipre5').textContent = oConjTable["ipre5"] || " ";
+ document.getElementById('ipre6').textContent = oConjTable["ipre6"] || " ";
+ // imparfait
+ document.getElementById('iimp_temps').textContent = oConjTable["t_iimp"] || " ";
+ document.getElementById('iimp1').textContent = oConjTable["iimp1"] || " ";
+ document.getElementById('iimp2').textContent = oConjTable["iimp2"] || " ";
+ document.getElementById('iimp3').textContent = oConjTable["iimp3"] || " ";
+ document.getElementById('iimp4').textContent = oConjTable["iimp4"] || " ";
+ document.getElementById('iimp5').textContent = oConjTable["iimp5"] || " ";
+ document.getElementById('iimp6').textContent = oConjTable["iimp6"] || " ";
+ // passé simple
+ document.getElementById('ipsi_temps').textContent = oConjTable["t_ipsi"] || " ";
+ document.getElementById('ipsi1').textContent = oConjTable["ipsi1"] || " ";
+ document.getElementById('ipsi2').textContent = oConjTable["ipsi2"] || " ";
+ document.getElementById('ipsi3').textContent = oConjTable["ipsi3"] || " ";
+ document.getElementById('ipsi4').textContent = oConjTable["ipsi4"] || " ";
+ document.getElementById('ipsi5').textContent = oConjTable["ipsi5"] || " ";
+ document.getElementById('ipsi6').textContent = oConjTable["ipsi6"] || " ";
+ // futur
+ document.getElementById('ifut_temps').textContent = oConjTable["t_ifut"] || " ";
+ document.getElementById('ifut1').textContent = oConjTable["ifut1"] || " ";
+ document.getElementById('ifut2').textContent = oConjTable["ifut2"] || " ";
+ document.getElementById('ifut3').textContent = oConjTable["ifut3"] || " ";
+ document.getElementById('ifut4').textContent = oConjTable["ifut4"] || " ";
+ document.getElementById('ifut5').textContent = oConjTable["ifut5"] || " ";
+ document.getElementById('ifut6').textContent = oConjTable["ifut6"] || " ";
+ // Conditionnel
+ document.getElementById('conda_temps').textContent = oConjTable["t_conda"] || " ";
+ document.getElementById('conda1').textContent = oConjTable["conda1"] || " ";
+ document.getElementById('conda2').textContent = oConjTable["conda2"] || " ";
+ document.getElementById('conda3').textContent = oConjTable["conda3"] || " ";
+ document.getElementById('conda4').textContent = oConjTable["conda4"] || " ";
+ document.getElementById('conda5').textContent = oConjTable["conda5"] || " ";
+ document.getElementById('conda6').textContent = oConjTable["conda6"] || " ";
+ document.getElementById('condb_temps').textContent = oConjTable["t_condb"] || " ";
+ document.getElementById('condb1').textContent = oConjTable["condb1"] || " ";
+ document.getElementById('condb2').textContent = oConjTable["condb2"] || " ";
+ document.getElementById('condb3').textContent = oConjTable["condb3"] || " ";
+ document.getElementById('condb4').textContent = oConjTable["condb4"] || " ";
+ document.getElementById('condb5').textContent = oConjTable["condb5"] || " ";
+ document.getElementById('condb6').textContent = oConjTable["condb6"] || " ";
+ // subjonctif présent
+ document.getElementById('spre_temps').textContent = oConjTable["t_spre"] || " ";
+ document.getElementById('spre1').textContent = oConjTable["spre1"] || " ";
+ document.getElementById('spre2').textContent = oConjTable["spre2"] || " ";
+ document.getElementById('spre3').textContent = oConjTable["spre3"] || " ";
+ document.getElementById('spre4').textContent = oConjTable["spre4"] || " ";
+ document.getElementById('spre5').textContent = oConjTable["spre5"] || " ";
+ document.getElementById('spre6').textContent = oConjTable["spre6"] || " ";
+ // subjonctif imparfait
+ document.getElementById('simp_temps').textContent = oConjTable["t_simp"] || " ";
+ document.getElementById('simp1').textContent = oConjTable["simp1"] || " ";
+ document.getElementById('simp2').textContent = oConjTable["simp2"] || " ";
+ document.getElementById('simp3').textContent = oConjTable["simp3"] || " ";
+ document.getElementById('simp4').textContent = oConjTable["simp4"] || " ";
+ document.getElementById('simp5').textContent = oConjTable["simp5"] || " ";
+ document.getElementById('simp6').textContent = oConjTable["simp6"] || " ";
+ }
+ catch (e) {
+ console.error(e);
+ }
+ }
+};
+
+conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
+oConj.init();
ADDED gc_lang/fr/mailext/content/conjugueur.xul
Index: gc_lang/fr/mailext/content/conjugueur.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/conjugueur.xul
@@ -0,0 +1,162 @@
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/editor.js
Index: gc_lang/fr/mailext/content/editor.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/editor.js
@@ -0,0 +1,113 @@
+// JavaScript
+
+class Editor {
+
+ constructor (sLang) {
+ this.xEditor = GetCurrentEditor();
+ this.lNode = [];
+ this.lParsableNodes = ["P", "LI"];
+ this.lRootNodes = ["DIV", "UL", "OL"];
+ };
+
+ _getTextFromNode (xNode) {
+ if ("innerHTML" in xNode) {
+ return xNode.innerHTML;
+ } else {
+ return xNode.textContent;
+ }
+ };
+
+ * _getParsableNodes (xRootNode=this.xEditor.rootElement) {
+ // recursive function
+ try {
+ for (let xNode of xRootNode.childNodes) {
+ if (xNode.className !== "moz-cite-prefix" && xNode.tagName !== "BLOCKQUOTE"
+ && (xNode.nodeType == Node.TEXT_NODE || (xNode.nodeType == Node.ELEMENT_NODE && !xNode.textContent.startsWith(">")))
+ && xNode.textContent !== "") {
+ if (xNode.tagName === undefined) {
+ if (!prefs.getBoolPref("bCheckSignature") && xNode.textContent.startsWith("-- ")) {
+ break;
+ }
+ yield xNode;
+ } else if (this.lParsableNodes.includes(xNode.tagName)) {
+ yield xNode;
+ } else if (this.lRootNodes.includes(xNode.tagName)) {
+ yield* this._getParsableNodes(xNode);
+ }
+ }
+ }
+ } catch (e) {
+ console.error(e);
+ // Cu.reportError(e);
+ }
+ };
+
+ * getParagraphs () {
+ try {
+ let i = 0;
+ for (let xNode of this._getParsableNodes()) {
+ this.lNode.push(xNode);
+ yield [i, this._getTextFromNode(xNode)];
+ i += 1;
+ }
+ } catch (e) {
+ console.error(e);
+ // Cu.reportError(e);
+ }
+ };
+
+ getContent () {
+ try {
+ let sContent = "";
+ for (let [i, sHTML] of this.getParagraphs()) {
+ if (sContent.length > 0) {
+ sContent += "\n";
+ }
+ sContent += sHTML;
+ }
+ return sContent;
+ } catch (e) {
+ console.error(e);
+ // Cu.reportError(e);
+ }
+ };
+
+ getParagraph (iPara) {
+ try {
+ return this._getTextFromNode(this.lNode[iPara]);
+ } catch (e) {
+ console.error(e);
+ // Cu.reportError(e);
+ }
+ };
+
+ writeParagraph (iPara, sText) {
+ try {
+ let xNode = this.lNode[iPara];
+ if ("innerHTML" in xNode) {
+ xNode.innerHTML = sText;
+ } else {
+ xNode.textContent = sText;
+ }
+ } catch (e) {
+ console.error(e);
+ // Cu.reportError(e);
+ }
+ };
+
+ changeParagraph (iPara, sModif, iStart, iEnd) {
+ let sText = this.getParagraph(iPara);
+ this.writeParagraph(iPara, sText.slice(0, iStart) + sModif + sText.slice(iEnd));
+ };
+
+ getLangFromSpellChecker () {
+ try {
+ let gSpellChecker = this.xEditor.getInlineSpellChecker(true);
+ let sLang = gSpellChecker.spellChecker.GetCurrentDictionary();
+ return sLang.slice(0, 2);
+ } catch (e) {
+ console.error(e);
+ // Cu.reportError(e);
+ }
+ };
+}
ADDED gc_lang/fr/mailext/content/file_handler.js
Index: gc_lang/fr/mailext/content/file_handler.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/file_handler.js
@@ -0,0 +1,100 @@
+// JavaScript
+
+"use strict";
+
+// Assuming that Cc, Ci and Cu are already loaded
+
+const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm", {});
+
+//ChromeUtils.import("resource://gre/modules/osfile.jsm")
+
+const oFileHandler = {
+ // https://developer.mozilla.org/fr/docs/Mozilla/JavaScript_code_modules/OSFile.jsm/OS.File_for_the_main_thread
+
+ xDataFolder: null,
+
+ prepareDataFolder: function () {
+ let xDirectoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
+ // this is a reference to the profile dir (ProfD) now.
+ let xExtFolder = xDirectoryService.get("ProfD", Ci.nsIFile);
+ xExtFolder.append("grammalecte-data");
+ if (!xExtFolder.exists() || !xExtFolder.isDirectory()) {
+ // read and write permissions to owner and group, read-only for others.
+ xExtFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 774);
+ }
+ this.xDataFolder = xExtFolder;
+ },
+
+ createPathFileName: function (sFilename) {
+ let spfDest = this.xDataFolder.path;
+ spfDest += (/^[A-Z]:/.test(this.xDataFolder.path)) ? "\\" + sFilename : "/" + sFilename;
+ return spfDest;
+ },
+
+ loadFile: async function (sFilename) {
+ if (!this.xDataFolder) {
+ this.prepareDataFolder();
+ }
+ try {
+ let array = await OS.File.read(this.createPathFileName(sFilename));
+ let xDecoder = new TextDecoder();
+ return xDecoder.decode(array);
+ }
+ catch (e) {
+ console.error(e);
+ return null;
+ }
+ },
+
+ loadAs: function (callback) {
+ let xFilePicker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ xFilePicker.init(window, "Charger fichier", Ci.nsIFilePicker.modeOpen);
+ xFilePicker.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterText);
+ xFilePicker.open(async function (nReturnValue) {
+ if (nReturnValue == Ci.nsIFilePicker.returnOK || nReturnValue == Ci.nsIFilePicker.returnReplace) {
+ console.log(xFilePicker.file.path);
+ try {
+ let array = await OS.File.read(xFilePicker.file.path);
+ let xDecoder = new TextDecoder();
+ callback(xDecoder.decode(array));
+ }
+ catch (e) {
+ console.error(e);
+ callback(null);
+ }
+ }
+ });
+ },
+
+ saveFile: function (sFilename, sData) {
+ if (!this.xDataFolder) {
+ this.prepareDataFolder();
+ }
+ let xEncoder = new TextEncoder();
+ let xEncodedRes = xEncoder.encode(sData);
+ console.log("save dictionary: " + this.createPathFileName(sFilename));
+ OS.File.writeAtomic(this.createPathFileName(sFilename), xEncodedRes);
+ //OS.File.writeAtomic(this.createPathFileName(sFilename), xEncodedRes, {tmpPath: "file.txt.tmp"}); // error with a temporary file (can’t move it)
+ },
+
+ deleteFile: function (sFilename) {
+ if (!this.xDataFolder) {
+ this.prepareDataFolder();
+ }
+ OS.File.remove(this.createPathFileName(sFilename), {ignoreAbsent: true});
+ },
+
+ saveAs: function (sData) {
+ // save anywhere with file picker
+ let xFilePicker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ xFilePicker.init(window, "Enregistrer sous", Ci.nsIFilePicker.modeSave);
+ xFilePicker.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterText);
+ xFilePicker.open(function (nReturnValue) {
+ if (nReturnValue == Ci.nsIFilePicker.returnOK || nReturnValue == Ci.nsIFilePicker.returnReplace) {
+ let xEncoder = new TextEncoder();
+ let xEncodedRes = xEncoder.encode(sData);
+ OS.File.writeAtomic(xFilePicker.file.path, xEncodedRes, {tmpPath: "file.txt.tmp"});
+ }
+ });
+ }
+}
ADDED gc_lang/fr/mailext/content/gc_options.css
Index: gc_lang/fr/mailext/content/gc_options.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/gc_options.css
@@ -0,0 +1,18 @@
+/* CSS */
+
+.section {
+ font-size: 16px;
+ font-weight: bold;
+ color: hsl(210, 50%, 50%);
+}
+
+.dialogheader-title {
+ margin: 5px;
+ padding: 5px 8px;
+ border: 1px solid hsl(210, 50%, 80%);
+ background-color: hsl(210, 50%, 50%);
+ color: hsl(210, 10%, 90%);
+ font-size: larger;
+ font-weight: bold;
+}
+
ADDED gc_lang/fr/mailext/content/gc_options.js
Index: gc_lang/fr/mailext/content/gc_options.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/gc_options.js
@@ -0,0 +1,53 @@
+// JavaScript
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+// const Cu = Components.utils;
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");
+
+
+var oOptControl = {
+ oOptions: null,
+ load: function () {
+ this._setDialogOptions(false);
+ this.listen();
+ },
+ listen: function () {
+ document.addEventListener("dialogaccept", (event) => {
+ this.save();
+ });
+ document.addEventListener("dialogextra1", (event) => {
+ this.reset();
+ });
+ },
+ _setDialogOptions: function (bDefaultOptions=false) {
+ try {
+ sOptions = bDefaultOptions ? prefs.getCharPref("sGCDefaultOptions") : prefs.getCharPref("sGCOptions");
+ this.oOptions = JSON.parse(sOptions);
+ for (let sParam in this.oOptions) {
+ if (document.getElementById("option_"+sParam) !== null) {
+ document.getElementById("option_"+sParam).checked = this.oOptions[sParam];
+ }
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ save: function () {
+ try {
+ for (let xNode of document.getElementsByClassName("option")) {
+ this.oOptions[xNode.id.slice(7)] = xNode.checked;
+ }
+ prefs.setCharPref("sGCOptions", JSON.stringify(this.oOptions));
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ reset: function () {
+ this._setDialogOptions(true);
+ }
+}
+
+oOptControl.load();
ADDED gc_lang/fr/mailext/content/gc_options.xul
Index: gc_lang/fr/mailext/content/gc_options.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/gc_options.xul
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/lex_editor.css
Index: gc_lang/fr/mailext/content/lex_editor.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/lex_editor.css
@@ -0,0 +1,134 @@
+/* CSS */
+
+button {
+ font-weight: bold;
+}
+
+.dialogheader-title {
+ margin: 5px;
+ padding: 5px 8px;
+ border: 1px solid hsl(210, 50%, 80%);
+ background-color: hsl(210, 50%, 50%);
+ color: hsl(210, 10%, 90%);
+ font-size: larger;
+ font-weight: bold;
+}
+
+/*
+ Dictionary
+*/
+.dictionary {
+ font-size: 18px;
+ font-weight: bold;
+ color: hsl(210, 50%, 50%);
+}
+.dic_text {
+ font-size: 18px;
+ color: hsl(210, 50%, 50%);
+}
+.align_right {
+ text-align: right;
+}
+
+
+/*
+ Add new words
+*/
+.section {
+ font-size: 16px;
+ font-weight: bold;
+ color: hsl(210, 50%, 50%);
+}
+
+.subsection {
+ font-size: 14px;
+ font-weight: bold;
+ color: hsl(210, 50%, 50%);
+}
+
+.option {
+ width: 120px;
+ font-size: 12px;
+}
+
+.m_left {
+ margin-left: 20px;
+}
+
+.m_left2 {
+ margin-left: 40px;
+}
+
+.v_usage {
+ width: 150px;
+}
+.v_textbox {
+ width: 200px;
+}
+
+.other_label {
+ width: 80px;
+}
+.other_textbox {
+ width: 250px;
+}
+
+#generated_words_table {
+ width: 400px;
+ height: 600px;
+}
+
+.delete_entry {
+ color: hsl(0, 100%, 50%);
+ font-weight: bold;
+}
+
+/*
+ Lexicon tab
+*/
+
+#lexicon_table {
+ width: 600px;
+ height: 650px;
+}
+
+.listheader {
+ padding: 2px 0;
+ font-weight: bold;
+ background-color: hsl(0, 0%, 95%);
+ border-bottom: 1px solid hsl(0, 0%, 50%);
+}
+.info_label {
+ width: 120px;
+}
+.data {
+ width: 90px;
+}
+
+/*
+ Search tab
+*/
+
+#search_table {
+ width: 600px;
+ height: 650px;
+}
+
+.bold {
+ font-weight: bold;
+}
+description {
+ width: 200px;
+}
+
+/*
+ Informations tab
+*/
+
+#tags_table {
+ width: 600px;
+ height: 650px;
+ font-family: "Courier new", "Ubuntu Mono", Courier, Consolas, monospace;
+}
+
+
ADDED gc_lang/fr/mailext/content/lex_editor.js
Index: gc_lang/fr/mailext/content/lex_editor.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/lex_editor.js
@@ -0,0 +1,558 @@
+// JavaScript
+
+"use strict";
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");
+
+
+/*
+ Common functions
+*/
+
+function showError (e) {
+ Cu.reportError(e);
+ console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
+}
+
+function createNode (sType, oAttr) {
+ try {
+ let xNode = document.createElement(sType);
+ for (let sParam in oAttr) {
+ xNode.setAttribute(sParam, oAttr[sParam]);
+ }
+ return xNode;
+ }
+ catch (e) {
+ showError(e);
+ }
+}
+
+function enableElement (sElemId) {
+ if (document.getElementById(sElemId)) {
+ document.getElementById(sElemId).disabled = false;
+ } else {
+ console.log("HTML node named <" + sElemId + "> not found.")
+ }
+}
+
+function disableElement (sElemId) {
+ if (document.getElementById(sElemId)) {
+ document.getElementById(sElemId).disabled = true;
+ } else {
+ console.log("HTML node named <" + sElemId + "> not found.")
+ }
+}
+
+
+
+class Table {
+
+ constructor (sNodeId, lColumn, lColumnWidth, sProgressBarId, sResultId="") {
+ this.sNodeId = sNodeId;
+ this.xTable = document.getElementById(sNodeId);
+ this.nColumn = lColumn.length;
+ this.lColumn = lColumn;
+ this.lColumnWidth = lColumnWidth;
+ this.xProgressBar = document.getElementById(sProgressBarId);
+ this.xNumEntry = sResultId ? document.getElementById(sResultId) : null;
+ this.iEntryIndex = 0;
+ this.lEntry = [];
+ this.nEntry = 0
+ this._createHeader();
+ }
+
+ _createHeader () {
+ let xListheadNode = createNode("richlistitem", { class: "listheader" });
+ for (let i=0; i < this.lColumn.length; i++) {
+ xListheadNode.appendChild(createNode("label", { value: this.lColumn[i], width: this.lColumnWidth[i] }));
+ }
+ this.xTable.appendChild(xListheadNode);
+ }
+
+ 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;
+ for (let lData of lFlex) {
+ this._addRow(lData);
+ this.xProgressBar.value += 1;
+ }
+ this.xProgressBar.value = this.xProgressBar.max;
+ window.setTimeout(() => { this.xProgressBar.value = 0; }, 3000);
+ }
+ this.lEntry = lFlex;
+ this.nEntry = lFlex.length;
+ this.showEntryNumber();
+ }
+
+ addEntries (lFlex) {
+ this.lEntry.push(...lFlex);
+ for (let lData of lFlex) {
+ this._addRow(lData);
+ }
+ this.nEntry += lFlex.length;
+ this.showEntryNumber();
+ }
+
+ showEntryNumber () {
+ if (this.xNumEntry) {
+ this.xNumEntry.value = this.nEntry;
+ }
+ }
+
+ _addRow (lData) {
+ let xRowNode = createNode("richlistitem", { id: this.sNodeId + "_item_" + this.iEntryIndex, value: this.iEntryIndex });
+ for (let i=0; i < lData.length; i++) {
+ xRowNode.appendChild(createNode("label", { class: "listcell", value: lData[i], width: this.lColumnWidth[i] }));
+ }
+ this.xTable.appendChild(xRowNode);
+ this.iEntryIndex += 1;
+ }
+
+ deleteSelection () {
+ for (let xItem of this.xTable.selectedItems) {
+ this.lEntry[parseInt(xItem.value)] = null;
+ xItem.style.display = "none";
+ this.nEntry -= 1;
+ }
+ this.showEntryNumber();
+ }
+
+ getEntries () {
+ return this.lEntry.filter((e) => e !== null);
+ }
+}
+
+
+const oGenerator = {
+
+ sLemma: "",
+
+ cMainTag: "",
+
+ lFlexion: [],
+
+ listen: function () {
+ document.getElementById("lemma").addEventListener("keyup", () => { this.update(); }, false);
+ // nom commun
+ document.getElementById("tag_N").addEventListener("click", () => { this.update("N"); }, false);
+ document.getElementById("nom_adj").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("nom").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("adj").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("N_epi").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("N_mas").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("N_fem").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("N_s").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("N_x").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("N_inv").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("lemma2").addEventListener("keyup", () => { this.update(); }, false);
+ // nom propre
+ document.getElementById("tag_M").addEventListener("click", () => { this.update("M"); }, false);
+ document.getElementById("M1").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("M2").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("MP").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("M_epi").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("M_mas").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("M_fem").addEventListener("click", () => { this.update(); }, false);
+ // verbe
+ document.getElementById("tag_V").addEventListener("click", () => { this.update("V"); }, false);
+ document.getElementById("v_i").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_t").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_n").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_p").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_m").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_ae").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_aa").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("v_ppas").addEventListener("click", () => { this.update(); }, false);
+ document.getElementById("verbe_modele").addEventListener("keyup", () => { this.update(); }, false);
+ // adverbe
+ document.getElementById("tag_W").addEventListener("click", () => { this.update("W"); }, false);
+ // autre
+ document.getElementById("tag_X").addEventListener("click", () => { this.update("X"); }, false);
+ document.getElementById("flexion").addEventListener("keyup", () => { this.update(); }, false);
+ document.getElementById("tags").addEventListener("keyup", () => { this.update(); }, false);
+ // ajout
+ document.getElementById("add_to_lexicon").addEventListener("click", () => { this.addToLexicon(); }, false);
+ document.getElementById("delete_selection").addEventListener("click", () => { oGenWordsTable.deleteSelection(); }, false);
+ },
+
+ clear: function () {
+ try {
+ // nom commun
+ document.getElementById("tag_N").checked = false;
+ document.getElementById("nom_adj").checked = false;
+ document.getElementById("nom").checked = false;
+ document.getElementById("adj").checked = false;
+ document.getElementById("N_epi").checked = false;
+ document.getElementById("N_mas").checked = false;
+ document.getElementById("N_fem").checked = false;
+ document.getElementById("N_s").checked = false;
+ document.getElementById("N_x").checked = false;
+ document.getElementById("N_inv").checked = false;
+ document.getElementById("lemma2").value = "";
+ // nom propre
+ document.getElementById("tag_M").checked = false;
+ document.getElementById("M1").checked = false;
+ document.getElementById("M2").checked = false;
+ document.getElementById("MP").checked = false;
+ document.getElementById("M_epi").checked = false;
+ document.getElementById("M_mas").checked = false;
+ document.getElementById("M_fem").checked = false;
+ // verbe
+ document.getElementById("tag_V").checked = false;
+ document.getElementById("v_i").checked = false;
+ document.getElementById("v_t").checked = false;
+ document.getElementById("v_n").checked = false;
+ document.getElementById("v_p").checked = false;
+ document.getElementById("v_m").checked = false;
+ document.getElementById("v_ae").checked = false;
+ document.getElementById("v_aa").checked = false;
+ document.getElementById("v_ppas").checked = false;
+ document.getElementById("verbe_modele").value = "";
+ // adverbe
+ document.getElementById("tag_W").checked = false;
+ // autre
+ document.getElementById("tag_X").checked = false;
+ document.getElementById("flexion").value = "";
+ document.getElementById("tags").value = "";
+ }
+ catch (e) {
+ showError(e);
+ }
+ },
+
+ lTag: ["N", "M", "V", "W", "X"],
+
+ setMainTag: function (cTag) {
+ this.cMainTag = cTag;
+ for (let c of this.lTag) {
+ if (c !== cTag) {
+ document.getElementById("tag_"+c).checked = false;
+ }
+ }
+ },
+
+ update: function (cTag=null) {
+ if (cTag !== null) {
+ this.setMainTag(cTag);
+ }
+ try {
+ this.lFlexion = [];
+ this.sLemma = document.getElementById("lemma").value.trim();
+ if (this.sLemma.length > 0) {
+ switch (this.cMainTag) {
+ case "N":
+ if (!this.getRadioValue("pos_nom_commun") || !this.getRadioValue("genre_nom_commun")) {
+ break;
+ }
+ let sTag = this.getRadioValue("pos_nom_commun") + this.getRadioValue("genre_nom_commun");
+ switch (this.getRadioValue("pluriel_nom_commun")) {
+ case "s":
+ this.lFlexion.push([this.sLemma, sTag+":s/*"]);
+ this.lFlexion.push([this.sLemma+"s", sTag+":p/*"]);
+ break;
+ case "x":
+ this.lFlexion.push([this.sLemma, sTag+":s/*"]);
+ this.lFlexion.push([this.sLemma+"x", sTag+":p/*"]);
+ break;
+ case "i":
+ this.lFlexion.push([this.sLemma, sTag+":i/*"]);
+ break;
+ }
+ let sLemma2 = document.getElementById("lemma2").value.trim();
+ if (sLemma2.length > 0 && this.getRadioValue("pos_nom_commun2") && this.getRadioValue("genre_nom_commun2")) {
+ let sTag2 = this.getRadioValue("pos_nom_commun2") + this.getRadioValue("genre_nom_commun2");
+ switch (this.getRadioValue("pluriel_nom_commun2")) {
+ case "s":
+ this.lFlexion.push([sLemma2, sTag2+":s/*"]);
+ this.lFlexion.push([sLemma2+"s", sTag2+":p/*"]);
+ break;
+ case "x":
+ this.lFlexion.push([sLemma2, sTag2+":s/*"]);
+ this.lFlexion.push([sLemma2+"x", sTag2+":p/*"]);
+ break;
+ case "i":
+ this.lFlexion.push([sLemma2, sTag2+":i/*"]);
+ break;
+ }
+ }
+ break;
+ case "V": {
+ if (!this.sLemma.endsWith("er") && !this.sLemma.endsWith("ir") && !this.sLemma.endsWith("re")) {
+ break;
+ }
+ this.sLemma = this.sLemma.toLowerCase();
+ let cGroup = "";
+ let c_i = (document.getElementById("v_i").checked) ? "i" : "_";
+ let c_t = (document.getElementById("v_t").checked) ? "t" : "_";
+ let c_n = (document.getElementById("v_n").checked) ? "n" : "_";
+ let c_p = (document.getElementById("v_p").checked) ? "p" : "_";
+ let c_m = (document.getElementById("v_m").checked) ? "m" : "_";
+ let c_ae = (document.getElementById("v_ae").checked) ? "e" : "_";
+ let c_aa = (document.getElementById("v_aa").checked) ? "a" : "_";
+ let sVerbTag = c_i + c_t + c_n + c_p + c_m + c_ae + c_aa;
+ if (sVerbTag.includes("p") && !sVerbTag.startsWith("___p_")) {
+ sVerbTag = sVerbTag.replace("p", "q");
+ }
+ if (!sVerbTag.endsWith("__") && !sVerbTag.startsWith("____")) {
+ let sVerbPattern = document.getElementById("verbe_modele").value.trim();
+ if (sVerbPattern.length == 0) {
+ // utilisation du générateur de conjugaison
+ let bVarPpas = !document.getElementById("v_ppas").checked;
+ for (let [sFlexion, sFlexTags] of conj_generator.conjugate(this.sLemma, sVerbTag, bVarPpas)) {
+ this.lFlexion.push([sFlexion, sFlexTags]);
+ }
+ } else {
+ // copie du motif d’un autre verbe : utilisation du conjugueur
+ if (conj.isVerb(sVerbPattern)) {
+ let oVerb = new Verb(this.sLemma, sVerbPattern);
+ for (let [sTag1, dFlex] of oVerb.dConj.entries()) {
+ if (sTag1 !== ":Q") {
+ for (let [sTag2, sConj] of dFlex.entries()) {
+ if (sTag2.startsWith(":") && sConj !== "") {
+ this.lFlexion.push([sConj, ":V" + oVerb.cGroup + "_" + sVerbTag + sTag1 + sTag2]);
+ }
+ }
+ } else {
+ // participes passés
+ if (dFlex.get(":Q3") !== "") {
+ if (dFlex.get(":Q2") !== "") {
+ this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"]);
+ this.lFlexion.push([dFlex.get(":Q2"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"]);
+ } else {
+ this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"]);
+ }
+ this.lFlexion.push([dFlex.get(":Q3"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"]);
+ this.lFlexion.push([dFlex.get(":Q4"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"]);
+ } else {
+ this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"]);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ case "W":
+ this.sLemma = this.sLemma.toLowerCase();
+ this.lFlexion.push([this.sLemma, ":W/*"]);
+ break;
+ case "M":
+ this.sLemma = this.sLemma.slice(0,1).toUpperCase() + this.sLemma.slice(1);
+ let sPOSTag = this.getRadioValue("pos_nom_propre");
+ let sGenderTag = this.getRadioValue("genre_nom_propre");
+ if (sGenderTag) {
+ this.lFlexion.push([this.sLemma, sPOSTag+sGenderTag+":i/*"]);
+ }
+ break;
+ case "X":
+ let sFlexion = document.getElementById("flexion").value.trim();
+ let sTags = document.getElementById("tags").value.trim();
+ if (sFlexion.length > 0 && sTags.startsWith(":")) {
+ this.lFlexion.push([sFlexion, sTags]);
+ }
+ break;
+ }
+ }
+ oGenWordsTable.fill(this.lFlexion);
+ }
+ catch (e) {
+ showError(e);
+ }
+ },
+
+ getRadioValue: function (sName) {
+ if (document.getElementById(sName)) {
+ for (let xNode of document.getElementById(sName).children) {
+ if (xNode.selected) {
+ return xNode.value;
+ }
+ }
+ }
+ return null;
+ },
+
+ createFlexLemmaTagArray: function () {
+ let lEntry = [];
+ for (let [sFlex, sTags] of oGenWordsTable.getEntries()) {
+ lEntry.push([sFlex, this.sLemma, sTags]);
+ }
+ return lEntry;
+ },
+
+ addToLexicon: function () {
+ try {
+ oLexiconTable.addEntries(this.createFlexLemmaTagArray());
+ oGenWordsTable.clear();
+ document.getElementById("lemma").value = "";
+ document.getElementById("lemma").focus();
+ enableElement("save_button");
+ this.clear();
+ this.cMainTag = "";
+ }
+ catch (e) {
+ showError(e);
+ }
+ }
+}
+
+
+const oBinaryDict = {
+
+ oIBDAWG: null,
+
+ load: async function () {
+ let sJSON = await oFileHandler.loadFile("fr.personal.json");
+ this._load(sJSON);
+ },
+
+ _load: function (sJSON, bSave=false) {
+ //console.log("_load");
+ if (sJSON) {
+ try {
+ let oJSON = JSON.parse(sJSON);
+ this.oIBDAWG = new IBDAWG(oJSON);
+ }
+ catch (e) {
+ this.setDictData(0, "#Erreur. Voir la console.");
+ console.error(e);
+ return;
+ }
+ if (bSave) {
+ oFileHandler.saveFile("fr.personal.json", sJSON);
+ }
+ let lEntry = [];
+ for (let aRes of this.oIBDAWG.select()) {
+ lEntry.push(aRes);
+ }
+ oLexiconTable.fill(lEntry);
+ this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
+ enableElement("export_button");
+ } else {
+ this.setDictData(0, "[néant]");
+ disableElement("export_button");
+ }
+ },
+
+ import: function () {
+ oFileHandler.loadAs(this._import.bind(this));
+ },
+
+ _import: function (sJSON) {
+ this._load(sJSON, true);
+ },
+
+ setDictData: function (nEntries, sDate) {
+ document.getElementById("dic_num_entries").value = nEntries;
+ document.getElementById("dic_save_date").value = sDate;
+ },
+
+ listen: function () {
+ document.getElementById("delete_button").addEventListener("click", () => { oLexiconTable.deleteSelection(); }, false);
+ document.getElementById("save_button").addEventListener("click", () => { this.build(); }, false);
+ document.getElementById("export_button").addEventListener("click", () => { this.export(); }, false);
+ 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 {
+ oFileHandler.deleteFile("fr.personal.json");
+ this.setDictData(0, "[néant]");
+ disableElement("export_button");
+ }
+ },
+
+ export: function () {
+ let sJSON = JSON.stringify(this.oIBDAWG.getJSON());
+ oFileHandler.saveAs(sJSON);
+ }
+}
+
+
+const oSearch = {
+
+ oSpellChecker: null,
+
+ load: function () {
+ this.oSpellChecker = new SpellChecker("fr", "", "fr-allvars.json");
+ },
+
+ listen: function () {
+ document.getElementById("search_similar_button").addEventListener("click", () => { this.searchSimilar(); }, false);
+ document.getElementById("search_regex_button").addEventListener("click", () => { this.searchRegex() }, false);
+ },
+
+ searchSimilar: function () {
+ oSearchTable.clear();
+ let sWord = document.getElementById("search_similar").value;
+ if (sWord !== "") {
+ let lResult = this.oSpellChecker.getSimilarEntries(sWord, 20);
+ oSearchTable.fill(lResult);
+ }
+ },
+
+ searchRegex: function () {
+ let sFlexPattern = document.getElementById("search_flexion_pattern").value.trim();
+ let sTagsPattern = document.getElementById("search_tags_pattern").value.trim();
+ let lEntry = [];
+ let i = 0;
+ for (let aRes of this.oSpellChecker.select(sFlexPattern, sTagsPattern)) {
+ lEntry.push(aRes);
+ i++;
+ if (i >= 2000) {
+ break;
+ }
+ }
+ oSearchTable.fill(lEntry);
+ }
+}
+
+
+const oTagsInfo = {
+ load: function () {
+ let lEntry = [];
+ for (let [sTag, [_, sLabel]] of _dTag) {
+ lEntry.push([sTag, sLabel.trim()]);
+ }
+ oTagsTable.fill(lEntry);
+ }
+}
+
+
+const oGenWordsTable = new Table("generated_words_table", ["Flexions", "Étiquettes"], ["125px", "225px"], "progress_new_words");
+const oLexiconTable = new Table("lexicon_table", ["Flexions", "Lemmes", "Étiquettes"], ["190px", "150px", "200px"], "progress_lexicon", "num_entries");
+const oSearchTable = new Table("search_table", ["Flexions", "Lemmes", "Étiquettes"], ["190px", "150px", "200px"], "progress_search", "search_num_entries");
+const oTagsTable = new Table("tags_table", ["Étiquette", "Signification"], ["75px", "475px"], "progress_lexicon");
+
+conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
+
+
+oTagsInfo.load();
+oSearch.load();
+oBinaryDict.load();
+oBinaryDict.listen();
+oGenerator.listen();
+oSearch.listen();
ADDED gc_lang/fr/mailext/content/lex_editor.xul
Index: gc_lang/fr/mailext/content/lex_editor.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/lex_editor.xul
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/options.css
Index: gc_lang/fr/mailext/content/options.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/options.css
@@ -0,0 +1,12 @@
+/* CSS */
+
+
+.dialogheader-title {
+ margin: 5px;
+ padding: 5px 8px;
+ border: 1px solid hsl(210, 50%, 80%);
+ background-color: hsl(210, 50%, 50%);
+ color: hsl(210, 10%, 90%);
+ font-size: larger;
+ font-weight: bold;
+}
ADDED gc_lang/fr/mailext/content/options.js
Index: gc_lang/fr/mailext/content/options.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/options.js
@@ -0,0 +1,40 @@
+// JavaScript
+
+"use strict";
+
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+// const Cu = Components.utils;
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");
+
+
+var oOptControl = {
+
+ load: function () {
+ try {
+ document.getElementById('check_signature').checked = prefs.getBoolPref('bCheckSignature');
+ }
+ catch (e) {
+ console.error(e);
+ }
+ this.listen();
+ },
+
+ listen: function () {
+ document.addEventListener("dialogaccept", (event) => {
+ this.save();
+ });
+ },
+
+ save: function () {
+ try {
+ prefs.setBoolPref('bCheckSignature', document.getElementById('check_signature').checked);
+ }
+ catch (e) {
+ console.error(e);
+ }
+ }
+}
+
+oOptControl.load();
ADDED gc_lang/fr/mailext/content/options.xul
Index: gc_lang/fr/mailext/content/options.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/options.xul
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/overlay.css
Index: gc_lang/fr/mailext/content/overlay.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/overlay.css
@@ -0,0 +1,162 @@
+#grammarchecker-toolbar-button {
+ list-style-image: url("chrome://grammarchecker/skin/grammarcheck.png");
+}
+[iconsize="small"] #grammarchecker-toolbar-button {
+ list-style-image: url("chrome://grammarchecker/skin/grammarcheck_small.png");
+}
+#grammarchecker-toolbar-button[disabled="true"] {
+ list-style-image: url("chrome://grammarchecker/skin/grammarcheck_disabled.png");
+}
+[iconsize="small"] #grammarchecker-toolbar-button[disabled="true"] {
+ list-style-image: url("chrome://grammarchecker/skin/grammarcheck_small_disabled.png");
+}
+
+#grammalecte-menu {
+ list-style-image: url("chrome://grammarchecker/skin/grammarcheck.png");
+}
+menuitem#gl-item-analyze {
+ list-style-image: url('chrome://grammarchecker/skin/grammarcheck.png');
+}
+
+#textformatter-panel {
+ overflow: auto;
+ height: 500px;
+ max-height: 650px;
+}
+#textformatter-title {
+ margin-top: 10px;
+}
+#textformatter-commands {
+ margin: 10px 0;
+}
+#textformatter-infomsg {
+ padding: 5px;
+ font-size: 10px;
+}
+.optiongroup {
+ color: hsl(210, 50%, 40%);
+ font-size: 14px;
+ font-weight: bold;
+}
+#textformatter-progressbar {
+ padding: 5px;
+}
+#textformatter-timer {
+ padding: 5px;
+}
+
+
+#grammarchecker-panel {
+ overflow: auto;
+ margin-left: 0.5em;
+ height: 400px;
+ max-height: 600px;
+}
+
+#grammalecte-title {
+ margin-top: 10px;
+}
+
+#grammalecte-infobox {
+ display: block;
+ margin: 20px 10px 5px 10px;
+ padding: 10px;
+ background-color: hsl(210, 20%, 40%);
+ border-radius: 3px;
+ color: hsl(210, 50%, 96%);
+ font-weight: bold;
+}
+#grammalecte-info {
+ padding: 1px 5px;
+}
+#closebutton {
+ padding: 1px 5px;
+ background-color: hsl(0, 50%, 50%);
+ color: hsl(0, 10%, 96%);
+ border-radius: 2px;
+ cursor: pointer;
+}
+
+#grammalecte-errors div {
+ display: block;
+ /*display: list-item;
+ list-style-position: inside;*/
+ margin-top: 10px;
+}
+#grammalecte-errors p {
+ display: block;
+ margin-left: 10px;
+}
+#grammalecte-errors p.paragraph {
+ margin-top: 20px;
+ font-size: 16px;
+ font-family: "Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter", monospace;
+}
+#grammalecte-errors p.message {
+ margin-left: 20px;
+}
+#grammalecte-errors p.moreinfo {
+ margin-left: 40px;
+}
+#grammalecte-errors p.suggestions {
+ margin-left: 40px;
+ color: hsl(120, 5%, 33%);
+}
+#grammalecte-errors span.suggestions_button {
+ padding: 1px 6px;
+ background-color: hsl(120, 40%, 60%);
+ color: hsl(120, 10%, 96%);
+ border-radius: 2px;
+ cursor: pointer;
+}
+#grammalecte-errors {
+ display: block;
+}
+
+a {
+ font-weight: bold;
+ color: hsl(30, 50%, 50%);
+ text-decoration: underline;
+ cursor: pointer;
+}
+.error {
+ /* default color */
+ background-color: hsl(210, 50%, 50%);
+ color: hsl(210, 10%, 96%);
+ font-weight: bold;
+ border-radius: 3px;
+ /*border-bottom: 2px solid hsl(210, 50%, 50%);*/
+}
+.errornum {
+ color: hsl(210, 10%, 30%);
+ font-weight: bold;
+}
+.sugg {
+ padding: 1px 6px;
+ background-color: hsl(120, 50%, 30%);
+ color: hsl(210, 10%, 90%);
+ border-radius: 2px;
+ font-weight: bold;
+ cursor: pointer;
+}
+.debug_info {
+ color: hsl(0, 50%, 50%);
+ font-style: italic;
+}
+
+.spell {
+ background-color: hsl(0, 50%, 50%);
+ color: hsl(0, 0%, 96%);
+ border-radius: 3px;
+}
+
+
+.dialogheader-title {
+ margin: 5px;
+ padding: 5px 8px;
+ border: 1px solid hsl(210, 50%, 80%);
+ background-color: hsl(210, 50%, 50%);
+ color: hsl(210, 10%, 90%);
+ font-size: larger;
+ font-weight: bold;
+}
ADDED gc_lang/fr/mailext/content/overlay.js
Index: gc_lang/fr/mailext/content/overlay.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/overlay.js
@@ -0,0 +1,873 @@
+// JavaScript
+
+"use strict";
+
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+//const Cu = Components.utils;
+//const { require } = Cu.import("resource://gre/modules/commonjs/toolkit/require.js", {});
+
+const { BasePromiseWorker } = ChromeUtils.import('resource://gre/modules/PromiseWorker.jsm', {});
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");
+
+//const text = require("resource://grammalecte/text.js");
+//const tf = require("resource://grammalecte/fr/textformatter.js");
+
+
+const oConverterToExponent = {
+ dNumbers: new Map ([
+ ["1", "¹"], ["2", "²"], ["3", "³"], ["4", "⁴"], ["5", "⁵"],
+ ["6", "⁶"], ["7", "⁷"], ["8", "⁸"], ["9", "⁹"], ["0", "⁰"]
+ ]),
+ convert: function (sText) {
+ let sRes = "";
+ for (let c of sText) {
+ sRes += (this.dNumbers.has(c)) ? this.dNumbers.get(c) : "⁻";
+ }
+ return sRes;
+ }
+};
+
+
+var oGrammarChecker = {
+ // you must use var to be able to call this object from elsewhere
+ xGCEWorker: null,
+ loadGC: function () {
+ if (this.xGCEWorker === null) {
+ // Grammar checker
+ console.log('Loading Grammalecte');
+ this.xGCEWorker = new BasePromiseWorker('chrome://promiseworker/content/gce_worker.js');
+ let that = this;
+ let xPromise = this.xGCEWorker.post('loadGrammarChecker', [prefs.getCharPref("sGCOptions"), "Thunderbird"]);
+ xPromise.then(
+ function (aVal) {
+ console.log(aVal);
+ prefs.setCharPref("sGCOptions", aVal);
+ if (prefs.getBoolPref("bPersonalDictionary")) {
+ let sDicJSON = oFileHandler.loadFile("fr.personal.json");
+ if (sDicJSON) {
+ that.xGCEWorker.post('setDictionary', ["personal", sDicJSON]);
+ }
+ }
+ },
+ function (aReason) { console.log('Promise rejected - ', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Promise Error - ', aCaught); }
+ );
+ }
+ },
+ fullTests: function () {
+ console.log('Performing tests... Wait...');
+ let xPromise = this.xGCEWorker.post('fullTests', ['{"nbsp":true, "esp":true, "unit":true, "num":true}']);
+ xPromise.then(
+ function (aVal) {
+ console.log('Done.');
+ console.log(aVal);
+ },
+ function (aReason) { console.log('Promise rejected', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Promise Error', aCaught); }
+ );
+ },
+ test: function (sText) {
+ console.log("Test...");
+ let xPromise = this.xGCEWorker.post('parse', [sText, "FR", true]);
+ xPromise.then(
+ function (aVal) {
+ let lErr = JSON.parse(aVal);
+ if (lErr.length > 0) {
+ for (let dErr of lErr) {
+ console.log(text.getReadableError(dErr));
+ }
+ } else {
+ console.log("no error found");
+ }
+ },
+ function (aReason) { console.log('Promise rejected', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Promise Error', aCaught); }
+ );
+ },
+ setOptions: function () {
+ console.log('Set options');
+ let xPromise = this.xGCEWorker.post('setOptions', [prefs.getCharPref("sGCOptions")]);
+ xPromise.then(
+ function (aVal) {
+ console.log(aVal);
+ prefs.setCharPref("sGCOptions", aVal);
+ },
+ function (aReason) { console.log('Promise rejected', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Promise Error', aCaught); }
+ );
+ },
+ resetOptions: function () {
+ let xPromise = this.xGCEWorker.post('resetOptions');
+ xPromise.then(
+ function (aVal) {
+ console.log(aVal);
+ prefs.setCharPref("sGCOptions", aVal);
+ },
+ function (aReason) { console.log('Promise rejected', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Promise Error', aCaught); }
+ );
+ },
+ parse: async function () {
+ this.clearPreview();
+ this.openPanel();
+ this.setInfo("Analyse en cours…");
+ try {
+ let xEditor = new Editor();
+ let nParagraph = 0;
+ let bIsError = false;
+ for (let [iParagraph, sParagraph] of xEditor.getParagraphs()) {
+ if (sParagraph.trim() !== "") {
+ let sRes = await this.xGCEWorker.post('parseAndSpellcheck', [sParagraph, "FR", false, false]);
+ let oRes = JSON.parse(sRes);
+ if (oRes.aGrammErr.length > 0 || oRes.aSpellErr.length > 0) {
+ document.getElementById("grammalecte-errors").appendChild(this.createResultNode(xEditor, sParagraph, iParagraph, oRes.aGrammErr, oRes.aSpellErr));
+ bIsError = true;
+ }
+ nParagraph += 1;
+ }
+ }
+ if (bIsError === false) {
+ let xNodeP = document.createElement("p");
+ xNodeP.setAttribute("class", "message");
+ xNodeP.textContent = "Aucune erreur détectée…";
+ document.getElementById("grammalecte-errors").appendChild(xNodeP);
+ }
+ this.setInfo("Nombre de paragraphes analysés : " + nParagraph);
+ }
+ catch (e) {
+ this.setInfo("Erreur : " + e.message);
+ console.error(e);
+ }
+ },
+ createResultNode: function (xEditor, sParagraph, iParagraph, aGrammErr, aSpellErr) {
+ let xResultNode = document.createElement("div");
+ xResultNode.setAttribute("id", "resnode" + iParagraph);
+ this.fillResultNode(xResultNode, xEditor, sParagraph, iParagraph, aGrammErr, aSpellErr);
+ return xResultNode;
+ },
+ reparseParagraph: function (xEditor, iParagraph) {
+ try {
+ let that = this;
+ let xResultNode = document.getElementById("resnode"+iParagraph);
+ xResultNode.textContent = "…………… réanalyse en cours ……………";
+ let sParagraph = xEditor.getParagraph(iParagraph);
+ let xPromise = this.xGCEWorker.post('parseAndSpellcheck', [sParagraph, "FR", false, false]);
+ xPromise.then(function (res) {
+ xResultNode.textContent = "";
+ let oRes = JSON.parse(res);
+ if (oRes.aGrammErr.length > 0 || oRes.aSpellErr.length > 0) {
+ that.fillResultNode(xResultNode, xEditor, sParagraph, iParagraph, oRes.aGrammErr, oRes.aSpellErr);
+ }
+ }, function (res) {
+ xResultNode.textContent = "Erreur: " + res;
+ });
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ fillResultNode: function (xResultNode, xEditor, sParagraph, iParagraph, aGrammErr, aSpellErr) {
+ try {
+ if (aGrammErr.length === 0 && aSpellErr.length === 0) {
+ return null;
+ }
+ aGrammErr.push(...aSpellErr);
+ aGrammErr.sort(function (a, b) {
+ if (a["nStart"] < b["nStart"])
+ return -1;
+ if (a["nStart"] > b["nStart"])
+ return 1;
+ return 0;
+ });
+ let xParagraphNode = document.createElement("p");
+ let lNodeError = [];
+ let nEndLastErr = 0;
+ let nError = 1;
+ xParagraphNode.setAttribute("class", "paragraph");
+ for (let dErr of aGrammErr) {
+ let nStart = dErr["nStart"];
+ let nEnd = dErr["nEnd"];
+ if (nStart >= nEndLastErr) {
+ xParagraphNode.appendChild(document.createTextNode(this._purgeTags(sParagraph.slice(nEndLastErr, nStart))));
+ let xNodeError = document.createElement("b");
+ if (dErr['sType'] !== 'WORD') {
+ xNodeError.setAttribute("class", "error");
+ xNodeError.textContent = oConverterToExponent.convert(nError.toString()) + sParagraph.slice(nStart, nEnd);
+ xNodeError.style.backgroundColor = dErr["aColor"];
+ xParagraphNode.appendChild(xNodeError);
+ lNodeError.push(this._createNodeGCErrorDescription(xEditor, nError, dErr, iParagraph));
+ }
+ else {
+ xNodeError.setAttribute("class", "error spell");
+ xNodeError.textContent = oConverterToExponent.convert(nError.toString()) + sParagraph.slice(nStart, nEnd);
+ xParagraphNode.appendChild(xNodeError);
+ lNodeError.push(this._createNodeSpellErrorDescription(xEditor, nError, dErr, iParagraph));
+ }
+ nEndLastErr = nEnd;
+ nError += 1;
+ }
+ }
+ xParagraphNode.appendChild(document.createTextNode(this._purgeTags(sParagraph.slice(nEndLastErr))));
+ xResultNode.appendChild(xParagraphNode);
+ for (let xNode of lNodeError) {
+ xResultNode.appendChild(xNode);
+ }
+ }
+ catch (e) {
+ console.error(e);
+ xResultNode.textContent = "# Error: " + e.message;
+ }
+ },
+ _createNodeGCErrorDescription: function (xEditor, nError, dErr, iParagraph) {
+ let xNodeDiv = document.createElement("div");
+ let that = this;
+ // message
+ let xNodeMessage = document.createElement("p");
+ xNodeMessage.setAttribute("class", "message");
+ let xNodeErrorNumber = document.createElement("b");
+ xNodeErrorNumber.setAttribute("class", "errornum");
+ xNodeErrorNumber.textContent = "[" + nError + "] ";
+ xNodeMessage.appendChild(xNodeErrorNumber);
+ xNodeMessage.appendChild(document.createTextNode(" " + dErr["sMessage"].replace(/ /g, " ") + " "));
+ if (false) {
+ // debug info
+ let xNodeDebug = document.createElement("span");
+ xNodeDebug.setAttribute("class", "debug_info");
+ xNodeDebug.textContent = " #" + dErr["sRuleId"] + " #" + dErr["sLineId"];
+ xNodeMessage.appendChild(xNodeDebug);
+ }
+ xNodeDiv.appendChild(xNodeMessage);
+ // URL
+ if (dErr["URL"]) {
+ let xNodeP = document.createElement("p");
+ xNodeP.setAttribute("class", "moreinfo");
+ xNodeP.appendChild(document.createTextNode("→ "));
+ let xNodeURL = document.createElement("a");
+ xNodeURL.setAttribute("href", dErr["URL"]);
+ xNodeURL.textContent = "Plus d’informations…";
+ xNodeURL.addEventListener("click", function (e) {
+ that.openInTabURL(dErr["URL"]);
+ });
+ xNodeP.appendChild(xNodeURL);
+ xNodeDiv.appendChild(xNodeP);
+ }
+ // suggestions
+ if (dErr["aSuggestions"].length > 0) {
+ let xNodeSuggLine = document.createElement("p");
+ xNodeSuggLine.setAttribute("class", "suggestions");
+ xNodeSuggLine.textContent = "Suggestions : ";
+ let n = 0;
+ for (let sSugg of dErr["aSuggestions"]) {
+ if (n > 0) {
+ xNodeSuggLine.appendChild(document.createTextNode(" "));
+ }
+ let xNodeSugg = document.createElement("span");
+ xNodeSugg.setAttribute("class", "sugg");
+ xNodeSugg.textContent = sSugg.replace(" ", " "); // use nnbsp
+ xNodeSugg.addEventListener("click", function (e) {
+ xEditor.changeParagraph(iParagraph, sSugg, dErr["nStart"], dErr["nEnd"]);
+ xNodeDiv.textContent = "";
+ that.reparseParagraph(xEditor, iParagraph);
+ });
+ xNodeSuggLine.appendChild(xNodeSugg);
+ n += 1;
+ }
+ xNodeDiv.appendChild(xNodeSuggLine);
+ }
+ return xNodeDiv;
+ },
+ _purgeTags: function (sText) {
+ sText = sText.replace(/
/ig, " ");
+ sText = sText.replace(//g, "");
+ return sText.replace(/<\/? ?[a-zA-Z]+ ?>/g, "");
+ },
+ _createNodeSpellErrorDescription: function (xEditor, nError, dErr, iParagraph) {
+ let xNodeDiv = document.createElement("div");
+ let that = this;
+ // message
+ let xNodeMessage = document.createElement("p");
+ xNodeMessage.setAttribute("class", "message");
+ let xNodeErrorNumber = document.createElement("b");
+ xNodeErrorNumber.setAttribute("class", "errornum");
+ xNodeErrorNumber.textContent = "[" + nError + "] ";
+ xNodeMessage.appendChild(xNodeErrorNumber);
+ xNodeMessage.appendChild(document.createTextNode(" Mot inconnu du dictionnaire. "));
+ xNodeDiv.appendChild(xNodeMessage);
+ // suggestions
+ let xNodeSuggLine = document.createElement("p");
+ xNodeSuggLine.setAttribute("class", "suggestions");
+ let xNodeSuggButton = document.createElement("span");
+ xNodeSuggButton.setAttribute("class", "suggestions_button");
+ xNodeSuggButton.textContent = "Suggestions : ";
+ xNodeSuggButton.addEventListener("click", (e) => {
+ let xPromise = this.xGCEWorker.post('suggest', [dErr['sValue'], 10]);
+ xPromise.then(
+ function (sVal) {
+ if (sVal != "") {
+ let lSugg = sVal.split("|");
+ let n = 0;
+ for (let sSugg of lSugg) {
+ xNodeSuggLine.appendChild(document.createTextNode(" "));
+ let xNodeSugg = document.createElement("span");
+ xNodeSugg.setAttribute("class", "sugg");
+ xNodeSugg.textContent = sSugg;
+ xNodeSugg.addEventListener("click", function (e) {
+ xEditor.changeParagraph(iParagraph, xNodeSugg.textContent, dErr["nStart"], dErr["nEnd"]);
+ xNodeDiv.textContent = "";
+ that.reparseParagraph(xEditor, iParagraph);
+ });
+ xNodeSuggLine.appendChild(xNodeSugg);
+ n += 1;
+ }
+ } else {
+ xNodeSuggLine.appendChild(document.createTextNode("Aucune suggestion."));
+ }
+ },
+ function (aReason) { console.error('Promise rejected - ', aReason); }
+ ).catch(
+ function (aCaught) { console.error('Promise Error - ', aCaught); }
+ );
+ });
+ xNodeSuggLine.appendChild(xNodeSuggButton);
+ xNodeDiv.appendChild(xNodeSuggLine);
+ return xNodeDiv;
+ },
+ loadUI: function () {
+ this._strings = document.getElementById("grammarchecker-strings");
+ let that = this;
+ let nsGrammarCommand = {
+ isCommandEnabled: function (aCommand, dummy) {
+ return (IsDocumentEditable() && !IsInHTMLSourceMode());
+ },
+ getCommandStateParams: function (aCommand, aParams, aRefCon) {},
+ doCommandParams: function (aCommand, aParams, aRefCon) {},
+ doCommand: function (aCommand) {
+ that.onParseText(aCommand);
+ }
+ };
+ let xCommandTable = GetComposerCommandTable();
+ xCommandTable.registerCommand("cmd_grammar", nsGrammarCommand);
+ let sButtonId = "grammarchecker-toolbar-button";
+ let sButtonId2 = "grammalecte-menu";
+ let xNavBar = document.getElementById("composeToolbar2");
+ let lCurSet = xNavBar.currentSet.split(",");
+ if (lCurSet.indexOf(sButtonId) == -1) {
+ let iPos = lCurSet.indexOf("spellingButton") + 1 || lCurSet.length;
+ let aSet = lCurSet.slice(0, iPos).concat(sButtonId).concat(sButtonId2).concat(lCurSet.slice(iPos));
+ xNavBar.setAttribute("currentset", aSet.join(","));
+ //xNavBar.currentSet = aSet.join(",");
+ Services.xulStore.persist(xNavBar, "currentset");
+ Ci.BrowserToolboxCustomizeDone(true);
+ }
+ },
+ clearPreview: function () {
+ let xPreview = document.getElementById("grammalecte-errors");
+ while (xPreview.firstChild) {
+ xPreview.removeChild(xPreview.firstChild);
+ };
+ let xEditor = GetCurrentEditor();
+ if (xEditor != null) {
+ try {
+ xEditor.QueryInterface(Ci.nsIEditorStyleSheets);
+ xEditor.addOverrideStyleSheet("chrome://grammarchecker/content/overlay.css");
+ }
+ catch (e) {
+ console.error(e);
+ }
+ }
+ this.setInfo("[vide]");
+ },
+ setInfo: function (sText) {
+ document.getElementById("grammalecte-info").textContent = sText;
+ },
+ openPanel: function () {
+ document.getElementById("textformatter-splitter").setAttribute("state", "collapsed");
+ document.getElementById("grammarchecker-splitter").setAttribute("state", "open");
+ },
+ closePanel: function () {
+ document.getElementById("grammarchecker-splitter").setAttribute("state", "collapsed");
+ },
+ openDialog: function (sWhat, sName="", sOptions="") {
+ try {
+ window.openDialog(sWhat, sName, sOptions);
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ openInTabURL: function (sURL) {
+ // method found in S3.Google.Translator
+ try {
+ let xWM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+ let xWin = xWM.getMostRecentWindow("mail:3pane");
+ let xTabmail = xWin.document.getElementById('tabmail');
+ xWin.focus();
+ if (xTabmail) {
+ xTabmail.openTab('contentTab', { contentPage: sURL });
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ openInBrowserURL: function (sURL) {
+ // method found in S3.Google.Translator
+ try {
+ openURL(sURL);
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ onParseText: function (e) {
+ this.parse();
+ },
+ onClosePanel: function (e) {
+ this.closePanel();
+ },
+ onOpenGCOptions: function (e) {
+ let that = this;
+ let xPromise = this.xGCEWorker.post('getDefaultOptions');
+ xPromise.then(
+ function (aVal) {
+ console.log(aVal);
+ prefs.setCharPref("sGCDefaultOptions", aVal);
+ },
+ function (aReason) { console.log('Promise rejected', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Promise Error', aCaught); }
+ ).then(
+ function () {
+ that.openDialog("chrome://grammarchecker/content/gc_options.xul", "", "chrome, dialog, modal, resizable=no");
+ that.setOptions();
+ },
+ function (aReason) { console.log('Error options dialog', aReason); }
+ ).catch(
+ function (aCaught) { console.log('Error', aCaught); }
+ );
+ },
+ onOpenSpellOptions: function (e) {
+ this.openDialog("chrome://grammarchecker/content/spell_options.xul", "", "chrome, dialog, modal, resizable=no");
+ },
+ onOpenOptions: function (e) {
+ this.openDialog("chrome://grammarchecker/content/options.xul", "", "chrome, dialog, modal, resizable=no");
+ },
+ onOpenTextFormatter: function (e) {
+ oTextFormatter.openPanel();
+ },
+ onOpenConjugueur: function (e) {
+ this.openDialog("chrome://grammarchecker/content/conjugueur.xul", "", "chrome, resizable=no");
+ },
+ onOpenLexiconEditor: function (e) {
+ this.openDialog("chrome://grammarchecker/content/lex_editor.xul", "", "chrome, resizable=no");
+ },
+ onAbout: function (e) {
+ this.openDialog("chrome://grammarchecker/content/about.xul", "", "chrome, dialog, modal, resizable=no");
+ }
+};
+
+
+var oTextFormatter = {
+ init: function () {
+ try {
+ this.closePanel();
+ this.listen();
+ let sTFOptions = prefs.getCharPref("sTFOptions");
+ if (sTFOptions !== "") {
+ this.setOptionsInPanel(JSON.parse(sTFOptions));
+ this.resetProgressBar();
+ } else {
+ this.reset();
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ listen: function () {
+ window.addEventListener("click", (xEvent) => {
+ let xElem = xEvent.target;
+ if (xElem.id && xElem.id.startsWith("o_group_")) {
+ this.switchGroup(xElem.id);
+ this.resetProgressBar();
+ }
+ }, false);
+ },
+ apply: function () {
+ try {
+ this.saveOptions();
+ this.resetProgressBar();
+ let xEditor = new Editor();
+ let sText = xEditor.getContent();
+ let iParagraph = 0;
+ sText = this.applyOptions(sText);
+ for (let sParagraph of text.getParagraph(sText)) {
+ xEditor.writeParagraph(iParagraph, sParagraph);
+ iParagraph += 1;
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ saveOptions: function () {
+ let oOptions = {};
+ for (let xNode of document.getElementsByClassName("option")) {
+ oOptions[xNode.id] = xNode.checked;
+ }
+ //console.log("save options: " + JSON.stringify(oOptions));
+ prefs.setCharPref("sTFOptions", JSON.stringify(oOptions));
+ },
+ setOptionsInPanel: function (oOptions) {
+ for (let sOptName in oOptions) {
+ //console.log(sOptName + ":" + oOptions[sOptName]);
+ if (document.getElementById(sOptName) !== null) {
+ document.getElementById(sOptName).checked = oOptions[sOptName];
+ if (sOptName.startsWith("o_group_")) {
+ this.switchGroup(sOptName);
+ }
+ if (document.getElementById("res_"+sOptName) !== null) {
+ document.getElementById("res_"+sOptName).textContent = "";
+ }
+ }
+ }
+ },
+ switchGroup: function (sOptName) {
+ if (document.getElementById(sOptName).checked) {
+ document.getElementById(sOptName.slice(2)).style.opacity = 1;
+ } else {
+ document.getElementById(sOptName.slice(2)).style.opacity = 0.3;
+ }
+ },
+ reset: function () {
+ try {
+ this.resetProgressBar();
+ for (let xNode of document.getElementsByClassName('option')) {
+ xNode.checked = (xNode.getAttribute('data-default') === "true");
+ if (xNode.id.startsWith("o_group_")) {
+ this.switchGroup(xNode.id);
+ }
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ resetProgressBar: function () {
+ document.getElementById('textformatter-progressbar').value = 0;
+ document.getElementById('textformatter-timer').textContent = "";
+ },
+ getTimeRes: function (n) {
+ // returns duration in seconds as string
+ if (n < 10) {
+ return n.toFixed(3).toString() + " s";
+ }
+ if (n < 100) {
+ return n.toFixed(2).toString() + " s";
+ }
+ if (n < 1000) {
+ return n.toFixed(1).toString() + " s";
+ }
+ return n.toFixed().toString() + " s";
+ },
+ openPanel: function () {
+ document.getElementById("grammarchecker-splitter").setAttribute("state", "collapsed");
+ document.getElementById("textformatter-splitter").setAttribute("state", "open");
+ },
+ closePanel: function () {
+ document.getElementById("textformatter-splitter").setAttribute("state", "collapsed");
+ },
+ onOpenPanel: function (e) {
+ this.openPanel();
+ },
+ onClosePanel: function (e) {
+ this.closePanel();
+ },
+ onApply: function (e) {
+ this.apply();
+ },
+ onReset: function (e) {
+ this.reset();
+ },
+ //
+ applyOptions: function (sText) {
+ try {
+ const t0 = Date.now();
+ //window.setCursor("wait"); // change pointer
+ document.getElementById('textformatter-progressbar').value = 0;
+ document.getElementById('textformatter-progressbar').max = 6;
+ let n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0, n7 = 0;
+
+ // espaces surnuméraires
+ if (document.getElementById("o_group_ssp").checked) {
+ if (document.getElementById("o_end_of_paragraph").checked) {
+ [sText, n1] = this.formatText(sText, "end_of_paragraph");
+ document.getElementById('res_o_end_of_paragraph').textContent = n1;
+ }
+ if (document.getElementById("o_between_words").checked) {
+ [sText, n1] = this.formatText(sText, "between_words");
+ document.getElementById('res_o_between_words').textContent = n1;
+ }
+ if (document.getElementById("o_start_of_paragraph").checked) {
+ [sText, n1] = this.formatText(sText, "start_of_paragraph");
+ document.getElementById('res_o_start_of_paragraph').textContent = n1;
+ }
+ if (document.getElementById("o_before_punctuation").checked) {
+ [sText, n1] = this.formatText(sText, "before_punctuation");
+ document.getElementById('res_o_before_punctuation').textContent = n1;
+ }
+ if (document.getElementById("o_within_parenthesis").checked) {
+ [sText, n1] = this.formatText(sText, "within_parenthesis");
+ document.getElementById('res_o_within_parenthesis').textContent = n1;
+ }
+ if (document.getElementById("o_within_square_brackets").checked) {
+ [sText, n1] = this.formatText(sText, "within_square_brackets");
+ document.getElementById('res_o_within_square_brackets').textContent = n1;
+ }
+ if (document.getElementById("o_within_quotation_marks").checked) {
+ [sText, n1] = this.formatText(sText, "within_quotation_marks");
+ document.getElementById('res_o_within_quotation_marks').textContent = n1;
+ }
+ document.getElementById("o_group_ssp").checked = false;
+ this.switchGroup("o_group_ssp");
+ }
+ document.getElementById('textformatter-progressbar').value = 1;
+
+ // espaces insécables
+ if (document.getElementById("o_group_nbsp").checked) {
+ if (document.getElementById("o_nbsp_before_punctuation").checked) {
+ [sText, n1] = this.formatText(sText, "nbsp_before_punctuation");
+ [sText, n2] = this.formatText(sText, "nbsp_repair");
+ document.getElementById('res_o_nbsp_before_punctuation').textContent = n1 - n2;
+ }
+ if (document.getElementById("o_nbsp_within_quotation_marks").checked) {
+ [sText, n1] = this.formatText(sText, "nbsp_within_quotation_marks");
+ document.getElementById('res_o_nbsp_within_quotation_marks').textContent = n1;
+ }
+ if (document.getElementById("o_nbsp_before_symbol").checked) {
+ [sText, n1] = this.formatText(sText, "nbsp_before_symbol");
+ document.getElementById('res_o_nbsp_before_symbol').textContent = n1;
+ }
+ if (document.getElementById("o_nbsp_within_numbers").checked) {
+ [sText, n1] = this.formatText(sText, "nbsp_within_numbers");
+ document.getElementById('res_o_nbsp_within_numbers').textContent = n1;
+ }
+ if (document.getElementById("o_nbsp_before_units").checked) {
+ [sText, n1] = this.formatText(sText, "nbsp_before_units");
+ document.getElementById('res_o_nbsp_before_units').textContent = n1;
+ }
+ if (document.getElementById("o_nbsp_titles").checked) {
+ [sText, n1] = this.formatText(sText, "nbsp_titles");
+ document.getElementById('res_o_nbsp_titles').textContent = n1;
+ }
+ document.getElementById("o_group_nbsp").checked = false;
+ this.switchGroup("o_group_nbsp");
+ }
+ document.getElementById('textformatter-progressbar').value = 2;
+
+ // espaces manquants
+ if (document.getElementById("o_group_typo").checked) {
+ if (document.getElementById("o_ts_units").checked) {
+ [sText, n1] = this.formatText(sText, "ts_units");
+ document.getElementById('res_o_ts_units').textContent = n1;
+ }
+ }
+ if (document.getElementById("o_group_space").checked) {
+ if (document.getElementById("o_add_space_after_punctuation").checked) {
+ [sText, n1] = this.formatText(sText, "add_space_after_punctuation");
+ [sText, n2] = this.formatText(sText, "add_space_repair");
+ document.getElementById('res_o_add_space_after_punctuation').textContent = n1 - n2;
+ }
+ if (document.getElementById("o_add_space_around_hyphens").checked) {
+ [sText, n1] = this.formatText(sText, "add_space_around_hyphens");
+ document.getElementById('res_o_add_space_around_hyphens').textContent = n1;
+ }
+ document.getElementById("o_group_space").checked = false;
+ this.switchGroup("o_group_space");
+ }
+ document.getElementById('textformatter-progressbar').value = 3;
+
+ // suppression
+ if (document.getElementById("o_group_delete").checked) {
+ if (document.getElementById("o_erase_non_breaking_hyphens").checked) {
+ [sText, n1] = this.formatText(sText, "erase_non_breaking_hyphens");
+ document.getElementById('res_o_erase_non_breaking_hyphens').textContent = n1;
+ }
+ document.getElementById("o_group_delete").checked = false;
+ this.switchGroup("o_group_delete");
+ }
+ document.getElementById('textformatter-progressbar').value = 4;
+
+ // signes typographiques
+ if (document.getElementById("o_group_typo").checked) {
+ if (document.getElementById("o_ts_apostrophe").checked) {
+ [sText, n1] = this.formatText(sText, "ts_apostrophe");
+ document.getElementById('res_o_ts_apostrophe').textContent = n1;
+ }
+ if (document.getElementById("o_ts_ellipsis").checked) {
+ [sText, n1] = this.formatText(sText, "ts_ellipsis");
+ document.getElementById('res_o_ts_ellipsis').textContent = n1;
+ }
+ if (document.getElementById("o_ts_dash_start").checked) {
+ if (document.getElementById("o_ts_m_dash_start").checked) {
+ [sText, n1] = this.formatText(sText, "ts_m_dash_start");
+ } else {
+ [sText, n1] = this.formatText(sText, "ts_n_dash_start");
+ }
+ document.getElementById('res_o_ts_dash_start').textContent = n1;
+ }
+ if (document.getElementById("o_ts_dash_middle").checked) {
+ if (document.getElementById("o_ts_m_dash_middle").checked) {
+ [sText, n1] = this.formatText(sText, "ts_m_dash_middle");
+ } else {
+ [sText, n1] = this.formatText(sText, "ts_n_dash_middle");
+ }
+ document.getElementById('res_o_ts_dash_middle').textContent = n1;
+ }
+ if (document.getElementById("o_ts_quotation_marks").checked) {
+ [sText, n1] = this.formatText(sText, "ts_quotation_marks");
+ document.getElementById('res_o_ts_quotation_marks').textContent = n1;
+ }
+ if (document.getElementById("o_ts_spell").checked) {
+ [sText, n1] = this.formatText(sText, "ts_spell");
+ document.getElementById('res_o_ts_spell').textContent = n1;
+ }
+ if (document.getElementById("o_ts_ligature").checked) {
+ // ligatures typographiques : fi, fl, ff, ffi, ffl, ft, st
+ if (document.getElementById("o_ts_ligature_do").checked) {
+ if (document.getElementById("o_ts_ligature_ffi").checked) {
+ [sText, n1] = this.formatText(sText, "ts_ligature_ffi_do");
+ }
+ if (document.getElementById("o_ts_ligature_ffl").checked) {
+ [sText, n2] = this.formatText(sText, "ts_ligature_ffl_do");
+ }
+ if (document.getElementById("o_ts_ligature_fi").checked) {
+ [sText, n3] = this.formatText(sText, "ts_ligature_fi_do");
+ }
+ if (document.getElementById("o_ts_ligature_fl").checked) {
+ [sText, n4] = this.formatText(sText, "ts_ligature_fl_do");
+ }
+ if (document.getElementById("o_ts_ligature_ff").checked) {
+ [sText, n5] = this.formatText(sText, "ts_ligature_ff_do");
+ }
+ if (document.getElementById("o_ts_ligature_ft").checked) {
+ [sText, n6] = this.formatText(sText, "ts_ligature_ft_do");
+ }
+ if (document.getElementById("o_ts_ligature_st").checked) {
+ [sText, n7] = this.formatText(sText, "ts_ligature_st_do");
+ }
+ }
+ if (document.getElementById("o_ts_ligature_undo").checked) {
+ if (document.getElementById("o_ts_ligature_ffi").checked) {
+ [sText, n1] = this.formatText(sText, "ts_ligature_ffi_undo");
+ }
+ if (document.getElementById("o_ts_ligature_ffl").checked) {
+ [sText, n2] = this.formatText(sText, "ts_ligature_ffl_undo");
+ }
+ if (document.getElementById("o_ts_ligature_fi").checked) {
+ [sText, n3] = this.formatText(sText, "ts_ligature_fi_undo");
+ }
+ if (document.getElementById("o_ts_ligature_fl").checked) {
+ [sText, n4] = this.formatText(sText, "ts_ligature_fl_undo");
+ }
+ if (document.getElementById("o_ts_ligature_ff").checked) {
+ [sText, n5] = this.formatText(sText, "ts_ligature_ff_undo");
+ }
+ if (document.getElementById("o_ts_ligature_ft").checked) {
+ [sText, n6] = this.formatText(sText, "ts_ligature_ft_undo");
+ }
+ if (document.getElementById("o_ts_ligature_st").checked) {
+ [sText, n7] = this.formatText(sText, "ts_ligature_st_undo");
+ }
+ }
+ document.getElementById('res_o_ts_ligature').textContent = n1 + n2 + n3 + n4 + n5 + n6 + n7;
+ }
+ document.getElementById("o_group_typo").checked = false;
+ this.switchGroup("o_group_typo");
+ }
+ document.getElementById('textformatter-progressbar').value = 5;
+
+ // divers
+ if (document.getElementById("o_group_misc").checked) {
+ if (document.getElementById("o_ordinals_no_exponant").checked) {
+ if (document.getElementById("o_ordinals_exponant").checked) {
+ [sText, n1] = this.formatText(sText, "ordinals_exponant");
+ } else {
+ [sText, n1] = this.formatText(sText, "ordinals_no_exponant");
+ }
+ document.getElementById('res_o_ordinals_no_exponant').textContent = n1;
+ }
+ if (document.getElementById("o_etc").checked) {
+ [sText, n1] = this.formatText(sText, "etc");
+ document.getElementById('res_o_etc').textContent = n1;
+ }
+ if (document.getElementById("o_missing_hyphens").checked) {
+ [sText, n1] = this.formatText(sText, "missing_hyphens");
+ document.getElementById('res_o_missing_hyphens').textContent = n1;
+ }
+ if (document.getElementById("o_ma_word").checked) {
+ [sText, n1] = this.formatText(sText, "ma_word");
+ if (document.getElementById("o_ma_1letter_lowercase").checked) {
+ [sText, n1] = this.formatText(sText, "ma_1letter_lowercase");
+ if (document.getElementById("o_ma_1letter_uppercase").checked) {
+ [sText, n1] = this.formatText(sText, "ma_1letter_uppercase");
+ }
+ }
+ document.getElementById('res_o_ma_word').textContent = n1;
+ }
+ document.getElementById("o_group_misc").checked = false;
+ this.switchGroup("o_group_misc");
+ }
+ document.getElementById('textformatter-progressbar').value = document.getElementById('textformatter-progressbar').max;
+ document.getElementById('textformatter-progressbar').value = "Formatage terminé.";
+ // end of processing
+
+ //window.setCursor("auto"); // restore pointer
+ const t1 = Date.now();
+ document.getElementById('textformatter-timer').textContent = this.getTimeRes((t1-t0)/1000);
+ }
+ catch (e) {
+ console.error(e);
+ }
+ return sText;
+ },
+ formatText: function (sText, sOptName) {
+ let nCount = 0;
+ try {
+ if (!oReplTable.hasOwnProperty(sOptName)) {
+ console.log("# Error. TF: there is no option “" + sOptName+ "”.");
+ return [sText, nCount];
+ }
+ for (let [zRgx, sRep] of oReplTable[sOptName]) {
+ nCount += (sText.match(zRgx) || []).length;
+ sText = sText.replace(zRgx, sRep);
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+ return [sText, nCount];
+ }
+}
+
+
+/* EVENTS */
+
+window.addEventListener("load", function (xEvent) {
+ oGrammarChecker.loadGC();
+ //oGrammarChecker.fullTests();
+}, false);
+
+window.addEventListener("compose-window-init", function (xEvent) {
+ oGrammarChecker.loadUI();
+ oGrammarChecker.closePanel();
+ oGrammarChecker.clearPreview();
+ oTextFormatter.init();
+}, true);
ADDED gc_lang/fr/mailext/content/overlay.xul
Index: gc_lang/fr/mailext/content/overlay.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/overlay.xul
@@ -0,0 +1,377 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &tf_infomsg;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/spell_options.css
Index: gc_lang/fr/mailext/content/spell_options.css
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/spell_options.css
@@ -0,0 +1,36 @@
+/* CSS */
+
+#grouptitle {
+ font-size: 16px;
+ font-weight: bold;
+ color: hsl(0, 50%, 50%);
+}
+
+.option {
+ font-size: 16px;
+ font-weight: bold;
+ color: hsl(210, 50%, 50%);
+}
+
+description {
+ width: 340px;
+}
+
+.dicdescr {
+ margin-left: 27px;
+}
+
+.disabled {
+ opacity: .25;
+}
+
+
+.dialogheader-title {
+ margin: 5px;
+ padding: 5px 8px;
+ border: 1px solid hsl(210, 50%, 80%);
+ background-color: hsl(210, 50%, 50%);
+ color: hsl(210, 10%, 90%);
+ font-size: larger;
+ font-weight: bold;
+}
ADDED gc_lang/fr/mailext/content/spell_options.js
Index: gc_lang/fr/mailext/content/spell_options.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/spell_options.js
@@ -0,0 +1,38 @@
+// JavaScript
+
+"use strict";
+
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+// const Cu = Components.utils;
+const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");
+
+
+var oDialogControl = {
+ load: function () {
+ try {
+ // center window
+ document.getElementById('grammalecte-spelloptions-window').centerWindowOnScreen();
+ // Graphspell dictionaries
+ document.getElementById('personal_dic').checked = prefs.getBoolPref('bPersonalDictionary');
+ this.listen();
+ }
+ catch (e) {
+ console.error(e);
+ }
+ },
+ listen: function () {
+ document.addEventListener("dialogaccept", (event) => {
+ oDialogControl.setDictionaries();
+ });
+ },
+ setDictionaries: function () {
+ oSpellControl.init();
+ this._setGraphspellDictionaries();
+ },
+ _setGraphspellDictionaries: function () {
+ let bActivate = document.getElementById('personal_dic').checked;
+ prefs.setBoolPref("bPersonalDictionary", bActivate);
+ }
+};
ADDED gc_lang/fr/mailext/content/spell_options.xul
Index: gc_lang/fr/mailext/content/spell_options.xul
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/spell_options.xul
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/content/spellchecker.js
Index: gc_lang/fr/mailext/content/spellchecker.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/content/spellchecker.js
@@ -0,0 +1,144 @@
+// JavaScript
+
+/*
+ Hunspell wrapper
+
+ XPCOM obsolete (?), but there is nothing else...
+ Overly complicated and weird. To throw away ASAP if possible.
+
+ And you can’t access to this from a PromiseWorker (it sucks).
+
+ https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/mozISpellCheckingEngine
+ https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Using_spell_checking_in_XUL
+ https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile
+ https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/FileUtils.jsm
+*/
+
+"use strict";
+
+
+const { FileUtils } = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
+const { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
+
+
+var oSpellControl = {
+ xSCEngine: null,
+ init: function () {
+ if (this.xSCEngine === null) {
+ try {
+ let sSpellchecker = "@mozilla.org/spellchecker/myspell;1";
+ if ("@mozilla.org/spellchecker/hunspell;1" in Cc) {
+ sSpellchecker = "@mozilla.org/spellchecker/hunspell;1";
+ }
+ if ("@mozilla.org/spellchecker/engine;1" in Cc) {
+ sSpellchecker = "@mozilla.org/spellchecker/engine;1";
+ }
+ this.xSCEngine = Cc[sSpellchecker].getService(Ci.mozISpellCheckingEngine);
+ }
+ catch (e) {
+ console.log("Can’t initiate the spellchecker.");
+ console.error(e);
+ }
+ }
+ },
+ getDictionariesList: function () {
+ this.init();
+ try {
+ let l = {};
+ let c = {};
+ this.xSCEngine.getDictionaryList(l, c);
+ return l.value;
+ }
+ catch (e) {
+ console.error(e);
+ return [];
+ }
+ },
+ setDictionary: function (sLocale) {
+ if (this.getDictionariesList().includes(sLocale)) {
+ try {
+ this.xSCEngine.dictionary = sLocale; // en-US, fr, etc.
+ return true;
+ }
+ catch (e) {
+ console.error(e);
+ return false;
+ }
+ } else {
+ console.log("Warning. No dictionary for locale: " + sLocale);
+ console.log("Existing dictionaries: " + this.getDictionariesList().join(" | "));
+ }
+ return false;
+ },
+ check: function (sWord) {
+ // todo: check in personal dict?
+ try {
+ return this.xSCEngine.check(sWord);
+ }
+ catch (e) {
+ console.error(e);
+ return false;
+ }
+ },
+ suggest: function (sWord) {
+ try {
+ let lSugg = {};
+ this.xSCEngine.suggest(sWord, lSugg, {});
+ return lSugg.value;
+ // lSugg.value is a JavaScript Array of strings
+ }
+ catch (e) {
+ console.error(e);
+ return ['#Erreur.'];
+ }
+ },
+ addDirectory: function (sFolder) {
+ try {
+ let xNsiFolder = new FileUtils.File(sFolder);
+ this.xSCEngine.addDirectory(xNsiFolder);
+ }
+ catch (e) {
+ console.log("Unable to add directory: " + sFolder);
+ console.error(e);
+ }
+ },
+ removeDirectory: function (sFolder) {
+ // does not work but no exception raised (bug?)
+ try {
+ let xNsiFolder = new FileUtils.File(sFolder);
+ this.xSCEngine.removeDirectory(xNsiFolder);
+ }
+ catch (e) {
+ console.log("Unable to remove directory: " + sFolder);
+ console.error(e);
+ }
+ },
+ setExtensionDictFolder: function (sDictName, bActivate) {
+ try {
+ let that = this;
+ let sPath = "/content/dictionaries/" + sDictName;
+ AddonManager.getAddonByID("French-GC-TB@grammalecte.net")
+ .then(function (xAddon) {
+ let xURI = xAddon.getResourceURI(sPath);
+ //console.log(xURI);
+ let sFolder = xURI.filePath;
+ if (sFolder !== undefined) {
+ if (/^\/[A-Z]:\//.test(sFolder)) {
+ // Windows path
+ sFolder = sFolder.slice(1).replace(/\//g, "\\\\");
+ }
+ console.log("folder: " + sFolder);
+ if (bActivate) {
+ that.addDirectory(sFolder);
+ } else {
+ that.removeDirectory(sFolder);
+ }
+ }
+ });
+ }
+ catch (e) {
+ console.log("Unable to add extension folder");
+ console.error(e);
+ }
+ }
+};
ADDED gc_lang/fr/mailext/defaults/preferences/grammarchecker.js
Index: gc_lang/fr/mailext/defaults/preferences/grammarchecker.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/defaults/preferences/grammarchecker.js
@@ -0,0 +1,10 @@
+pref("extensions.grammarchecker.sGCOptions", "");
+pref("extensions.grammarchecker.sTFOptions", "");
+pref("extensions.grammarchecker.bDictModern", false);
+pref("extensions.grammarchecker.bDictClassic", true);
+pref("extensions.grammarchecker.bDictReform", false);
+pref("extensions.grammarchecker.bDictClassicReform", false);
+pref("extensions.grammarchecker.bCheckSignature", true);
+pref("extensions.grammarchecker.bExtendedDictionary", false);
+pref("extensions.grammarchecker.bCommunityDictionary", false);
+pref("extensions.grammarchecker.bPersonalDictionary", true);
ADDED gc_lang/fr/mailext/gce_worker.js
Index: gc_lang/fr/mailext/gce_worker.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/gce_worker.js
@@ -0,0 +1,428 @@
+/*
+ WORKER:
+ https://developer.mozilla.org/en-US/docs/Web/API/Worker
+ https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope
+
+
+ JavaScript sucks.
+ No module available in WebExtension at the moment! :(
+ No require, no import/export.
+
+ In Worker, we have importScripts() which imports everything in this scope.
+
+ In order to use the same base of code with XUL-addon for Thunderbird and SDK-addon for Firefox,
+ all modules have been “objectified”. And while they are still imported via “require”
+ in the previous extensions, they are loaded as background scripts in WebExtension sharing
+ the same memory space…
+
+ When JavaScript become a modern language, “deobjectify” the modules…
+
+ ATM, import/export are not available by default:
+ — Chrome 60 – behind the Experimental Web Platform flag in chrome:flags.
+ — Firefox 54 – behind the dom.moduleScripts.enabled setting in about:config.
+ — Edge 15 – behind the Experimental JavaScript Features setting in about:flags.
+
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
+*/
+
+"use strict";
+
+
+//console.log("[Worker] GC Engine Worker [start]");
+//console.log(self);
+
+importScripts("grammalecte/graphspell/helpers.js");
+importScripts("grammalecte/graphspell/str_transform.js");
+importScripts("grammalecte/graphspell/char_player.js");
+importScripts("grammalecte/graphspell/suggest.js");
+importScripts("grammalecte/graphspell/ibdawg.js");
+importScripts("grammalecte/graphspell/spellchecker.js");
+importScripts("grammalecte/text.js");
+importScripts("grammalecte/graphspell/tokenizer.js");
+importScripts("grammalecte/fr/conj.js");
+importScripts("grammalecte/fr/mfsp.js");
+importScripts("grammalecte/fr/phonet.js");
+importScripts("grammalecte/fr/cregex.js");
+importScripts("grammalecte/fr/gc_options.js");
+importScripts("grammalecte/fr/gc_rules.js");
+importScripts("grammalecte/fr/gc_rules_graph.js");
+importScripts("grammalecte/fr/gc_engine.js");
+importScripts("grammalecte/fr/lexicographe.js");
+importScripts("grammalecte/tests.js");
+/*
+ Warning.
+ Initialization can’t be completed at startup of the worker,
+ for we need the path of the extension to load data stored in JSON files.
+ This path is retrieved in background.js and passed with the event “init”.
+*/
+
+
+function createResponse (sActionDone, result, dInfo, bEnd, bError=false) {
+ return {
+ "sActionDone": sActionDone,
+ "result": result, // can be of any type
+ "dInfo": dInfo,
+ "bEnd": bEnd,
+ "bError": bError
+ };
+}
+
+function createErrorResult (e, sDescr="no description") {
+ return {
+ "sType": "error",
+ "sDescription": sDescr,
+ "sMessage": e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message
+ };
+}
+
+function showData (e) {
+ for (let sParam in e) {
+ console.log(sParam);
+ console.log(e[sParam]);
+ }
+}
+
+
+/*
+ Message Event Object
+ https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
+*/
+onmessage = function (e) {
+ let {sCommand, dParam, dInfo} = e.data;
+ switch (sCommand) {
+ case "init":
+ init(dParam.sExtensionPath, dParam.dOptions, dParam.sContext, dInfo);
+ break;
+ case "parse":
+ parse(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
+ break;
+ case "parseAndSpellcheck":
+ parseAndSpellcheck(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
+ break;
+ case "parseAndSpellcheck1":
+ parseAndSpellcheck1(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
+ break;
+ case "parseFull":
+ parseFull(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
+ break;
+ case "getListOfTokens":
+ getListOfTokens(dParam.sText, dInfo);
+ break;
+ case "getOptions":
+ getOptions(dInfo);
+ break;
+ case "getDefaultOptions":
+ getDefaultOptions(dInfo);
+ break;
+ case "setOptions":
+ setOptions(dParam.sOptions, dInfo);
+ break;
+ case "setOption":
+ setOption(dParam.sOptName, dParam.bValue, dInfo);
+ break;
+ case "resetOptions":
+ resetOptions(dInfo);
+ break;
+ case "textToTest":
+ textToTest(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
+ break;
+ case "fullTests":
+ fullTests(dInfo);
+ break;
+ case "setDictionary":
+ setDictionary(dParam.sDictionary, dParam.oDict, dInfo);
+ break;
+ case "setDictionaryOnOff":
+ setDictionaryOnOff(dParam.sDictionary, dParam.bActivate, dInfo);
+ break;
+ case "getSpellSuggestions":
+ getSpellSuggestions(dParam.sWord, dInfo);
+ break;
+ case "getVerb":
+ getVerb(dParam.sVerb, dParam.bPro, dParam.bNeg, dParam.bTpsCo, dParam.bInt, dParam.bFem, dInfo);
+ break;
+ default:
+ console.log("[Worker] Unknown command: " + sCommand);
+ showData(e.data);
+ }
+}
+
+
+
+let bInitDone = false;
+
+let oSpellChecker = null;
+let oTokenizer = null;
+let oLxg = null;
+let oTest = null;
+let oLocution = null;
+
+
+/*
+ Technical note:
+ This worker don’t work as a PromiseWorker (which returns a promise), so when we send request
+ to this worker, we can’t wait the return of the answer just after the request made.
+ The answer is received by the background in another function (onmessage).
+ That’s why the full text to analyze is send in one block, but analyse is returned paragraph
+ by paragraph.
+*/
+
+function init (sExtensionPath, dOptions=null, sContext="JavaScript", dInfo={}) {
+ try {
+ if (!bInitDone) {
+ console.log("[Worker] Loading… Extension path: " + sExtensionPath);
+ conj.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/conj_data.json"));
+ phonet.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/phonet_data.json"));
+ mfsp.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/mfsp_data.json"));
+ //console.log("[Worker] Modules have been initialized…");
+ gc_engine.load(sContext, "sCSS", sExtensionPath+"grammalecte/graphspell/_dictionaries");
+ oSpellChecker = gc_engine.getSpellChecker();
+ oTest = new TestGrammarChecking(gc_engine, sExtensionPath+"/grammalecte/fr/tests_data.json");
+ oTokenizer = new Tokenizer("fr");
+ oLocution = helpers.loadFile(sExtensionPath + "/grammalecte/fr/locutions_data.json");
+ oLxg = new Lexicographe(oSpellChecker, oTokenizer, oLocution);
+ if (dOptions !== null) {
+ if (!(dOptions instanceof Map)) {
+ dOptions = helpers.objectToMap(dOptions);
+ }
+ gc_engine.setOptions(dOptions);
+ }
+ //tests();
+ bInitDone = true;
+ } else {
+ console.log("[Worker] Already initialized…")
+ }
+ // we always retrieve options from the gc_engine, for setOptions filters obsolete options
+ dOptions = helpers.mapToObject(gc_engine.getOptions());
+ postMessage(createResponse("init", dOptions, dInfo, true));
+ }
+ catch (e) {
+ console.error(e);
+ postMessage(createResponse("init", createErrorResult(e, "init failed"), dInfo, true, true));
+ }
+}
+
+
+function parse (sText, sCountry, bDebug, bContext, dInfo={}) {
+ sText = sText.replace(//g, "").normalize("NFC");
+ for (let sParagraph of text.getParagraph(sText)) {
+ let aGrammErr = gc_engine.parse(sParagraph, sCountry, bDebug, bContext);
+ postMessage(createResponse("parse", aGrammErr, dInfo, false));
+ }
+ postMessage(createResponse("parse", null, dInfo, true));
+}
+
+function parseAndSpellcheck (sText, sCountry, bDebug, bContext, dInfo={}) {
+ let i = 0;
+ sText = sText.replace(//g, "").normalize("NFC");
+ for (let sParagraph of text.getParagraph(sText)) {
+ let aGrammErr = gc_engine.parse(sParagraph, sCountry, bDebug, null, bContext);
+ let aSpellErr = oSpellChecker.parseParagraph(sParagraph);
+ postMessage(createResponse("parseAndSpellcheck", {sParagraph: sParagraph, iParaNum: i, aGrammErr: aGrammErr, aSpellErr: aSpellErr}, dInfo, false));
+ i += 1;
+ }
+ postMessage(createResponse("parseAndSpellcheck", null, dInfo, true));
+}
+
+function parseAndSpellcheck1 (sParagraph, sCountry, bDebug, bContext, dInfo={}) {
+ sParagraph = sParagraph.replace(//g, "").normalize("NFC");
+ let aGrammErr = gc_engine.parse(sParagraph, sCountry, bDebug, null, bContext);
+ let aSpellErr = oSpellChecker.parseParagraph(sParagraph);
+ postMessage(createResponse("parseAndSpellcheck1", {sParagraph: sParagraph, aGrammErr: aGrammErr, aSpellErr: aSpellErr}, dInfo, true));
+}
+
+function parseFull (sText, sCountry, bDebug, bContext, dInfo={}) {
+ let i = 0;
+ sText = sText.replace(//g, "").normalize("NFC");
+ for (let sParagraph of text.getParagraph(sText)) {
+ let lSentence = gc_engine.parse(sParagraph, sCountry, bDebug, null, bContext, true);
+ console.log("*", lSentence);
+ postMessage(createResponse("parseFull", {sParagraph: sParagraph, iParaNum: i, lSentence: lSentence}, dInfo, false));
+ i += 1;
+ }
+ postMessage(createResponse("parseFull", null, dInfo, true));
+}
+
+function getListOfTokens (sText, dInfo={}) {
+ // lexicographer
+ try {
+ sText = sText.replace(//g, "").normalize("NFC");
+ for (let sParagraph of text.getParagraph(sText)) {
+ if (sParagraph.trim() !== "") {
+ postMessage(createResponse("getListOfTokens", oLxg.getListOfTokensReduc(sParagraph, true), dInfo, false));
+ }
+ }
+ postMessage(createResponse("getListOfTokens", null, dInfo, true));
+ }
+ catch (e) {
+ console.error(e);
+ postMessage(createResponse("getListOfTokens", createErrorResult(e, "no tokens"), dInfo, true, true));
+ }
+}
+
+function getOptions (dInfo={}) {
+ let dOptions = helpers.mapToObject(gc_engine.getOptions());
+ postMessage(createResponse("getOptions", dOptions, dInfo, true));
+}
+
+function getDefaultOptions (dInfo={}) {
+ let dOptions = helpers.mapToObject(gc_engine.getDefaultOptions());
+ postMessage(createResponse("getDefaultOptions", dOptions, dInfo, true));
+}
+
+function setOptions (dOptions, dInfo={}) {
+ if (!(dOptions instanceof Map)) {
+ dOptions = helpers.objectToMap(dOptions);
+ }
+ gc_engine.setOptions(dOptions);
+ dOptions = helpers.mapToObject(gc_engine.getOptions());
+ postMessage(createResponse("setOptions", dOptions, dInfo, true));
+}
+
+function setOption (sOptName, bValue, dInfo={}) {
+ console.log(sOptName+": "+bValue);
+ if (sOptName) {
+ gc_engine.setOption(sOptName, bValue);
+ let dOptions = helpers.mapToObject(gc_engine.getOptions());
+ postMessage(createResponse("setOption", dOptions, dInfo, true));
+ }
+}
+
+function resetOptions (dInfo={}) {
+ gc_engine.resetOptions();
+ let dOptions = helpers.mapToObject(gc_engine.getOptions());
+ postMessage(createResponse("resetOptions", dOptions, dInfo, true));
+}
+
+function tests () {
+ console.log(conj.getConj("devenir", ":E", ":2s"));
+ console.log(mfsp.getMasForm("emmerdeuse", true));
+ console.log(mfsp.getMasForm("pointilleuse", false));
+ console.log(phonet.getSimil("est"));
+ let aRes = gc_engine.parse("Je suit...");
+ for (let oErr of aRes) {
+ console.log(text.getReadableError(oErr));
+ }
+}
+
+function textToTest (sText, sCountry, bDebug, bContext, dInfo={}) {
+ if (!gc_engine) {
+ postMessage(createResponse("textToTest", "# Grammar checker not loaded.", dInfo, true));
+ return;
+ }
+ sText = sText.replace(//g, "").normalize("NFC");
+ let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
+ let sMsg = "";
+ for (let oErr of aGrammErr) {
+ sMsg += text.getReadableError(oErr) + "\n";
+ }
+ if (sMsg == "") {
+ sMsg = "Aucune erreur détectée.";
+ }
+ postMessage(createResponse("textToTest", sMsg, dInfo, true));
+}
+
+function fullTests (dInfo={}) {
+ if (!gc_engine) {
+ postMessage(createResponse("fullTests", "# Grammar checker not loaded.", dInfo, true));
+ return;
+ }
+ let dMemoOptions = gc_engine.getOptions();
+ let dTestOptions = gc_engine.getDefaultOptions();
+ dTestOptions.set("nbsp", true);
+ dTestOptions.set("esp", true);
+ dTestOptions.set("unit", true);
+ dTestOptions.set("num", true);
+ gc_engine.setOptions(dTestOptions);
+ let sMsg = "";
+ for (let sRes of oTest.testParse()) {
+ sMsg += sRes + "\n";
+ console.log(sRes);
+ }
+ gc_engine.setOptions(dMemoOptions);
+ postMessage(createResponse("fullTests", sMsg, dInfo, true));
+}
+
+
+// SpellChecker
+
+function setDictionary (sDictionary, oDict, dInfo) {
+ if (!oSpellChecker) {
+ postMessage(createResponse("setDictionary", "# Error. SpellChecker not loaded.", dInfo, true));
+ 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;
+ case "personal":
+ if (bActivate) {
+ oSpellChecker.activatePersonalDictionary();
+ } else {
+ oSpellChecker.deactivatePersonalDictionary();
+ }
+ break;
+ default:
+ console.log("[worker] setDictionaryOnOff: Unknown dictionary <"+sDictionary+">");
+ }
+ postMessage(createResponse("setDictionaryOnOff", true, dInfo, true));
+}
+
+function getSpellSuggestions (sWord, dInfo) {
+ if (!oSpellChecker) {
+ postMessage(createResponse("getSpellSuggestions", "# Error. SpellChecker not loaded.", dInfo, true));
+ return;
+ }
+ let i = 0;
+ for (let aSugg of oSpellChecker.suggest(sWord)) {
+ postMessage(createResponse("getSpellSuggestions", {sWord: sWord, aSugg: aSugg, iSuggBlock: i}, dInfo, true));
+ i += 1;
+ }
+}
+
+
+// Conjugueur
+
+function getVerb (sWord, bPro, bNeg, bTpsCo, bInt, bFem, dInfo) {
+ try {
+ let oVerb = null;
+ let oConjTable = null;
+ if (conj.isVerb(sWord)) {
+ oVerb = new Verb(sWord);
+ oConjTable = oVerb.createConjTable(bPro, bNeg, bTpsCo, bInt, bFem);
+ }
+ postMessage(createResponse("getVerb", { oVerb: oVerb, oConjTable: oConjTable }, dInfo, true));
+ }
+ catch (e) {
+ console.error(e);
+ postMessage(createResponse("getVerb", createErrorResult(e, "no verb"), dInfo, true, true));
+ }
+}
ADDED gc_lang/fr/mailext/icon.png
Index: gc_lang/fr/mailext/icon.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/icon.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/locale/en/about.dtd
Index: gc_lang/fr/mailext/locale/en/about.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/about.dtd
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/en/gc_options.dtd
Index: gc_lang/fr/mailext/locale/en/gc_options.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/gc_options.dtd
@@ -0,0 +1,4 @@
+
+
+
+${gc_options_labels_en}
ADDED gc_lang/fr/mailext/locale/en/grammarchecker.properties
Index: gc_lang/fr/mailext/locale/en/grammarchecker.properties
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/grammarchecker.properties
@@ -0,0 +1,3 @@
+processingMessage=Parsing in progress…
+errorMessage=Error…
+noErrorMessage=No error detected.
ADDED gc_lang/fr/mailext/locale/en/lex_editor.dtd
Index: gc_lang/fr/mailext/locale/en/lex_editor.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/lex_editor.dtd
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/en/options.dtd
Index: gc_lang/fr/mailext/locale/en/options.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/options.dtd
@@ -0,0 +1,6 @@
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/en/overlay.dtd
Index: gc_lang/fr/mailext/locale/en/overlay.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/overlay.dtd
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/en/spell_options.dtd
Index: gc_lang/fr/mailext/locale/en/spell_options.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/en/spell_options.dtd
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/fr/about.dtd
Index: gc_lang/fr/mailext/locale/fr/about.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/about.dtd
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/fr/gc_options.dtd
Index: gc_lang/fr/mailext/locale/fr/gc_options.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/gc_options.dtd
@@ -0,0 +1,4 @@
+
+
+
+${gc_options_labels_fr}
ADDED gc_lang/fr/mailext/locale/fr/grammarchecker.properties
Index: gc_lang/fr/mailext/locale/fr/grammarchecker.properties
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/grammarchecker.properties
@@ -0,0 +1,3 @@
+processingMessage=Analyse en cours
+errorMessage=Erreur…
+noErrorMessage=Aucune erreur détectée.
ADDED gc_lang/fr/mailext/locale/fr/lex_editor.dtd
Index: gc_lang/fr/mailext/locale/fr/lex_editor.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/lex_editor.dtd
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/fr/options.dtd
Index: gc_lang/fr/mailext/locale/fr/options.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/options.dtd
@@ -0,0 +1,4 @@
+
+
+
+
ADDED gc_lang/fr/mailext/locale/fr/overlay.dtd
Index: gc_lang/fr/mailext/locale/fr/overlay.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/overlay.dtd
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/locale/fr/spell_options.dtd
Index: gc_lang/fr/mailext/locale/fr/spell_options.dtd
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/locale/fr/spell_options.dtd
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ADDED gc_lang/fr/mailext/manifest.json
Index: gc_lang/fr/mailext/manifest.json
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/manifest.json
@@ -0,0 +1,21 @@
+{
+ "manifest_version": 2,
+ "applications": {
+ "gecko": {
+ "id": "${tb_identifier}",
+ "strict_min_version": "68.0a1"
+ }
+ },
+ "name": "${tb_name}",
+ "description": "${description}",
+ "version": "${version}",
+
+ "author": "${author}",
+ "homepage_url": "${link}",
+
+
+
+ "legacy": {
+ "type": "xul"
+ }
+}
ADDED gc_lang/fr/mailext/skin/Algoo_logo.png
Index: gc_lang/fr/mailext/skin/Algoo_logo.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/Algoo_logo.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/LaMouette_small.png
Index: gc_lang/fr/mailext/skin/LaMouette_small.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/LaMouette_small.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/grammarcheck.png
Index: gc_lang/fr/mailext/skin/grammarcheck.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/grammarcheck.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/grammarcheck_disabled.png
Index: gc_lang/fr/mailext/skin/grammarcheck_disabled.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/grammarcheck_disabled.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/grammarcheck_small.png
Index: gc_lang/fr/mailext/skin/grammarcheck_small.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/grammarcheck_small.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/grammarcheck_small_disabled.png
Index: gc_lang/fr/mailext/skin/grammarcheck_small_disabled.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/grammarcheck_small_disabled.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/logo100.png
Index: gc_lang/fr/mailext/skin/logo100.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/logo100.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/skin/logo120_text.png
Index: gc_lang/fr/mailext/skin/logo120_text.png
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/skin/logo120_text.png
cannot compute difference between binary files
ADDED gc_lang/fr/mailext/worker/gce_worker.js
Index: gc_lang/fr/mailext/worker/gce_worker.js
==================================================================
--- /dev/null
+++ gc_lang/fr/mailext/worker/gce_worker.js
@@ -0,0 +1,160 @@
+// JavaScript
+
+// Grammar checker engine
+// PromiseWorker
+// This code is executed in a separate thread (×20 faster too!!!)
+
+// Firefox WTF: it’s impossible to use require as in the main thread here,
+// so it is required to declare a resource in the file “chrome.manifest”.
+
+
+"use strict";
+
+// copy/paste
+// https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/PromiseWorker.jsm
+
+importScripts("resource://gre/modules/workers/require.js");
+let PromiseWorker = require("resource://gre/modules/workers/PromiseWorker.js");
+
+// Instantiate AbstractWorker (see below).
+let worker = new PromiseWorker.AbstractWorker();
+
+worker.dispatch = function(method, args = []) {
+ // Dispatch a call to method `method` with args `args`
+ return self[method](...args);
+};
+worker.postMessage = function(...args) {
+ // Post a message to the main thread
+ self.postMessage(...args);
+};
+worker.close = function() {
+ // Close the worker
+ self.close();
+};
+worker.log = function(...args) {
+ // Log (or discard) messages (optional)
+ dump("Worker: " + args.join(" ") + "\n");
+};
+
+// Connect it to message port.
+self.addEventListener("message", msg => worker.handleMessage(msg));
+
+// end of copy/paste
+
+
+// no console here, use “dump”
+
+let gce = null; // module: grammar checker engine
+let text = null;
+let tkz = null; // module: tokenizer
+let lxg = null; // module: lexicographer
+let helpers = null;
+
+let oTokenizer = null;
+let oSpellChecker = null;
+let oLxg = null;
+
+function loadGrammarChecker (sGCOptions="", sContext="JavaScript") {
+ if (gce === null) {
+ try {
+ gce = require("resource://grammalecte/fr/gc_engine.js");
+ helpers = require("resource://grammalecte/graphspell/helpers.js");
+ text = require("resource://grammalecte/text.js");
+ tkz = require("resource://grammalecte/graphspell/tokenizer.js");
+ //lxg = require("resource://grammalecte/fr/lexicographe.js");
+ oTokenizer = new tkz.Tokenizer("fr");
+ gce.load(sContext, "sCSS");
+ oSpellChecker = gce.getSpellChecker();
+ if (sGCOptions !== "") {
+ gce.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
+ }
+ // we always retrieve options from the gce, for setOptions filters obsolete options
+ return gce.getOptions().gl_toString();
+ }
+ catch (e) {
+ console.log("# Error: " + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
+ }
+ }
+}
+
+function setDictionary (sTypeDic, sDicJSON) {
+ try {
+ console.log("set dictionary: " + sTypeDic);
+ let oJSON = JSON.parse(sDicJSON);
+ switch (sTypeDic) {
+ case "extended":
+ break;
+ case "community":
+ break;
+ case "personal":
+ oSpellChecker.setPersonalDictionary(oJSON);
+ break;
+ default:
+ console.log("[GCE worker] unknown dictionary type");
+ }
+ }
+ catch (e) {
+ console.error(e);
+ }
+}
+
+function parse (sText, sCountry, bDebug, bContext) {
+ let aGrammErr = gce.parse(sText, sCountry, bDebug, bContext);
+ return JSON.stringify(aGrammErr);
+}
+
+function parseAndSpellcheck (sText, sCountry, bDebug, bContext) {
+ let aGrammErr = gce.parse(sText, sCountry, bDebug, null, bContext);
+ let aSpellErr = oSpellChecker.parseParagraph(sText);
+ return JSON.stringify({ aGrammErr: aGrammErr, aSpellErr: aSpellErr });
+}
+
+function suggest (sWord, nSuggLimit=10) {
+ let lSugg = []
+ for (let aSugg of oSpellChecker.suggest(sWord, nSuggLimit)) {
+ lSugg.push(...aSugg);
+ }
+ return lSugg.join("|");
+}
+
+function getOptions () {
+ return gce.getOptions().gl_toString();
+}
+
+function getDefaultOptions () {
+ return gce.getDefaultOptions().gl_toString();
+}
+
+function setOptions (sGCOptions) {
+ gce.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
+ return gce.getOptions().gl_toString();
+}
+
+function setOption (sOptName, bValue) {
+ gce.setOptions(new Map([ [sOptName, bValue] ]));
+ return gce.getOptions().gl_toString();
+}
+
+function resetOptions () {
+ gce.resetOptions();
+ return gce.getOptions().gl_toString();
+}
+
+function fullTests (sGCOptions="") {
+ if (!gce || !oSpellChecker) {
+ return "# Error: grammar checker or dictionary not loaded."
+ }
+ let dMemoOptions = gce.getOptions();
+ if (sGCOptions) {
+ gce.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
+ }
+ let tests = require("resource://grammalecte/tests.js");
+ let oTest = new tests.TestGrammarChecking(gce);
+ let sAllRes = "";
+ for (let sRes of oTest.testParse()) {
+ console.log(sRes+"\n");
+ sAllRes += sRes+"\n";
+ }
+ gce.setOptions(dMemoOptions);
+ return sAllRes;
+}
Index: helpers.py
==================================================================
--- helpers.py
+++ helpers.py
@@ -34,11 +34,11 @@
if os.path.isdir(spInstall):
eraseFolder(spInstall)
with zipfile.ZipFile(spfZip) as hZip:
hZip.extractall(spDest)
else:
- print("# folder not found")
+ print("# folder <" + spDest + "> not found")
else:
print("path destination is empty")
def eraseFolder (sp):
@@ -94,9 +94,9 @@
spfDst = (spDst + "/" + sf).strip("/ ")
if os.path.isdir(spfSrc):
if bRecursive:
addFolderToZipAndFileFile(hZip, spfSrc, spfDst, dVars, bRecursive)
else:
- if spfSrc.endswith((".py", ".js", ".css", ".xcu", ".xul", ".rdf", ".dtd", ".properties")):
+ if spfSrc.endswith((".py", ".js", ".json", ".css", ".xcu", ".xul", ".rdf", ".dtd", ".properties")):
hZip.writestr(spfDst, fileFile(spfSrc, dVars))
else:
hZip.write(spfSrc, spfDst)
Index: make.py
==================================================================
--- make.py
+++ make.py
@@ -288,11 +288,11 @@
try:
buildjs = importlib.import_module("gc_lang."+sLang+".build")
except ImportError:
print("# No complementary builder in folder gc_lang/"+sLang)
else:
- buildjs.build(sLang, dVars, spLangPack)
+ buildjs.build(sLang, dVars)
return dVars['version']
def copyGraphspellCore (bJavaScript=False):