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 @@ -231,10 +231,11 @@ oToken["bValidToken"] = gc_engine.oSpellChecker.isValidToken(oToken["sValue"]); } if (!oToken.hasOwnProperty("lMorph")) { oToken["lMorph"] = gc_engine.oSpellChecker.getMorph(oToken["sValue"]); } + gc_engine.oSpellChecker.setLabelsOnToken(oToken); } lSentences.push({ "nStart": iStart, "nEnd": iEnd, "sSentence": this.sSentence0, Index: gc_core/py/lang_core/gc_engine.py ================================================================== --- gc_core/py/lang_core/gc_engine.py +++ gc_core/py/lang_core/gc_engine.py @@ -290,10 +290,11 @@ for dToken in self.lTokens0: if dToken["sType"] == "WORD": dToken["bValidToken"] = _oSpellChecker.isValidToken(dToken["sValue"]) if "lMorph" not in dToken: dToken["lMorph"] = _oSpellChecker.getMorph(dToken["sValue"]) + _oSpellChecker.setLabelsOnToken(dToken) lSentences.append({ "nStart": iStart, "nEnd": iEnd, "sSentence": self.sSentence0, "lTokens": self.lTokens0, Index: gc_lang/fr/webext/content_scripts/panel_gc.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_gc.js +++ gc_lang/fr/webext/content_scripts/panel_gc.js @@ -599,39 +599,40 @@ _createTokenBlock2 (oToken) { let xTokenBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_block"}); // token description xTokenBlock.appendChild(this._createTokenDescr2(oToken)); - // subtoken description - if (oToken.aSubElem) { - let xSubBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_subblock"}); - for (let oSubElem of oToken.aSubElem) { - xSubBlock.appendChild(this._createTokenDescr2(oSubElem)); - } - xTokenBlock.appendChild(xSubBlock); - } return xTokenBlock; } _createTokenDescr2 (oToken) { try { let xTokenDescr = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_descr"}); - if (oToken.sType == "LOCP") { - xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_also", textContent: "possiblement › "})); - } xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token grammalecte_lxg_token_" + oToken.sType, textContent: oToken.sValue})); xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_colon", textContent: ":"})); - if (oToken.lMorph.length < 2) { - // one morphology only - xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: oToken.lMorph[0]})); + if (oToken.aLabels) { + if (oToken.aLabels.length < 2) { + // one morphology only + xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: oToken.aLabels[0]})); + } else { + // several morphology + let xMorphList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"}); + for (let sLabel of oToken.aLabels) { + xMorphList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel})); + } + xTokenDescr.appendChild(xMorphList); + } } else { - // several morphology - let xMorphList = oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_list"}); - for (let sLabel of oToken.lMorph) { - xMorphList.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem", textContent: "• " + sLabel})); + xTokenDescr.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_morph_elem_inline", textContent: "étiquettes non décrites : [" + oToken.lMorph + "]" })); + } + // other labels description + if (oToken.aOtherLabels) { + let xSubBlock = oGrammalecte.createNode("div", {className: "grammalecte_lxg_token_subblock"}); + for (let sLabel of oToken.aOtherLabels) { + xSubBlock.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_lxg_other_tags", textContent: "• " + sLabel})); } - xTokenDescr.appendChild(xMorphList); + xTokenDescr.appendChild(xSubBlock); } return xTokenDescr; } catch (e) { showError(e); Index: gc_lang/fr/webext/content_scripts/panel_lxg.css ================================================================== --- gc_lang/fr/webext/content_scripts/panel_lxg.css +++ gc_lang/fr/webext/content_scripts/panel_lxg.css @@ -130,10 +130,16 @@ } div.grammalecte_lxg_morph_elem { font-family: "Trebuchet MS", "Fira Sans", "Ubuntu Condensed", "Liberation Sans", sans-serif; color: hsl(0, 0%, 0%); } +div.grammalecte_lxg_other_tags { + padding-left: 20px; + font-family: "Trebuchet MS", "Fira Sans", "Ubuntu Condensed", "Liberation Sans", sans-serif; + color: hsl(0, 0%, 50%); +} + div.grammalecte_lxg_token_LOC { background-color: hsla(150, 50%, 30%, 1); } div.grammalecte_lxg_token_WORD { background-color: hsla(150, 50%, 50%, 1); Index: gc_lang/fr/webext/gce_worker.js ================================================================== --- gc_lang/fr/webext/gce_worker.js +++ gc_lang/fr/webext/gce_worker.js @@ -242,11 +242,11 @@ // lexicographer try { sText = sText.replace(/­/g, "").normalize("NFC"); for (let sParagraph of text.getParagraph(sText)) { if (sParagraph.trim() !== "") { - postMessage(createResponse("getListOfTokens", { sParagraph: sParagraph, lTokens: lexgraph_fr.getListOfTokensReduc(sParagraph, true) }, oInfo, false)); + postMessage(createResponse("getListOfTokens", { sParagraph: sParagraph, lTokens: lexgraph_fr.getListOfTokens(sParagraph, true) }, oInfo, false)); } } postMessage(createResponse("getListOfTokens", null, oInfo, true)); } catch (e) { Index: graphspell-js/lexgraph_fr.js ================================================================== --- graphspell-js/lexgraph_fr.js +++ graphspell-js/lexgraph_fr.js @@ -164,13 +164,16 @@ [':f', [" féminin", "féminin"]], [':s', [" singulier", "singulier"]], [':p', [" pluriel", "pluriel"]], [':i', [" invariable", "invariable"]], - [':V1', [" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"]], - [':V2', [" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"]], - [':V3', [" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"]], + [':V1_', [" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"]], + [':V2_', [" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"]], + [':V3_', [" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"]], + [':V1e', [" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"]], + [':V2e', [" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"]], + [':V3e', [" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"]], [':V0e', [" verbe,", "Verbe auxiliaire être"]], [':V0a', [" verbe,", "Verbe auxiliaire avoir"]], [':Y', [" infinitif,", "infinitif"]], [':P', [" participe présent,", "participe présent"]], @@ -277,64 +280,87 @@ ['t', " transitive directe"], ['p', " pronominale"], ['m', " impersonnelle"], ]), - dElidedPrefix: new Map([ - ['d', "(de), déterminant épicène invariable"], - ['l', "(le/la), déterminant masculin/féminin singulier"], - ['j', "(je), pronom personnel sujet, 1ʳᵉ pers., épicène singulier"], - ['m', "(me), pronom personnel objet, 1ʳᵉ pers., épicène singulier"], - ['t', "(te), pronom personnel objet, 2ᵉ pers., épicène singulier"], - ['s', "(se), pronom personnel objet, 3ᵉ pers., épicène singulier/pluriel"], - ['n', "(ne), adverbe de négation"], - ['c', "(ce), pronom démonstratif, masculin singulier/pluriel"], - ['ç', "(ça), pronom démonstratif, masculin singulier"], + dValues: new Map([ + ['d’', "(de), préposition ou déterminant épicène invariable"], + ['l’', "(le/la), déterminant ou pronom personnel objet, masculin/féminin singulier"], + ['j’', "(je), pronom personnel sujet, 1ʳᵉ pers., épicène singulier"], + ['m’', "(me), pronom personnel objet, 1ʳᵉ pers., épicène singulier"], + ['t’', "(te), pronom personnel objet, 2ᵉ pers., épicène singulier"], + ['s’', "(se), pronom personnel objet, 3ᵉ pers., épicène singulier/pluriel"], + ['n’', "(ne), adverbe de négation"], + ['c’', "(ce), pronom démonstratif, masculin singulier/pluriel"], + ['ç’', "(ça), pronom démonstratif, masculin singulier"], ['qu', "(que), conjonction de subordination"], - ['lorsqu', "(lorsque), conjonction de subordination"], - ['puisqu', "(lorsque), conjonction de subordination"], - ['quoiqu', "(quoique), conjonction de subordination"], - ['jusqu', "(jusque), préposition"] - ]), - - dPronoms: new Map([ - ['je', " pronom personnel sujet, 1ʳᵉ pers. sing."], - ['tu', " pronom personnel sujet, 2ᵉ pers. sing."], - ['il', " pronom personnel sujet, 3ᵉ pers. masc. sing."], - ['on', " pronom personnel sujet, 3ᵉ pers. sing. ou plur."], - ['elle', " pronom personnel sujet, 3ᵉ pers. fém. sing."], - ['nous', " pronom personnel sujet/objet, 1ʳᵉ pers. plur."], - ['vous', " pronom personnel sujet/objet, 2ᵉ pers. plur."], - ['ils', " pronom personnel sujet, 3ᵉ pers. masc. plur."], - ['elles', " pronom personnel sujet, 3ᵉ pers. masc. plur."], - - ["là", " particule démonstrative"], - ["ci", " particule démonstrative"], - - ['le', " COD, masc. sing."], - ['la', " COD, fém. sing."], - ['les', " COD, plur."], - - ['moi', " COI (à moi), sing."], - ['toi', " COI (à toi), sing."], - ['lui', " COI (à lui ou à elle), sing."], - ['nous2', " COI (à nous), plur."], - ['vous2', " COI (à vous), plur."], - ['leur', " COI (à eux ou à elles), plur."], - - ['y', " pronom adverbial"], - ["m'y", " (me) pronom personnel objet + (y) pronom adverbial"], - ["t'y", " (te) pronom personnel objet + (y) pronom adverbial"], - ["s'y", " (se) pronom personnel objet + (y) pronom adverbial"], - - ['en', " pronom adverbial"], - ["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"] - ]), - - dChar: new Map([ + ['lorsqu’', "(lorsque), conjonction de subordination"], + ['puisqu’', "(lorsque), conjonction de subordination"], + ['quoiqu’', "(quoique), conjonction de subordination"], + ['jusqu’', "(jusque), préposition"], + + ['-je', " pronom personnel sujet, 1ʳᵉ pers. sing."], + ['-tu', " pronom personnel sujet, 2ᵉ pers. sing."], + ['-il', " pronom personnel sujet, 3ᵉ pers. masc. sing."], + ['-iel', " pronom personnel sujet, 3ᵉ pers. sing."], + ['-on', " pronom personnel sujet, 3ᵉ pers. sing. ou plur."], + ['-elle', " pronom personnel sujet, 3ᵉ pers. fém. sing."], + ['-t-il', " “t” euphonique + pronom personnel sujet, 3ᵉ pers. masc. sing."], + ['-t-on', " “t” euphonique + pronom personnel sujet, 3ᵉ pers. sing. ou plur."], + ['-t-elle', " “t” euphonique + pronom personnel sujet, 3ᵉ pers. fém. sing."], + ['-t-iel', " “t” euphonique + pronom personnel sujet, 3ᵉ pers. sing."], + ['-nous', " pronom personnel sujet/objet, 1ʳᵉ pers. plur. ou COI (à nous), plur."], + ['-vous', " pronom personnel sujet/objet, 2ᵉ pers. plur. ou COI (à vous), plur."], + ['-ils', " pronom personnel sujet, 3ᵉ pers. masc. plur."], + ['-elles', " pronom personnel sujet, 3ᵉ pers. masc. plur."], + ['-iels', " pronom personnel sujet, 3ᵉ pers. plur."], + + ["-là", " particule démonstrative (là)"], + ["-ci", " particule démonstrative (ci)"], + + ['-le', " COD, masc. sing."], + ['-la', " COD, fém. sing."], + ['-les', " COD, plur."], + + ['-moi', " COI (à moi), sing."], + ['-toi', " COI (à toi), sing."], + ['-lui', " COI (à lui ou à elle), sing."], + ['-nous2', " COI (à nous), plur."], + ['-vous2', " COI (à vous), plur."], + ['-leur', " COI (à eux ou à elles), plur."], + + ['-le-moi', " COD, masc. sing. + COI (à moi), sing."], + ['-le-toi', " COD, masc. sing. + COI (à toi), sing."], + ['-le-lui', " COD, masc. sing. + COI (à lui ou à elle), sing."], + ['-le-nous', " COD, masc. sing. + COI (à nous), plur."], + ['-le-vous', " COD, masc. sing. + COI (à vous), plur."], + ['-le-leur', " COD, masc. sing. + COI (à eux ou à elles), plur."], + + ['-la-moi', " COD, fém. sing. + COI (à moi), sing."], + ['-la-toi', " COD, fém. sing. + COI (à toi), sing."], + ['-la-lui', " COD, fém. sing. + COI (à lui ou à elle), sing."], + ['-la-nous', " COD, fém. sing. + COI (à nous), plur."], + ['-la-vous', " COD, fém. sing. + COI (à vous), plur."], + ['-la-leur', " COD, fém. sing. + COI (à eux ou à elles), plur."], + + ['-les-moi', " COD, plur. + COI (à moi), sing."], + ['-les-toi', " COD, plur. + COI (à toi), sing."], + ['-les-lui', " COD, plur. + COI (à lui ou à elle), sing."], + ['-les-nous', " COD, plur. + COI (à nous), plur."], + ['-les-vous', " COD, plur. + COI (à vous), plur."], + ['-les-leur', " COD, plur. + COI (à eux ou à elles), plur."], + + ['-y', " pronom adverbial"], + ["-m’y", " (me) pronom personnel objet + (y) pronom adverbial"], + ["-t’y", " (te) pronom personnel objet + (y) pronom adverbial"], + ["-s’y", " (se) pronom personnel objet + (y) pronom adverbial"], + + ['-en', " pronom adverbial"], + ["-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"], + ['.', "point"], ['·', "point médian"], ['…', "points de suspension"], [':', "deux-points"], [';', "point-virgule"], @@ -373,12 +399,12 @@ oTokenizer: null, oLocGraph: null, _zPartDemForm: new RegExp("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)-(là|ci)$", "i"), _aPartDemExceptList: new Set(["celui", "celle", "ceux", "celles", "de", "jusque", "par", "marie-couche-toi"]), - _zInterroVerb: new RegExp("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)-(t-(?:il|elle|on)|je|tu|ils?|elles?|on|[nv]ous)$", "i"), - _zImperatifVerb: new RegExp("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)-((?:les?|la)-(?:moi|toi|lui|[nv]ous|leur)|y|en|[mts][’'](?:y|en)|les?|la|[mt]oi|leur|lui)$", "i"), + _zInterroVerb: new RegExp("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)(-(?:t-(?:ie?l|elle|on)|je|tu|ie?ls?|elles?|on|[nv]ous))$", "i"), + _zImperatifVerb: new RegExp("([a-zA-Zà-ö0-9À-Öø-ÿØ-ßĀ-ʯ]+)(-(?:l(?:es?|a)-(?:moi|toi|lui|[nv]ous|leur)|y|en|[mts][’'](?:y|en)|les?|la|[mt]oi|leur|lui))$", "i"), _zTag: new RegExp("[:;/][a-zA-Z0-9ÑÂĴĈŔÔṼŴ!][^:;/]*", "g"), load: function (oSpellChecker, oTokenizer, oLocGraph) { this.oSpellChecker = oSpellChecker; @@ -403,10 +429,130 @@ sSuffix = m[2]; } // split word in 3 parts: prefix, root, suffix return [sPrefix, sWord, sSuffix]; }, + + analyze: function (sWord) { + // return meaning of if found else an empty string + sWord = sWord.toLowerCase(); + if (this.dValues.has(sWord)) { + return this.dValues.get(sWord); + } + return ""; + }, + + readableMorph: function (sMorph) { + let sRes = ""; + sMorph = sMorph.replace(/:V([0-3][ea_])[itpqnmr_eaxz]+/, ":V$1"); + let m; + while ((m = this._zTag.exec(sMorph)) !== null) { + if (this.dTag.has(m[0])) { + sRes += this.dTag.get(m[0])[0]; + } else { + sRes += " [" + m[0] + "]?"; + } + } + if (sRes.startsWith(" verbe") && !sRes.includes("infinitif")) { + sRes += " [" + sMorph.slice(1, sMorph.indexOf("/")) + "]"; + } + if (!sRes) { + return " [" + sMorph + "]: étiquettes inconnues"; + } + return sRes.gl_trimRight(","); + }, + + setLabelsOnToken (oToken) { + // Token: .sType, .sValue, .nStart, .nEnd, .lMorph + let m = null; + try { + switch (oToken.sType) { + case 'PUNC': + case 'SIGN': + oToken["aLabels"] = [this.dValues.gl_get(oToken.sValue, "signe de ponctuation divers")]; + break; + case 'NUM': + oToken["aLabels"] = ["nombre"]; + break; + case 'LINK': + oToken["aLabels"] = ["hyperlien"]; + break; + case 'TAG': + oToken["aLabels"] = ["étiquette (hashtag)"]; + break; + case 'HTML': + oToken["aLabels"] = ["balise HTML"]; + break; + case 'PSEUDOHTML': + oToken["aLabels"] = ["balise pseudo-HTML"]; + break; + case 'HTMLENTITY': + oToken["aLabels"] = ["entité caractère XML/HTML"]; + break; + case 'HOUR': + oToken["aLabels"] = ["heure"]; + break; + case 'WORD_ELIDED': + oToken["aLabels"] = [this.dValues.gl_get(oToken.sValue, "préfixe élidé inconnu")]; + break; + case 'WORD_ORDINAL': + oToken["aLabels"] = ["nombre ordinal"]; + break; + case 'FOLDERUNIX': + oToken["aLabels"] = ["dossier UNIX (et dérivés)"]; + break; + case 'FOLDERWIN': + oToken["aLabels"] = ["dossier Windows"]; + break; + case 'WORD_ACRONYM': + oToken["aLabels"] = ["sigle ou acronyme"]; + break; + case 'WORD': + if (oToken.hasOwnProperty("lMorph") && oToken["lMorph"].length > 0) { + // with morphology + oToken["aLabels"] = []; + for (let sMorph of oToken["lMorph"]) { + oToken["aLabels"].push(this.readableMorph(sMorph)); + } + if (oToken.hasOwnProperty("sTags")) { + let aTags = []; + for (let sTag of oToken["sTags"]) { + if (this.dValues.has(sTag)) { + aTags.push(this.dValues.get(sTag)) + } + } + if (aTags.length > 0) { + oToken["aOtherLabels"] = aTags; + } + } + } else { + // no morphology, guessing + if (oToken.sValue.gl_count("-") > 4) { + oToken["aLabels"] = ["élément complexe indéterminé"]; + } + else if (m = this._zPartDemForm.exec(oToken.sValue)) { + // mots avec particules démonstratives + oToken["aLabels"] = ["mot avec particule démonstrative"]; + } + else if (m = this._zImperatifVerb.exec(oToken.sValue)) { + // formes interrogatives + oToken["aLabels"] = ["forme verbale impérative"]; + } + else if (m = this._zInterroVerb.exec(oToken.sValue)) { + // formes interrogatives + oToken["aLabels"] = ["forme verbale interrogative"]; + } + } + break; + default: + oToken["aLabels"] = ["token de nature inconnue"]; + } + } catch (e) { + console.error(e); + } + return null; + }, getInfoForToken: function (oToken) { // Token: .sType, .sValue, .nStart, .nEnd // return a object {sType, sValue, aLabel} let m = null; @@ -415,11 +561,11 @@ case 'PUNC': case 'SIGN': return { sType: oToken.sType, sValue: oToken.sValue, - aLabel: [this.dChar.gl_get(oToken.sValue, "caractère indéterminé")] + aLabel: [this.dValues.gl_get(oToken.sValue, "caractère indéterminé")] }; break; case 'NUM': return { sType: oToken.sType, @@ -468,15 +614,14 @@ sValue: oToken.sValue, aLabel: ["heure"] }; break; case 'WORD_ELIDED': - let sTemp = oToken.sValue.replace("’", "").replace("'", "").replace("`", "").toLowerCase(); return { sType: oToken.sType, sValue: oToken.sValue, - aLabel: [this.dElidedPrefix.gl_get(sTemp, "préfixe élidé inconnu")] + aLabel: [this.dValues.gl_get(oToken.sValue.toLowerCase(), "préfixe élidé inconnu")] }; break; case 'WORD_ORDINAL': return { sType: oToken.sType, @@ -524,34 +669,34 @@ return { sType: oToken.sType, sValue: oToken.sValue, aLabel: ["mot avec particule démonstrative"], aSubElem: [ - { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) }, - { sType: oToken.sType, sValue: "-" + m[2], aLabel: [this._formatSuffix(m[2].toLowerCase())] } + { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) }, + { sType: oToken.sType, sValue: m[2], aLabel: [ this._formatSuffix(m[2]) ] } ] }; } else if (m = this._zImperatifVerb.exec(oToken.sValue)) { // formes interrogatives return { sType: oToken.sType, sValue: oToken.sValue, aLabel: ["forme verbale impérative"], aSubElem: [ - { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) }, - { sType: oToken.sType, sValue: "-" + m[2], aLabel: [this._formatSuffix(m[2].toLowerCase())] } + { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) }, + { sType: oToken.sType, sValue: m[2], aLabel: [ this._formatSuffix(m[2]) ] } ] }; } else if (m = this._zInterroVerb.exec(oToken.sValue)) { // formes interrogatives return { sType: oToken.sType, sValue: oToken.sValue, aLabel: ["forme verbale interrogative"], aSubElem: [ - { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) }, - { sType: oToken.sType, sValue: "-" + m[2], aLabel: [this._formatSuffix(m[2].toLowerCase())] } + { sType: oToken.sType, sValue: m[1], aLabel: this._getMorph(m[1]) }, + { sType: oToken.sType, sValue: m[2], aLabel: [ this._formatSuffix(m[2]) ] } ] }; } else if (this.oSpellChecker.isValidToken(oToken.sValue)) { return { sType: oToken.sType, @@ -580,65 +725,24 @@ }, _getMorph (sWord) { let aElem = []; for (let s of this.oSpellChecker.getMorph(sWord)) { - if (s.includes(":")) aElem.push(this._formatTags(s)); + if (s.includes(":")) aElem.push(this.readableMorph(s)); } if (aElem.length == 0) { aElem.push("mot inconnu du dictionnaire"); } return aElem; }, - _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 += this.dTag.get(m[0])[0]; - } - if (sRes.startsWith(" verbe") && !sRes.includes("infinitif")) { - sRes += " [" + sTags.slice(1, sTags.indexOf("/")) + "]"; - } - if (!sRes) { - return "#Erreur. Étiquette inconnue : [" + sTags + "]"; - } - return sRes.gl_trimRight(","); - }, - - _formatTagsLoc (sTags) { - let sRes = ""; - let m; - while ((m = this._zTag.exec(sTags)) !== null) { - if (m[0].startsWith(":LV")) { - sRes += this.dLocTag.get(":LV"); - for (let c of m[0].slice(3)) { - sRes += this.dLocVerb.get(c); - } - } else { - sRes += this.dLocTag.get(m[0]); - } - } - if (!sRes) { - return "#Erreur. Étiquette inconnue : [" + sTags + "]"; - } - return sRes.gl_trimRight(","); - }, - - _formatSuffix (s) { - if (s.startsWith("t-")) { - return "“t” euphonique +" + this.dPronoms.get(s.slice(2)); - } - if (!s.includes("-")) { - return this.dPronoms.get(s.replace("’", "'")); - } - if (s.endsWith("ous")) { - s += '2'; - } - let nPos = s.indexOf("-"); - return this.dPronoms.get(s.slice(0, nPos)) + " +" + this.dPronoms.get(s.slice(nPos + 1)); + _formatSuffix (sSuffix) { + sSuffix = sSuffix.replace(/['’ʼ‘‛´`′‵՚ꞌꞋ]/g, "’").toLowerCase(); + if (this.dValues.has(sSuffix)) { + return this.dValues.get(sSuffix); + } + return " suffixe inconnu"; }, getListOfTokens (sText, bInfo=true) { let aElem = []; if (sText !== "") { @@ -654,106 +758,13 @@ } } return aElem; }, - * generateInfoForTokenList (lToken) { - for (let oToken of lToken) { - let aRes = this.getInfoForToken(oToken); - if (aRes) { - yield aRes; - } - } - }, - - getListOfTokensReduc (sText, bInfo=true) { - let lToken = this.getListOfTokens(sText.replace("'", "’").trim(), false); - let iToken = 0; - let aElem = []; - if (lToken.length == 0) { - return aElem; - } - do { - let oToken = lToken[iToken]; - let sMorphLoc = ''; - let aTokenTempList = [oToken]; - if (oToken.sType == "WORD" || oToken.sType == "WORD_ELIDED"){ - let iLocEnd = iToken + 1; - let oLocNode = this.oLocGraph[oToken.sValue.toLowerCase()]; - while (oLocNode) { - let oTokenNext = lToken[iLocEnd]; - iLocEnd++; - if (oTokenNext) { - oLocNode = oLocNode[oTokenNext.sValue.toLowerCase()]; - } - if (oLocNode && iLocEnd <= lToken.length) { - sMorphLoc = oLocNode["_:_"]; - aTokenTempList.push(oTokenNext); - } else { - break; - } - } - } - - if (sMorphLoc) { - // we have a locution - let sValue = ''; - for (let oTokenWord of aTokenTempList) { - sValue += oTokenWord.sValue+' '; - } - let oTokenLocution = { - 'nStart': aTokenTempList[0].nStart, - 'nEnd': aTokenTempList[aTokenTempList.length-1].nEnd, - 'sType': "LOC", - 'sValue': sValue.replace('’ ','’').trim(), - 'aSubToken': aTokenTempList - }; - if (bInfo) { - let aSubElem = null; - if (sMorphLoc.startsWith("*|")) { - // cette suite de tokens n’est une locution que dans certains cas minoritaires - oTokenLocution.sType = "LOCP"; - for (let oElem of this.generateInfoForTokenList(aTokenTempList)) { - aElem.push(oElem); - } - sMorphLoc = sMorphLoc.slice(2); - } else { - aSubElem = [...this.generateInfoForTokenList(aTokenTempList)]; - } - // cette suite de tokens est la plupart du temps une locution - let aFormatedTag = []; - for (let sTagLoc of sMorphLoc.split('|') ){ - aFormatedTag.push(this._formatTagsLoc(sTagLoc)); - } - aElem.push({ - sType: oTokenLocution.sType, - sValue: oTokenLocution.sValue, - aLabel: aFormatedTag, - aSubElem: aSubElem - }); - } else { - aElem.push(oTokenLocution); - } - iToken = iToken + aTokenTempList.length; - } - else { - // No locution, we just add information - if (bInfo) { - let aRes = this.getInfoForToken(oToken); - if (aRes) { - aElem.push(aRes); - } - } else { - aElem.push(oToken); - } - iToken++; - } - } while (iToken < lToken.length); - return aElem; - }, // Other functions + filterSugg: function (aSugg) { return aSugg.filter((sSugg) => { return !sSugg.endsWith("è") && !sSugg.endsWith("È"); }); } } Index: graphspell-js/spellchecker.js ================================================================== --- graphspell-js/spellchecker.js +++ graphspell-js/spellchecker.js @@ -169,10 +169,18 @@ if (!this.lexicographer) { return []; } return this.lexicographer.formatTags(sMorph); } + + setLabelsOnToken (oToken) { + if (!this.lexicographer) { + return; + } + this.lexicographer.setLabelsOnToken(oToken); + } + // Storage activateStorage () { this.bStorage = true; Index: graphspell/lexgraph_fr.py ================================================================== --- graphspell/lexgraph_fr.py +++ graphspell/lexgraph_fr.py @@ -7,11 +7,11 @@ # : a dictionary for default suggestions. # : a boolean False # if the boolean is True, 4 functions are required: # split(sWord) -> returns a list of string (that will be analyzed) # analyze(sWord) -> returns a string with the meaning of word -# formatTags(sTags) -> returns a string with the meaning of tags +# readableMorph(sMorph) -> returns a string with the meaning of tags # filterSugg(aWord) -> returns a filtered list of suggestions import re @@ -170,13 +170,16 @@ ':f': (" féminin", "féminin"), ':s': (" singulier", "singulier"), ':p': (" pluriel", "pluriel"), ':i': (" invariable", "invariable"), - ':V1': (" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"), - ':V2': (" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"), - ':V3': (" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"), + ':V1_': (" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"), + ':V2_': (" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"), + ':V3_': (" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"), + ':V1e': (" verbe (1ᵉʳ gr.),", "Verbe du 1ᵉʳ groupe"), + ':V2e': (" verbe (2ᵉ gr.),", "Verbe du 2ᵉ groupe"), + ':V3e': (" verbe (3ᵉ gr.),", "Verbe du 3ᵉ groupe"), ':V0e': (" verbe,", "Verbe auxiliaire être"), ':V0a': (" verbe,", "Verbe auxiliaire avoir"), ':Y': (" infinitif,", "infinitif"), ':P': (" participe présent,", "participe présent"), @@ -272,22 +275,25 @@ 'jusqu’': "(jusque), préposition", '-je': " pronom personnel sujet, 1ʳᵉ pers. sing.", '-tu': " pronom personnel sujet, 2ᵉ pers. sing.", '-il': " pronom personnel sujet, 3ᵉ pers. masc. sing.", + '-iel': " pronom personnel sujet, 3ᵉ pers. sing.", '-on': " pronom personnel sujet, 3ᵉ pers. sing. ou plur.", '-elle': " pronom personnel sujet, 3ᵉ pers. fém. sing.", '-t-il': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. masc. sing.", '-t-on': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. sing. ou plur.", '-t-elle': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. fém. sing.", + '-t-iel': " “t” euphonique + pronom personnel sujet, 3ᵉ pers. sing.", '-nous': " pronom personnel sujet/objet, 1ʳᵉ pers. plur. ou COI (à nous), plur.", '-vous': " pronom personnel sujet/objet, 2ᵉ pers. plur. ou COI (à vous), plur.", '-ils': " pronom personnel sujet, 3ᵉ pers. masc. plur.", '-elles': " pronom personnel sujet, 3ᵉ pers. masc. plur.", + '-iels': " pronom personnel sujet, 3ᵉ pers. plur.", - "-là": " particule démonstrative", - "-ci": " particule démonstrative", + "-là": " particule démonstrative (là)", + "-ci": " particule démonstrative (ci)", '-le': " COD, masc. sing.", '-la': " COD, fém. sing.", '-les': " COD, plur.", @@ -324,10 +330,45 @@ '-en': " pronom adverbial", "-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", + + '.': "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 ouvrant", + ']': "crochet fermant", + '{': "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", + '"': "guillemets droits (déconseillé en typographie)", + '/': "signe de la division", + '+': "signe de l’addition", + '*': "signe de la multiplication", + '=': "signe de l’égalité", + '<': "inférieur à", + '>': "supérieur à", + '⩽': "inférieur ou égal à", + '⩾': "supérieur ou égal à", + '%': "signe de pourcentage", + '‰': "signe pour mille" } _zElidedPrefix = re.compile("(?i)^([ldmtsnjcç]|lorsqu|presqu|jusqu|puisqu|quoiqu|quelqu|qu)[’'‘`ʼ]([\\w-]+)") _zCompoundWord = re.compile("(?i)(\\w+)(-(?:(?: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|ce))$") @@ -356,22 +397,26 @@ if sWord in _dValues: return _dValues[sWord] return "" -def formatTags (sTags): +def readableMorph (sMorph): "returns string: readable tags" sRes = "" - sTags = re.sub("(?<=V[1-3])[itpqnmr_eaxz]+", "", sTags) - sTags = re.sub("(?<=V0[ea])[itpqnmr_eaxz]+", "", sTags) - for m in _zTag.finditer(sTags): - sRes += _dTAGS.get(m.group(0), " [{}]".format(m.group(0)))[0] + sMorph = re.sub("(?<=V[0123][ea_])[itpqnmr_eaxz]+", "", sMorph) + for m in _zTag.finditer(sMorph): + if m.group(0) in _dTAGS: + sRes += _dTAGS[m.group(0)][0] + else: + sRes += " [" + m.group(0) + "]?" if sRes.startswith(" verbe") and not sRes.endswith("infinitif"): - sRes += " [{}]".format(sTags[1:sTags.find("/")]) + sRes += " [" + sMorph[1:sMorph.find("/")] +"]" + if not sRes: + return " [" + sMorph + "]: étiquettes inconnues" return sRes.rstrip(",") # Other functions def filterSugg (aSugg): "exclude suggestions" return filter(lambda sSugg: not sSugg.endswith(("è", "È")), aSugg) Index: graphspell/spellchecker.py ================================================================== --- graphspell/spellchecker.py +++ graphspell/spellchecker.py @@ -120,19 +120,24 @@ lMorph = self.getMorph(sElem) sLex = self.lexicographer.analyze(sElem) if sLex: aRes = [ (" | ".join(lMorph), sLex) ] else: - aRes = [ (sMorph, self.lexicographer.formatTags(sMorph)) for sMorph in lMorph ] + aRes = [ (sMorph, self.lexicographer.readableMorph(sMorph)) for sMorph in lMorph ] if aRes: lWordAndMorph.append((sElem, aRes)) return lWordAndMorph def readableMorph (self, sMorph): if not self.lexicographer: - return [] - return self.lexicographer.formatTags(sMorph) + return "" + return self.lexicographer.readableMorph(sMorph) + + def setLabelsOnToken (dToken): + if not self.lexicographer: + return + self.lexicographer.setLabelsOnToken(dToken) # Storage def activateStorage (self):