Index: compile_rules.py ================================================================== --- compile_rules.py +++ compile_rules.py @@ -449,11 +449,11 @@ del lRule[-1] # tGroups positioning codes are useless for Python # error messages for aAction in lRuleJS[6]: if aAction[1] == "-": aAction[2] = aAction[2].replace(" ", " ") # nbsp --> nnbsp - aAction[4] = aAction[4].replace("« ", "« ").replace(" »", " »") + aAction[4] = aAction[4].replace("« ", "« ").replace(" »", " »") # js regexes lRuleJS[1], lNegLookBehindRegex = regex2js( dJSREGEXES.get(lRuleJS[3], lRuleJS[1]) ) lRuleJS.append(lNegLookBehindRegex) return lRuleJS Index: gc_core/js/helpers.js ================================================================== --- gc_core/js/helpers.js +++ gc_core/js/helpers.js @@ -30,10 +30,19 @@ } else { console.error(sMsg); } } +function inspect (o) { + let sMsg = "__inspect__: " + typeof o; + for (let sParam in o) { + sMsg += "\n" + sParam + ": " + o.sParam; + } + sMsg += "\n" + JSON.stringify(o) + "\n__end__"; + echo(sMsg); +} + // load ressources in workers (suggested by Mozilla extensions reviewers) // for more options have a look here: https://gist.github.com/Noitidart/ec1e6b9a593ec7e3efed // if not in workers, use sdk/data.load() instead function loadFile (spf) { @@ -78,11 +87,12 @@ obj[k] = v; } return obj; } +exports.setLogOutput = setLogOutput; exports.echo = echo; exports.logerror = logerror; +exports.inspect = inspect; exports.objectToMap = objectToMap; exports.mapToObject = mapToObject; -exports.setLogOutput = setLogOutput; exports.loadFile = loadFile; Index: gc_core/js/text.js ================================================================== --- gc_core/js/text.js +++ gc_core/js/text.js @@ -37,19 +37,20 @@ } function getReadableError (oErr) { // Returns an error oErr as a readable error try { - let s = "\n* " + oErr['nStart'] + ":" + oErr['nEnd'] + " # " + oErr['sRuleId']+":\n"; - s += " " + oErr["sMessage"]; + let sResult = "\n* " + oErr['nStart'] + ":" + oErr['nEnd'] + + " # " + oErr['sLineId'] + " # " + oErr['sRuleId'] + ":\n"; + sResult += " " + oErr["sMessage"]; if (oErr["aSuggestions"].length > 0) { - s += "\n > Suggestions : " + oErr["aSuggestions"].join(" | "); + sResult += "\n > Suggestions : " + oErr["aSuggestions"].join(" | "); } if (oErr["URL"] !== "") { - s += "\n > URL: " + oErr["URL"]; + sResult += "\n > URL: " + oErr["URL"]; } - return s; + return sResult; } catch (e) { helpers.logerror(e); return "\n# Error. Data: " + oErr.toString(); } Index: gc_core/js/tokenizer.js ================================================================== --- gc_core/js/tokenizer.js +++ gc_core/js/tokenizer.js @@ -3,17 +3,16 @@ "use strict"; const helpers = require("resource://grammalecte/helpers.js"); - const aPatterns = { // All regexps must start with ^. "default": [ [/^[   \t]+/, 'SPACE'], - [/^[,.;:!?…«»“”"()/·]+/, 'SEPARATOR'], + [/^[,.;:!?…«»“”‘’"(){}\[\]/·–—]+/, 'SEPARATOR'], [/^(?:https?:\/\/|www[.]|[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.])[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_.\/?&!%=+*"'@$#-]+/, 'LINK'], [/^[#@][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_-]+/, 'TAG'], [/^<[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+.*?>|<\/[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+ *>/, 'HTML'], [/^\[\/?[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+\]/, 'PSEUDOHTML'], [/^&\w+;(?:\w+;|)/, 'HTMLENTITY'], @@ -22,19 +21,19 @@ [/^[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+(?:[’'`-][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+)*/, 'WORD'] ], "fr": [ [/^[   \t]+/, 'SPACE'], - [/^[,.;:!?…«»“”"()/·]+/, 'SEPARATOR'], + [/^[,.;:!?…«»“”‘’"(){}\[\]/·–—]+/, 'SEPARATOR'], [/^(?:https?:\/\/|www[.]|[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_]+[@.])[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_.\/?&!%=+*"'@$#-]+/, 'LINK'], [/^[#@][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st_-]+/, 'TAG'], [/^<[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+.*?>|<\/[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+ *>/, 'HTML'], [/^\[\/?[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+\]/, 'PSEUDOHTML'], [/^&\w+;(?:\w+;|)/, 'HTMLENTITY'], [/^(?:l|d|n|m|t|s|j|c|ç|lorsqu|puisqu|jusqu|quoiqu|qu)['’`]/i, 'ELPFX'], [/^\d\d?[hm]\d\d\b/, 'HOUR'], - [/^\d+(?:er|nd|e|de|ième|ème|eme)\b/, 'ORDINAL'], + [/^\d+(?:er|nd|e|de|ième|ème|eme)s?\b/, 'ORDINAL'], [/^-?\d+(?:[.,]\d+|)/, 'NUM'], [/^[a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+(?:[’'`-][a-zA-Zà-öÀ-Ö0-9ø-ÿØ-ßĀ-ʯfi-st]+)*/, 'WORD'] ] } @@ -44,11 +43,11 @@ constructor (sLang) { this.sLang = sLang; if (!aPatterns.hasOwnProperty(sLang)) { this.sLang = "default"; } - this.aRules = aPatterns[sLang]; + this.aRules = aPatterns[this.sLang]; }; * genTokens (sText) { let m; let i = 0; @@ -55,11 +54,17 @@ while (sText) { let nCut = 1; for (let [zRegex, sType] of this.aRules) { try { if ((m = zRegex.exec(sText)) !== null) { - yield { "sType": sType, "sValue": m[0], "nStart": i, "nEnd": i + m[0].length } + if (sType == 'SEPARATOR') { + for (let c of m[0]) { + yield { "sType": sType, "sValue": c, "nStart": i, "nEnd": i + m[0].length } + } + } else { + yield { "sType": sType, "sValue": m[0], "nStart": i, "nEnd": i + m[0].length } + } nCut = m[0].length; break; } } catch (e) { @@ -67,9 +72,19 @@ } } i += nCut; sText = sText.slice(nCut); } + }; + + getSpellingErrors (sText, oDict) { + let aSpellErr = []; + for (let oToken of this.genTokens(sText)) { + if (oToken.sType === 'WORD' && !oDict.isValidToken(oToken.sValue)) { + aSpellErr.push(oToken); + } + } + return aSpellErr; } } exports.Tokenizer = Tokenizer; Index: gc_lang/fr/config.ini ================================================================== --- gc_lang/fr/config.ini +++ gc_lang/fr/config.ini @@ -3,11 +3,11 @@ lang_name = French locales = fr_FR fr_BE fr_CA fr_CH fr_LU fr_MC fr_BF fr_CI fr_SN fr_ML fr_NE fr_TG fr_BJ country_default = FR name = Grammalecte implname = grammalecte -version = 0.5.17.2 +version = 0.5.18 author = Olivier R. provider = Dicollecte link = http://grammalecte.net description = Correcteur grammatical pour le français. extras = README_fr.txt Index: gc_lang/fr/modules-js/lexicographe.js ================================================================== --- gc_lang/fr/modules-js/lexicographe.js +++ gc_lang/fr/modules-js/lexicographe.js @@ -2,13 +2,15 @@ // License: MPL 2 "use strict"; ${string} +${map} const helpers = require("resource://grammalecte/helpers.js"); +const tkz = require("resource://grammalecte/tokenizer.js"); const _dTAGS = new Map ([ [':G', "[mot grammatical]"], [':N', " nom,"], @@ -155,10 +157,42 @@ ["m'en", " (me) pronom personnel objet + (en) pronom adverbial"], ["t'en", " (te) pronom personnel objet + (en) pronom adverbial"], ["s'en", " (se) pronom personnel objet + (en) pronom adverbial"] ]); +const _dSeparator = new Map ([ + ['.', "point"], + ['·', "point médian"], + ['…', "points de suspension"], + [':', "deux-points"], + [';', "point-virgule"], + [',', "virgule"], + ['?', "point d’interrogation"], + ['!', "point d’exclamation"], + ['(', "parenthèse ouvrante"], + [')', "parenthèse fermante"], + ['[', "crochet ouvrante"], + [']', "crochet fermante"], + ['{', "accolade ouvrante"], + ['}', "accolade fermante"], + ['-', "tiret"], + ['—', "tiret cadratin"], + ['–', "tiret demi-cadratin"], + ['«', "guillemet ouvrant (chevrons)"], + ['»', "guillemet fermant (chevrons)"], + ['“', "guillemet ouvrant double"], + ['”', "guillemet fermant double"], + ['‘', "guillemet ouvrant"], + ['’', "guillemet fermant"], + ['/', "signe de la division"], + ['+', "signe de l’addition"], + ['*', "signe de la multiplication"], + ['=', "signe de l’égalité"], + ['<', "inférieur à"], + ['>', "supérieur à"], +]); + class Lexicographe { constructor (oDict) { this.oDict = oDict; @@ -165,71 +199,58 @@ this._zElidedPrefix = new RegExp ("^([dljmtsncç]|quoiqu|lorsqu|jusqu|puisqu|qu)['’](.+)", "i"); this._zCompoundWord = new RegExp ("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)-((?:les?|la)-(?:moi|toi|lui|[nv]ous|leur)|t-(?:il|elle|on)|y|en|[mts][’'](?:y|en)|les?|l[aà]|[mt]oi|leur|lui|je|tu|ils?|elles?|on|[nv]ous)$", "i"); this._zTag = new RegExp ("[:;/][a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ*][^:;/]*", "g"); }; - analyzeText (sText) { - sText = sText.replace(/[.,.?!:;…\/()\[\]“”«»"„{}–—#+*<>%=\n]/g, " ").replace(/\s+/g, " "); - let iStart = 0; - let iEnd = 0; - let sHtml = '
\n'; - while ((iEnd = sText.indexOf(" ", iStart)) !== -1) { - sHtml += this.analyzeWord(sText.slice(iStart, iEnd)); - iStart = iEnd + 1; - } - sHtml += this.analyzeWord(sText.slice(iStart)); - return sHtml + '
\n'; - } - - analyzeWord (sWord) { + getInfoForToken (oToken) { + // Token: .sType, .sValue, .nStart, .nEnd + // return a list [type, token_string, values] + let m = null; try { - if (!sWord) { - return ""; - } - if (sWord._count("-") > 4) { - return '

' + sWord + " : élément complexe indéterminé

\n"; - } - if (sWord._isDigit()) { - return '

' + sWord + " : nombre

\n"; - } - - let sHtml = ""; - // préfixes élidés - let m = this._zElidedPrefix.exec(sWord); - if (m !== null) { - sWord = m[2]; - sHtml += "

" + m[1] + "’ : " + _dPFX.get(m[1].toLowerCase()) + "

\n"; - } - // mots composés - let m2 = this._zCompoundWord.exec(sWord); - if (m2 !== null) { - sWord = m2[1]; - } - // Morphologies - let lMorph = this.oDict.getMorph(sWord); - if (lMorph.length === 1) { - sHtml += "

" + sWord + " : " + this.formatTags(lMorph[0]) + "

\n"; - } else if (lMorph.length > 1) { - sHtml += "

" + sWord + "

\n"; - } else { - sHtml += '

' + sWord + " : absent du dictionnaire

\n"; - } - // suffixe d’un mot composé - if (m2) { - sHtml += "

-" + m2[2] + " : " + this._formatSuffix(m2[2].toLowerCase()) + "

\n"; - } - // Verbes - //let aVerb = new Set([ for (s of lMorph) if (s.includes(":V")) s.slice(1, s.indexOf(" ")) ]); - return sHtml; + switch (oToken.sType) { + case 'SEPARATOR': + return { sType: oToken.sType, sValue: oToken.sValue, aLabel: [_dSeparator._get(oToken.sValue, "caractère indéterminé")] }; + break; + case 'NUM': + return { sType: oToken.sType, sValue: oToken.sValue, aLabel: ["nombre"] }; + break; + case 'LINK': + return { sType: oToken.sType, sValue: oToken.sValue.slice(0,40)+"…", aLabel: ["hyperlien"] }; + break; + case 'ELPFX': + let sTemp = oToken.sValue.replace("’", "").replace("'", "").replace("`", "").toLowerCase(); + return { sType: oToken.sType, sValue: oToken.sValue, aLabel: [_dPFX._get(sTemp, "préfixe élidé inconnu")] }; + break; + case 'WORD': + if (oToken.sValue._count("-") > 4) { + return { sType: "COMPLEX", sValue: oToken.sValue, aLabel: ["élément complexe indéterminé"] }; + } + else if (this.oDict.isValidToken(oToken.sValue)) { + let lMorph = this.oDict.getMorph(oToken.sValue); + let aElem = [ for (s of lMorph) if (s.includes(":")) this._formatTags(s) ]; + return { sType: oToken.sType, sValue: oToken.sValue, aLabel: aElem}; + } + else if (m = this._zCompoundWord.exec(oToken.sValue)) { + // mots composés + let lMorph = this.oDict.getMorph(m[1]); + let aElem = [ for (s of lMorph) if (s.includes(":")) this._formatTags(s) ]; + aElem.push("-" + m[2] + ": " + this._formatSuffix(m[2].toLowerCase())); + return { sType: oToken.sType, sValue: oToken.sValue, aLabel: aElem }; + } + else { + return { sType: "UNKNOWN", sValue: oToken.sValue, aLabel: ["inconnu du dictionnaire"] }; + } + break; + } } catch (e) { helpers.logerror(e); - return "#erreur"; } + return null; }; - formatTags (sTags) { + _formatTags (sTags) { let sRes = ""; sTags = sTags.replace(/V([0-3][ea]?)[itpqnmr_eaxz]+/, "V$1"); let m; while ((m = this._zTag.exec(sTags)) !== null) { sRes += _dTAGS.get(m[0]); Index: gc_lang/fr/xpi/data/gc_panel.css ================================================================== --- gc_lang/fr/xpi/data/gc_panel.css +++ gc_lang/fr/xpi/data/gc_panel.css @@ -73,10 +73,14 @@ } #errorlist p.green { background-color: hsla(120, 10%, 50%, 1); color: hsla(120, 0%, 96%, 1); } + +.paragraph_block { + margin: 0 0 30px 0; +} .paragraph { background-color: hsla(0, 0%, 90%, 1); padding: 10px; border-radius: 2px; @@ -266,16 +270,16 @@ background-color: hsl(240, 10%, 40%); color: hsl(240, 0%, 100%); } /* elems */ -.spell { +.WORD { background-color: hsl(0, 50%, 50%); color: hsl(0, 0%, 96%); /*text-decoration: underline wavy hsl(0, 50%, 50%);*/ } -.spell:hover { +.WORD:hover { background-color: hsl(0, 60%, 40%); color: hsl(0, 0%, 100%); } /* elems */ Index: gc_lang/fr/xpi/data/gc_panel.js ================================================================== --- gc_lang/fr/xpi/data/gc_panel.js +++ gc_lang/fr/xpi/data/gc_panel.js @@ -5,18 +5,11 @@ /* Events */ -if (Date.now() < Date.UTC(2017, 6, 12)) { - try { - document.getElementById('special_message').style.display = "block"; - document.getElementById('errorlist').style.padding = "20px 20px 30px 20px"; - } catch (e) { - console.log(e.message + e.lineNumber); - } -} +showSpecialMessage(); document.getElementById('close').addEventListener("click", function (event) { bExpanded = true; // size is reset in ui.js self.port.emit('closePanel'); @@ -42,20 +35,20 @@ self.port.on("setPanelWidth", function (n) { nPanelWidth = n; }); -self.port.on("addElem", function (sHtml) { - let xElem = document.createElement("div"); - xElem.innerHTML = sHtml; - document.getElementById("errorlist").appendChild(xElem); +self.port.on("addMessage", function (sClass, sText) { + addMessage(sClass, sText); +}); + +self.port.on("addParagraph", function (sText, iParagraph, sJSON) { + addParagraph(sText, iParagraph, sJSON); }); -self.port.on("refreshParagraph", function (sIdParagr, sHtml) { - document.getElementById("paragr"+sIdParagr).innerHTML = sHtml; - let sClassName = (sHtml.includes('' + sSugg + ' '; - iSugg += 1; - } - } + setSpellSuggestionsFor(sWord, sSuggestions, sTooltipId); }); window.addEventListener( "click", @@ -127,10 +106,196 @@ /* Actions */ + +function showError (e) { + console.error("\n" + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); +} + +function addMessage (sClass, sText) { + let xNode = document.createElement("p"); + xNode.className = sClass; + xNode.textContent = sText; + document.getElementById("errorlist").appendChild(xNode); +} + +function addParagraph (sText, iParagraph, sJSON) { + try { + let xNodeDiv = document.createElement("div"); + xNodeDiv.className = "paragraph_block"; + // paragraph + let xParagraph = document.createElement("p"); + xParagraph.id = "paragr" + iParagraph.toString(); + xParagraph.lang = "fr"; + xParagraph.setAttribute("spellcheck", false); + let oErrors = JSON.parse(sJSON); + xParagraph.className = (oErrors.aGrammErr.length || oErrors.aSpellErr.length) ? "paragraph softred" : "paragraph"; + _tagParagraph(sText, xParagraph, iParagraph, oErrors.aGrammErr, oErrors.aSpellErr); + xNodeDiv.appendChild(xParagraph); + // actions + let xDivActions = document.createElement("div"); + xDivActions.className = "actions"; + let xDivClose = document.createElement("div"); + xDivClose.id = "end" + iParagraph.toString(); + xDivClose.className = "button red"; + xDivClose.textContent = "×"; + let xDivEdit = document.createElement("div"); + xDivEdit.id = "edit" + iParagraph.toString(); + xDivEdit.className = "button"; + xDivEdit.textContent = "Éditer"; + let xDivCheck = document.createElement("div"); + xDivCheck.id = "check" + iParagraph.toString(); + xDivCheck.className = "button green"; + xDivCheck.textContent = "Réanalyser"; + xDivActions.appendChild(xDivClose); + xDivActions.appendChild(xDivEdit); + xDivActions.appendChild(xDivCheck); + xNodeDiv.appendChild(xDivActions); + document.getElementById("errorlist").appendChild(xNodeDiv); + } + catch (e) { + showError(e); + } +} + +function refreshParagraph (sText, sIdParagr, sJSON) { + try { + let xParagraph = document.getElementById("paragr"+sIdParagr); + let oErrors = JSON.parse(sJSON); + xParagraph.className = (oErrors.aGrammErr.length || oErrors.aSpellErr.length) ? "paragraph softred" : "paragraph softgreen"; + xParagraph.textContent = ""; + _tagParagraph(sText, xParagraph, sIdParagr, oErrors.aGrammErr, oErrors.aSpellErr); + } + catch (e) { + showError(e); + } +} + +function _tagParagraph (sParagraph, xParagraph, iParagraph, aSpellErr, aGrammErr) { + try { + if (aGrammErr.length === 0 && aSpellErr.length === 0) { + xParagraph.textContent = sParagraph; + return + } + 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 nErr = 0; // we count errors to give them an identifier + let nEndLastErr = 0; + for (let oErr of aGrammErr) { + let nStart = oErr["nStart"]; + let nEnd = oErr["nEnd"]; + if (nStart >= nEndLastErr) { + oErr["sId"] = iParagraph.toString() + "_" + nErr.toString(); // error identifier + if (nEndLastErr < nStart) { + xParagraph.appendChild(document.createTextNode(sParagraph.slice(nEndLastErr, nStart))); + } + xParagraph.appendChild(_createError(sParagraph.slice(nStart, nEnd), oErr)); + xParagraph.insertAdjacentHTML("beforeend", ""); + nEndLastErr = nEnd; + } + nErr += 1; + } + if (nEndLastErr < sParagraph.length) { + xParagraph.appendChild(document.createTextNode(sParagraph.slice(nEndLastErr))); + } + } + catch (e) { + showError(e); + } +} + +function _createError (sUnderlined, oErr) { + let xNodeErr = document.createElement("u"); + xNodeErr.id = "err" + oErr['sId']; + xNodeErr.className = "error " + oErr['sType']; + xNodeErr.textContent = sUnderlined; + xNodeErr.setAttribute("href", "#"); + xNodeErr.setAttribute("onclick", "return false;"); + let xTooltip = (oErr['sType'] !== "WORD") ? _getGrammarTooltip(oErr) : _getSpellingTooltip(oErr); + xNodeErr.appendChild(xTooltip); + return xNodeErr; +} + +function _getGrammarTooltip (oErr) { + let xSpan = document.createElement("span"); + xSpan.id = "tooltip" + oErr['sId']; + xSpan.className = "tooltip"; + xSpan.setAttribute("contenteditable", false); + xSpan.appendChild(document.createTextNode(oErr["sMessage"]+" ")); + xSpan.appendChild(_createIgnoreButton(oErr["sId"])); + if (oErr["URL"] !== "") { + xSpan.appendChild(_createInfoLink(oErr["URL"])); + } + if (oErr["aSuggestions"].length > 0) { + xSpan.appendChild(document.createElement("br")); + xSpan.appendChild(_createSuggestionLabel()); + xSpan.appendChild(document.createElement("br")); + let iSugg = 0; + for (let sSugg of oErr["aSuggestions"]) { + xSpan.appendChild(_createSuggestion(oErr["sId"], iSugg, sSugg)); + xSpan.appendChild(document.createTextNode(" ")); + iSugg += 1; + } + } + return xSpan; +} + +function _getSpellingTooltip (oErr) { + let xSpan = document.createElement("span"); + xSpan.id = "tooltip" + oErr['sId']; + xSpan.className = "tooltip"; + xSpan.setAttribute("contenteditable", "false"); + xSpan.appendChild(document.createTextNode("Mot inconnu du dictionnaire. ")); + xSpan.appendChild(_createIgnoreButton(oErr["sId"])); + xSpan.appendChild(document.createElement("br")); + xSpan.appendChild(_createSuggestionLabel()); + xSpan.appendChild(document.createElement("br")); + return xSpan; +} + +function _createIgnoreButton (sErrorId) { + let xIgnore = document.createElement("a"); + xIgnore.id = "ignore" + sErrorId; + xIgnore.className = "ignore"; + xIgnore.setAttribute("href", "#"); + xIgnore.setAttribute("onclick", "return false;"); + xIgnore.textContent = "IGNORER"; + return xIgnore; +} + +function _createInfoLink (sURL) { + let xInfo = document.createElement("a"); + xInfo.setAttribute("href", sURL); + xInfo.setAttribute("onclick", "return false;"); + xInfo.textContent = "Infos…"; + return xInfo; +} + +function _createSuggestionLabel () { + let xNode = document.createElement("s"); + xNode.textContent = "Suggestions :"; + return xNode; +} + +function _createSuggestion (sErrId, iSugg, sSugg) { + let xNodeSugg = document.createElement("a"); + xNodeSugg.id = "sugg" + sErrId + "-" + iSugg.toString(); + xNodeSugg.className = "sugg"; + xNodeSugg.setAttribute("href", "#"); + xNodeSugg.setAttribute("onclick", "return false;"); + xNodeSugg.textContent = sSugg; + return xNodeSugg; +} function closeMessageBox () { document.getElementById("messagebox").style.display = "none"; document.getElementById("message").textContent = ""; } @@ -143,12 +308,13 @@ document.getElementById(sIdErr).textContent = document.getElementById(sElemId).textContent; document.getElementById(sIdErr).className = "corrected"; document.getElementById(sIdErr).removeAttribute("style"); self.port.emit("correction", sIdParagr, getPurgedTextOfElem("paragr"+sIdParagr)); stopWaitIcon("paragr"+sIdParagr); - } catch (e) { - console.log(e.message + e.lineNumber); + } + catch (e) { + showError(e); } } function ignoreError (sElemId) { // ignore let sIdErr = "err" + sElemId.slice(6); @@ -166,11 +332,11 @@ if (document.getElementById(sElemId).offsetLeft > nLimit) { xTooltipElem.style.left = "-" + (document.getElementById(sElemId).offsetLeft - nLimit) + "px"; } xTooltipElem.setAttribute("contenteditable", false); xTooltipElem.className = 'tooltip_on'; - if (document.getElementById(sElemId).className === "error spell" && xTooltipElem.textContent.endsWith(":")) { + if (document.getElementById(sElemId).className === "error WORD" && xTooltipElem.textContent.endsWith(":")) { // spelling mistake self.port.emit("getSuggestionsForTo", document.getElementById(sElemId).innerHTML.replace(/"; + sAllRes += sRes+"\n"; } gce.setOptions(dMemoOptions); return sAllRes; } // Lexicographer -function analyzeWords (sText) { - return oLxg.analyzeText(sText); +function getListOfElements (sText) { + try { + let aElem = []; + let aRes = null; + for (let oToken of oTokenizer.genTokens(sText)) { + aRes = oLxg.getInfoForToken(oToken); + if (aRes) { + aElem.push(aRes); + } + } + return JSON.stringify(aElem); + } + catch (e) { + helpers.logerror(e); + } } Index: gc_lang/fr/xpi/package.json ================================================================== --- gc_lang/fr/xpi/package.json +++ gc_lang/fr/xpi/package.json @@ -1,10 +1,10 @@ { "name": "grammalecte-fr", "title": "Grammalecte [fr]", "id": "French-GC@grammalecte.net", - "version": "0.5.17.2", + "version": "0.5.18", "description": "Correcteur grammatical pour le français", "homepage": "http://www.dicollecte.org/grammalecte", "main": "ui.js", "icon": "data/img/icon-48.png", "scripts": { Index: gc_lang/fr/xpi/ui.js ================================================================== --- gc_lang/fr/xpi/ui.js +++ gc_lang/fr/xpi/ui.js @@ -347,14 +347,15 @@ } return true; } function checkAndSendToPanel (sIdParagraph, sText) { - let xPromise = xGCEWorker.post('parseAndTag', [sText, parseInt(sIdParagraph), "FR", false]); + let xPromise = xGCEWorker.post('parseAndSpellcheck', [sText, "FR", false, false]); xPromise.then( function (aVal) { - xGCPanel.port.emit("refreshParagraph", sIdParagraph, aVal); + sText = text.addHtmlEntities(sText); + xGCPanel.port.emit("refreshParagraph", sText, sIdParagraph, aVal); }, function (aReason) { console.error('Promise rejected - ', aReason); } ).catch( @@ -416,20 +417,20 @@ let sRes = ""; try { sText = sText.normalize("NFC"); // remove combining diacritics for (let sParagraph of text.getParagraph(sText)) { if (sParagraph.trim() !== "") { - sRes = await xGCEWorker.post('parseAndGenerateParagraph', [sParagraph, iParagraph, "FR", false]) - xGCPanel.port.emit("addElem", sRes); + sRes = await xGCEWorker.post('parseAndSpellcheck', [sParagraph, "FR", false, false]); + xGCPanel.port.emit("addParagraph", sParagraph, iParagraph, sRes); nParagraph += 1; } iParagraph += 1; } - xGCPanel.port.emit("addElem", '

' + _("numberOfParagraphs") + " " + nParagraph + '

'); + xGCPanel.port.emit("addMessage", 'message', _("numberOfParagraphs") + " " + nParagraph); } catch (e) { - xGCPanel.port.emit("addElem", '

' + e.message + '

'); + xGCPanel.port.emit("addMessage", 'bug', e.message); } xGCPanel.port.emit("end"); } @@ -569,19 +570,19 @@ let nParagraph = 0; // non empty paragraphs let sRes = ""; try { for (let sParagraph of text.getParagraph(sText)) { if (sParagraph.trim() !== "") { - sRes = await xGCEWorker.post('analyzeWords', [sParagraph]) - xLxgPanel.port.emit("addElem", sRes); + sRes = await xGCEWorker.post('getListOfElements', [sParagraph]); + xLxgPanel.port.emit("addParagraphElems", sRes); nParagraph += 1; } } - xLxgPanel.port.emit("addElem", '

' + _("numberOfParagraphs") + " " + nParagraph + '

'); + xLxgPanel.port.emit("addMessage", 'message', _("numberOfParagraphs") + " " + nParagraph); } catch (e) { - xLxgPanel.port.emit("addElem", '

'+e.message+"

"); + xLxgPanel.port.emit("addMessage", 'bug', e.message); } xLxgPanel.port.emit("stopWaitIcon"); }