Index: gc_core/js/helpers.js
==================================================================
--- gc_core/js/helpers.js
+++ gc_core/js/helpers.js
@@ -61,11 +61,11 @@
             xRequest.send();
             return xRequest.responseText;
         }
         catch (e) {
             this.logerror(e);
-            return null
+            return null;
         }
     },
 
     // conversions
     objectToMap: function (obj) {
@@ -82,11 +82,11 @@
         for (let [k, v] of m) {
             obj[k] = v;
         }
         return obj;
     }
-}
+};
 
 
 if (typeof(exports) !== 'undefined') {
     exports.setLogOutput = helpers.setLogOutput;
     exports.echo = helpers.echo;

Index: gc_core/js/ibdawg.js
==================================================================
--- gc_core/js/ibdawg.js
+++ gc_core/js/ibdawg.js
@@ -74,18 +74,18 @@
                 throw ValueError("# Error: unknown code: " + this.nVersion);
         }
         //console.log(this.getInfo());
         this.bOptNumSigle = true;
         this.bOptNumAtLast = false;
-    };
+    }
 
     getInfo () {
         return  `  Language: ${this.sLang}      Version: ${this.nVersion}      Stemming: ${this.cStemming}FX\n` +
                 `  Arcs values:  ${this.nArcVal} = ${this.nChar} characters,  ${this.nAff} affixes,  ${this.nTag} tags\n` +
                 `  Dictionary: ${this.nEntries} entries,    ${this.nNode} nodes,   ${this.nArc} arcs\n` +
                 `  Address size: ${this.nBytesNodeAddress} bytes,  Arc size: ${this.nBytesArc} bytes\n`;
-    };
+    }
 
     isValidToken (sToken) {
         // checks if sToken is valid (if there is hyphens in sToken, sToken is split, each part is checked)
         if (this.isValid(sToken)) {
             return true;
@@ -95,11 +95,11 @@
                 return true;
             }
             return sToken.split("-").every(sWord  =>  this.isValid(sWord)); 
         }
         return false;
-    };
+    }
 
     isValid (sWord) {
         // checks if sWord is valid (different casing tested if the first letter is a capital)
         if (!sWord) {
             return null;
@@ -125,11 +125,11 @@
             } else {
                 return !!this.lookup(sWord.toLowerCase());
             }
         }
         return false;
-    };
+    }
 
     _convBytesToInteger (aBytes) {
         // Byte order = Big Endian (bigger first)
         let nVal = 0;
         let nWeight = (aBytes.length - 1) * 8;
@@ -136,11 +136,11 @@
         for (let n of aBytes) {
             nVal += n << nWeight;
             nWeight = nWeight - 8;
         }
         return nVal;
-    };
+    }
 
     lookup (sWord) {
         // returns true if sWord in dictionary (strict verification)
         let iAddr = 0;
         for (let c of sWord) {
@@ -151,11 +151,11 @@
             if (iAddr === null) {
                 return false;
             }
         }
         return Boolean(this._convBytesToInteger(this.byDic.slice(iAddr, iAddr+this.nBytesArc)) & this._finalNodeMask);
-    };
+    }
 
     getMorph (sWord) {
         // retrieves morphologies list, different casing allowed
         let l = this.morph(sWord);
         if (sWord[0].gl_isUpperCase()) {
@@ -163,15 +163,15 @@
             if (sWord.gl_isUpperCase() && sWord.length > 1) {
                 l = l.concat(this.morph(sWord.gl_toCapitalize()));
             }
         }
         return l;
-    };
+    }
 
     // morph (sWord) {
     //     is defined in constructor
-    // };
+    // }
     
     // VERSION 1
     _morph1 (sWord) {
         // returns morphologies of sWord
         let iAddr = 0;
@@ -207,11 +207,11 @@
                 iAddr = iEndArcAddr + this.nBytesNodeAddress;
             }
             return l;
         }
         return [];
-    };
+    }
 
     _stem1 (sWord) {
         // returns stems list of sWord
         let iAddr = 0;
         for (let c of sWord) {
@@ -237,11 +237,11 @@
                 iAddr = iEndArcAddr + this.nBytesNodeAddress;
             }
             return l;
         }
         return [];
-    };
+    }
 
     _lookupArcNode1 (nVal, iAddr) {
         // looks if nVal is an arc at the node at iAddr, if yes, returns address of next node else None
         while (true) {
             let iEndArcAddr = iAddr+this.nBytesArc;
@@ -257,39 +257,39 @@
                     return null;
                 }
                 iAddr = iEndArcAddr + this.nBytesNodeAddress;
             }
         }
-    };
+    }
 
     // VERSION 2
     _morph2 (sWord) {
         // to do
-    };
+    }
 
     _stem2 (sWord) {
         // to do
-    };
+    }
 
     _lookupArcNode2 (nVal, iAddr) {
         // to do
-    };
+    }
 
 
     // VERSION 3
     _morph3 (sWord) {
         // to do
-    };
+    }
 
     _stem3 (sWord) {
         // to do
-    };
+    }
 
     _lookupArcNode3 (nVal, iAddr) {
         // to do
-    };
+    }
 }
 
 
 if (typeof(exports) !== 'undefined') {
     exports.IBDAWG = IBDAWG;
 }

Index: gc_core/js/jsex_map.js
==================================================================
--- gc_core/js/jsex_map.js
+++ gc_core/js/jsex_map.js
@@ -6,42 +6,42 @@
         let oNewMap = new Map();
         for (let [key, val] of this.entries()) {
             oNewMap.set(key, val);
         }
         return oNewMap;
-    }
+    };
 
     Map.prototype.gl_get = function (key, defaultValue) {
         let res = this.get(key);
         if (res !== undefined) {
             return res;
         }
         return defaultValue;
-    }
+    };
 
     Map.prototype.gl_toString = function () {
         // Default .toString() gives nothing useful
         let sRes = "{ ";
         for (let [k, v] of this.entries()) {
             sRes += (typeof k === "string") ? '"' + k + '": ' : k.toString() + ": ";
             sRes += (typeof v === "string") ? '"' + v + '", ' : v.toString() + ", ";
         }
-        sRes = sRes.slice(0, -2) + " }"
+        sRes = sRes.slice(0, -2) + " }";
         return sRes;
-    }
+    };
 
     Map.prototype.gl_update = function (dDict) {
         for (let [k, v] of dDict.entries()) {
             this.set(k, v);
         }
-    }
+    };
 
     Map.prototype.gl_updateOnlyExistingKeys = function (dDict) {
         for (let [k, v] of dDict.entries()) {
             if (this.has(k)){
                 this.set(k, v);
             }
         }
-    }
+    };
 
     Map.prototype.grammalecte = true;
 }

Index: gc_core/js/jsex_regex.js
==================================================================
--- gc_core/js/jsex_regex.js
+++ gc_core/js/jsex_regex.js
@@ -40,23 +40,23 @@
                             // at the end of the pattern
                             m.start.push(this.lastIndex - m[i].length);
                             m.end.push(this.lastIndex);
                         } else if (codePos === "w") {
                             // word in the middle of the pattern
-                            iPos = m[0].search("[ ’,()«»“”]"+m[i]+"[ ,’()«»“”]") + 1 + m.index
+                            iPos = m[0].search("[ ’,()«»“”]"+m[i]+"[ ,’()«»“”]") + 1 + m.index;
                             m.start.push(iPos);
-                            m.end.push(iPos + m[i].length)
+                            m.end.push(iPos + m[i].length);
                         } else if (codePos === "*") {
                             // anywhere
                             iPos = m[0].indexOf(m[i]) + m.index;
                             m.start.push(iPos);
-                            m.end.push(iPos + m[i].length)
+                            m.end.push(iPos + m[i].length);
                         } else if (codePos === "**") {
                             // anywhere after previous group
                             iPos = m[0].indexOf(m[i], m.end[i-1]-m.index) + m.index;
                             m.start.push(iPos);
-                            m.end.push(iPos + m[i].length)
+                            m.end.push(iPos + m[i].length);
                         } else if (codePos.startsWith(">")) {
                             // >x:_
                             // todo: look in substring x
                             iPos = m[0].indexOf(m[i]) + m.index;
                             m.start.push(iPos);
@@ -81,9 +81,9 @@
             } else {
                 console.error(e);
             }
         }
         return m;
-    }
+    };
 
     RegExp.prototype.grammalecte = true;
 }

Index: gc_core/js/jsex_string.js
==================================================================
--- gc_core/js/jsex_string.js
+++ gc_core/js/jsex_string.js
@@ -13,45 +13,45 @@
         while ((iPos = this.indexOf(sSearch, iPos)) >= 0) {
             nOccur++;
             iPos += nStep;
         }
         return nOccur;
-    }
+    };
     String.prototype.gl_isDigit = function () {
         return (this.search(/^[0-9⁰¹²³⁴⁵⁶⁷⁸⁹]+$/) !== -1);
-    }
+    };
     String.prototype.gl_isLowerCase = function () {
         return (this.search(/^[a-zà-öø-ÿ0-9-]+$/) !== -1);
-    }
+    };
     String.prototype.gl_isUpperCase = function () {
         return (this.search(/^[A-ZÀ-ÖØ-ߌ0-9-]+$/) !== -1);
-    }
+    };
     String.prototype.gl_isTitle = function () {
         return (this.search(/^[A-ZÀ-ÖØ-ߌ][a-zà-öø-ÿ'’-]+$/) !== -1);
-    }
+    };
     String.prototype.gl_toCapitalize = function () {
         return this.slice(0,1).toUpperCase() + this.slice(1).toLowerCase();
-    }
+    };
     String.prototype.gl_expand = function (oMatch) {
         let sNew = this;
         for (let i = 0; i < oMatch.length ; i++) {
             let z = new RegExp("\\\\"+parseInt(i), "g");
             sNew = sNew.replace(z, oMatch[i]);
         }
         return sNew;
-    }
+    };
     String.prototype.gl_trimRight = function (sChars) {
         let z = new RegExp("["+sChars+"]+$");
         return this.replace(z, "");
-    }
+    };
     String.prototype.gl_trimLeft = function (sChars) {
         let z = new RegExp("^["+sChars+"]+");
         return this.replace(z, "");
-    }
+    };
     String.prototype.gl_trim = function (sChars) {
         let z1 = new RegExp("^["+sChars+"]+");
         let z2 = new RegExp("["+sChars+"]+$");
         return this.replace(z1, "").replace(z2, "");
-    }
+    };
 
     String.prototype.grammalecte = true;
 }

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
@@ -7,11 +7,10 @@
 ${map}
 
 
 if (typeof(require) !== 'undefined') {
     var helpers = require("resource://grammalecte/helpers.js");
-    var echo = require("resource://grammalecte/helpers.js").echo;
     var gc_options = require("resource://grammalecte/${lang}/gc_options.js");
     var gc_rules = require("resource://grammalecte/${lang}/gc_rules.js");
     var cregex = require("resource://grammalecte/${lang}/cregex.js");
     var text = require("resource://grammalecte/text.js");
 }
@@ -84,11 +83,11 @@
 
         // parse sentence
         for (let [iStart, iEnd] of this._getSentenceBoundaries(sText)) {
             if (4 < (iEnd - iStart) < 2000) {
                 dDA.clear();
-                //echo(sText.slice(iStart, iEnd));
+                //helpers.echo(sText.slice(iStart, iEnd));
                 try {
                     [, errs] = this._proofread(sText.slice(iStart, iEnd), sAlt.slice(iStart, iEnd), iStart, false, dDA, dPriority, sCountry, bDebug, bContext);
                     dErrors.gl_update(errs);
                 }
                 catch (e) {
@@ -102,11 +101,11 @@
     _zEndOfSentence: new RegExp ('([.?!:;…][ .?!… »”")]*|.$)', "g"),
     _zBeginOfParagraph: new RegExp ("^[-  –—.,;?!…]*", "ig"),
     _zEndOfParagraph: new RegExp ("[-  .,;?!…–—]*$", "ig"),
 
     _getSentenceBoundaries: function* (sText) {
-        let mBeginOfSentence = this._zBeginOfParagraph.exec(sText)
+        let mBeginOfSentence = this._zBeginOfParagraph.exec(sText);
         let iStart = this._zBeginOfParagraph.lastIndex;
         let m;
         while ((m = this._zEndOfSentence.exec(sText)) !== null) {
             yield [iStart, this._zEndOfSentence.lastIndex];
             iStart = this._zEndOfSentence.lastIndex;
@@ -126,60 +125,60 @@
                 for (let [zRegex, bUppercase, sLineId, sRuleId, nPriority, lActions, lGroups, lNegLookBefore] of lRuleGroup) {
                     if (!_aIgnoredRules.has(sRuleId)) {
                         while ((m = zRegex.gl_exec2(s, lGroups, lNegLookBefore)) !== null) {
                             bCondMemo = null;
                             /*if (bDebug) {
-                                echo(">>>> Rule # " + sLineId + " - Text: " + s + " opt: "+ sOption);
+                                helpers.echo(">>>> Rule # " + sLineId + " - Text: " + s + " opt: "+ sOption);
                             }*/
                             for (let [sFuncCond, cActionType, sWhat, ...eAct] of lActions) {
                             // action in lActions: [ condition, action type, replacement/suggestion/action[, iGroup[, message, URL]] ]
                                 try {
-                                    //echo(oEvalFunc[sFuncCond]);
-                                    bCondMemo = (!sFuncCond || oEvalFunc[sFuncCond](s, sx, m, dDA, sCountry, bCondMemo))
+                                    //helpers.echo(oEvalFunc[sFuncCond]);
+                                    bCondMemo = (!sFuncCond || oEvalFunc[sFuncCond](s, sx, m, dDA, sCountry, bCondMemo));
                                     if (bCondMemo) {
                                         switch (cActionType) {
                                             case "-":
                                                 // grammar error
-                                                //echo("-> error detected in " + sLineId + "\nzRegex: " + zRegex.source);
+                                                //helpers.echo("-> error detected in " + sLineId + "\nzRegex: " + zRegex.source);
                                                 nErrorStart = nOffset + m.start[eAct[0]];
                                                 if (!dErrs.has(nErrorStart) || nPriority > dPriority.get(nErrorStart)) {
                                                     dErrs.set(nErrorStart, this._createError(s, sx, sWhat, nOffset, m, eAct[0], sLineId, sRuleId, bUppercase, eAct[1], eAct[2], bIdRule, sOption, bContext));
                                                     dPriority.set(nErrorStart, nPriority);
                                                 }
                                                 break;
                                             case "~":
                                                 // text processor
-                                                //echo("-> text processor by " + sLineId + "\nzRegex: " + zRegex.source);
+                                                //helpers.echo("-> text processor by " + sLineId + "\nzRegex: " + zRegex.source);
                                                 s = this._rewrite(s, sWhat, eAct[0], m, bUppercase);
                                                 bChange = true;
                                                 if (bDebug) {
-                                                    echo("~ " + s + "  -- " + m[eAct[0]] + "  # " + sLineId);
+                                                    helpers.echo("~ " + s + "  -- " + m[eAct[0]] + "  # " + sLineId);
                                                 }
                                                 break;
                                             case "=":
                                                 // disambiguation
-                                                //echo("-> disambiguation by " + sLineId + "\nzRegex: " + zRegex.source);
+                                                //helpers.echo("-> disambiguation by " + sLineId + "\nzRegex: " + zRegex.source);
                                                 oEvalFunc[sWhat](s, m, dDA);
                                                 if (bDebug) {
-                                                    echo("= " + m[0] + "  # " + sLineId + "\nDA: " + dDA.gl_toString());
+                                                    helpers.echo("= " + m[0] + "  # " + sLineId + "\nDA: " + dDA.gl_toString());
                                                 }
                                                 break;
                                             case ">":
                                                 // we do nothing, this test is just a condition to apply all following actions
                                                 break;
                                             default:
-                                                echo("# error: unknown action at " + sLineId);
+                                                helpers.echo("# error: unknown action at " + sLineId);
                                         }
                                     } else {
                                         if (cActionType == ">") {
                                             break;
                                         }
                                     }
                                 }
                                 catch (e) {
-                                    echo(s);
-                                    echo("# line id: " + sLineId + "\n# rule id: " + sRuleId);
+                                    helpers.echo(s);
+                                    helpers.echo("# line id: " + sLineId + "\n# rule id: " + sRuleId);
                                     helpers.logerror(e);
                                 }
                             }
                         }
                     }
@@ -221,11 +220,11 @@
             }
         }
         // Message
         let sMessage = "";
         if (sMsg.slice(0,1) === "=") {
-            sMessage = oEvalFunc[sMsg.slice(1)](s, m)
+            sMessage = oEvalFunc[sMsg.slice(1)](s, m);
         } else {
             sMessage = sMsg.gl_expand(m);
         }
         if (bIdRule) {
             sMessage += " ##" + sLineId + " #" + sRuleId;
@@ -260,11 +259,11 @@
             }
         } else {
             sNew = sRepl.gl_expand(m);
             sNew = sNew + " ".repeat(ln-sNew.length);
         }
-        //echo("\n"+s+"\nstart: "+m.start[iGroup]+" end:"+m.end[iGroup])
+        //helpers.echo("\n"+s+"\nstart: "+m.start[iGroup]+" end:"+m.end[iGroup])
         return s.slice(0, m.start[iGroup]) + sNew + s.slice(m.end[iGroup]);
     },
 
     // Actions on rules
 
@@ -353,11 +352,11 @@
     },
 
     resetOptions: function () {
         _dOptions = gc_options.getOptions(_sAppContext).gl_shallowCopy();
     }
-}
+};
 
 
 //////// Common functions
 
 function option (sOpt) {
@@ -366,69 +365,69 @@
 }
 
 function displayInfo (dDA, aWord) {
     // for debugging: info of word
     if (!aWord) {
-        echo("> nothing to find");
+        helpers.echo("> nothing to find");
         return true;
     }
     if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
-        echo("> not in FSA");
+        helpers.echo("> not in FSA");
         return true;
     }
     if (dDA.has(aWord[0])) {
-        echo("DA: " + dDA.get(aWord[0]));
+        helpers.echo("DA: " + dDA.get(aWord[0]));
     }
-    echo("FSA: " + _dAnalyses.get(aWord[1]));
+    helpers.echo("FSA: " + _dAnalyses.get(aWord[1]));
     return true;
 }
 
 function _storeMorphFromFSA (sWord) {
     // retrieves morphologies list from _oDict -> _dAnalyses
-    //echo("register: "+sWord + " " + _oDict.getMorph(sWord).toString())
+    //helpers.echo("register: "+sWord + " " + _oDict.getMorph(sWord).toString())
     _dAnalyses.set(sWord, _oDict.getMorph(sWord));
     return !!_dAnalyses.get(sWord);
 }
 
 function morph (dDA, aWord, sPattern, bStrict=true, bNoWord=false) {
     // analyse a tuple (position, word), return true if sPattern in morphologies (disambiguation on)
     if (!aWord) {
-        //echo("morph: noword, returns " + bNoWord);
+        //helpers.echo("morph: noword, returns " + bNoWord);
         return bNoWord;
     }
-    //echo("aWord: "+aWord.toString());
+    //helpers.echo("aWord: "+aWord.toString());
     if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
         return false;
     }
     let lMorph = dDA.has(aWord[0]) ? dDA.get(aWord[0]) : _dAnalyses.get(aWord[1]);
-    //echo("lMorph: "+lMorph.toString());
+    //helpers.echo("lMorph: "+lMorph.toString());
     if (lMorph.length === 0) {
         return false;
     }
-    //echo("***");
+    //helpers.echo("***");
     if (bStrict) {
         return lMorph.every(s  =>  (s.search(sPattern) !== -1));
     }
     return lMorph.some(s  =>  (s.search(sPattern) !== -1));
 }
 
 function morphex (dDA, aWord, sPattern, sNegPattern, bNoWord=false) {
     // analyse a tuple (position, word), returns true if not sNegPattern in word morphologies and sPattern in word morphologies (disambiguation on)
     if (!aWord) {
-        //echo("morph: noword, returns " + bNoWord);
+        //helpers.echo("morph: noword, returns " + bNoWord);
         return bNoWord;
     }
-    //echo("aWord: "+aWord.toString());
+    //helpers.echo("aWord: "+aWord.toString());
     if (!_dAnalyses.has(aWord[1]) && !_storeMorphFromFSA(aWord[1])) {
         return false;
     }
     let lMorph = dDA.has(aWord[0]) ? dDA.get(aWord[0]) : _dAnalyses.get(aWord[1]);
-    //echo("lMorph: "+lMorph.toString());
+    //helpers.echo("lMorph: "+lMorph.toString());
     if (lMorph.length === 0) {
         return false;
     }
-    //echo("***");
+    //helpers.echo("***");
     // check negative condition
     if (lMorph.some(s  =>  (s.search(sNegPattern) !== -1))) {
         return false;
     }
     // search sPattern
@@ -465,11 +464,11 @@
         return [];
     }
     if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
         return [];
     }
-    return [ for (s of _dAnalyses.get(sWord))  s.slice(1, s.indexOf(" ")) ];
+    return _dAnalyses.get(sWord).map( s => s.slice(1, s.indexOf(" ")) );
 }
 
 
 //// functions to get text outside pattern scope
 
@@ -507,18 +506,18 @@
 
 const _zPrevWord = new RegExp ("([a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_][a-zà-öA-Zø-ÿÀ-Ö0-9Ø-ßĀ-ʯfi-st_-]*) +$", "i");
 
 function prevword1 (s, iEnd) {
     // get previous word (optimization)
-    //echo("prev1, s:"+s);
-    //echo("prev1, s.slice(0, iEnd):"+s.slice(0, iEnd));
+    //helpers.echo("prev1, s:"+s);
+    //helpers.echo("prev1, s.slice(0, iEnd):"+s.slice(0, iEnd));
     let m = _zPrevWord.exec(s.slice(0, iEnd));
-    //echo("prev1, m:"+m);
+    //helpers.echo("prev1, m:"+m);
     if (!m) {
         return null;
     }
-    //echo("prev1: " + m.index + " " + m[1]);
+    //helpers.echo("prev1: " + m.index + " " + m[1]);
     return [m.index, m[1]];
 }
 
 function look (s, zPattern, zNegPattern=null) {
     // seek zPattern in s (before/after/fulltext), if antipattern zNegPattern not in s
@@ -565,16 +564,16 @@
         return true;
     }
     if (!_dAnalyses.has(sWord) && !_storeMorphFromFSA(sWord)) {
         return true;
     }
-    //echo("morph: "+_dAnalyses.get(sWord).toString());
+    //helpers.echo("morph: "+_dAnalyses.get(sWord).toString());
     if (_dAnalyses.get(sWord).length === 1) {
         return true;
     }
-    let lSelect = [ for (sMorph of _dAnalyses.get(sWord))  if (sMorph.search(sPattern) !== -1)  sMorph ];
-    //echo("lSelect: "+lSelect.toString());
+    let lSelect = _dAnalyses.get(sWord).filter( sMorph => sMorph.search(sPattern) === -1 );
+    //helpers.echo("lSelect: "+lSelect.toString());
     if (lSelect.length > 0) {
         if (lSelect.length != _dAnalyses.get(sWord).length) {
             dDA.set(nPos, lSelect);
         }
     } else if (lDefault) {
@@ -594,12 +593,12 @@
         return true;
     }
     if (_dAnalyses.get(sWord).length === 1) {
         return true;
     }
-    let lSelect = [ for (sMorph of _dAnalyses.get(sWord))  if (sMorph.search(sPattern) === -1)  sMorph ];
-    //echo("lSelect: "+lSelect.toString());
+    let lSelect = _dAnalyses.get(sWord).filter( sMorph => sMorph.search(sPattern) === -1 );
+    //helpers.echo("lSelect: "+lSelect.toString());
     if (lSelect.length > 0) {
         if (lSelect.length != _dAnalyses.get(sWord).length) {
             dDA.set(nPos, lSelect);
         }
     } else if (lDefault) {

Index: gc_core/js/str_transform.js
==================================================================
--- gc_core/js/str_transform.js
+++ gc_core/js/str_transform.js
@@ -21,11 +21,11 @@
         }
         let [sPfxCode, sSfxCode] = sAffCode.split('/');
         sFlex = sPfxCode.slice(1) + sFlex.slice(sPfxCode.charCodeAt(0)-48);
         return sSfxCode[0] == '0' ? sFlex + sSfxCode.slice(1) : sFlex.slice(0, -(sSfxCode.charCodeAt(0)-48)) + sSfxCode.slice(1);
     }
-}
+};
 
 
 if (typeof(exports) !== 'undefined') {
     exports.getStemFromSuffixCode = str_transform.getStemFromSuffixCode;
     exports.getStemFromAffixCode = str_transform.getStemFromAffixCode;

Index: gc_core/js/tests.js
==================================================================
--- gc_core/js/tests.js
+++ gc_core/js/tests.js
@@ -10,20 +10,20 @@
 
 class TestGrammarChecking {
 
     constructor (gce, spfTests="") {
         this.gce = gce;
-        this.spfTests = spfTests
+        this.spfTests = spfTests;
         this._aRuleTested = new Set();
-    };
+    }
 
     * testParse (bDebug=false) {
         const t0 = Date.now();
         let sURL = (this.spfTests !== "") ? this.spfTests : "resource://grammalecte/"+this.gce.lang+"/tests_data.json";
         const aData = JSON.parse(helpers.loadFile(sURL)).aData;
-        let nInvalid = 0
-        let nTotal = 0
+        let nInvalid = 0;
+        let nTotal = 0;
         let sErrorText;
         let sSugg;
         let sExpectedErrors;
         let sTextToCheck;
         let sFoundErrors;
@@ -62,11 +62,11 @@
                               "\n# Line num: " + sLineNum +
                               "\n> to check: " + sTextToCheck +
                               "\n  expected: " + sExpectedErrors +
                               "\n  found:    " + sFoundErrors +
                               "\n  errors:   \n" + sListErr;
-                        nInvalid = nInvalid + 1
+                        nInvalid = nInvalid + 1;
                     }
                     nTotal = nTotal + 1;
                 }
                 i = i + 1;
                 if (i % 1000 === 0) {
@@ -93,11 +93,11 @@
         }
 
         const t1 = Date.now();
         yield "Tests parse finished in " + ((t1-t0)/1000).toString()
             + " s\nTotal errors: " + nInvalid.toString() + " / " + nTotal.toString();
-    };
+    }
 
     _getExpectedErrors (sLine) {
         try {
             let sRes = " ".repeat(sLine.length);
             let z = /\{\{.+?\}\}/g;
@@ -119,11 +119,11 @@
         }
         catch (e) {
             helpers.logerror(e);
         }
         return " ".repeat(sLine.length);
-    };
+    }
 
     _getFoundErrors (sLine, bDebug, sOption) {
         try {
             let aErrs = [];
             if (sOption) {
@@ -144,13 +144,13 @@
         }
         catch (e) {
             helpers.logerror(e);
         }
         return [" ".repeat(sLine.length), ""];
-    };
+    }
 
 }
 
 
 if (typeof(exports) !== 'undefined') {
     exports.TestGrammarChecking = TestGrammarChecking;
 }

Index: gc_core/js/text.js
==================================================================
--- gc_core/js/text.js
+++ gc_core/js/text.js
@@ -57,11 +57,11 @@
         catch (e) {
             helpers.logerror(e);
             return "\n# Error. Data: " + oErr.toString();
         }
     }
-}
+};
 
 
 if (typeof(exports) !== 'undefined') {
     exports.getParagraph = text.getParagraph;
     exports.wrap = text.wrap;

Index: gc_core/js/tokenizer.js
==================================================================
--- gc_core/js/tokenizer.js
+++ gc_core/js/tokenizer.js
@@ -37,11 +37,11 @@
             [/^\d\d?[hm]\d\d\b/, 'HOUR'],
             [/^\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']
         ]
-}
+};
 
 
 class Tokenizer {
 
     constructor (sLang) {
@@ -48,11 +48,11 @@
         this.sLang = sLang;
         if (!aTkzPatterns.hasOwnProperty(sLang)) {
             this.sLang = "default";
         }
         this.aRules = aTkzPatterns[this.sLang];
-    };
+    }
 
     * genTokens (sText) {
         let m;
         let i = 0;
         while (sText) {
@@ -76,11 +76,11 @@
                 }
             }
             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)) {

Index: gc_lang/fr/modules-js/conj.js
==================================================================
--- gc_lang/fr/modules-js/conj.js
+++ gc_lang/fr/modules-js/conj.js
@@ -168,11 +168,11 @@
         catch (e) {
             console.log(e);
             return "## erreur, code : " + sSfx + " ##";
         }
     }
-}
+};
 
 
 class Verb {
 
     constructor (sVerb) {
@@ -270,11 +270,11 @@
                 [":2s", conj._getConjWithTags(sVerb, this._tTags, ":E", ":2s")],
                 [":1p", conj._getConjWithTags(sVerb, this._tTags, ":E", ":1p")],
                 [":2p", conj._getConjWithTags(sVerb, this._tTags, ":E", ":2p")]
             ])]
         ]);
-    };
+    }
 
     _readableInfo () {
         // returns readable infos
         this.sVerbAux = (this._sRawInfo.slice(7,8) == "e") ? "être" : "avoir";
         let sGroup = conj._dGroup.get(this._sRawInfo[0]);
@@ -298,11 +298,11 @@
         }
         if (sInfo === "") {
             sInfo = "# erreur - code : " + this._sRawInfo;
         }
         return sGroup + " · " + sInfo;
-    };
+    }
 
     infinitif (bPro, bNeg, bTpsCo, bInt, bFem) {
         let sInfi;
         if (bTpsCo) {
             sInfi = (bPro) ? "être" : this.sVerbAux;
@@ -324,23 +324,23 @@
         }
         if (bInt) {
             sInfi += " … ?";
         }
         return sInfi;
-    };
+    }
 
     participePasse (sWho) {
         return this.dConj.get(":PQ").get(sWho);
-    };
+    }
 
     participePresent (bPro, bNeg, bTpsCo, bInt, bFem) {
         if (!this.dConj.get(":PQ").get(":P")) {
             return "";
         }
         let sPartPre;
         if (bTpsCo) {
-            sPartPre = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":PQ", ":P") : getConj("être", ":PQ", ":P");
+            sPartPre = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":PQ", ":P") : conj.getConj("être", ":PQ", ":P");
         } else {
             sPartPre = this.dConj.get(":PQ").get(":P");
         }
         if (sPartPre === "") {
             return "";
@@ -361,11 +361,11 @@
         }
         if (bInt) {
             sPartPre += " … ?";
         }
         return sPartPre;
-    };
+    }
 
     conjugue (sTemps, sWho, bPro, bNeg, bTpsCo, bInt, bFem) {
         if (!this.dConj.get(sTemps).get(sWho)) {
             return "";
         }
@@ -372,11 +372,11 @@
         let sConj;
         if (!bTpsCo && bInt && sWho == ":1s" && this.dConj.get(sTemps).gl_get(":1ś", false)) {
             sWho = ":1ś";
         }
         if (bTpsCo) {
-            sConj = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, sTemps, sWho) : getConj("être", sTemps, sWho);
+            sConj = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, sTemps, sWho) : conj.getConj("être", sTemps, sWho);
         } else {
             sConj = this.dConj.get(sTemps).get(sWho);
         }
         if (sConj === "") {
             return "";
@@ -412,11 +412,11 @@
         }
         if (bInt) {
             sConj += " … ?";
         }
         return sConj;
-    };
+    }
 
     _getPronom (sWho, bFem) {
         if (sWho == ":3s") {
             if (this._sRawInfo[5] == "r") {
                 return "on";
@@ -425,19 +425,19 @@
             }
         } else if (sWho == ":3p" && bFem) {
             return "elles";
         }
         return conj._dProSuj.get(sWho);
-    };
+    }
 
     imperatif (sWho, bPro, bNeg, bTpsCo, bFem) {
         if (!this.dConj.get(":E").get(sWho)) {
             return "";
         }
         let sImpe;
         if (bTpsCo) {
-            sImpe = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":E", sWho) : getConj("être", ":E", sWho);
+            sImpe = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":E", sWho) : conj.getConj("être", ":E", sWho);
         } else {
             sImpe = this.dConj.get(":E").get(sWho);
         }
         if (sImpe === "") {
             return "";
@@ -458,11 +458,11 @@
         }
         if (bTpsCo) {
             return sImpe + " " + this._seekPpas(bPro, bFem, sWho.endsWith("p") || this._sRawInfo[5] == "r");
         }
         return sImpe;
-    };
+    }
 
     _seekPpas (bPro, bFem, bPlur) {
         if (!bPro && this.sVerbAux == "avoir") {
             return this.dConj.get(":PQ").get(":Q1");
         }

Index: gc_lang/fr/modules-js/cregex.js
==================================================================
--- gc_lang/fr/modules-js/cregex.js
+++ gc_lang/fr/modules-js/cregex.js
@@ -261,11 +261,11 @@
         if (lMorph.some(s  =>  this._zNPf.test(s))) {
             return false;
         }
         return lMorph.some(s  =>  this._zNPm.test(s));
     }
-}
+};
 
 
 if (typeof(exports) !== 'undefined') {
     exports._zLemma = cregex._zLemma;
     exports._zGender = cregex._zGender;

Index: gc_lang/fr/modules-js/gce_analyseur.js
==================================================================
--- gc_lang/fr/modules-js/gce_analyseur.js
+++ gc_lang/fr/modules-js/gce_analyseur.js
@@ -73,11 +73,11 @@
 }
 
 function isVeryAmbiguousAndWrong (sWord1, sWord2, sReqMorphNA, sReqMorphConj, bLastHopeCond) {
     //// use it if sWord1 can be also a verb; word2 is assumed to be true via isAmbiguousNAV
     // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
-    let a2 = _dAnalyses.gl_get(sWord2, null)
+    let a2 = _dAnalyses.gl_get(sWord2, null);
     if (!a2 || a2.length === 0) {
         return false;
     }
     if (cregex.checkConjVerb(a2, sReqMorphConj)) {
         // verb word2 is ok
@@ -101,11 +101,11 @@
     return false;
 }
 
 function checkAgreement (sWord1, sWord2) {
     // We don’t check if word exists in _dAnalyses, for it is assumed it has been done before
-    let a2 = _dAnalyses.gl_get(sWord2, null)
+    let a2 = _dAnalyses.gl_get(sWord2, null);
     if (!a2 || a2.length === 0) {
         return true;
     }
     let a1 = _dAnalyses.gl_get(sWord1, null);
     if (!a1 || a1.length === 0) {

Index: gc_lang/fr/modules-js/gce_suggestions.js
==================================================================
--- gc_lang/fr/modules-js/gce_suggestions.js
+++ gc_lang/fr/modules-js/gce_suggestions.js
@@ -142,11 +142,11 @@
     return "";
 }
 
 function suggVerbInfi (sFlex) {
     //return stem(sFlex).join("|");
-    return [ for (sStem of stem(sFlex)) if (conj.isVerb(sStem)) sStem ].join("|");
+    return [ stem(sFlex).filter(sStem => conj.isVerb(sStem)) ].join("|");
 }
 
 
 const _dQuiEst = new Map ([
     ["je", ":1s"], ["j’", ":1s"], ["j’en", ":1s"], ["j’y", ":1s"],

Index: gc_lang/fr/modules-js/lexicographe.js
==================================================================
--- gc_lang/fr/modules-js/lexicographe.js
+++ gc_lang/fr/modules-js/lexicographe.js
@@ -197,11 +197,11 @@
     constructor (oDict) {
         this.oDict = oDict;
         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");
-    };
+    }
 
     getInfoForToken (oToken) {
         // Token: .sType, .sValue, .nStart, .nEnd
         // return a list [type, token_string, values]
         let m = null;
@@ -224,17 +224,23 @@
                     if (oToken.sValue.gl_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) ];
+                        let aElem = [];
+                        for (let s of lMorph){
+                            if (s.includes(":"))  aElem.push( 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) ];
+                        let aElem = [];
+                        for (let s of lMorph){
+                            if (s.includes(":"))  aElem.push( 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"] };
@@ -244,11 +250,11 @@
         }
         catch (e) {
             helpers.logerror(e);
         }
         return null;
-    };
+    }
 
     _formatTags (sTags) {
         let sRes = "";
         sTags = sTags.replace(/V([0-3][ea]?)[itpqnmr_eaxz]+/, "V$1");
         let m;
@@ -265,11 +271,11 @@
             sRes = "#Erreur. Étiquette inconnue : [" + sTags + "]";
             helpers.echo(sRes);
             return sRes;
         }
         return sRes.gl_trimRight(",");
-    };
+    }
 
     _formatSuffix (s) {
         if (s.startsWith("t-")) {
             return "“t” euphonique +" + _dAD.get(s.slice(2));
         }
@@ -279,12 +285,12 @@
         if (s.endsWith("ous")) {
             s += '2';
         }
         let nPos = s.indexOf("-");
         return _dAD.get(s.slice(0, nPos)) + " +" + _dAD.get(s.slice(nPos+1));
-    };
+    }
 }
 
 
 if (typeof(exports) !== 'undefined') {
     exports.Lexicographe = Lexicographe;
 }

Index: gc_lang/fr/modules-js/mfsp.js
==================================================================
--- gc_lang/fr/modules-js/mfsp.js
+++ gc_lang/fr/modules-js/mfsp.js
@@ -36,11 +36,15 @@
     },
 
     getMasForm: function (sWord, bPlur) {
         // returns masculine form with feminine form
         if (this._dMasForm.has(sWord)) {
-            return [ for (sTag of this._whatSuffixCode(sWord, bPlur))  this._modifyStringWithSuffixCode(sWord, sTag) ];
+            let masForm = [];
+            for (var sTag of this._whatSuffixCode(sWord, bPlur)){
+                masForm.push( this._modifyStringWithSuffixCode(sWord, sTag) );
+            }
+            return masForm;
         }
         return [];
     },
 
     hasMiscPlural: function (sWord) {
@@ -49,11 +53,15 @@
     },
 
     getMiscPlural: function (sWord) {
         // returns plural form with singular form
         if (this._dMiscPlur.has(sWord)) {
-            return [ for (sTag of this._lTagMiscPlur[this._dMiscPlur.get(sWord)].split("|"))  this._modifyStringWithSuffixCode(sWord, sTag) ];
+            let miscPlurial = [];
+            for (var sTag of this._lTagMiscPlur[this._dMiscPlur.get(sWord)].split("|")){
+                miscPlurial.push( this._modifyStringWithSuffixCode(sWord, sTag) );
+            }
+            return miscPlurial;
         }
         return [];
     },
 
     _whatSuffixCode: function (sWord, bPlur) {
@@ -86,11 +94,11 @@
         catch (e) {
             console.log(e);
             return "## erreur, code : " + sSfx + " ##";
         }
     }
-}
+};
 
 
 // Initialization
 if (typeof(browser) !== 'undefined') {
     // WebExtension

Index: gc_lang/fr/modules-js/phonet.js
==================================================================
--- gc_lang/fr/modules-js/phonet.js
+++ gc_lang/fr/modules-js/phonet.js
@@ -75,11 +75,11 @@
                 }
             }
         }
         return aSelect;
     }
-}
+};
 
 
 // Initialization
 if (typeof(browser) !== 'undefined') {
     // WebExtension

Index: gc_lang/fr/modules-js/textformatter.js
==================================================================
--- gc_lang/fr/modules-js/textformatter.js
+++ gc_lang/fr/modules-js/textformatter.js
@@ -256,11 +256,11 @@
 
 class TextFormatter {
 
     constructor () {
         this.sLang = "fr";
-    };
+    }
 
     formatText (sText, dOpt=null) {
         if (dOpt !== null) {
             dTFOptions.gl_updateOnlyExistingKeys(dOpt);
         }
@@ -270,11 +270,11 @@
                     sText = sText.replace(zRgx, sRep);
                 }
             }
         }
         return sText;
-    };
+    }
 
     getDefaultOptions () {
         return dTFDefaultOptions;
     }
 }