الفرق بين المراجعتين لصفحة: «ميدياويكي:Gadget-Extra-Editbuttons-Functions-test.js»

    من الشعر الشيعي
    dfghjk>Admin
    ط (۱ نسخه واردشده)
     
    ط (مراجعة واحدة)
     

    المراجعة الحالية بتاريخ ١٨:١٥، ٢ أغسطس ٢٠٢٣

    var EE_faChrs = "ءاآأإئؤبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهیةيک" + "ًٌٍَُِّْ";
    var EE_faNums = "۰۱۲۳۴۵۶۷۸۹";
    var EE_arNums = "٠١٢٣٤٥٦٧٨٩";
    //here we will list none farsi chars like ە ە which is Kurdish char  instead of ه ه (Farsi)
    var NoneFarsi={//حروف کردی به فارسی
    
                   'ہ':'ه',//Urdu ہ > ه ه (Farsi)
                   'ى':'ی',//Urdu ى > ی
                    'ې':'ی',//Uyghur ې >ی
                   'ە':'ه',//Kurdish ە > ه ه (Farsi)
                   'ھ':'ه',
                  }
    
    var tupN = [];
    var tupO = [];
    
    //Also it uses variables  of [[Mediawiki:Gadget-Extra-Editbuttons-Dictionary.js]] 
    
    /*
     * Javascript Diff Algorithm
     *  http://ejohn.org/projects/javascript-diff-algorithm/
     */
    
    function links_underline(str, rev_type) {
        //this function is used to have better results for Diff Algorithm in wikilinks
        var falinks = str.match(/\[\[.*?\]\]/g);
        if (falinks) {
            if (rev_type == 'Start') {
                for (var i = 0; i < falinks.length; i++) {
                    var item_s = falinks[i];
                    var intem_u = falinks[i].replace(/\s/g, '_');
                    str = str.replace(item_s, intem_u);
                }
            } else {
                for (var i = 0; i < falinks.length; i++) {
                    var item_s = falinks[i].replace(/\_/g, ' ');
                    var intem_u = falinks[i];
                    str = str.replace(intem_u, item_s);
                }
            }
        };
        return str;
    }
    
    function escape(s) {
        //Diff Algorithm's functions
        var n = s;
        n = n.replace(/&/g, "&amp;");
        n = n.replace(/</g, "&lt;");
        n = n.replace(/>/g, "&gt;");
        n = n.replace(/"/g, "&quot;");
    
        return n;
    };
    
    function di_escape(s) {
        //Diff Algorithm's functions
        var n = s;
        n = n.replace(/&amp;/g, "&");
        n = n.replace(/&lt;/g, "<");
        n = n.replace(/&gt;/g, ">");
        n = n.replace(/&quot;/g, '"');
    
        return n;
    };
    
    
    function diffString(o, n) {
        //Diff Algorithm's functions
        tupN = [];
        tupO = [];
        o = o.replace(/\s+$/, '');
        n = n.replace(/\s+$/, '');
        var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
        var oSpace = o.match(/\s+/g);
        if (oSpace == null) {
            oSpace = ["\n"];
        } else {
            oSpace.push("\n");
        }
        var nSpace = n.match(/\s+/g);
        if (nSpace == null) {
            nSpace = ["\n"];
        } else {
            nSpace.push("\n");
        }
        if (out.n.length == 0) {
            for (var i = 0; i < out.o.length; i++) {
                tupO.push(escape(out.o[i]))
            }
        } else {
            if (out.n[0].text == null) {
                for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
                    tupO.push(escape(out.o[n]));
                }
            }
            for (var i = 0; i < out.n.length; i++) {
                if (out.n[i].text == null) {
                    tupN.push(escape(out.n[i]));
                } else {
                    for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
                        tupO.push(escape(out.o[n]));
                    }
                }
            }
        }
        o = '';
        n = '';
    }
    
    function diff(o, n) {
        //Diff Algorithm's functions
        var ns = new Object();
        var os = new Object();
    
        for (var i = 0; i < n.length; i++) {
            if (ns[n[i]] == null) ns[n[i]] = {
                rows: new Array(),
                o: null
            };
            ns[n[i]].rows.push(i);
        }
    
        for (var i = 0; i < o.length; i++) {
            if (os[o[i]] == null) os[o[i]] = {
                rows: new Array(),
                n: null
            };
            os[o[i]].rows.push(i);
        }
    
        for (var i in ns) {
            if (ns[i].rows.length == 1 && typeof (os[i]) != "undefined" && os[i].rows.length == 1) {
                n[ns[i].rows[0]] = {
                    text: n[ns[i].rows[0]],
                    row: os[i].rows[0]
                };
                o[os[i].rows[0]] = {
                    text: o[os[i].rows[0]],
                    row: ns[i].rows[0]
                };
            }
        }
    
        for (var i = 0; i < n.length - 1; i++) {
            if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) {
                n[i + 1] = {
                    text: n[i + 1],
                    row: n[i].row + 1
                };
                o[n[i].row + 1] = {
                    text: o[n[i].row + 1],
                    row: i + 1
                };
            }
        }
    
        for (var i = n.length - 1; i > 0; i--) {
            if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && n[i - 1] == o[n[i].row - 1]) {
                n[i - 1] = {
                    text: n[i - 1],
                    row: n[i].row - 1
                };
                o[n[i].row - 1] = {
                    text: o[n[i].row - 1],
                    row: i - 1
                };
            }
        }
    
        return {
            o: o,
            n: n
        };
    };
    
    function RevertBug(diffO, diffN, str) {
        //Diff Algorithm's functions + Reverting Bug's functions
        for (var i = 0; i < diffN.length; i++) {
    
            //Checking Interwikis' Links
            var diffN_di = di_escape(diffN[i])
            var diffO_di = di_escape(diffO[i])
            var item = diffN_di
            var regex = /\[\[([a-z]{2,3}|[a-z]{2,3}\-[a-z\-]{2,}|simple)(\s|_|)\:(.*?)(\s|_|\:.*|)\]\]/g
            var interwikis = item.match(regex);
            if (interwikis != null) {
                str = str.replace(diffN_di, diffO_di);
            };
    
            //Checking Files' Links
            if (item.replace(/\|/g, "") != item) {
                var regex = /\[\[ *(?:پرونده|تصویر|[Ff]ile|[Ii]mage)(\s|_|)\:(\s|_|)(.*?)\|/g
            } else {
                var regex = /\[\[ *(?:پرونده|تصویر|[Ff]ile|[Ii]mage)(\s|_|)\:(\s|_|)(.*?)\]\]/g
            };
            var filelinkN = diffN_di.match(regex);
            var filelinkO = diffO_di.match(regex);
            if (filelinkN != null) {
                str = str.replace(filelinkN, filelinkO);
            };
    
            //Checking User's Sign Link
            var regex = /\[\[(\s|_|)([Uu]ser|کاربر|بحث کاربر|بحث_کاربر|ویژه)(\s|_|)\:/g
            var UserSign = item.match(regex);
            if (UserSign != null) {
                str = str.replace(diffN_di, diffO_di);
            };
    
            //Checking URLs
            var regex = /(\[\/\/[\w\-]+?\.wiki|https?\:\/\/)(\S+)/g
            var URLlinkN = diffN_di.match(regex);
            var URLlinkO = diffO_di.match(regex);
            if (URLlinkN != null) {
                str = str.replace(URLlinkN, URLlinkO);
            };
        };
        diffO = '';
        diffN = '';
        return str;
    };
    
    /** applyOnSelection
     *
     *  Description: Applies the string functions defined below to the
     *  selected text in the edit box. If no text is selected, applies
     *  the function to the whole contents of edit box.
     *
     */
    function applyOnSelection(callback) {
        if (document.getElementById("editform")) {
            var txtarea = document.getElementById("wpTextbox1");
        } else if (document.getElementById("wpNewTitleMain")) {
            var txtarea = document.getElementById("wpNewTitleMain");
        } else {
            return;
        }
        var selText;
        if (document.selection && document.selection.createRange) { // IE/Opera
            // get current selection  
            txtarea.focus();
            var range = document.selection.createRange();
            selText = range.text;
            if (selText) {
                range.text = callback.apply(this, [selText]);
                range.select();
            } else {
                txtarea.value = callback.apply(this, [txtarea.value]);
            }
        } else if (txtarea.selectionStart || txtarea.selectionStart == '0') { // Mozilla
            // get current selection
            txtarea.focus();
            var startPos = txtarea.selectionStart;
            var endPos = txtarea.selectionEnd;
            selText = txtarea.value.substring(startPos, endPos);
            //insert tags
            if (selText) {
                txtarea.value = txtarea.value.substring(0, startPos) + callback.apply(this, [selText]) + txtarea.value.substring(endPos, txtarea.value.length);
                txtarea.selectionStart = startPos + selText.length;
                txtarea.selectionEnd = txtarea.selectionStart;
            } else {
                txtarea.value = callback.apply(this, [txtarea.value]);
            }
        }
    }
    
    
    /** toggleDir
     *
     *  Description: Toggles the directionality of the text in the edit
     *  box textarea. It is helpful when working on wikitext that contains
     *  mixed Persian and English content, or contains commands that are
     *  in English (e.g. untranslated parser functions, etc.)
     *
     */
    function toggleDir(obj) {
        var isrtl = 0;
        if (obj) {
            isrtl = obj.style.direction != 'ltr';
            if (isrtl) {
                obj.style.textAlign = "left";
                obj.style.direction = "ltr";
            } else {
                obj.style.textAlign = "right";
                obj.style.direction = "rtl";
            }
        }
    }
    
    
    /** fromEntityToUtf8
     *
     *  Description: Takes an HTML entitiy like &#118; and returns the
     *  Unicode equivalent of it (in this example, letter "v").
     *
     *  This is needed because older browsers sometimes turned in HTML
     *  entities instead of Unicode characters.
     *
     */
    function fromEntityToUtf8(str) {
        return str.replace(/&#([0-9]+);/g, function (s, n, ofs, all) {
            return String.fromCharCode(n);
        });
    }
    
    
    /** fromUtf8ToEntity
     *
     *  Description: Takes a Unicode character like the letter "v" and
     *  returns the equivalent HTML entity (in this example, &#118;).
     *
     *  This is not in use anymore and is only kept for historical
     *  purposes.
     *
     */
    function fromUtf8ToEntity(str) {
        return str.replace(/([^\x00-\x7f])/g, function (s, c, ofs, all) {
            c = String(c);
            return "&#" + c.charCodeAt(0) + ";";
        });
    }
    
    
    /** AtSignReplace
     *
     *  Description: Replaces the @ sign in the text with {{at}} to
     *  prevent spam bots from picking up email addresses. 
     *
     *  This function is not used by the default buttons.
     *
     */
    function AtSignReplace(str) {
        return str.replace(/(\S+?)@(\S+?)/g, '$1{{at}}$2');
    }
    
    
    /** URLfix
     *
     *  Description: Finds all links to Wikipedia pages, strips the
     *  http(s) prefix (to ensure the user will not switch protocols
     *  by clicking on the link), and removes the unnecessary parts of
     *  the query string (such as the "title" attribute of a diff link)
     *  to make the URLs shorter and easier to maintain.
     *
     */
    function URLfix(str) {
        // Replace every %20 with _ to protect them from decodeURI
        var old = "";
        while (old != str) {
            old = str;
            str = str.replace(/(http\S+?)\%20/g, '$1\u200c\u200c\u200c_\u200c\u200c\u200c');
        }
    
        // Decode URIs
        // NOTE: This would convert all %20's to _'s which could break some links
        // but we will undo that later on
        str = str.replace(/(http\S+)/g, function (s, p) {
            return decodeURI(p)
        });
    
        // Revive all instances of %20 to make sure no links is broken
        str = str.replace(/\u200c\u200c\u200c_\u200c\u200c\u200c/g, '%20');
    
        // Shorten Wikipedia diff URLs
        str = str.replace(/\[(https?\:|)\/\/([\w\-]+)\.wikipedia\.org\/w\/index\.php\?title=[^&\s]*&(diff=[^&\s]+&|)(oldid=\d+)/g, '[//$2.wikipedia.org/w/index.php?$3$4');
    
        // Strip the http(s) prefix
        str = str.replace(/\[(https?\:|)\/\/([\w\-]+)\.wikipedia\.org\/(\S*)/g, '[//$2.wikipedia.org/$3');
    
        return str;
    }
    
    
    /** YKarabic
     *
     *  Description: Replaces all instances of ي and ك withی and ک,
     *  respectively. It should not make any ch anges to Arabic text
     *  surrounded by appropriate templates, and to interwikis.
     *
     */
    function YKarabic(str) {
        var old = "";
    
       /* to do: we should list all of none farsi chars (Kurdish, Urdu, Arabic which are similar to farsi but their unicode is diffrent like (Kurdish ە &#x06D5; and ه &#x0647; Farsi)
       */
    
        // Do not touch the text inside links, images, categories or interwikis
        while (old != str) {
            old = str;
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ي(.*?)\]\]/g, '[[$1\u200c\u200c\u200cی\u200c\u200c\u200c$2]]');
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ك(.*?)\]\]/g, '[[$1\u200c\u200c\u200cک\u200c\u200c\u200c$2]]');
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ہ(.*?)\]\]/g, '[[$1؛؛؛؛ه؛؛؛؛$2]]');//&#x06D5; to &#x0647;
            str = str.replace(/\{\{(عربی|به عربی)\|(.*?)ى(.*?)\}\}/g, '{{$1|$2؛؛؛؛ڎ؛؛؛؛$3}}');// Urdu and Arabic for {{عربی
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ى(.*?)\]\]/g, '[[$1؛؛؛؛ی؛؛؛؛$2]]');// Urdu
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ﻲ(.*?)\]\]/g, '[[$1\u200c\u200c\u200c\u200cڎ\u200c\u200c\u200c\u200c$2]]');// Urdu-Arabic,I used char ڎ temporary and it will replace in next lines! 
    
    
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ۍ(.*?)\]\]/g, '[[$1،،،،ڎ،،،،$2]]');// Pushtu ,I used char ڎ temporary and it will replace in next lines! 
    
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ې(.*?)\]\]/g, '[[$1،،،،ی،،،،$2]]');//Uyghur
    
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ە(.*?)\]\]/g, '[[$1\u200c\u200c\u200cه\u200c\u200c\u200c$2]]');//&#x06D5; to &#x0647;
            str = str.replace(/\[\[([^\]]*?\:[^\]]*?)ھ(.*?)\]\]/g, '[[$1،،،،ه،،،،$2]]');//&#x06BE; to  &#x0647;
    
        }
    
        // Replace every ي and ك with ی and ک, respectively
        // NOTE: This WILL mess with images, links, categories and interwikis
        // but we will undo it later
        str = str.replace(/ي/g, 'ی');
        str = str.replace(/ك/g, 'ک');
    
        //Uyghur
        str = str.replace(/ې/g, 'ی');
    
        //Urdu
        // Convert &#1609; to &#1740; (the latter is standard Persian Yeh)
        str = str.replace(/ى/g, 'ی');
        str = str.replace(/ﻲ/g, 'ی');
        // Convert &#x06C1; to &#x0647; // ہہہہ to ههه
        str = str.replace(/ہ/g, 'ه');
    
        //Pushtu 
        str = str.replace(/ۍ/g, 'ی');
    
        //Kurdish
        //(Kurdish ە &#x06D5; to ه &#x0647; Farsi)
        str =str.replace(/ە/g,'ه'); 
       //(Kurdish ھ &#x06BE; to ه &#x0647; Farsi)
        str =str.replace(/ھ/g,'ه'); 
    
        // Undo the changes to interwikis, links and images
        // NOTE: This will also undo changes to categories which is not good
        // but we will undo that later
        str = str.replace(/\u200c\u200c\u200cی\u200c\u200c\u200c/g, 'ي');
        str = str.replace(/\u200c\u200c\u200cک\u200c\u200c\u200c/g, 'ك');
        str = str.replace(/؛؛؛؛ه؛؛؛؛/g, 'ہ');//Urdu
        str = str.replace(/؛؛؛؛ی؛؛؛؛/g, 'ى');//Urdu
        str = str.replace(/\u200c\u200c\u200c\u200cڎ\u200c\u200c\u200c\u200c/g, 'ﻲ');//Urdu Arabic, this line revert previous line's replaces
        str = str.replace(/،،،،ڎ،،،،/g, 'ۍ');//Pushtu , this line revert previous line's replaces
        str = str.replace(/،،،،ی،،،،/g, 'ې');//Uyghur
        str = str.replace(/\u200c\u200c\u200cه\u200c\u200c\u200c/g, 'ە');//Kurdish
        str = str.replace(/،،،،ه،،،،/g, 'ھ');//Kurdish
    
    
        old = "";
        // Replace every ي and ك in categories with ی and ک, respectively
        while (old != str) {
            old = str;
            str = str.replace(/\[\[(رده|[Cc]ategory):(.*?)(ى|ي|ې|ۍ)(.*?)\]\]/g, '[[$1:$2ی$4]]');//Urdu and Arabic and Uyghur
            str = str.replace(/\[\[(رده|[Cc]ategory):(.*?)ك(.*?)\]\]/g, '[[$1:$2ک$3]]');
            str = str.replace(/\[\[(رده|[Cc]ategory):(.*?)(ھ|ە|ہ)(.*?)\]\]/g, '[[$1:$2ه$3]]');//Urdu and Kurdish ه
        }
    
        // Finally, replace every ی and ک in Arabic text with ي and ك, respectively
        old = "";
        while (old != str) {
            old = str;
            str = str.replace(/\{\{(عربی|شروع عربی|آغاز عربی)\}\}([^\}]*)ی([^\{]*)\{\{پایان\sعربی\}\}/g,'{{$1}}$2ي$3{{پایان عربی}}');
            str = str.replace(/\{\{(عربی?)\|(.*?)ی(.*?)\}\}/g, '{{عربی\|$2ي$3}}');
            str = str.replace(/\{\{(عربی?)\|(.*?)ک(.*?)\}\}/g, '{{عربی\|$2ك$3}}');
            str = str.replace(/\{\{(به عربی?)\|(.*?)ی(.*?)\}\}/g, '{{به عربی\|$2ي$3}}');
            str = str.replace(/\{\{(به عربی?)\|(.*?)ک(.*?)\}\}/g, '{{به عربی\|$2ك$3}}');
            str = str.replace(/\{\{(عربی|شروع عربی|آغاز عربی)\}\}([^\}]*)ک([^\{]*)\{\{پایان\sعربی\}\}/g, '{{$1}}$2ك$3{{پایان عربی}}');
            str = str.replace(/؛؛؛؛ڎ؛؛؛؛/g, 'ى');//Urdu and Arabic ya maghsureh
        }
    
        return str;
    }
    
    
    /** NonStandard
     *
     *  Description: Replaces all instances of non-standard characters
     *  used for heh+yeh, with the standard form of «هٔ».
     *
     */
    function NonStandard(str) {
        // The non-standard character ۀ is used in Urdu; we would like to
        // undo changes to Urdu interwikis
        var old = "";
        while (old != str) {
            old = str;
            str = str.replace(/\[\[(ur\:[^\]]*?)ۀ(.*?)\]\]/g, '[[$1\u200c\u200c\u200cهٔ\u200c\u200c\u200c$2]]');
        }
    
        // Replace ه followed by (space|ZWNJ|lrm) follow by ی with هٔ
        str = str.replace(/ه[\u200c\u200e\s]+ی([\s\n])/g, 'هٔ$1');
    
        // Replace ه followed by (space|ZWNJ|lrm|nothing) follow by ء or   ٔ with هٔ
        str = str.replace(/ه[\u200c\u200e\s]*[ءٔ]([\s\n])/g, 'هٔ$1');
    
        // Replace هٓ or single-character ۀ with the standard هٔ
        str = str.replace(/(ۀ|هٓ)/g, 'هٔ');
    
        // Replace ه followed by ئ or ی, and then by ی, with ه‌ای
        // example: خانهئی becomes خانه‌ای
        str = str.replace(/ه‌[ئی]ی/g, 'ه‌ای');
    
        // Revert the changes to the Urdu interwikis
        old = "";
        while (old != str) {
            old = str;
            str = str.replace(/\u200c\u200c\u200cهٔ\u200c\u200c\u200c/g, 'ۀ');
        }
    
    
        var FaGlyphs={'\u200cه':'ﻫ','ی\u200c':'ﻰﻲ','ﺃ':'ﺄﺃ','ﺁ':'ﺁﺂ','ﺇ':'ﺇﺈ','ا':'ﺎا',
                'ب':'ﺑﺐﺏﺒ','پ':'ﭙﭘﭗﭖ','ت':'ﺘﺖﺗﺖﺕ',
                'ث':'ﺜﺛﺚﺙ','ج':'ﺠﺟﺞﺝ','چ':'ﭼﭻﭺﭽ','ح':'ﺤﺣﺢﺡ','خ':'ﺥﺨﺧﺦ','د':'ﺪﺩ',
                'ذ':'ﺬﺫ','ر':'ﺮﺭ','ز':'ﺰﺯ','ژ':'ﮋﮊ','س':'ﺴﺳﺲﺱ','ش':'ﺸﺷﺶﺵ','ص':'ﺼﺻﺺﺹ',
                'ض':'ﻀﺿﺾﺽ','ط':'ﻄﻃﻂﻁ','ظ':'ﻈﻇﻆﻅ','ع':'ﻌﻋﻊﻉ','غ':'ﻍﻐﻏﻎ','ف':'ﻔﻓﻒﻑ',
                'ق':'ﻘﻗﻖﻕ','ک':'ﮑﮐﮏﮎﻜﻛﻚﻙ','گ':'ﮕﮔﮓﮒ','ل':'ﻠﻟﻞﻝ','م':'ﻡﻤﻣﻢﻣ','ن':'ﻨﻧﻦﻥ',
                'ه':'ﻩﻪﻫﻬ','هٔ':'ﮥﮤ','و':'ﻮﻭ','ﺅ':'ﺆﺅ','ی':'ﻴﻳﻲﻱﻰىىﻯ','ئ':'ﺌﺋﺊﺉ','لا':'ﻼ','ﻹ':'ﻺ','ﻷ':'ﻸ','ﻵ':'ﻶ'
                };
        for (var character in FaGlyphs) {
            var Ch1 = character ;
            var Ch2 = FaGlyphs[character];
            var old=''
            while (old != str) {
                old = str;
                var regex = new RegExp("[" + Ch2 + "]", "g");
                str = str.replace(regex, Ch1);
            }
        };
       //Function for removing incorrect ZWNJs
        str=RemoveBadZWNJ(str)
        return str;
    }
    
    
    /** InterwikiSorter
     *
     *  Description: Finds all the interwiki links in the text and sorts
     *  them alphabetaically.
     *
     */
    function InterwikiSorter(str) {
        var ref = /\[\[([A-Za-z][A-Za-z-]{1,20}?)\:(.*?)\]\]\r?\n?(\s*)/g
    
        //extract interwiki's and delete them temporarily from the string
        interwikis = str.match(ref);
        if (interwikis == null) return;
        str = str.replace(ref, "");
    
        //sort interwikis
        interwikis = interwikis.sort();
    
        //put interwiki's back
        str = str + interwikis.join("");
    
        return str;
    }
    
    /** SortText
     *
     *  Description: Takes a piece of text in Persian which contains
     *  several lines (separated by the newline character), and sorts
     *  the lines alphabetically, with respect to their first character.
     *
     */
    function SortText(str) {
        function sortPreparation(instr) { // solve persian problem on sorting by replace characters in strings
            return instr.replace(/ی/g, "ي")
                .replace(/ک/g, "ك")
                .replace(/گ/g, "كی")
                .replace(/ژ/g, "زی")
                .replace(/چ/g, "جی")
                .replace(/پ/g, "بی");
        }
        temp = str.split('\n');
        temp.sort(function (a, b) {
            var keyA = sortPreparation(a);
            var keyB = sortPreparation(b);
            if (keyA < keyB) return -1;
            if (keyA > keyB) return 1;
            return 0;
        });
        var result = temp.join('\n');
        return result;
    }
    
    
    function FM(str) {
        //بن‌های ماضی
        var verbs = "(آراست|آرامید|آزرد|آزمود|آسود|آشامید|آشفت|آغازید|آغشت|آفرید|آگند|آلود|آمد|آمرزید" + "|آموخت|آمیخت|آورد|آویخت|آهیخت|ارزید|افتاد|افراشت|افروخت|افزود|افسرد|افشاند|افگند" + "|انباشت|انجامید|انداخت|اندوخت|اندود|اندیشید|انگاشت|انگیخت|اوباشت|ایستاد|باخت" + "|بارید|بافت|بالید|بایست|بخشود|بخشید|برازید|برد|برید|بست|بسود|بسیجید|بلعید|بود" + "|بوسید|بویید|بیخت|پاشید|پالود|پخت|پذیرفت|پراکند|پرداخت|پرستید|پرسید|پرورد|پرید" + "|پژمرد|پژوهید|پسندید|پلاسید|پلکید|پناهید|پنداشت|پوسید|پوشید|پویید|پیچید|پیراست" + "|پیمود|پیوست|تاخت|تافت|تپید|تراشید|تراوید|ترسید|ترشید|ترکید|تکاند|تکانید|تنید|توانست" + "|جست|جُست|جَست|جنبید|جنگید|جوشید|جوید|جهید|چاپید|چایید|چپید|چربید|چرخید|چرید|چسبید|چشید" + "|چکید|چلاند|چلانید|چمید|چید|خارید|خاست|خایید|خراشید|خرامید|خروشید|خرید|خزید|خست" + "|خشکید|خلید|خمید|خوابید|خواست|خواند|خورد|خوفید|خیسید|داد|داشت|دانست|درخشید|دروید" + "|درید|دزدید|دمید|دوخت|دوشید|دوید|دیدم|ربود|رخشید|رسید|رست|رَست|رُست|رشت|رفت|رُفت|روفت" + "|رقصید|رمید|رنجید|رندید|رویید|ریخت|رید|زارید|زایید|زد|زدود|زیست|ساخت|سپرد|سپوخت" + "|ستد|سترد|ستود|ستیزید|سرود|سرشت|سرید|سزید|سفت|سگالید|سنجید|سوخت|سود|شاشید|شایست" + "|شتافت|شد|شست|شکافت|شکست|شکفت|شکیفت|شگفت|شمرد|شناخت|شنید|شورید|طلبید|طوفید|غارتید" + "|غرید|غلطید|غنود|فرستاد|فرسود|فرمود|فروخت|فریفت|فشرد|فهمید|قاپید|قبولاند|کاست" + "|کاشت|کاوید|کرد|کشت|کشید|مکشید|کفت|کفید|کند|کوچید|کوشید|کوفت|گایید|گداخت|گذاشت" + "|گذشت|گرازید|گرایید|گردید|گرفت|گروید|گریخت|گریست|گزارد|گزید|گُزید|گَزید|گسارد|گسترد|گسست" + "|گشت|گشود|گفت|گماشت|گنجید|گندید|گوارید|گوزید|لرزید|لغزید|لمدنی|لندید|لنگید|لهید" + "|لیسید|ماسید|مالید|ماند|مرد|مکید|مولید|مویید|نازید|نالید|نامید|نشست|نکوهید|نگاشت" + "|نگریست|نمود|نواخت|نوردید|نوشت|نوشید|نهاد|نهفت|نیوشید|ورزید|وزید|هراسید|هشت" + "|یارست|یازید|یافت)";
    
        var re = new RegExp("(^|[^" + EE_faChrs + "])(می|نمی)\\s?" + verbs + "(م|ی|یم|ید|ند|)($|[^" + EE_faChrs + "])", "g");
        str = str.replace(re, "$1$2\u200c$3$4$5");
    
        //بن‌های مضارع
        verbs = "(آرای|آرام|آزار|آزمای|آسای|آشام|آشوب|آغاز|آغار|آفرین|آگن|آلای|آی|آمرز" + "|آموز|آمیز|آور|آویز|آهنج|ارز|افت|افراز|افروز|افزای|افسر|افشان|افگن" + "|انبار|انجام|انداز|اندوز|اندای|اندیش|انگار|انگیز|اوبار|ایست|باز" + "|بار|باش|باف|بال|بای|بخشای|بخش|براز|بر|بُر|بَر|بند|بساو|بسیج|بلع|بو" + "|بوس|بوی|بیز|پاش|پالای|پز|پذیر|پراکن|پرداز|پرست|پرس|پرور|پر" + "|پژمر|پژوه|پسند|پلاس|پلک|پناه|پندار|پوس|پوش|پوی|پیچ|پیرای" + "|پیمای|پیوند|تاز|تاب|تپ|توپ|تراش|تراو|ترس|ترش|ترک|تکان|تن|توان" + "|جه|جوی|جنب|جنگ|جوش|جو|چاپ|چای|چپ|چرب|چرخ|چر|چسب|چش" + "|چک|چلان|چم|چین|خار|خیز|خای|خراش|خرام|خروش|خر|خز|خست" + "|خشک|خل|خم|خواب|خواه|خوان|خور|خوف|خیس|ده|دار|درخش|درو" + "|در|دزد|دم|دوز|دوش|دو|بین|ربای|رخش|رس|ره|روی|رشت|رو|روب" + "|رقص|رم|رنج|رند|روی|ریز|رین|زار|زای|زن|زدای|زی|ساز|سپر|سپوز" + "|ستان|ستر|ستان|ستیز|سرای|سرشت|سر|سز|سنب|سگال|سنج|سوز|سای|شاش|شای" + "|شتاب|شو|شوی|شکاف|شکن|شکوف|شکیب|شمر|شناس|شنو|شور|طلب|طوف|غارت" + "|غر|غلط|غنو|فرست|فرسای|فرمای|فروش|فریب|فشر|فهم|قاپ|قبولان|کاه" + "|کار|کاو|کن|کار|کُش|کش|کِش|کَش|کف|کن|کوچ|کوش|کوب|گای|گداز|گذار" + "|گذر|گراز|گرای|گرد|گیر|گرو|گریز|گری|گزار|گز|گزین|گسار|گستر|گسل" + "|گشای|گو|گمار|گنج|گند|گوار|گوز|لرز|لغز|لم|لند|لنگ|له" + "|لیس|ماس|مال|مان|میر|مک|مول|موی|ناز|نال|نام|نشین|نکوه|نگار" + "|نگر|نمای|نواز|نورد|نویس|نوش|نه|نهنب|نیوش|ورز|وز|هراس|هل" + "|یار|یاز|یاب)";
    
        var re = new RegExp("(^|[^" + EE_faChrs + "])(می|نمی)\\s?" + verbs + "(م|ی|د|یم|ید|ند)($|[^" + EE_faChrs + "])", "g");
        str = str.replace(re, "$1$2\u200c$3$4$5");
    
        // ای «توان» ناقلا!
        str = str.replace(/(می|نمی) ?توان/g, "$1\u200cتوان");
    
        // چسباندن تمام «ها»ها با فاصلهٔ مجازی
        str = str.replace(/\sها([\]\.،\:»\)\s])/g, '\u200cها$1');
        str = str.replace(/\sها(ی|یی|یم|یت|یش|مان|تان|شان)([\]\.،\:»\)\s])/g, '\u200cها$1$2');
    
        // برای حذف علامت ستاره اضافی قبل از عنوان‌ها
        str = str.replace(/\n\*\s*(\=+.+?\=+\n)/g, "\n$1");
    
        // عضو علامت‌های نقل قول تکی از عنوان‌ها
        str = str.replace(/(\n=+)(.*?)(?:'+)(.*?)(?:'+)(.*?)(=+\n)/g, "$1$2$3$4$5");
    
        // برای حذف فاصله‌های اضافی در پیوندها
        str = str.replace(/\[\[\s*(.*?)\s*]]/g, "[[$1]]");
    
        // تبدیل به نویسه / یکی‌کردن فاصله‌های مجازی پشت‌سرهم
        str = str.replace(/(\{\{فم\}\}|\&zwnj\;|\u200c+)/g, '\u200c');
    
        // اول و آخر هم خط اگر فاصلهٔ مجازی باشد، حذف شود
        str = str.replace(/(^\u200c|\u200c$)/mg, '');
    
        //شناسه‌ها
        //توجه: «است» تعدماً از شناسه ها حذف شده چون به عنوان فعل مستقل هم کاربرد دارد و در آن موارد باید جدا نوشته شود
        // مثال: «این یک خانه است» که است در آن باید از خانه جدا نوشته شود
        str = str.replace(new RegExp("ه\\s+(ام|ای|ایم|اید|اند)($|[^" + EE_faChrs + "])", "g"), 'ه\u200c$1$2');
    
        // موارد جزئی دیگر و بی‌ربط به فاصلهٔ مجازی، باید منتقل شود
        str = str.replace(/ا\sً/g, 'اً');
    
       //Function for removing incorrect ZWNJs
        str=RemoveBadZWNJ(str)
    
        //These two lines are for reverting link's bugs!
        str = links_underline(str, 'Start')
        var old_text = str;
        // end
    
        //حذف فاصلهٔ مجازی پیش از حروف لاتین 
        //سجاوندی را از بخش واگردانی باگ خارج کردم
        str = str.replace(/\u200c([\w])/g, '$1');
        str = str.replace(/([\w])\u200c/g, '$1');
    
        //These three lines are for reverting link's bugs!
        diffString(old_text, str);
        str = RevertBug(tupO, tupN, str);
        str = links_underline(str, 'End')
        //end
    
        //حذف فاصلهٔ مجازی قبل و بعد از سجاوندی 
        str = str.replace(/\u200c([\n\s\[\]\.،«»\:\(\)\؛\؟\?\;\$\!\@\-\=\+\\])/g, '$1');
        str = str.replace(/([\n\s\[\]\.،«»\:\(\)\؛\؟\?\;\$\!\@\-\=\+\\])\u200c/g, '$1');
    
        return str;
    }
    
    
    /** digitsEnToFa
     *
     *  Description: Takes a string made of English digits only, and
     *  returns a string that represents the same number but with
     *  Persian digits
     *
     */
    function digitsEnToFa(str) {
        for (var i = 0; i < 10; i++) {
            reEnToFa = new RegExp("" + i);
            str = str.replace(reEnToFa, EE_faNums[i]);
        }
    
        return str;
    }
    
    
    /** digitsFaToEn
     *
     *  Description: Takes a string made of English digits only, and
     *  returns a string that represents the same number but with
     *  Persian digits
     *
     */
    function digitsFaToEn(str) {
        for (var i = 0; i < 10; i++) {
            reFaToEn = new RegExp(EE_faNums[i]);
            str = str.replace(reFaToEn, i);
        }
    
        return str;
    }
    
    
    /** digitsArToFa
     *
     *  Description: Takes a string that contains digits, and
     *  replaces all Arabic digits with the corresponding Persian
     *  digits
     *
     */
    function digitsArToFa(str) {
        for (var i = 0; i < 10; i++) {
            reArToFa = new RegExp(EE_arNums[i]);
            str = str.replace(reArToFa, EE_faNums[i]);
        }
    
        return str;
    }
    
    
    /** digits_move
     *
     *  Description: A special flavor of digits() function that is
     *  to be used only on the move page. It is more simplistic than
     *  the digits() function itself.
     *
     */
    function digits_move(str) {
        str = fromEntityToUtf8(str, true);
    
        old = "";
        // Convert all English digits to Persian digits
        while (old != str) {
            old = str;
            re = new RegExp("[0-9]+");
            str = str.replace(re, digitsEnToFa);
        }
    
        old = "";
        // Convert all Arabic digits to Persian digits
        while (old != str) {
            old = str;
            re = new RegExp("[" + EE_arNums + "]+");
            str = str.replace(re, digitsArToFa);
        }
    
        return (str);
    }
    
    
    function digits(str) {
        // Disabled for Template namespace, due to recurring problems
        if (mw.config.get('wgNamespaceNumber') == 10) {
            return str;
        } else {
            //These two lines are for reverting link's bugs!
            str = links_underline(str, 'Start')
            var old_text = str;
            // end
            str = fromEntityToUtf8(str, true);
            var old = str;
            // فارسی به انگلیسی
            while (1 == 1) {
                for (var i = 0; i < 10; i++) {
                    var reFaToEn = new RegExp("([A-Za-z0-9][^" + EE_faChrs + EE_faNums + "\\n\\{\\}\\|=]*)" + EE_faNums[i] + "([^" + EE_faNums + "\\n\\{\\}\\|=]*?[A-Za-z0-9])", "g");
                    old = old.replace(reFaToEn, "$1¬!¬" + i + "$2");
                    old = old.replace(/¬!¬/g, "");
                    var reFaToEn = new RegExp("(^|[\\n=>])([^" + EE_faChrs + EE_faNums + "\\n\\{\\}\\|=]*)" + EE_faNums[i] + "([^" + EE_faNums + "\\n\\{\\}\\|=]*?[A-Za-z0-9])", "g");
                    old = old.replace(reFaToEn, "$1$2¬!¬" + i + "$3");
                    old = old.replace(/¬!¬/g, "");
                    var reFaToEn = new RegExp("([A-Za-z0-9][^" + EE_faChrs + EE_faNums + "\\n\\{\\}\\|=]*)" + EE_faNums[i] + "([^" + EE_faNums + "\\n\\{\\}\\|=]*?[\\n\\{\\}\\|<$])", "g");
                    old = old.replace(reFaToEn, "$1¬!¬" + i + "$2");
                    old = old.replace(/¬!¬/g, "");
                }
                if (old == str) break;
                str = old;
            }
            // انگلیسی به فارسی
            while (1 == 1) {
                for (var i = 0; i < 10; i++) {
                    var reEnToFa = new RegExp("([" + EE_faChrs + ">][^A-Za-z0-9\\n\\{\\}\\|=]*)" + i + "([^A-Za-z\\n\\{\\}\\|=]*?[<" + EE_faChrs + EE_faNums + "])", "g");
                    old = old.replace(reEnToFa, "$1" + EE_faNums[i] + "$2");
                    var reEnToFa = new RegExp("(^|[=\\n\\{\\}\\|>])([^A-Za-z0-9\\n\\{\\}\\|=]*)" + i + "([^A-Za-z\\n\\{\\}\\|=]*?[\\n\\{\\}\\|<$])", "g");
                    old = old.replace(reEnToFa, "$1$2" + EE_faNums[i] + "$3");
                }
                if (old == str) break;
                str = old;
            }
            // فارسی به انگلیسی (آن‌هایی که صددرصد باید انگلیسی شوند)
            while (1 == 1) {
                for (var i = 0; i < 10; i++) {
                    var reFaToEn = new RegExp('(style|colspan|rowspan|cellspacing|width|size|border|thumbtime)( *= *[^\\|\\n]*?)' + EE_faNums[i] + '(.*?\\|)', 'g');
                    old = old.replace(reFaToEn, "$1$2¬!¬" + i + "$3");
                    old = old.replace(/¬!¬/g, "");
                    var reFaToEn = new RegExp('(<math>[^<]*?)' + EE_faNums[i] + '([^<]*<\\/math>)', 'g');
                    old = old.replace(reFaToEn, "$1¬!¬" + i + "$2");
                    old = old.replace(/¬!¬/g, "");
                    var reFaToEn = new RegExp('(https?://[^\\s\\r\\n\\|\\}]*?)' + EE_faNums[i], 'g');
                    old = old.replace(reFaToEn, "$1¬!¬" + i);
                    old = old.replace(/¬!¬/g, "");
                    var reFaToEn = new RegExp('(' + EE_faNums[i] + ')پیکسل', 'g');
                    old = old.replace(reFaToEn, "$1¬!¬پیکسل" + i);
                    old = old.replace(/¬!¬/g, "");
                }
                if (old == str) break;
                str = old;
            }
    
            // عربی به فارسی
            for (var i = 0; i < 10; i++) {
                str = str.replace(new RegExp(EE_arNums[i], 'g'), EE_faNums[i]);
            }
    
            //These three lines are for reverting link's bugs!
            diffString(old_text, str);
            str = RevertBug(tupO, tupN, str);
            str = links_underline(str, 'End')
            //end 
    
            // Decimal point, and thousands' separator
            str = str.replace(/([۱۲۳۴۵۶۷۸۹۰])\.([۱۲۳۴۵۶۷۸۹۰])/g, '$1٫$2');
            str = str.replace(/([۱۲۳۴۵۶۷۸۹۰]),([۱۲۳۴۵۶۷۸۹۰])/g, '$1٬$2');
    
            return str;
        }
    };
    
    
    function Punctuation(str) {
        str = str.replace(/ *(\<\/? ?br ?\/?\>|\{\{بر\}\}) */g, "{{سخ}}");
    
        str = str.replace(/([،\.])([^\s\.\(\)«»\"\[\]\<\>\d\w\{\}\|۰-۹])/g, "$1 $2");
    
        str = str.replace(/([\(«])\s/g, '$1');
        str = str.replace(/\s([\)»])/g, '$1');
        str = str.replace(/٬\s/g, "، ");
    
        str = str.replace(/(\<\/ref\>)\s+(\<ref)/g, "$1$2");
    
        // Format headings level 2 and above
        str = str.replace(/(\={2,})\s*([^\=]*?)\s*(\={2,})/g, "$1 $2 $3");
        // TODO: remove extra lines AFTER this part
    
        // تغییرات جزئی که برای ربات‌ها تعریف شده بود
        str = str.replace(/[\r\n]{3,}/g, "\n\n");
        str = str.replace(/[\r\n]\s{1,}[\r\n]/g, "\n\n");
        str = str.replace(/([^=])[\r\n]+(\=.*?\=[\r\n]+)/g, "$1\n\n$2");
        str = str.replace(/[\s\r\n]+\<ref/g, "<ref");
        str = str.replace(/([\r\n]?)[\s\r\n]+?\<\/ref\>/g, "$1</ref>");
    
        // Add a space after the # or * for lists
        str = str.replace(/^([*#]+)([^*#:\s])/mg, "$1 $2");
    
        // Remove extra newlines between two list lines
        old = "";
        while (str != old) {
            old = str;
            str = str.replace(/(^|\n)(#+[^\n]*)\n\n+([#])/mg, "$1$2\n$3");
            str = str.replace(/(^|\n)(\*+[^\n]*)\n\n+([\*])/mg, "$1$2\n$3");
        }
    
        //برداشتن حروف نالازم در ابتدا و انتهای عنوان زیر بخش‌های سطح ۲ به بالا
        var notneededs = ":,;'<>»«&^#@•→←↔↑↓—–…~٫،؛ٔ"
        for (var i = 0; i < 27; i++) {
            str = str.replace(new RegExp('((\=+){2,}) ' + notneededs[i], 'g'), "== ");
            str = str.replace(new RegExp(notneededs[i] + ' ((\=+){2,})', 'g'), " $1");
        }
    
        // Redirect pages must start with #تغییرمسیر with no extra spaces
        // before or inside the تغییرمسیر part, and one space after it but
        // before the link
        str = str.replace(/^#\s*(REDIRECT|تغییر[ _]?مسیر)/ig, '#تغییرمسیر');
        str = str.replace(/^#تغییرمسیر(\S)/g, '#تغییرمسیر $1');
    
        // Remove extra newline between two lines both starting with a *
        str = str.replace(/(\n\*.*?)\n+(?=\n\*)/g, '$1');
    
        // فاصله را از آخر خط پاک می‌کند
        str = str.replace(/([^=]) *$/mg, "$1");
    
    
        // اصلاح {{•}}
        str = str.replace(/[\n\s]*\{\{[•·ن](w?)\}\}\s*/g, "{{•$1}} ");
    
        // برای گذاشتن گیومه برای خاصیت‌های برچسب طبق اکس‌ام‌ال
        // اشکال مشخصی که دارد این است که همهٔ نویسه‌های قابل قبول برای اکس‌ام‌ال را نمی‌پذیرد، چه نویسه‌هایی لازم است؟
        var old = "";
        while (old != str) {
            old = str;
            str = str.replace(/(\<\w*(?:\s\w*=['"\w\d]+)*\s+\w*=)([\w\d_]+)((?:\s\w*=['"\w\d]+)*\s?\/?\>)/g, "$1\"$2\"$3")
            // first version: .replace(/\<(\w*\s+\w*=)(\w+[\w\d]*)\>/, "<$1\"$2\">");
        }
    
        // Remove spaces preceding the }} closing tag for templates
        str = str.replace(/\s+\}\}/g, '}}');
    
        // Remove space after ( and before ) if there are Persian characters
        // on both sides; also, add a space before ( and after ) in the same
        // situation
        re = new RegExp("([" + EE_faChrs + "]+)\\s*\\(\\s*([" + EE_faChrs + "]+)", "g");
        str = str.replace(re, "$1 ($2");
        re = new RegExp("([" + EE_faChrs + "]+)\\s*\\)\\s*([" + EE_faChrs + "]+)", "g");
        str = str.replace(re, "$1) $2");
    
        // Full stop and comma should be before citation.
        old = "";
        while (old != str) {
            old = str;
            str = str.replace(/\.? ?(<ref>[^<]*<\/ref>) ?\./g, '.$1');
            str = str.replace(/\،? ?(<ref>[^<]*<\/ref>) ?\،/g, '،$1');
        }
    
        old = "";
        while (old != str) {
            old = str;
            // Convert , to ، if there are Persian characters on both sides of it
            // and also remove any spaces between the words on each side and the
            // Persian comma itself.
            // NOTE: we will add a space after the comma later on
            var re = new RegExp(" ([ " + EE_faChrs + "]+),([ " + EE_faChrs + "]+)", "g");
            str = str.replace(re, "$1،$2");
    
            // Remove space preceding puncations
            str = str.replace(/ ([؟،:؛!\.])/g, "$1");
    
    
            // Add space after punctuations
            // NOTE: Adds a space after :, which affects internal links (categories, images, etc)
            re = new RegExp("([" + EE_faChrs + "]+)([؟،؛!\.])([" + EE_faChrs + "]+)", "g");
            str = str.replace(re, "$1$2 $3");
        }
    
        // Remove unnecessary space caused by last line in category links (it had bug for پرونده:)
        re = new RegExp("\\[\\[(رده|الگو|ویکی\u200cپدیا)\\:\\s+", "g");
        str = str.replace(re, "[[$1\:");
    
        str = str.trim(); //Removing \n and \r from first and end of pages
        return str;
    };
    
    
    /** Dictation Tool
     *
     *  Description: Correcting ZWNJ and diction mistakes
     *  it uses [[Mediawiki:Gadget-Extra-Editbuttons-Dictionary.js]] as dictionary.
     *
     */
    function Regex_Replace(W1, W2, Extensions, str) {
        var regex = new RegExp("(^|[^" + EE_faChrs + "])(\\s|\u200c|\_|)(" + W1 + ")(\\s|\_)(" + W2 + ")(\\s|\u200c|\_|)(" + Extensions + ")($|[^" + EE_faChrs + "])", "g");
        str = str.replace(regex, "$1$2$3\u200c$5$6$7$8");
        return str;
    };
    function ZWNJ_Dictation(str) {
    
        //These two lines are for reverting link's bugs!
        str = links_underline(str, 'Start')
        var old_text = str;
        // end
        //for Complexes
        for (var word in Complexes) {
            var W1 = word;
            var W2 = Complexes[word];
            var Extensions = "ی|ها|های|هایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|";
            str = Regex_Replace(W1, W2, Extensions, str)
        };
    
        //for last name 
        var W1 = Person_Name;
        var W2 = "ی|زاده|نیا|پور|گان|فر|نژاد|یان|ی‌ها|یها";
        var Extensions = "ی|";
        str = Regex_Replace(W1, W2, Extensions, str)
        //for Abad 
        var W1 = Person_Name + "|" + Add2Abad;
        var W2 = "آباد";
        var Extensions = "زاده|نیا|پور|گان|فر|نژاد|ی|یان|ها|های|هایی|ی‌ها|یها|";
        str = Regex_Replace(W1, W2, Extensions, str)
        //for First name 
        for (var word in FirstNameComplex) {
            var W1 = word;
            var W2 = FirstNameComplex[word];
        var regex = new RegExp("(^|[^" + EE_faChrs + "]|\\s|\_)(" + W1 + ")(\\s|\_)(" + W2 + ")(\\s|\_)($|[^" + EE_faChrs + "]|[^+ EE_faChrs +])", "g");
        str = str.replace(regex, "$1$2\u200c$4$5$6");
        };
        //for colors
        var W1 = Color_Name;
        var W2 = "فام|گون";
        var Extensions = "زاده|نیا|پور|گان|فر|نژاد|ی|ها|های|هایی|ی‌ها|یها|هایم|هایت|هایش|هایمان|هایتان|هایشان|";
        str = Regex_Replace(W1, W2, Extensions, str)
        //for Numbers
        var W1 = Farsi_Numbers;
        var W2 = "گانه|ماهه";
        var Extensions = "زاده|نیا|پور|گان|فر|نژاد|ی|ها|های|هایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|";
        str = Regex_Replace(W1, W2, Extensions, str)
        //wrong dictation
        for (var word in ForReplace) {
            var W1 = word;
            var W2 = ForReplace[word];
            var regex = new RegExp("(^|[^" + EE_faChrs + "])(\\s|\u200c|_|)(" + W1 + ")(\\s|\u200c|_|)($|[^" + EE_faChrs + "])", "g");
            str = str.replace(regex, "$1$2" + W2 + "$4$5");
        };
    
       //Function for removing incorrect ZWNJs
        str=RemoveBadZWNJ(str)
    
        //حذف فاصلهٔ مجازی قبل و بعد از سجاوندی 
        str = str.replace(/\u200c([\n\s\.،«»\:\(\)\؛\؟\?\;\$\!\@\-\=\+\\])/g, '$1');
        str = str.replace(/([\n\s\.،«»\:\(\)\؛\؟\?\;\$\!\@\-\=\+\\])\u200c/g, '$1');
        //These three lines are for reverting link's bugs!
        diffString(old_text, str);
        str = RevertBug(tupO, tupN, str);
        str = links_underline(str, 'End')
        //end 
    
        return str;
    };
    function RemoveBadZWNJ(str) {
        var old=''
        while (old != str) {
            old = str;
    		// Remove ZWNJ after characters that don't conncet to the next letter
    		re = new RegExp("([" + EE_faNums +
    			"0-9" +
    			"إأةؤورزژاآدذ" +
    			"،؛,\\:" +
    			"«»\\/@#$٪×\\*\\(\\)ـ\\-=\\|" +
    			"])" + "\u200c");
    		str = str.replace(re, "$1");
    
    		// Remove ZWNJ before characters that don't conncet to the previous letter
    		re = new RegExp("([" + EE_faNums +
    			"0-9" +
    			"،؛,\\:" +
    			"«»\\/@#$٪×\\*\\(\\)ـ\\-=\\|" +
    			"])" + "\u200c");
    		str = str.replace(re, "$1"); 
        };
        return str;
    };
    /** SuperTool
     *
     *  Description: Applies all of YKarabic, FM, NonStandard and digits
     *  functions to the text.
     *
     */
    function SuperTool(str) {
        str = YKarabic(str);
        str = FM(str);
        str = NonStandard(str);
        str = digits(str);
        str = Punctuation(str);
        str = URLfix(str);
        return str;
    };
    
    /** SuperTool_move
     *
     *  Description: A special flavor of the SuperTool() function
     *  that should only be used on the move page.
     *
     */
    function SuperTool_move(str) {
        str = YKarabic(str);
        str = FM(str);
        str = NonStandard(str);
        str = digits_move(str);
        str = Punctuation(str);
        return str;
    };