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 @@ -91,10 +91,14 @@ if (!bParagraph) { return gc_rules.lSentenceRules; } return gc_rules.lParagraphRules; }, + + getIgnoreRules: function (bParagraph) { + return gc_rules._aIgnoredRules; + }, ignoreRule: function (sRuleId) { _aIgnoredRules.add(sRuleId); }, @@ -1415,10 +1419,11 @@ exports._zEndOfSentence = gc_engine._zEndOfSentence; exports._zBeginOfParagraph = gc_engine._zBeginOfParagraph; exports._zEndOfParagraph = gc_engine._zEndOfParagraph; exports.getSentenceBoundaries = gc_engine.getSentenceBoundaries; // rules + exports.getIgnoreRules = gc_engine.getIgnoreRules; exports.ignoreRule = gc_engine.ignoreRule; exports.resetIgnoreRules = gc_engine.resetIgnoreRules; exports.reactivateRule = gc_engine.reactivateRule; exports.listRules = gc_engine.listRules; exports.getRules = gc_engine.getRules; Index: gc_lang/fr/build.py ================================================================== --- gc_lang/fr/build.py +++ gc_lang/fr/build.py @@ -1,8 +1,9 @@ # Builder for French language import os +import subprocess import platform import zipfile from distutils import dir_util, file_util import helpers @@ -89,8 +90,20 @@ if not os.path.isdir(spLangPack+"/"+sf): hZip.write(spLangPack+"/"+sf, sAddPath+spLangPack+"/"+sf) def createNodeJSPackage (sLang): + print("Building for NodeJS") helpers.createCleanFolder("_build/nodejs/"+sLang) dir_util.copy_tree("gc_lang/"+sLang+"/nodejs/", "_build/nodejs/"+sLang) dir_util.copy_tree("grammalecte-js", "_build/nodejs/"+sLang+"/core/grammalecte") + corePack = "" + cliPack = "" + with helpers.cd("_build/nodejs/"+sLang): + corePack = subprocess.check_output("npm pack ./core", shell=True) + with helpers.cd("_build/nodejs/"+sLang+"/cli"): + subprocess.check_output("npm --no-save install ../"+corePack.decode("utf-8").split('\n', 1)[0], shell=True) + with helpers.cd("_build/nodejs/"+sLang): + cliPack = subprocess.check_output("npm pack ./cli", shell=True) + print("Fichiers à distribuer:") + print(" pour le dev: "+corePack.decode("utf-8").split('\n', 1)[0]) + print(" pour une installation du client: "+cliPack.decode("utf-8").split('\n', 1)[0]) Index: gc_lang/fr/nodejs/cli/bin/gramma-cli.js ================================================================== --- gc_lang/fr/nodejs/cli/bin/gramma-cli.js +++ gc_lang/fr/nodejs/cli/bin/gramma-cli.js @@ -109,16 +109,34 @@ short: "", arg: "+/-name", description: "Définit les options à utiliser par le correcteur grammatical.", execute: "" }, + gcerule: { + short: "", + arg: "+/-name", + description: "Définit les règles à exclure par le correcteur grammatical.", + execute: "" + }, tfoption: { short: "", arg: "+/-name", description: "Définit les options à utiliser par le formateur de texte.", execute: "" - } + }, + dicomain: { + short: "", + arg: "path/json", + description: "Charge un dictionnaire principal.", + execute: "" + }, + dicoperso: { + short: "", + arg: "path/json", + description: "Charge un dictionnaire personnel.", + execute: "" + }, }; var cmdOne = ["json", "perf", "help", "exit"]; var cmdMulti = ["text", "format", "check", "lexique", "spell", "suggest", "morph", "lemma"]; @@ -159,11 +177,11 @@ } function repToText(oRep) { //console.log(oRep); let repText = ""; - for (const action of ["json", "perf", "gceoption", "tfoption"]) { + for (const action of ["json", "perf", "gceoption", "tfoption", "gcerule", "dicomain", "dicoperso"]) { if (action in oRep) { repText += toTitle(action) + " " + oRep[action]; } } @@ -295,11 +313,11 @@ numRep1++; if (numRep1 == replength) { ascii1 = "└"; ascii1a = " "; } - repText += "\n " + ascii1 + " " + gramma.nStart + "->" + gramma.nEnd + " " + gramma.sMessage; + repText += "\n " + ascii1 + " " + gramma.nStart + "->" + gramma.nEnd + " [" + gramma.sRuleId + "]\n " + ascii1a + " " + gramma.sMessage; ascii2 = "├"; numRep2 = 0; for (let suggestion of gramma.aSuggestions) { numRep2++; if (numRep2 == gramma.aSuggestions.length) { @@ -408,13 +426,21 @@ repPreference[action] = getArgVal(aArg, [action]); repAction[action] = repPreference[action] ? "ON" : "OFF"; } } - for (const action of ["gceoption", "tfoption"]) { + if (getArg(aArg, ["dicomain"])) { + repAction["dicomain"] = "Chargement du dictionnaire principal " + (oGrammarChecker.setMainDictionary(sText) ? "OK" : "Pas OK"); + } + + if (getArg(aArg, ["dicoperso"])) { + repAction["dicoperso"] = "Chargement du dictionnaire personnel " + (oGrammarChecker.setPersonalDictionary(sText) ? "OK" : "Pas OK"); + } + + for (const action of ["gceoption", "tfoption", "gcerule"]) { if (getArg(aArg, [action])) { - let sFonction = action == "gceoption" ? "GceOption" : "TfOption"; + let sFonction = action == "gceoption" ? "GceOption" : action == "tfoption" ? "TfOption" : "GceIgnoreRule"; let sOpt = sText.split(" "); if (sOpt[0] == "reset") { oGrammarChecker["reset" + sFonction + "s"](); repAction[action] = "reset"; } else { @@ -460,11 +486,11 @@ repAction["help"].push(""); repAction["help"].push("========================= Les commandes/arguments: ========================"); repAction["help"].push(""); for (const action in cmdAction) { - repAction["help"].push(action.padEnd(10, " ") + ": " + cmdAction[action].arg.padEnd(8, " ") + ": " + cmdAction[action].description); + repAction["help"].push(action.padEnd(10, " ") + ": " + cmdAction[action].arg.padEnd(10, " ") + ": " + cmdAction[action].description); } repAction["help"].push(""); repAction["help"].push("================================== Note: =================================="); repAction["help"].push(""); repAction["help"].push("En mode client: les arguments sont de la forme «--argument» !"); Index: gc_lang/fr/nodejs/cli/package.json ================================================================== --- gc_lang/fr/nodejs/cli/package.json +++ gc_lang/fr/nodejs/cli/package.json @@ -7,12 +7,16 @@ "french", "grammar", "proofreader" ], "author": "Sébastien GRAVIER, Olivier R.", - "license": "GPL-3.0-or-later", + "license": "GPL-3.0", "homepage": "https://www.dicollecte.org/", + "repository": { + "type" : "fossil", + "url" : "http://212.47.254.152:8080/index" + }, "bin": { "gramma-cli": "bin/gramma-cli.js" }, "engines": { "node": ">=9.0.0" @@ -21,12 +25,15 @@ "test": "node bin/gramma-cli.js" }, "dependencies": { "grammalecte": "~1.0.0" }, + "bundledDependencies": [ + "grammalecte" + ], "files": [ "bin", "lib", "data", "readme.md" ] } Index: gc_lang/fr/nodejs/cli/readme.md ================================================================== --- gc_lang/fr/nodejs/cli/readme.md +++ gc_lang/fr/nodejs/cli/readme.md @@ -12,26 +12,29 @@ > npm install grammalecte-cli -g ## Commandes -| Commande | Argument | Description | -| --------- | -------- | ------------------------------------------------------------- | -| help | | Affiche les informations que vous lisez ;) | -| perf | on/off | Permet d’afficher le temps d’exécution des commandes. | -| json | on/off | Réponse en format json. | -| exit | | Client interactif : permet de le quitter. | -| text | texte | Client / Server: Définir un texte pour plusieurs actions. | -| format | texte | Permet de mettre en forme le texte. | -| check | texte | Vérifie la grammaire et l’orthographe d'un texte. | -| lexique | texte | Affiche le lexique du texte. | -| spell | mot | Vérifie l’existence d'un mot. | -| suggest | mot | Suggestion des orthographes possible d’un mot. | -| morph | mot | Affiche les informations pour un mot. | -| lemma | mot | Donne le lemme d’un mot. | -| gceoption | +/-name | Définit les options à utiliser par le correcteur grammatical. | -| tfoption | +/-name | Définit les options à utiliser par le formateur de texte. | +| Commande | Argument | Description | +| --------- | --------- | ------------------------------------------------------------- | +| help | | Affiche les informations que vous lisez ;) | +| perf | on/off | Permet d’afficher le temps d’exécution des commandes. | +| json | on/off | Réponse en format json. | +| exit | | Client interactif : permet de le quitter. | +| text | texte | Client / Server: Définir un texte pour plusieurs actions. | +| format | texte | Permet de mettre en forme le texte. | +| check | texte | Vérifie la grammaire et l’orthographe d'un texte. | +| lexique | texte | Affiche le lexique du texte. | +| spell | mot | Vérifie l’existence d'un mot. | +| suggest | mot | Suggestion des orthographes possible d’un mot. | +| morph | mot | Affiche les informations pour un mot. | +| lemma | mot | Donne le lemme d’un mot. | +| gceoption | +/-name | Définit les options à utiliser par le correcteur grammatical. | +| gcerule | +/-name | Définit les règles à exclure par le correcteur grammatical. | +| tfoption | +/-name | Définit les options à utiliser par le formateur de texte. | +| dicomain | path/json | Charge un dictionnaire principal. | +| dicoperso | path/json | Charge un dictionnaire personnel. | ## Client interactif Le mode interactif est un mode question/réponse. Pour le lancer vous devez saisir `gramma-cli -i`. Index: gc_lang/fr/nodejs/core/api.js ================================================================== --- gc_lang/fr/nodejs/core/api.js +++ gc_lang/fr/nodejs/core/api.js @@ -7,12 +7,14 @@ /* jslint esversion:6 */ /* global require, exports, console */ "use strict"; -class GrammarChecker { +const path = require("path"); +const fs = require("fs"); +class GrammarChecker { constructor(aInit, sLangCode = "fr", sContext = "Javascript") { this.sLangCode = sLangCode; this.sContext = sContext; //Importation des fichiers nécessaire @@ -25,22 +27,22 @@ Tokenizer: false, TextFormatter: false, Lexicographer: false }; - if (aInit){ + if (aInit) { this.load(aInit); } } //Auto-chargement avec dépendence - load(aInit = ["Grammalecte", "Graphspell", "TextFormatter", "Lexicographer", "Tokenizer"]){ + load(aInit = ["Grammalecte", "Graphspell", "TextFormatter", "Lexicographer", "Tokenizer"]) { //aInit permet de charger que certain composant // => évite de charger toutes données si par exemple on a besoin que du lexigraphe // => sorte de gestionnaire de dépendence (peut être amélioré) this.isInit = {}; - if ( aInit.indexOf("Grammalecte") !== false ){ + if (aInit.indexOf("Grammalecte") !== false) { //console.log('init Grammalecte'); this._oGce = require(this.sPathRoot + "/fr/gc_engine.js"); this._oGce.load(this.sContext); this.isInit.Grammalecte = true; this.oSpellChecker = this._oGce.getSpellChecker(); @@ -47,34 +49,34 @@ this.isInit.Graphspell = true; this.oTokenizer = this.oSpellChecker.getTokenizer(); this.isInit.Tokenizer = true; } - if ( !this.isInit.Graphspell && (aInit.indexOf("Graphspell") !== false || aInit.indexOf("Lexicographer") !== false)){ + if (!this.isInit.Graphspell && (aInit.indexOf("Graphspell") !== false || aInit.indexOf("Lexicographer") !== false)) { //console.log('init Graphspell'); this._SpellChecker = require(this.sPathRoot + "/graphspell/spellchecker.js"); this.oSpellChecker = new this._SpellChecker.SpellChecker(this.sLangCode, this.sPathRoot + "/graphspell/_dictionaries"); this.isInit.Graphspell = true; this.oTokenizer = this.oSpellChecker.getTokenizer(); this.isInit.Tokenizer = true; } - if ( !this.isInit.Tokenizer && aInit.indexOf("Tokenizer") !== false ){ + if (!this.isInit.Tokenizer && aInit.indexOf("Tokenizer") !== false) { //console.log('init Tokenizer'); this._Tokenizer = require(this.sPathRoot + "/graphspell/tokenizer.js"); this.oTokenizer = new this._Tokenizer.Tokenizer(this.sLangCode); this.isInit.Tokenizer = true; } - if ( aInit.indexOf("TextFormatter") !== false ){ + if (aInit.indexOf("TextFormatter") !== false) { //console.log('init TextFormatter'); this._oText = require(this.sPathRoot + "/fr/textformatter.js"); this.oTextFormatter = new this._oText.TextFormatter(); this.isInit.TextFormatter = true; } - if ( aInit.indexOf("Lexicographer") !== false ){ + if (aInit.indexOf("Lexicographer") !== false) { //console.log('init Lexicographer'); this._oLex = require(this.sPathRoot + "/fr/lexicographe.js"); this.oLexicographer = new this._oLex.Lexicographe( this.oSpellChecker, this.oTokenizer, @@ -83,39 +85,39 @@ this.isInit.Lexicographer = true; } } //Fonctions concernant: Grammalecte - getGrammalecte(){ + getGrammalecte() { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } return this._oGce; } - gramma(sText){ + gramma(sText) { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } return Array.from(this._oGce.parse(sText, this.sLangCode)); } - getGceOptions () { + getGceOptions() { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } return this._helpers.mapToObject(this._oGce.getOptions()); } - getGceDefaultOptions () { + getGceDefaultOptions() { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } return this._helpers.mapToObject(this._oGce.getDefaultOptions()); } - setGceOptions (dOptions) { + setGceOptions(dOptions) { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } if (!(dOptions instanceof Map)) { dOptions = this._helpers.objectToMap(dOptions); @@ -122,11 +124,11 @@ } this._oGce.setOptions(dOptions); return this._helpers.mapToObject(this._oGce.getOptions()); } - setGceOption (sOptName, bValue) { + setGceOption(sOptName, bValue) { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } if (sOptName) { this._oGce.setOption(sOptName, bValue); @@ -133,31 +135,117 @@ return this._helpers.mapToObject(this._oGce.getOptions()); } return false; } - resetGceOptions () { + resetGceOptions() { if (!this.isInit.Grammalecte) { this.load(["Grammalecte"]); } this._oGce.resetOptions(); return this._helpers.mapToObject(this._oGce.getOptions()); } + + getGceRules(bParagraph) { + if (!this.isInit.Grammalecte) { + this.load(["Grammalecte"]); + } + return this._oGce.getRules(bParagraph); + } + + getGceIgnoreRules() { + if (!this.isInit.Grammalecte) { + this.load(["Grammalecte"]); + } + return Array.from(this._oGce.getIgnoreRules()); + } + + setGceIgnoreRules(dRules) { + if (!this.isInit.Grammalecte) { + this.load(["Grammalecte"]); + } + if (!(dRules instanceof Set)) { + dRules = new Set(dRules); + } + this._oGce._aIgnoredRules = dRules; + return Array.from(this._oGce.getIgnoreRules()); + } + + setGceIgnoreRule(sRuleId, bValue) { + if (!this.isInit.Grammalecte) { + this.load(["Grammalecte"]); + } + if (bValue) { + //Add + this._oGce.ignoreRule(sRuleId); + } else { + //Delete + this._oGce.reactivateRule(sRuleId); + } + return Array.from(this._oGce.getIgnoreRules()); + } + + resetGceIgnoreRules() { + if (!this.isInit.Grammalecte) { + this.load(["Grammalecte"]); + } + this._oGce.resetIgnoreRules(); + return Array.from(this._oGce.getIgnoreRules()); + } //Fonctions concernant: Graphspell - getGraphspell(){ + getGraphspell() { if (!this.isInit.Graphspell) { this.load(["Graphspell"]); } return this.oSpellChecker; } - spellParagraph(sText, bSuggest = true){ + setMainDictionary(dictionary) { + if (typeof dictionary == "string") { + let pathnormalized = path.normalize(dictionary); + if (pathnormalized == "fr-allvars" || pathnormalized == "fr-classic" || pathnormalized == "fr-reform") { + pathnormalized = path.normalize(this.sPathRoot + "/graphspell/_dictionaries/" + pathnormalized); + } + pathnormalized = !pathnormalized.endsWith(".json") ? pathnormalized + ".json" : pathnormalized; + if (fs.existsSync(pathnormalized)) { + let filename = path.basename(pathnormalized); + let dirname = path.dirname(pathnormalized); + return this.oSpellChecker.setMainDictionary(filename, dirname); + } + return false; + } + //It's a valid json? + if (typeof dictionary !== "undefined" && dictionary.sHeader && dictionary.sHeader.startsWith("/grammalecte-fsa/")) { + return this.oSpellChecker.setMainDictionary(dictionary); + } + return false; + } + + setPersonalDictionary(dictionary, bActivate = true) { + if (typeof dictionary == "string") { + let pathnormalized = path.normalize(dictionary); + pathnormalized = !pathnormalized.endsWith(".json") ? pathnormalized + ".json" : pathnormalized; + if (fs.existsSync(pathnormalized)) { + let filename = path.basename(pathnormalized); + let dirname = path.dirname(pathnormalized); + return this.oSpellChecker.setPersonalDictionary(filename, dirname, bActivate); + } + return false; + } + //It's a valid json? + if (typeof dictionary !== "undefined" && dictionary.sHeader && dictionary.sHeader.startsWith("/grammalecte-fsa/")) { + return this.oSpellChecker.setPersonalDictionary(dictionary, "", bActivate); + } + return false; + } + + spellParagraph(sText, bSuggest = true) { if (!this.isInit.Graphspell) { this.load(["Graphspell"]); } - if (bSuggest){ + if (bSuggest) { let lError = this.oSpellChecker.parseParagraph(sText); for (let token of lError) { token.aSuggestions = this.suggest(token.sValue); } return lError; @@ -164,23 +252,23 @@ } else { return this.oSpellChecker.parseParagraph(sText); } } - spell(sWord){ + spell(sWord) { if (!this.isInit.Graphspell) { this.load(["Graphspell"]); } return this.oSpellChecker.isValid(sWord); } - suggest(sWord, nbLimit = 10, bMerge = true){ + suggest(sWord, nbLimit = 10, bMerge = true) { if (!this.isInit.Graphspell) { this.load(["Graphspell"]); } let lSuggest = this.oSpellChecker.suggest(sWord, nbLimit); - if (bMerge){ + if (bMerge) { let lSuggestRep = []; for (let lSuggestTmp of lSuggest) { for (let word of lSuggestTmp) { lSuggestRep.push(word); } @@ -187,51 +275,50 @@ } return lSuggestRep; } else { return Array.from(lSuggest); } - } - lemma(sWord){ + lemma(sWord) { if (!this.isInit.Graphspell) { this.load(["Graphspell"]); } return this.oSpellChecker.getLemma(sWord); } - morph(sWord){ + morph(sWord) { if (!this.isInit.Graphspell) { this.load(["Graphspell"]); } return this.oSpellChecker.getMorph(sWord); } //Fonctions concernant: Lexicographer - getLexicographer(){ + getLexicographer() { if (!this.isInit.Lexicographer) { this.load(["Lexicographer"]); } return this.oLexicographer; } - lexique(sText){ + lexique(sText) { if (!this.isInit.Lexicographer) { this.load(["Lexicographer"]); } return this.oLexicographer.getListOfTokensReduc(sText); } //Fonctions concernant: TextFormatter - getTextFormatter(){ + getTextFormatter() { if (!this.isInit.TextFormatter) { this.load(["TextFormatter"]); } return this.oTextFormatter; } - formatText(sText){ + formatText(sText) { if (!this.isInit.TextFormatter) { this.load(["TextFormatter"]); } return this.oTextFormatter.formatText(sText); } @@ -264,20 +351,19 @@ this.oTextFormatter.setOptions(optionsTF); return this._helpers.mapToObject(this.oTextFormatter.getOptions()); } //fonctions concernant plussieurs parties - verifParagraph(sText, bSuggest = true){ + verifParagraph(sText, bSuggest = true) { if (!this.isInit.Grammalecte || !this.isInit.Graphspell) { this.load(["Grammalecte"]); } return { lGrammarErrors: Array.from(this._oGce.parse(sText, this.sLangCode)), lSpellingErrors: this.spellParagraph(sText, bSuggest) }; } - } if (typeof exports !== "undefined") { exports.GrammarChecker = GrammarChecker; } Index: gc_lang/fr/nodejs/core/package.json ================================================================== --- gc_lang/fr/nodejs/core/package.json +++ gc_lang/fr/nodejs/core/package.json @@ -6,15 +6,19 @@ "french", "grammar", "proofreader" ], "author": "Olivier R.", - "license": "GPL-3.0-or-later", + "license": "GPL-3.0", "homepage": "https://www.dicollecte.org/", + "repository": { + "type" : "fossil", + "url" : "http://212.47.254.152:8080/index" + }, "main": "api.js", "engines": { "node": ">=9.0.0" }, "scripts": { "test": "echo \"Error: no test specified\"" } }