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(" »", " »").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/lang_core/gc_engine.js ================================================================== --- gc_core/js/lang_core/gc_engine.js +++ gc_core/js/lang_core/gc_engine.js @@ -218,11 +218,11 @@ sMessage = oEvalFunc[sMsg.slice(1)](s, m) } else { sMessage = sMsg._expand(m); } if (bIdRule) { - sMessage += " #" + sLineId + " #" + sRuleId; + sMessage += " ##" + sLineId + " #" + sRuleId; } oErr["sMessage"] = sMessage; // URL oErr["URL"] = sURL || ""; // Context 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 @@ -5,19 +5,16 @@ header { background-color: hsl(0, 0%, 96%); padding: 10px 20px; border-bottom: 1px solid hsl(0, 0%, 90%); color: hsl(0, 0%, 0%); - z-index: 99; } - - body { - background-color: hsl(0, 0%, 98%); - font-family: Tahoma, "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", sans-serif; - overflow-x: hidden; + background-color: hsl(0, 0%, 98%); + font-family: Tahoma, "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", sans-serif; + overflow-x: hidden; color: hsl(0, 0%, 0%); } #special_message { display: none; @@ -50,16 +47,20 @@ border-radius: 5px; text-align: center; color: hsla(0, 0%, 100%, .9); font-size: 16px; font-weight: bold; - z-index: 99; } #message { padding: 10px 20px; } + +/* + Error list +*/ + #errorlist { padding: 60px 20px 30px 20px; } #errorlist p.message { @@ -69,14 +70,19 @@ font-size: 18px; color: hsla(240, 0%, 96%, 1); border-radius: 3px; text-align: center; } + #errorlist p.green { background-color: hsla(120, 10%, 50%, 1); color: hsla(120, 0%, 96%, 1); } + +.paragraph_block { + margin: 0 0 10px 0; +} .paragraph { background-color: hsla(0, 0%, 90%, 1); padding: 10px; border-radius: 2px; @@ -86,11 +92,11 @@ } .softred { background-color: hsla(0, 20%, 90%, 1); } .softgreen { - background-color: hsla(120, 20%, 90%, 1); + background-color: hsla(120, 15%, 90%, 1); } .paragraph a { background-color: hsla(210, 50%, 50%, 1); padding: 1px 5px; @@ -103,36 +109,12 @@ background-color: hsla(210, 60%, 40%, 1); color: hsla(0, 0%, 100%, 1); text-shadow: 0 0 3px hsl(210, 30%, 60%); } -.paragraph a.sugg { - padding: 1px 6px; - background-color: hsla(150, 50%, 40%, 1); - color: hsla(150, 0%, 96%, 1); - border-radius: 2px; - cursor: pointer; - text-decoration: none; -} -.paragraph a.sugg:hover { - background-color: hsla(150, 70%, 30%, 1); - color: hsla(0, 0%, 100%, 1); - text-shadow: 0 0 3px hsl(150, 30%, 60%); -} - -.paragraph a.ignore { - padding: 0 2px; - background-color: hsla(30, 20%, 60%, 1); - color: hsla(30, 0%, 96%, 1); - border-radius: 2px; - cursor: pointer; - text-decoration: none; -} -.paragraph a.ignore:hover { - background-color: hsla(30, 20%, 50%, 1); - color: hsla(0, 0%, 100%, 1); - text-shadow: 0 0 3px hsl(30, 30%, 60%); +.paragraph u { + text-decoration: none; } .paragraph u.corrected, .paragraph u.ignored { background-color: hsla(120, 50%, 70%, 1); @@ -152,62 +134,147 @@ } .paragraph u.error:hover { cursor: pointer; } -.paragraph u.error .tooltip, .paragraph u.error .tooltip_on { - position: absolute; - background-color: hsla(210, 10%, 90%, 1); - font-family: Tahoma, "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", sans-serif; - top: 90%; - left: 0; - width: 250px; - font-size: 12px; - line-height: 18px; - color: hsla(0, 10%, 20%, 1); - cursor: default; - /*visibility: hidden;*/ - display: none; - padding: 10px; - box-shadow: 0 0 6px hsla(0, 0%, 0%, 0.3); - z-index: 10; - border: 2px solid hsl(0, 0%, 0%); - border-radius: 3px; - text-decoration: none; -} -.paragraph u.error .tooltip_on { - display: block; -} - -.tooltip_on s { - color: hsla(0, 0%, 66%, 1); - font-weight: bold; - font-size: 8px; - line-height: 16px; - text-transform: uppercase; - text-decoration: none; -} - -.debug { - float: right; - background-color: hsla(0, 5%, 35%, 1); - padding: 2px 5px; - margin-left: 5px; - border-radius: 2px; - color: hsla(0, 0%, 96%, 1); + +/* + TOOLTIPS +*/ +.tooltip { + position: absolute; + display: none; + width: 300px; + border-radius: 5px; + box-shadow: 0 0 6px hsla(0, 0%, 0%, 0.3); + font-family: Tahoma, "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", sans-serif; + font-size: 12px; + line-height: 18px; + cursor: default; + text-decoration: none; +} +#gc_tooltip { + border: 3px solid hsl(210, 50%, 30%); + color: hsla(210, 10%, 20%, 1); +} +#sc_tooltip { + border: 3px solid hsl(0, 50%, 30%); + color: hsla(0, 10%, 20%, 1); +} +#gc_tooltip_arrow, #sc_tooltip_arrow { + position: absolute; + display: none; +} +#gc_tooltip #gc_rule_id { + display: none; + margin: 0 0 5px 0; + border: 1px solid hsl(210, 50%, 60%); + background-color: hsl(210, 50%, 40%); + padding: 2px 5px; + border-radius: 2px; + color: hsla(210, 0%, 96%, 1); font-size: 11px; font-style: normal; + text-align: center; +} +#gc_message_block { + padding: 5px 10px 10px 10px; + background-color: hsl(210, 50%, 30%); + color: hsl(210, 50%, 96%); +} +#sc_message_block { + padding: 5px 10px 10px 10px; + background-color: hsl(0, 50%, 30%); + color: hsl(0, 50%, 96%); +} +#gc_message, #sc_message { + font-size: 15px; + margin-bottom: 5px; +} +a#gc_ignore, a#sc_ignore { + padding: 0 2px; + background-color: hsla(30, 30%, 40%, 1); + color: hsla(30, 0%, 96%, 1); + border-radius: 2px; + cursor: pointer; + text-decoration: none; +} +a#gc_ignore:hover, a#sc_ignore:hover { + background-color: hsla(30, 30%, 50%, 1); + color: hsla(0, 0%, 100%, 1); + text-shadow: 0 0 3px hsl(30, 30%, 60%); +} +a#gc_url { + padding: 0 2px; + background-color: hsla(210, 50%, 50%, 1); + color: hsla(210, 0%, 96%, 1); + border-radius: 2px; + cursor: pointer; + text-decoration: none; +} +a#gc_url:hover { + background-color: hsla(210, 50%, 60%, 1); + color: hsla(0, 0%, 100%, 1); + text-shadow: 0 0 3px hsl(210, 30%, 60%); +} +#gc_sugg_title { + padding: 0 10px; + background-color: hsl(210, 10%, 90%); + color: hsl(210, 50%, 30%); + font-size: 10px; + font-weight: bold; +} +#sc_sugg_title { + padding: 0 10px; + background-color: hsl(0, 10%, 90%); + color: hsl(0, 50%, 30%); + font-size: 9px; + font-weight: bold; +} +#gc_sugg_block { + padding: 10px; + background-color: hsl(210, 10%, 96%); + border-radius: 0 0 2px 2px; + line-height: 20px; +} +#sc_sugg_block { + padding: 10px; + background-color: hsl(0, 10%, 96%); + border-radius: 0 0 2px 2px; + line-height: 20px; +} +#gc_sugg_block a.sugg { + padding: 1px 6px; + background-color: hsla(180, 60%, 40%, 1); + color: hsla(180, 0%, 96%, 1); + border-radius: 2px; + cursor: pointer; + text-decoration: none; +} +#gc_sugg_block a.sugg:hover { + background-color: hsla(180, 70%, 45%, 1); + color: hsla(0, 0%, 100%, 1); +} +#sc_sugg_block a.sugg { + padding: 1px 6px; + background-color: hsla(30, 90%, 45%, 1); + color: hsla(30, 0%, 96%, 1); + border-radius: 2px; + cursor: pointer; + text-decoration: none; } - -.data { - font-style: normal; +#sc_sugg_block a.sugg:hover { + background-color: hsla(30, 100%, 50%, 1); + color: hsla(0, 0%, 100%, 1); } +/* + Action buttons +*/ .actions { - margin-top: -10px; - margin-bottom: 10px; + margin: 0 0 5px 10px; } .actions .button { background-color: hsl(0, 0%, 50%); text-align: center; @@ -216,11 +283,10 @@ padding: 1px 4px 3px 4px; /*width: 18px; height: 18px;*/ cursor: pointer; font-size: 14px; - font-weight: bold; color: hsl(0, 0%, 96%); border-radius: 2px; } .actions .button:hover { background-color: hsl(0, 0%, 40%); @@ -249,10 +315,13 @@ } .actions .orange:hover { background-color: hsl(30, 70%, 40%); color: hsl(30, 0%, 100%); } +.actions .bold { + font-weight: bold; +} /* ERRORS */ @@ -266,16 +335,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.html ================================================================== --- gc_lang/fr/xpi/data/gc_panel.html +++ gc_lang/fr/xpi/data/gc_panel.html @@ -51,10 +51,34 @@
+ ^ + ^ + +
+ +
+

+

Erreur grammaticale.

+ Ignorer   + Voulez-vous en savoir plus ?… +
+
SUGGESTIONS :
+
+
+ +
+ +
+

Mot inconnu du dictionnaire.

+ Ignorer +
+
SUGGESTIONS :
+
+
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 @@ -2,272 +2,460 @@ let nPanelWidth = 0; // must be set at launch let bExpanded = true; /* - Events + Ignored errors + idendified by + sIgnoredKey: +*/ +let aIgnoredErrors = new Set(); + + +/* + 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'); + bExpanded = true; // size is reset in ui.js + self.port.emit('closePanel'); }); document.getElementById('expand_reduce').addEventListener("click", function (event) { - if (bExpanded) { - self.port.emit("resize", "reduce", 10); // the number has no meaning here - bExpanded = false; - } else { - self.port.emit("resize", "expand", 10); // the number has no meaning here - bExpanded = true; - } + if (bExpanded) { + self.port.emit("resize", "reduce", 10); // the number has no meaning here + bExpanded = false; + } else { + self.port.emit("resize", "expand", 10); // the number has no meaning here + bExpanded = true; + } }); document.getElementById('copy_to_clipboard').addEventListener("click", function (event) { - copyToClipboard(); + copyToClipboard(); }); document.getElementById('closemsg').addEventListener("click", function (event) { - closeMessageBox(); + closeMessageBox(); }); self.port.on("setPanelWidth", function (n) { - nPanelWidth = n; + nPanelWidth = n; +}); + +self.port.on("addMessage", function (sClass, sText) { + addMessage(sClass, sText); }); -self.port.on("addElem", function (sHtml) { - let xElem = document.createElement("div"); - xElem.innerHTML = sHtml; - document.getElementById("errorlist").appendChild(xElem); +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; - } - } +self.port.on("suggestionsFor", function (sWord, sSuggestions, sErrId) { + setSpellSuggestionsFor(sWord, sSuggestions, sErrId); }); window.addEventListener( - "click", - function (xEvent) { - let xElem = xEvent.target; - if (xElem.id) { - if (xElem.id.startsWith("sugg")) { - applySuggestion(xElem.id); - } else if (xElem.id.startsWith("ignore")) { - ignoreError(xElem.id); - } else if (xElem.id.startsWith("check")) { - sendBackAndCheck(xElem.id); - } else if (xElem.id.startsWith("edit")) { - switchEdition(xElem.id); - } else if (xElem.id.startsWith("end")) { - document.getElementById(xElem.id).parentNode.parentNode.style.display = "none"; - } else if (xElem.tagName === "U" && xElem.id.startsWith("err")) { - showTooltip(xElem.id); - } else if (xElem.id.startsWith("resize")) { - self.port.emit("resize", xElem.id, 10); - } else { - hideAllTooltips(); - } - } else if (xElem.tagName === "A") { - self.port.emit("openURL", xElem.getAttribute("href")); - } else { - hideAllTooltips(); - } - }, - false + "click", + function (xEvent) { + try { + let xElem = xEvent.target; + if (xElem.id) { + if (xElem.id.startsWith("sugg")) { + applySuggestion(xElem.id); + } else if (xElem.id.endsWith("_ignore")) { + ignoreError(xElem.id); + } else if (xElem.id.startsWith("check")) { + sendBackAndCheck(xElem.id); + /*} else if (xElem.id.startsWith("edit")) { + switchEdition(xElem.id);*/ + } else if (xElem.id.startsWith("end")) { + document.getElementById(xElem.id).parentNode.parentNode.style.display = "none"; + } else if (xElem.tagName === "U" && xElem.id.startsWith("err") + && xElem.className !== "corrected" && xElem.className !== "ignored") { + showTooltip(xElem.id); + } else if (xElem.id.startsWith("resize")) { + self.port.emit("resize", xElem.id, 10); + } else if (xElem.id === "gc_url") { + self.port.emit("openURL", xElem.getAttribute("href")); + } else { + hideAllTooltips(); + } + } else if (xElem.tagName === "A") { + self.port.emit("openURL", xElem.getAttribute("href")); + } else { + hideAllTooltips(); + } + } + catch (e) { + showError(e); + } + }, + false ); /* - Actions + Actions */ + +function showError (e) { + console.error("\n" + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); +} function closeMessageBox () { - document.getElementById("messagebox").style.display = "none"; - document.getElementById("message").textContent = ""; -} - -function applySuggestion (sElemId) { // sugg - try { - let sIdParagr = sElemId.slice(4, sElemId.indexOf("_")); - startWaitIcon("paragr"+sIdParagr); - let sIdErr = "err" + sElemId.slice(4, sElemId.indexOf("-")); - 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); - } -} - -function ignoreError (sElemId) { // ignore - let sIdErr = "err" + sElemId.slice(6); - let xTooltipElem = document.getElementById("tooltip"+sElemId.slice(6)); - document.getElementById(sIdErr).removeChild(xTooltipElem); - document.getElementById(sIdErr).className = "ignored"; - document.getElementById(sIdErr).removeAttribute("style"); -} - -function showTooltip (sElemId) { // err - hideAllTooltips(); - let sTooltipId = "tooltip" + sElemId.slice(3); - let xTooltipElem = document.getElementById(sTooltipId); - let nLimit = nPanelWidth - 300; // paragraph width - tooltip width - 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(":")) { - // spelling mistake - self.port.emit("getSuggestionsForTo", document.getElementById(sElemId).innerHTML.replace(/, we also remove style attribute - let xParagraphElem = document.getElementById(sId); - for (xNode of xParagraphElem.getElementsByTagName("u")) { - if (xNode.id.startsWith('err')) { - xNode.innerHTML = xNode.innerHTML.replace(/<\/?u>/g, ""); - xNode.removeAttribute("style"); - } - } - // we remove style attribute on tooltip - for (xNode of xParagraphElem.getElementsByTagName("span")) { - if (xNode.id.startsWith('tooltip')) { - xNode.removeAttribute("style"); - } - } - // now, we remove tooltips, then errors, and we change some html entities - let sText = xParagraphElem.innerHTML; - sText = sText.replace(/ *$/ig, ""); - sText = sText.replace(/(.+?)<\/u>/g, "$1"); - sText = sText.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); - return sText; -} - -function getPurgedTextOfElem2 (sId) { - // It is better to remove tooltips via DOM and retrieve textContent, - // but for some reason getElementsByClassName “hazardously” forgets elements. - // Unused. Needs investigation. - let xParagraphElem = document.getElementById(sId).cloneNode(true); - for (let xNode of xParagraphElem.getElementsByClassName("tooltip")) { - xNode.parentNode.removeChild(xNode); - } - return xParagraphElem.textContent; + document.getElementById("messagebox").style.display = "none"; + document.getElementById("message").textContent = ""; +} + +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"; + // actions + let xDivActions = document.createElement("div"); + xDivActions.className = "actions"; + let xDivClose = document.createElement("div"); + xDivClose.id = "end" + iParagraph.toString(); + xDivClose.className = "button red bold"; + xDivClose.textContent = "×"; + xDivActions.appendChild(xDivClose); + /*let xDivEdit = document.createElement("div"); + xDivEdit.id = "edit" + iParagraph.toString(); + xDivEdit.className = "button"; + xDivEdit.textContent = "Éditer"; + xDivActions.appendChild(xDivEdit);*/ + let xDivCheck = document.createElement("div"); + xDivCheck.id = "check" + iParagraph.toString(); + xDivCheck.className = "button green"; + xDivCheck.textContent = "Réanalyser"; + xDivCheck.setAttribute("title", "Réanalyser le texte"); + xDivActions.appendChild(xDivCheck); + xNodeDiv.appendChild(xDivActions); + // paragraph + let xParagraph = document.createElement("p"); + xParagraph.id = "paragr" + iParagraph.toString(); + xParagraph.lang = "fr"; + xParagraph.setAttribute("spellcheck", false); + xParagraph.setAttribute("contenteditable", true); + 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); + 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['sErrorId'] = iParagraph.toString() + "_" + nErr.toString(); // error identifier + oErr['sIgnoredKey'] = iParagraph.toString() + ":" + nStart.toString() + ":" + nEnd.toString() + ":" + sParagraph.slice(nStart, nEnd); + 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['sErrorId']; + xNodeErr.textContent = sUnderlined; + xNodeErr.dataset.error_id = oErr['sErrorId']; + xNodeErr.dataset.ignored_key = oErr['sIgnoredKey']; + xNodeErr.dataset.error_type = (oErr['sType'] === "WORD") ? "spelling" : "grammar"; + xNodeErr.setAttribute("href", "#"); + xNodeErr.setAttribute("onclick", "return false;"); + if (xNodeErr.dataset.error_type === "grammar") { + xNodeErr.dataset.gc_message = oErr['sMessage']; + xNodeErr.dataset.gc_url = oErr['URL']; + if (xNodeErr.dataset.gc_message.includes(" #")) { + xNodeErr.dataset.line_id = oErr['sLineId']; + xNodeErr.dataset.rule_id = oErr['sRuleId']; + } + xNodeErr.dataset.suggestions = oErr["aSuggestions"].join("|"); + } + xNodeErr.className = (aIgnoredErrors.has(xNodeErr.dataset.ignored_key)) ? "ignored" : "error " + oErr['sType']; + return xNodeErr; +} + +function applySuggestion (sSuggId) { // sugg + try { + let sErrorId = document.getElementById(sSuggId).dataset.error_id; + let sIdParagr = sErrorId.slice(0, sErrorId.indexOf("_")); + startWaitIcon("paragr"+sIdParagr); + let xNodeErr = document.getElementById("err" + sErrorId); + xNodeErr.textContent = document.getElementById(sSuggId).textContent; + xNodeErr.className = "corrected"; + xNodeErr.removeAttribute("style"); + self.port.emit("correction", sIdParagr, getPurgedTextOfParagraph("paragr"+sIdParagr)); + hideAllTooltips(); + stopWaitIcon("paragr"+sIdParagr); + } + catch (e) { + showError(e); + } +} + +function ignoreError (sIgnoreButtonId) { // ignore + try { + //console.log("ignore button: " + sIgnoreButtonId + " // error id: " + document.getElementById(sIgnoreButtonId).dataset.error_id); + let xNodeErr = document.getElementById("err"+document.getElementById(sIgnoreButtonId).dataset.error_id); + aIgnoredErrors.add(xNodeErr.dataset.ignored_key); + xNodeErr.className = "ignored"; + xNodeErr.removeAttribute("style"); + hideAllTooltips(); + } + catch (e) { + showError(e); + } +} + +function showTooltip (sNodeErrorId) { // err + try { + hideAllTooltips(); + let xNodeErr = document.getElementById(sNodeErrorId); + let sTooltipId = (xNodeErr.dataset.error_type === "grammar") ? "gc_tooltip" : "sc_tooltip"; + let xNodeTooltip = document.getElementById(sTooltipId); + let xNodeTooltipArrow = document.getElementById(sTooltipId+"_arrow"); + let nLimit = nPanelWidth - 330; // paragraph width - tooltip width + xNodeTooltipArrow.style.top = (xNodeErr.offsetTop + 16) + "px" + xNodeTooltipArrow.style.left = (xNodeErr.offsetLeft + Math.floor((xNodeErr.offsetWidth / 2))-4) + "px" // 4 is half the width of the arrow. + xNodeTooltip.style.top = (xNodeErr.offsetTop + 20) + "px"; + xNodeTooltip.style.left = (xNodeErr.offsetLeft > nLimit) ? nLimit + "px" : xNodeErr.offsetLeft + "px"; + if (xNodeErr.dataset.error_type === "grammar") { + // grammar error + if (xNodeErr.dataset.gc_message.includes(" ##")) { + let n = xNodeErr.dataset.gc_message.indexOf(" ##"); + document.getElementById("gc_message").textContent = xNodeErr.dataset.gc_message.slice(0, n); + document.getElementById("gc_rule_id").textContent = "Règle : " + xNodeErr.dataset.gc_message.slice(n+2); + document.getElementById("gc_rule_id").style.display = "block"; + } else { + document.getElementById("gc_message").textContent = xNodeErr.dataset.gc_message; + } + if (xNodeErr.dataset.gc_url != "") { + document.getElementById("gc_url").style.display = "inline"; + document.getElementById("gc_url").setAttribute("href", xNodeErr.dataset.gc_url); + } else { + document.getElementById("gc_url").style.display = "none"; + } + document.getElementById("gc_ignore").dataset.error_id = xNodeErr.dataset.error_id; + let iSugg = 0; + let xGCSugg = document.getElementById("gc_sugg_block"); + xGCSugg.textContent = ""; + for (let sSugg of xNodeErr.dataset.suggestions.split("|")) { + xGCSugg.appendChild(_createSuggestion(xNodeErr.dataset.error_id, iSugg, sSugg)); + xGCSugg.appendChild(document.createTextNode(" ")); + iSugg += 1; + } + } + xNodeTooltipArrow.style.display = "block"; + xNodeTooltip.style.display = "block"; + if (xNodeErr.dataset.error_type === "spelling") { + // spelling mistake + document.getElementById("sc_ignore").dataset.error_id = xNodeErr.dataset.error_id; + //console.log("getSuggFor: " + xNodeErr.textContent.trim() + " // error_id: " + xNodeErr.dataset.error_id); + self.port.emit("getSuggestionsForTo", xNodeErr.textContent.trim(), xNodeErr.dataset.error_id); + } + } + catch (e) { + showError(e); + } +} + +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.dataset.error_id = sErrId; + xNodeSugg.textContent = sSugg; + return xNodeSugg; +} + +/*function switchEdition (sEditButtonId) { // edit + let xParagraph = document.getElementById("paragr" + sEditButtonId.slice(4)); + if (xParagraph.hasAttribute("contenteditable") === false + || xParagraph.getAttribute("contenteditable") === "false") { + xParagraph.setAttribute("contenteditable", true); + document.getElementById(sEditButtonId).className = "button orange"; + xParagraph.focus(); + } else { + xParagraph.setAttribute("contenteditable", false); + document.getElementById(sEditButtonId).className = "button"; + } +}*/ + +function sendBackAndCheck (sCheckButtonId) { // check + startWaitIcon(); + let sIdParagr = sCheckButtonId.slice(5); + self.port.emit("modifyAndCheck", sIdParagr, getPurgedTextOfParagraph("paragr"+sIdParagr)); + stopWaitIcon(); } function hideAllTooltips () { - for (let xElem of document.getElementsByClassName("tooltip_on")) { - xElem.className = "tooltip"; - xElem.removeAttribute("style"); - } + document.getElementById("gc_tooltip").style.display = "none"; + document.getElementById("gc_rule_id").style.display = "none"; + document.getElementById("sc_tooltip").style.display = "none"; + document.getElementById("gc_tooltip_arrow").style.display = "none"; + document.getElementById("sc_tooltip_arrow").style.display = "none"; +} + +function setSpellSuggestionsFor (sWord, sSuggestions, sErrId) { + // spell checking suggestions + try { + // console.log("setSuggestionsFor: " + sWord + " > " + sSuggestions + " // " + sErrId); + let xSuggBlock = document.getElementById("sc_sugg_block"); + xSuggBlock.textContent = ""; + if (sSuggestions === "") { + xSuggBlock.appendChild(document.createTextNode("Aucune.")); + } else if (sSuggestions.startsWith("#")) { + xSuggBlock.appendChild(document.createTextNode(sSuggestions)); + } else { + let lSugg = sSuggestions.split("|"); + let iSugg = 0; + for (let sSugg of lSugg) { + xSuggBlock.appendChild(_createSuggestion(sErrId, iSugg, sSugg)); + xSuggBlock.appendChild(document.createTextNode(" ")); + iSugg += 1; + } + } + } + catch (e) { + showError(e); + } +} + +function getPurgedTextOfParagraph (sNodeParagrId) { + let sText = document.getElementById(sNodeParagrId).textContent; + sText = sText.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); + return sText; } function copyToClipboard () { - startWaitIcon(); - try { - document.getElementById("clipboard_msg").textContent = "copie en cours…"; - let sText = ""; - for (let xNode of document.getElementById("errorlist").getElementsByClassName("paragraph")) { - sText += getPurgedTextOfElem(xNode.id); - sText += "\n"; - } - self.port.emit('copyToClipboard', sText); - document.getElementById("clipboard_msg").textContent = "-> presse-papiers"; - window.setTimeout(function() { document.getElementById("clipboard_msg").textContent = "∑"; } , 3000); - } - catch (e) { - console.log(e.lineNumber + ": " +e.message); - } - stopWaitIcon(); + startWaitIcon(); + try { + let xClipboardButton = document.getElementById("clipboard_msg"); + xClipboardButton.textContent = "copie en cours…"; + let sText = ""; + for (let xNode of document.getElementById("errorlist").getElementsByClassName("paragraph")) { + sText += xNode.textContent + "\n"; + } + self.port.emit('copyToClipboard', sText); + xClipboardButton.textContent = "-> presse-papiers"; + window.setTimeout(function() { xClipboardButton.textContent = "∑"; } , 3000); + } + catch (e) { + console.log(e.lineNumber + ": " +e.message); + } + stopWaitIcon(); } function startWaitIcon (sIdParagr=null) { - if (sIdParagr) { - document.getElementById(sIdParagr).disabled = true; - document.getElementById(sIdParagr).style.opacity = .3; - } - document.getElementById("waiticon").hidden = false; + if (sIdParagr) { + document.getElementById(sIdParagr).disabled = true; + document.getElementById(sIdParagr).style.opacity = .3; + } + document.getElementById("waiticon").hidden = false; } function stopWaitIcon (sIdParagr=null) { - if (sIdParagr) { - document.getElementById(sIdParagr).disabled = false; - document.getElementById(sIdParagr).style.opacity = 1; - } - document.getElementById("waiticon").hidden = true; + if (sIdParagr) { + document.getElementById(sIdParagr).disabled = false; + document.getElementById(sIdParagr).style.opacity = 1; + } + document.getElementById("waiticon").hidden = true; +} + +function showSpecialMessage () { + 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) { + showError(e); + } + } } ADDED gc_lang/fr/xpi/data/img/gc_tooltip_arrow.png Index: gc_lang/fr/xpi/data/img/gc_tooltip_arrow.png ================================================================== --- gc_lang/fr/xpi/data/img/gc_tooltip_arrow.png +++ gc_lang/fr/xpi/data/img/gc_tooltip_arrow.png cannot compute difference between binary files ADDED gc_lang/fr/xpi/data/img/sc_tooltip_arrow.png Index: gc_lang/fr/xpi/data/img/sc_tooltip_arrow.png ================================================================== --- gc_lang/fr/xpi/data/img/sc_tooltip_arrow.png +++ gc_lang/fr/xpi/data/img/sc_tooltip_arrow.png cannot compute difference between binary files Index: gc_lang/fr/xpi/data/lxg_panel.css ================================================================== --- gc_lang/fr/xpi/data/lxg_panel.css +++ gc_lang/fr/xpi/data/lxg_panel.css @@ -40,28 +40,43 @@ color: hsla(0, 0%, 96%, 1); border-radius: 5px; text-align: center; font-size: 20px; } +#wordlist .token { + margin: 8px; +} #wordlist ul { margin: 0 0 5px 40px; } #wordlist b { - background-color: hsla(150, 50%, 50%, 1); + background-color: hsla(150, 10%, 50%, 1); color: hsla(0, 0%, 96%, 1); padding: 2px 5px; border-radius: 2px; text-decoration: none; } -#wordlist b.unknown { +#wordlist b.WORD { + background-color: hsla(150, 50%, 50%, 1); +} +#wordlist b.ELPFX { + background-color: hsla(150, 30%, 50%, 1); +} +#wordlist b.UNKNOWN { background-color: hsla(0, 50%, 50%, 1); } -#wordlist b.nb { +#wordlist b.NUM { + background-color: hsla(180, 50%, 50%, 1); +} +#wordlist b.COMPLEX { + background-color: hsla(60, 50%, 50%, 1); +} +#wordlist b.SEPARATOR { background-color: hsla(210, 50%, 50%, 1); } -#wordlist b.mbok { - background-color: hsla(60, 50%, 50%, 1); +#wordlist b.LINK { + background-color: hsla(270, 50%, 50%, 1); } #wordlist s { color: hsla(0, 0%, 60%, 1); text-decoration: none; } Index: gc_lang/fr/xpi/data/lxg_panel.js ================================================================== --- gc_lang/fr/xpi/data/lxg_panel.js +++ gc_lang/fr/xpi/data/lxg_panel.js @@ -25,22 +25,19 @@ self.port.emit('openConjugueur'); }); */ self.port.on("addSeparator", function (sText) { - if (document.getElementById("wordlist").innerHTML !== "") { - let xElem = document.createElement("p"); - xElem.className = "separator"; - xElem.innerHTML = sText; - document.getElementById("wordlist").appendChild(xElem); - } + addSeparator(sText); +}); + +self.port.on("addParagraphElems", function (sJSON) { + addParagraphElems(sJSON); }); -self.port.on("addElem", function (sHtml) { - let xElem = document.createElement("div"); - xElem.innerHTML = sHtml; - document.getElementById("wordlist").appendChild(xElem); +self.port.on("addMessage", function (sClass, sText) { + addMessage(sClass, sText); }); self.port.on("clear", function (sHtml) { document.getElementById("wordlist").textContent = ""; }); @@ -65,10 +62,71 @@ } }, false ); + +/* + Actions +*/ + +function addSeparator (sText) { + if (document.getElementById("wordlist").textContent !== "") { + let xElem = document.createElement("p"); + xElem.className = "separator"; + xElem.textContent = sText; + document.getElementById("wordlist").appendChild(xElem); + } +} + +function addMessage (sClass, sText) { + let xNode = document.createElement("p"); + xNode.className = sClass; + xNode.textContent = sText; + document.getElementById("wordlist").appendChild(xNode); +} + +function addParagraphElems (sJSON) { + try { + let xNodeDiv = document.createElement("div"); + xNodeDiv.className = "paragraph"; + let lElem = JSON.parse(sJSON); + for (let oToken of lElem) { + xNodeDiv.appendChild(createTokenNode(oToken)); + } + document.getElementById("wordlist").appendChild(xNodeDiv); + } + catch (e) { + console.error("\n" + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); + console.error(sJSON); + } +} + +function createTokenNode (oToken) { + let xTokenNode = document.createElement("div"); + xTokenNode.className = "token " + oToken.sType; + let xTokenValue = document.createElement("b"); + xTokenValue.className = oToken.sType; + xTokenValue.textContent = oToken.sValue; + xTokenNode.appendChild(xTokenValue); + let xSep = document.createElement("s"); + xSep.textContent = " : "; + xTokenNode.appendChild(xSep); + if (oToken.aLabel.length === 1) { + xTokenNode.appendChild(document.createTextNode(oToken.aLabel[0])); + } else { + let xTokenList = document.createElement("ul"); + for (let sLabel of oToken.aLabel) { + let xTokenLine = document.createElement("li"); + xTokenLine.textContent = sLabel; + xTokenList.appendChild(xTokenLine); + } + xTokenNode.appendChild(xTokenList); + } + return xTokenNode; +} + // display selection function displayClasses () { setHidden("ok", document.getElementById("ok").checked); Index: gc_lang/fr/xpi/data/test_panel.js ================================================================== --- gc_lang/fr/xpi/data/test_panel.js +++ gc_lang/fr/xpi/data/test_panel.js @@ -2,13 +2,13 @@ /* Events */ -self.port.on("addElem", function (sHtml) { - let xElem = document.createElement("p"); - xElem.innerHTML = sHtml; +self.port.on("addElem", function (sText) { + let xElem = document.createElement("pre"); + xElem.textContent = sText; document.getElementById("results").appendChild(xElem); }); self.port.on("clear", function () { document.getElementById("results").textContent = ""; Index: gc_lang/fr/xpi/gce_worker.js ================================================================== --- gc_lang/fr/xpi/gce_worker.js +++ gc_lang/fr/xpi/gce_worker.js @@ -84,36 +84,14 @@ return JSON.stringify(aGrammErr); } function parseAndSpellcheck (sText, sLang, bDebug, bContext) { let aGrammErr = gce.parse(sText, sLang, bDebug, bContext); - let aSpellErr = []; - for (let oToken of oTokenizer.genTokens(sText)) { - if (oToken.sType === 'WORD' && !oDict.isValidToken(oToken.sValue)) { - aSpellErr.push(oToken); - } - } + let aSpellErr = oTokenizer.getSpellingErrors(sText, oDict); return JSON.stringify({ aGrammErr: aGrammErr, aSpellErr: aSpellErr }); } -function parseAndTag (sText, iParagraph, sLang, bDebug) { - sText = text.addHtmlEntities(sText); - let aSpellErr = []; - for (let oToken of oTokenizer.genTokens(sText)) { - if (oToken.sType === 'WORD' && !oDict.isValidToken(oToken.sValue)) { - aSpellErr.push(oToken); - } - } - let aGrammErr = gce.parse(sText, sLang, bDebug); - let sHtml = text.tagParagraph(sText, iParagraph, aGrammErr, aSpellErr); - return sHtml; -} - -function parseAndGenerateParagraph (sText, iParagraph, sLang, bDebug) { - return text.createHTMLBlock(parseAndTag(sText, iParagraph, sLang, bDebug), iParagraph); -} - function getOptions () { return gce.getOptions()._toString(); } function getDefaultOptions () { @@ -146,17 +124,30 @@ let tests = require("resource://grammalecte/tests.js"); let oTest = new tests.TestGrammarChecking(gce); let sAllRes = ""; for (let sRes of oTest.testParse()) { dump(sRes+"\n"); - sAllRes += sRes+"
"; + 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,14 @@ } 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); + xGCPanel.port.emit("refreshParagraph", sText, sIdParagraph, aVal); }, function (aReason) { console.error('Promise rejected - ', aReason); } ).catch( @@ -416,20 +416,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 +569,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"); }