משתמש:Mikimik/js/autoStandardContent.js

מתוך ויקיפדיה, האנציקלופדיה החופשית

הערה: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.

  • פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
  • גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
  • אינטרנט אקספלורר / אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
  • אופרה: ללחוץ על Ctrl-F5.
// alert if interwiki links are not in order or duplicate
function checkInterwikiOrder()
{
  try {
    var langbox = document.getElementById("p-lang");
    if ( !langbox ) return;
    var items = langbox.getElementsByTagName("li");
    if ( !items.length ) return;

    var duplicates = new Array();
    var orderFlag = false;
    var duplicateFlag = false;
    var englishpart = wgContentLanguage == "he";
    var wikiLink = wgServer.replace ( /^.+?\./, "" );

    for ( var i = 0 ; i < items.length ; i++ )
    {
        var link = items[i].getElementsByTagName("a")[0].href;
        if ( link.indexOf(wikiLink) == -1 ) continue;                // skip if this is not a link to the same project

        if ( duplicates[link] )
        {
            duplicateFlag = true;
            break;
        }
        duplicates[link] = true;

        englishpart = englishpart && /^http:\/\/en\./.test(link);

        if ( !englishpart && ( ( wgContentLanguage == "he" && /^http:\/\/en\./.test(link) ) ||
             ( items[i+1] && items[i+1].getElementsByTagName("a")[0].href.indexOf(wikiLink) != -1 &&
               link.replace(/-/g, "\xFF") > items[i+1].getElementsByTagName("a")[0].href.replace(/-/g, "\xFF") ) ) )
            orderFlag = true;
    }

    if ( !orderFlag && !duplicateFlag ) return;

    langbox.style.borderColor = duplicateFlag ? "red" : "orange";                // mark the box in red/orange
    document.title = (duplicateFlag ? "DUP: " : "ORDER: ") + document.title;     // change the page title
  }
  catch(e)
  {
    return;      // lets just ignore what's happened
  }
}

if ( wgNamespaceNumber >= 0 ) addOnloadHook ( checkInterwikiOrder );


/* ************************************ auto standardize page *********************************** */
var standardizeButtonObject = null;
var autoStandardizeTextBox = null;
var standardizePhase = 0;                       // phase of standardization
var standardizeSummaryBoard = new Array();      // reportStandardizeMessage() keeps report-codes here
var autoStandardizeSummary = { value : "" };    // summary message for the user


function autoStandardizeButton ( event )
{
  try {
    if ( !document.getElementById("wpTextbox1") || !document.getElementById("wpSummary") ) return;

    if ( event )
    {
        autoStandardizeTextBox = document.getElementById("wpTextbox1");
        autoStandardizeSummary = document.getElementById("wpSummary");
        autoStandardizePage ( autoStandardizeTextBox.value );   // get the text from the textbox and send it to the autoStandardize function
        autoStandardizeTextBox = null;
        autoStandardizeSummary = { value : "" };
        return;
    }

    standardizeButtonObject = addSystemButton ( "סטנדרט", autoStandardizeButton, "autoStandardizeButton", "Standardize", "" );
  }
  catch(e)
  {
    return;      // lets just ignore what's happened
  }
}


function addSystemButton ( value, onclick, id, tooltip, accesskey )
{
    var insertPoint = document.getElementById("wpDiff");
    if ( !insertPoint ) return null;

    var btn = document.createElement("input");
    btn.type = "button";
    if ( value ) btn.value = value;
    if ( onclick ) btn.onclick = onclick;
    if ( id ) btn.id = id;
    if ( tooltip ) btn.title = tooltip;
    if ( accesskey )
    {
        btn.accessKey = accesskey;
        btn.title += " [" + tooltipAccessKeyPrefix + btn.accessKey + "]";
    }

    insertPoint.parentNode.insertBefore ( btn, insertPoint );
    return btn;
}


function autoStandardizePage ( text )
{

    function reportStandardizeMessage ( msgCode, msgInfo )               // deliver message to the user in the summary field
    {
        if ( msgCode == "CRASH" )
        {
            if ( msgInfo != "CRASH" )                                    // if it's an internal problem
            {
                autoStandardizeSummary.value = msgInfo;                  // output the crash message
                throw ( 7 );                                             // and terminate the script
            }
            if ( standardizeButtonObject )
                standardizeButtonObject.style.backgroundColor = "red";   // mark button in color - "CRASH!"
            return "*****" + autoStandardizeSummary.value + "*****";
        }

        if ( msgCode == "INIT" )
        {
            if ( standardizeButtonObject )
            {
                standardizeButtonObject.disabled = true;
                standardizeButtonObject.style.backgroundColor = "blue";           // mark button in color - "I'm working!"
            }
            standardizeSummaryBoard["STAGE"] = 0;                                 // set stage = 0
            standardizeSummaryBoard["ORIGINAL"] = autoStandardizeSummary.value;   // save original summary
            standardizeSummaryBoard["MORE_THAN_ONE"] = "";                        // clear error message
            autoStandardizeSummary.value += "סקריפט רץ... "

            if ( document.getElementById("wpWatchthis") &&
                 ( ( document.getElementById("ca-unwatch") && document.getElementById("ca-unwatch").tagName == "LI" &&
                     /&action=watch$/.test(document.getElementById("ca-unwatch").getElementsByTagName("a")[0].href) ) ||
                   ( document.getElementById("ca-watch")   && document.getElementById("ca-watch").tagName == "LI"   &&
                     /&action=watch$/.test(document.getElementById("ca-watch").getElementsByTagName("a")[0].href)   ) ) )
                document.getElementById("wpWatchthis").checked = false;  // uncheck the "watch this page", unless the page is already watched

            return autoStandardizeSummary.value;
        }

        if ( msgCode == "PROGRESS" )
        {
            if ( !standardizeSummaryBoard["PROGRESS"] ) autoStandardizeSummary.value += msgInfo;
             else autoStandardizeSummary.value = autoStandardizeSummary.value.replace ( standardizeSummaryBoard["PROGRESS"], msgInfo );
            standardizeSummaryBoard["PROGRESS"] = msgInfo;
            return autoStandardizeSummary.value;
        }

        if ( msgCode != "ERROR" && msgCode != "DONE" )
        {
            switch ( msgCode )
            {
                case "" :
                    break;
                case "DUPLICATE" :    case "DUPLICATE_CATEGORY" :
                    if ( msgInfo ) standardizeSummaryBoard[msgCode] = (standardizeSummaryBoard[msgCode] ? standardizeSummaryBoard[msgCode] : 0) + msgInfo;
                    break;
                case "LIST" :         case "HTTPinBRACKETS" :   case "FAKE_HTTP" :  case "SPACE" :              case "LINK" :
                case "SELFLINK" :     case "PREPOSITION" :      case "COLON" :      case "CATEGORY_LOCATION" :  case "LANG_TEMPLATES" :
                case "DOUBLE_REF" :   case "TEMPLATES_MOVED" :  case "ELEMENTS" :   case "HEADLINE" :           case "TAGS_ERROR" :
                case "DOUBLE_PIPE" :
                    if ( msgInfo ) standardizeSummaryBoard[msgCode] = msgInfo;
                    break;
                default :
                    standardizeSummaryBoard[msgCode] = (standardizeSummaryBoard[msgCode] ? standardizeSummaryBoard[msgCode] : "") + (msgInfo ? msgInfo : "active");
                    if ( msgCode == "MORE_THAN_ONE" ) return;
            }

            standardizeSummaryBoard["STAGE"]++;
            autoStandardizeSummary.value += standardizeSummaryBoard["STAGE"] + ", ";
            return autoStandardizeSummary.value;
        }

//---
        var reporttext = "";
        if ( msgCode == "ERROR" ) reporttext = msgInfo;
         else
        {
            if ( standardizeSummaryBoard["HTML_TAGS"]           ) reporttext += ", תגים";
            if ( standardizeSummaryBoard["MISC"]                ) reporttext += ", זוטות";
            if ( standardizeSummaryBoard["LIST"]                ) reporttext += ", רשימות"            + "x\u200F" + standardizeSummaryBoard["LIST"];
            if ( standardizeSummaryBoard["HTTPinBRACKETS"]      ) reporttext += ", [קישור חיצוני]"    + "x\u200F" + standardizeSummaryBoard["HTTPinBRACKETS"];
            if ( standardizeSummaryBoard["FAKE_HTTP"]           ) reporttext += ", קישור מקומי"       + "x\u200F" + standardizeSummaryBoard["FAKE_HTTP"];
            if ( standardizeSummaryBoard["SPACE"]               ) reporttext += ", רווחים"            + "x\u200F" + standardizeSummaryBoard["SPACE"];
            if ( standardizeSummaryBoard["LINK"]                ) reporttext += ", קישורים"           + "x\u200F" + standardizeSummaryBoard["LINK"];
            if ( standardizeSummaryBoard["SELFLINK"]            ) reporttext += ", קישור עצמי"        + "x\u200F" + standardizeSummaryBoard["SELFLINK"];
            if ( standardizeSummaryBoard["PREPOSITION"]         ) reporttext += ', אותיות בכלמהו"ש'   + "x\u200F" + standardizeSummaryBoard["PREPOSITION"];
            if ( standardizeSummaryBoard["COLON"]               ) reporttext += ", נקודתיים"          + "x\u200F" + standardizeSummaryBoard["COLON"];
            if ( standardizeSummaryBoard["CATEGORY_LOCATION"]   ) reporttext += ", מיקום בקטגוריה"    + "x\u200F" + standardizeSummaryBoard["CATEGORY_LOCATION"];
            if ( standardizeSummaryBoard["LANG_TEMPLATES"]      ) reporttext += ", {{שפה}}"           + "x\u200F" + standardizeSummaryBoard["LANG_TEMPLATES"];
            if ( standardizeSummaryBoard["DOUBLE_REF"]          ) reporttext += ", הערות זהות"        + "x\u200F" + standardizeSummaryBoard["DOUBLE_REF"];
            if ( standardizeSummaryBoard["TEMPLATES_MOVED"]     ) reporttext += ", מיקום תבניות"      + "x\u200F" + standardizeSummaryBoard["TEMPLATES_MOVED"];
            if ( standardizeSummaryBoard["ELEMENTS"]            ) reporttext += ", אלמנטים של סוף דף" + "x\u200F" + standardizeSummaryBoard["ELEMENTS"];
            if ( standardizeSummaryBoard["DUPLICATE"]           ) reporttext += ", כפילות"            + "x\u200F" + standardizeSummaryBoard["DUPLICATE"];
            if ( standardizeSummaryBoard["DUPLICATE_CATEGORY"]  ) reporttext += ", כפילות בקטגוריות"  + "x\u200F" + standardizeSummaryBoard["DUPLICATE_CATEGORY"];
            if ( standardizeSummaryBoard["INTERWIKI"]           ) reporttext += ", סדר בינוויקי";
            if ( standardizeSummaryBoard["INTERWIKI_FA"]        ) reporttext += ", סדר מומלצי בינוויקי";
            if ( standardizeSummaryBoard["NOINTERWIKI"]         ) reporttext += ", הסרת {{אין בינוויקי}} - יש בינוויקי" + (standardizeSummaryBoard["NOINTERWIKI"] == "en" ? " באנגלית" : "");
            if ( standardizeSummaryBoard["HEADLINE"]            ) reporttext += ", כותרות"            + "x\u200F" + standardizeSummaryBoard["HEADLINE"];
            if ( standardizeSummaryBoard["ORDER"]               ) reporttext += ", סדר כותרות";

            if ( reporttext ) reporttext = "תיקון:" + reporttext.substr(1) + " [JS]";

            if ( standardizeSummaryBoard["MORE_THAN_ONE"] ) reporttext += (reporttext ? ", " : "") + "הערה: יותר מידי תבניות" + standardizeSummaryBoard["MORE_THAN_ONE"].substr(1);
            if ( standardizeSummaryBoard["TAGS_ERROR"] ) reporttext += (reporttext ? ", " : "") + "אזהרה: תחביר שגוי -" + standardizeSummaryBoard["TAGS_ERROR"].substr(1);
            if ( standardizeSummaryBoard["DOUBLE_PIPE"] ) reporttext += (reporttext ? ", " : "") + "אזהרה: צינור כפול בקישור - " + standardizeSummaryBoard["DOUBLE_PIPE"];
        }

        if ( !reporttext ) autoStandardizeSummary.value = standardizeSummaryBoard["ORIGINAL"];   // restore original summary
         else
        {
            if ( standardizeSummaryBoard["PREVIOUS"] && standardizeSummaryBoard["ORIGINAL"].indexOf(standardizeSummaryBoard["PREVIOUS"]) != -1 )
                    autoStandardizeSummary.value = standardizeSummaryBoard["ORIGINAL"].replace(standardizeSummaryBoard["PREVIOUS"], reporttext);
               else autoStandardizeSummary.value = standardizeSummaryBoard["ORIGINAL"] + (/^(\/\*.+?\*\/)? *$/.test(standardizeSummaryBoard["ORIGINAL"]) ? "" : ", ") + reporttext;

            standardizeSummaryBoard["PREVIOUS"] = reporttext;
        }

        if ( standardizeButtonObject )
        {                                                                                        // color the button - "done working!"
            if ( !standardizePhase ) standardizeButtonObject.style.backgroundColor = "#FFBBBB";  // shade of pink
             else standardizeButtonObject.style.backgroundColor = "#FFFFBB";                     // light yellow
            standardizeButtonObject.disabled = false;
        }
        standardizePhase++;

        return autoStandardizeSummary.value;
    }


    function removeHardExcessSpaces ( text )
    {
        return removeExcessSpaces (
                   removeExcessSpaces (text)                                          // first remove simple excess spaces
                       .replace(/ +(\n|$)/g, " \n")                                   // reduce excess spaces at end of empty lines to 1 space
                       .replace(/( \n)*$/, "\n")                                      // remove lines at end of text that have only a space + add a linebreak at the end
                       .split("").reverse().join("")                                  // reverse text so I can mimick lookbehind assertion
                       .replace(/\n (?=(\n|$))(?!\n( \n)*[^ \n].*? +(\n|$))/g, "\n")  // remove space in empty line if it's not part of a <pre> section
                       .split("").reverse().join("")                                  // reverse text back to the original
                   );                                                                 // remove empty lines from the beginning and the end
    }


    function removeExcessSpaces ( text, howmany )
    {
        text = text.replace(/([^ \n]) +(\n|$)/g, "$1\n")    // remove excess spaces at end of non-empty lines
                   .replace(/(^\n*|\n*$)/g, "");            // remove linebreaks from the beginning and the end

        return ( text ? text + "\n\n\n\n".substr(0, howmany ? howmany : 1) : "" );   // add linebreaks at the end as needed
    }


    function storeInRepository ( repository, section, rxfragment, id )  // if id is not set then no place holder is placed in the text
    {
        var fragments = section.match ( rxfragment );
        if ( !fragments ) return section;
        var out = "";

        for ( var i = 0 ; i < fragments.length ; i++ )
        {
            out += section.substring(0,section.indexOf(fragments[i])) + ( id ? "\xFF" + id + "%" + repository.length + "%" : "" );
            section = section.substring(section.indexOf(fragments[i]) + fragments[i].length);
            repository.push ( fragments[i] );
        }

        return out + section;
    }


    function restoreFromRepository ( repository, section, id, flag )              // restore stored parts with "id" from the repository
    {                                                                             // in default this is done recursivly, unless the flag is set
        var rx = new RegExp ( "\xFF(" + (id ? id : ".+?") + ")%(\\d+)%", "g" );   // if ID is empty - restore everything

        do {
            var out = "";
            var markers = section.match ( rx );

            if ( markers )
                for ( var i = 0 ; i < markers.length ; i++ )
                {
                    out += section.substring ( 0, section.indexOf(markers[i]) ) + repository[ markers[i].replace(rx,"$2") ];
                    section = section.substring ( section.indexOf(markers[i]) + markers[i].length );
                }

            section = out + section;
        } while ( !flag && markers );

        return section;
    }


    function grabSpecialFragments ( section, id, fragments )
    {
        var rx = new RegExp ( "( |\n)*(\xFF(" + id + ")%\\d+%)(\n|)\n*" );            // grab anywhere, from beginning to end

        while ( rx.test(section) )
        {
            fragments.push ( rx.exec(section)[0].replace(rx,"$2") );  // save the fragment
            section = section.replace ( rx, "$4" );    // remove the fragment -or-
        }                                              // if there is a linebreak after the fragment replace it with a linebreak

        return section;
    }


    function grabTemplatesInSection ( arr, section, name )
    {
        section = storeInRepository ( arr, section, new RegExp("\\{\\{" + name + "(\n?\\|(.|\n)*?)?}}( *\\{\\{כ}})*","g"), "st" );

        return section.replace( /(^|\n)( |\*|:|#)+(?=\xFFst%\d+%)/g, "$1" )
                      .replace( /((^|\n)( *\xFFst%\d+%)+) +/g, "$1" )
                      .replace( /(^|\n)( *(\xFFst%\d+% *)+\n)+/g, "$1" )
                      .replace( /\xFFst%\d+%/g, "" );
    }


    function deleteDuplicatesAndReport ( elements, reportcode, onlyone )  // delete duplicates in the array and report the action
    {
        var duplicates = new Array();
        var num = 0;                      // the number of non-duplicate elements in the array
        var dup = 0;                      // the number of deleted duplicates

        for ( var i = 0 ; i < elements.length ; i++ )
            if ( elements[i] )
            {
                var head = /\{\{(מיון רגיל:|Coord|ללא בוט|קצרמר|תריג)/.test(elements[i]) ? "" : elements[i].replace(/(\n?\|(.|\n)*|}}|]])/,"");

                if ( !duplicates[elements[i]] && duplicates[head] == undefined )
                {
                    duplicates[elements[i]] = true;
                    if ( head ) duplicates[head] = i;
                    num++;
                }
                else
                {
                    if ( duplicates[elements[i]] || elements[i].length <= elements[duplicates[head]].length )     // delete duplicate
                          elements[i] = "";
                     else elements[duplicates[head]] = "";
                    dup++;
                }
            }

        reportStandardizeMessage ( reportcode, dup );
        if ( onlyone && num > 1 ) reportStandardizeMessage ( "MORE_THAN_ONE", onlyone );
    }


    function sortInterwikiAndReport ( elements, rx, reportcode )
    {
        for ( var i = elements.length - 1 ; i >= 0 ; i-- )
            if ( elements[i].replace(rx,"$2").toLowerCase() == wgContentLanguage ) elements.splice ( i, 1 ); // remove interwiki to the local language
             else
                elements[i] = elements[i].replace( rx, "$1" ) +
                              elements[i].replace( rx, "$2" )         // get the language code and:
                                         .toLowerCase()               // 1. turn it to lower case
                                         .replace ( /^en$/, "00" )    // 2. the EN interwiki(s) will be first in the sort operation
                                         .replace ( /-/g, "\xFF" ) +  // 3. fix order of language codes that contain "-"
                              elements[i].replace( rx, "$3" );

        var originalorder = elements.join("");                        // save the original order

        elements.sort();                                              // sort the elements
        for ( var i = elements.length - 2 ; i >= 0 ; i-- )            // and remove duplicates if any
            if ( elements[i+1] == elements[i] ) elements.splice ( i+1, 1 );

        var flag = originalorder == elements.join("");

        for ( var i = elements.length - 1 ; i >= 0 ; i-- )
            elements[i] = elements[i].replace( rx, "$1" ) +
                          elements[i].replace( rx, "$2" )             // get the language code and:
                                     .replace( "00", "en" )           // 1. change the EN interwiki back to the original name
                                     .replace( /\xFF/g, "-" ) +       // 2. change the "-" back
                          elements[i].replace( rx, "$3" );

        reportStandardizeMessage ( flag ? "" : reportcode, "" );
    }


    function insertLanguageTemplates ( section )
    {
        var repo = new Array();
        var t = 0;
        section = section.replace(/\n/g,"\n\n");

        for ( var i = 0 ; i < langTemplateInfo.length ; i++ )
        {
            section = storeInRepository ( repo, section, langTemplateInfo[i].rx, "lt" );
            for ( ; t < repo.length ; t++ )
                if ( new RegExp("([^ \n] *\xFFlt%" + t + "%|\xFFlt%" + t + "% *[^ \n])").test(section) )
                {
                    repo[t] = repo[t].replace ( langTemplateInfo[i].rx, langTemplateInfo[i].text )
                                     .replace ( /, , ( ו(?=}))?/, ", " )                 // remove extra commas
                                     .replace ( /, (?=(}| ו))/, "" )                     // and remove another unneeded comma
                                     .replace ( existingLangTemplates, "{{$2$3}}" );     // use a language-template if one exists
                    langCounter++;
                }
        }

        return restoreFromRepository(repo,section,"lt").replace(/\n\n/g,"\n");
    }


    function getLengthOfMatch ( arr )
    {
        return arr ? arr.length : 0;
    }


    function getTextAround ( section, pos, len )
    {
        return restoreFromRepository ( allBitsInPage,section.substring(pos-2*len,pos      ) ).replace (/\n/g, "-" ).replace( new RegExp("^.*?(.{0," + len + "})$"), "$1" ) +
               restoreFromRepository ( allBitsInPage,section.substring(pos      ,pos+2*len) ).replace (/\n/g, "-" ).substring(0,len);
    }


    function unescape ( s )
    {
        var sbuf = "";
        var ch = -1;
        var b = 0;
        var sumb = 0;

        s = s.replace ( /#.+/, s.replace(/.*#/,"#").replace(/\.([0-9A-Z][0-9A-Z])/ig,"%$1") );  // xyz#.AA.AA.AA  -->  xyz#%AA%AA%AA

        for ( var i = 0, more = -1 ; i < s.length ; i++ )
        {
            switch ( ch = s.charAt(i) )                  // Get next byte b from URL segment s
            {
                case "%":
                    ch = s.charAt(++i);
                    var hb = /[0-9]/.test(ch) ? ch - "0" : 10 + (ch.toLowerCase().charCodeAt(0) - 0x61) & 0xF;
                    ch = s.charAt(++i);
                    var lb = /[0-9]/.test(ch) ? ch - "0" : 10 + (ch.toLowerCase().charCodeAt(0) - 0x61) & 0xF;
                    b = (hb << 4) | lb;
                    break;
                case "+":
                    b = " ";
                    break;
                default:
                    b = ch;
            }
                                             // Decode byte b as UTF-8, sumb collects incomplete chars
            if ( (b & 0xc0) == 0x80 ) {                  // 10xxxxxx (continuation byte)
                sumb = (sumb << 6) | (b & 0x3f);         // Add 6 bits to sumb
                if ( --more == 0 ) sbuf += String.fromCharCode(sumb);  // Add char to sbuf
            }
            else if ( (b & 0x80) == 0x00 ) {             // 0xxxxxxx (yields 7 bits)
                sbuf += b;                               // Store in sbuf
            }
            else if ( (b & 0xe0) == 0xc0 ) {             // 110xxxxx (yields 5 bits)
                sumb = b & 0x1f;
                more = 1;                                // Expect 1 more byte
            }
            else if ( (b & 0xf0) == 0xe0 ) {             // 1110xxxx (yields 4 bits)
                sumb = b & 0x0f;
                more = 2;                                // Expect 2 more bytes
            }
            else if ( (b & 0xf8) == 0xf0 ) {             // 11110xxx (yields 3 bits)
                sumb = b & 0x07;
                more = 3;                                // Expect 3 more bytes
            }
            else if ( (b & 0xfc) == 0xf8 ) {             // 111110xx (yields 2 bits)
                sumb = b & 0x03;
                more = 4;                                // Expect 4 more bytes
            }
            else /*if ((b & 0xfe) == 0xfc)*/ {           // 1111110x (yields 1 bit)
                sumb = b & 0x01;
                more = 5;                                // Expect 5 more bytes
            }
          // We don't test if the UTF-8 encoding is well-formed
        }

        return sbuf;
    }


  try {                              // ****************** autoStandardizePage() function body starts *******************

// ------------------------------------------ stage X: initiate constants and variables ---------------------------

    var startofpagerx = /__(NOTOC|ללא_תוכן|NOEDITSECTION|ללא_עריכה|NEWSECTIONLINK|יצירת_הערה|HIDDENCAT|קטגוריה_מוסתרת|INDEX|לחיפוש|NOINDEX|לא_לחיפוש|NOGALLERY|ללא_גלריה)__/gi;
//---
    var htmlTagsA = [ "div", "p", "pre", "blockquote", "span", "font", "center", "big", "small", "sup", "sub", "u", "s", "strike",
                      "b", "i", "tt", "h1", "h2", "h3", "h4", "h5", "h6", "em", "strong", "code", "var", "cite", "abbr", "del", "ins",
                      "table", "tbody", "caption", "th", "tr", "td", "col", "ol", "ul", "li", "a",
                      "ref", "math", "timeline", "gallery", "imagemap","noinclude", "includeonly", "poem", "hiero", // special wiki tags
                      "inputbox", "categorytree", "nowiki", "source" ];
    var htmlTagsB = [ "br", "hr", "img", "references" ];
//---
    var interwikiNames =
        "|aa|ab|ace|af|ak|als|am|an|ang|ar|arc|arz|as|ast|av|ay|az|ba|bar|bat-smg|bcl|be|be-x-old|bg|bh|bi"      + // wikipedias
        "|bjn|bm|bn|bo|bpy|br|bs|bug|bxr|ca|cbk-zam|cdo|ce|ceb|ch|cho|chr|chy|ckb|co|cr|crh|cs|csb|cu|cv|cy|da"  + // (see [[:meta:List of Wikipedias]])
        "|de|diq|dsb|dv|dz|ee|el|eml|en|eo|es|et|eu|ext|fa|ff|fi|fiu-vro|fj|fo|fr|frp|frr|fur|fy|ga|gag|gan|gd|gl|glk" +
        "|gn|got|gu|gv|ha|hak|haw|he|hi|hif|ho|hr|hsb|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|ilo|io|is|it|iu|ja|jbo"      +
        "|jv|ka|kaa|kab|kbd|kg|ki|kj|kk|kl|km|kn|ko|koi|kr|krc|ks|ksh|ku|kv|kw|ky|la|lad|lb|lbe|lg|li|lij|lmo|ln|lo|lt|ltg|lv" +
        "|map-bms|mdf|mg|mh|mhr|mi|mk|ml|mn|mo|mr|mrj|ms|mt|mus|mwl|my|myv|mzn|na|nah|nap|nds|nds-nl|ne|new|ng"      +
        "|nl|nn|no|nov|nrm|nv|ny|oc|om|or|os|pa|pag|pam|pap|pcd|pdc|pfl|pi|pih|pl|pms|pnb|pnt|ps|pt|qu|rm|rmy|rn|ro" +
        "|roa-rup|roa-tara|ru|rue|rw|sa|sah|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|sn|so|sq|sr|srn|ss|st|stq"     +
        "|su|sv|sw|szl|ta|te|tet|tg|th|ti|tk|tl|tn|to|tokipona|tpi|tr|ts|tt|tum|tw|ty|udm|ug|uk|ur|uz|ve|vec"    +
        "|vi|vls|vo|wa|war|wo|wuu|xal|xh|xmf|yi|yo|za|zea|zh|zh-classical|zh-min-nan|zh-yue|zu|";
    var langlinkRX = new RegExp ( "\\[\\[ *(:?) *(" + interwikiNames.substring(1,interwikiNames.length-1) + ") *: *(.*?) *]]", "i" );
    var interwikiRX = new RegExp ( "\\[\\[(" + interwikiNames.substring(1,interwikiNames.length-1) + "):.*?]]", "g" );
//---
    var langTemplates =
        "אוקראינית|איטלקית|איסלנדית|אנגלית|אסטונית|בוסנית|בסקית|גאורגית|גליסית|גרמנית|דנית|הולנדית|הונגרית|" +  // 35 language-templates on wikipedia
        "טורקית|יוונית|יידיש|יפנית|לטבית|לטינית|ליטאית|נורבגית|סינית|ספרדית|סרבית|עברית|ערבית|פולנית|"       +  // from [[:קטגוריה:תבניות שפת קישור]]
        "פורטוגזית|פרסית|צ'כית|צרפתית|קטלאנית|רומנית|רוסית|שבדית";                                              // taken on 25/12/09

    var existingLangTemplates = new RegExp ( "\\{\\{שפת קישור\\|שפה=((" + langTemplates + ")|\\[\\[(" + langTemplates + ")]])}}", "g" );

    var allLanguages =
        "אוואדהי|אוזבקית|אויגור|אוקראינית|אורדו|אורומו|אורייה|אזרית|איבו|איטלקית|אילוקאנית|אינדונזית|אלבנית|אמהרית|"       + // 94 languages
        "אנגלית|אסאמית|אפריקאנס|אקאן|ארמנית|בוג'פורי|בולגרית|בורמזית|בלארוסית|בלוצ'ית|בנגלית|ג'אווית|ג'ואנג|"              + // from [[:w:שפות (לפי מספר דוברים)]]
        "גוג'רטית|גרמנית|האוסה|הולנדית|הונגרית|היליגיינון|הינדי|המונג|וייטנאמית|זולו|חוסה|טורקית|טורקמנית|טיגריניה|טלוגו|" + // taken on 11/10/2009
        "טמילית|יוונית|יורובה|יי|יפנית|כורדית|לאית|לומברדית|מאיתילי|מאלאיאלאם|מדורזית|מינאנגקבאו|מלאית|מלגשית|מרטהי|"      +
        "נפאלית|נפוליטנית|סבואנו|סוואהילית|סומלית|סונדנזית|סינדהית|סינהאלית|סינית|ספרדית|סרבית|עברית|ערבית|פאשטו|"         +
        "פולאנית|פולנית|פורטוגזית|פנג'אבי|פרסית|צ'ילובה|צ'יצ'ווה|צ'כית|צרפתית|קאנאדה|קונגו|קוריאנית|קזחית|קטלאנית|"        +
        "קירירואנדה|קמרית|קנטונזית|קצ'ואה|רומנית|רוסית|שבדית|שונה|תאית|"                                                   +
        langTemplates + "|"                                                                                                + // languages with language-template
        "געז|לועזית|מקדונית|אירית|בנטו|לדינו|פינית|סקוטית|"                                                                + // plus a few more
        "הינדית|טאמילית|קטלנית|שוודית";                                                                                      // and common mistakes

    var langTemplateInfo = new Array();

// ,? '''<small>'''(''' ''' in'''[[any lang]]''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?'''''' ''')'''</small>'''
    langTemplateInfo.push ( { "rx" : new RegExp( "( *(,|;|-))? *(''')?\\< *(small|sub) *\\> *(''')?\\((''')? *(''')? *ב?(''')?" +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"                      + // 10-11
                                                 "\\8\\7(((( *[,/]| ) *(''')? *ו?ב?(''')?"                                      +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"                      + // 19-20
                                                 "\\17\\16)?( *[,/]| ) *(''')? *ו?ב?(''')?"                                     +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"                      + // 25-26
                                                 "\\23\\22)?( *[,/]| ) *(''')? *ו?ב?(''')?"                                     +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"                      + // 31-32
                                                 "\\29\\28)? *\\6\\)\\5 *\\<\\/ *\\4 *\\>\\3( *(])(?!]))?"                      , "g" ) ,
                              "text" : "$34 {{שפת קישור|שפה=$10$11, $19$20, $25$26 ו$31$32}}" } );

// ,? '''<small>''' ''' in'''[[any lang]]''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?'''''' '''</small>'''
    langTemplateInfo.push ( { "rx" : new RegExp( "( *(,|;|-))? *(''')?\\< *(small|sub) *\\> *(''')? *(''')? *ב?(''')?" +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"             + //  9-10
                                                 "\\7\\6(((( *[,/]| ) *(''')? *ו?ב?(''')?"                             +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"             + // 18-19
                                                 "\\16\\15)?( *[,/]| ) *(''')? *ו?ב?(''')?"                            +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"             + // 24-25
                                                 "\\22\\21)?( *[,/]| ) *(''')? *ו?ב?(''')?"                            +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])"             + // 30-31
                                                 "\\28\\27)? *\\5 *\\<\\/ *\\4 *\\>\\3( *(])(?!]))?"                   , "g" ) ,
                              "text" : "$33 {{שפת קישור|שפה=$9$10, $18$19, $24$25 ו$30$31}}" } );

// ,? '''(''' ''' in'''[[any lang]]''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?'''''' ''')'''
    langTemplateInfo.push ( { "rx" : new RegExp( "( *(,|;|-))? *(''')?\\((''')? *(''')? *ב?(''')?"         +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 8-9
                                                 "\\6\\5(((( *[,/]| ) *(''')? *ו?ב?(''')?"                 +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 17-18
                                                 "\\15\\14)?( *[,/]| ) *(''')? *ו?ב?(''')?"                +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 23-24
                                                 "\\21\\20)?( *[,/]| ) *(''')? *ו?ב?(''')?"                +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 29-30
                                                 "\\27\\26)? *\\4\\)\\3( *(])(?!]))?"                      , "g" ) ,
                              "text" : "$32 {{שפת קישור|שפה=$8$9, $17$18, $23$24 ו$29$30}}" } );

// , ''' ''' in'''[[any lang]]''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?''''''   ''' and in'''[[any lang]]?'''''' ''' $
    langTemplateInfo.push ( { "rx" : new RegExp( " *(,|;|-) *(''')? *(''')? *ב?(''')?"                     +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 6-7
                                                 "\\4\\3(((( *[,/]| ) *(''')? *ו?ב?(''')?"                 +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 15-16
                                                 "\\13\\12)?( *[,/]| ) *(''')? *ו?ב?(''')?"                +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 21-22
                                                 "\\19\\18)?( *[,/]| ) *(''')? *ו?ב?(''')?"                +
                                                 "((" + allLanguages + ")|\\[\\[(" + allLanguages + ")]])" + // 27-28
                                                 "\\25\\24)? *\\2( |\u200F)*($|(\n)|(](?!])))"                   , "g" ) ,
                              "text" : "$32 {{שפת קישור|שפה=$6$7, $15$16, $21$22 ו$27$28}}$31" } );
//---
    var fullWikiName    = [ "wikipedia", "wikiquote", "wiktionary", "wikibooks", "wikisource", "wikinews" ];
    var shortWikiPrefix = [ "w"        , "q"        , "wikt"      , "b"        , "s"         , "n"        ];
    var localWikiPrefix = "";
    for ( i = 0 ; i < fullWikiName.length ; i++ )
        if ( wgServer.indexOf(fullWikiName[i]) != -1 )
        {
            localWikiPrefix = shortWikiPrefix[i];              /* set local wiki prefix */
            break;
        }
//---
    var wlinkRXtext = new RegExp ( "\\[\\[( ?:)?" + localWikiPrefix + " *: *(.+?)]]", "i" );      // links of the form [[(:)w : xxx ]]
    var wlinkRXinternal = /^([a-z-]+) *: *(.+| )/i;
//---
    var selfLinkRX       = new RegExp ("\\[\\["  + wgPageName.replace(/(\^|\[|\.|\$|\{|\*|\(|\\|\+|\)|\?|\<|\>)/g,"\\$1").replace(/_/g,"[_ ]") +              "(\\|.*)?]]");
    var selfSubSectionRX = new RegExp ("\\[\\[(" + wgPageName.replace(/(\^|\[|\.|\$|\{|\*|\(|\\|\+|\)|\?|\<|\>)/g,"\\$1").replace(/_/g,"[_ ]") + ") *# *([^|]+)(\\|.*)?]]");
//---
    var hebPreRX_1 = /\[\[ה([^|]+?)(( \([^|]+\))?( *#[^|]*)?)?\|(ו?(כ?ש)?[בל])\1]]/;
    var hebPreRX_2 = /\[\[([^|]+)(( \([^|]+\))?( *#[^|]*)?)?\|((ו(?!ו))?(כ?ש)?(ב|כ|ל|מה?|ה)?)(ו(?=ו))?\1]]/;
//---
    var allBitsInPage = new Array();
    var tmpr = new Array();
    var originalText = "";
    var pageOpeningPart = "";
    var pageClosingPart = "";

    reportStandardizeMessage ( "INIT", "" );

// ------------------------------- stage X: check the text and remove excess spaces -------------------------------

    var xFFreplacement = "";
    if ( /\xFF/.test(text) )                                // check if the text has the special character
    {
        for ( xFFreplacement = "91818362268373754612" ; text.indexOf(xFFreplacement) != -1 ; ) xFFreplacement += xFFreplacement.charAt(xFFreplacement.length-13);
        xFFreplacement += xFFreplacement + xFFreplacement + xFFreplacement;
        text = text.replace ( /\xFF/g, xFFreplacement );    // replace the special character
    }

    text = text.replace( /\n\t[ \t]*/g, "\n" )              // remove nonstandard tabs after a linebreak
               .replace( /\t/g, " " );                      // replace nonstandard tabs with spaces
/* not perfect. inside <source> parts should be: replace( /\t/g, "        " )  */
    text = "\n" + removeHardExcessSpaces(text) + "\n";      // remove any excess spaces and pad with line breaks
                                                            // in order to prevent problems if the text starts or ends with a headline

// --------------------------------------------- stage X: hide remarks --------------------------------------------

    text = text.replace ( /\<!-- הערה מוסתרת --\>/g, "" );                                  // remove "<!-- הערה מוסתרת -->"
                                                                                            // mark and hide line-remarks, not nested
    text = storeInRepository ( allBitsInPage, text, /\<!--((?!.*--\>).*\n *|[^<>\n]+\[\[תבנית:בוט יישובים]][^<>\n]+)-->(?=.)/g, "rl" );
    text = storeInRepository ( allBitsInPage, text, /\<!--(.|\n)*?--\>/g, "r" );            // mark and hide <!-- ... --> parts, not nested

// --------------------------------- stage X.1: normalize and hide nowiki and parts -------------------------------
// ----------------------------------------- stage X.2: fix BR tags -----------------------------------------------

    originalText = text;
    text = text.replace( /(\<\/?)nowiki[ \n]*(|[ \n][^<>]+?)[ \n]*\>/gi, "$1nowiki$2>" )    // normalize <nowiki> tags
               .replace( /(\<\/?)source[ \n]*(|[ \n][^<>]+?)[ \n]*\>/gi, "$1source$2>" )    // normalize <source> tags
               .replace( /(\<\/?(nowiki|source))\n([^<>]+\>)/g, "$1 $3" )
               .replace( /\<(br *\/?|\/br) *\>/gi, "<br />" );                              // fix common <br /> mistakes
    var flag = originalText != text;
                                                                                            // mark and hide <nowiki> and <source> parts, not nested
    text = storeInRepository ( allBitsInPage, text, /\<(nowiki|source)( [^<>]+)?\>(.|\n)*?\<\/\1( [^<>]+)?\>/g, "w" );

// ---------------------------------------- stage X.1: normalize html tags ----------------------------------------
// -------------------------- stage X.2: check match between opening and closing html tags ------------------------

    var htmlmsg = "";
    originalText = text;

    if ( /(\{\||\|}(?!}))/.test(text) )                                    // are there any {|wiki style tables|} in the text ?
    {
        tmpr = new Array();
        text = storeInRepository ( tmpr, text, /\<(math|timeline)([ \n][^<>]*)?\>(.|\n)*?\<\/\1([ \n][^<>]*)?\>/gi, "nWT" );
        text = text.replace( /\{\|/g, "<wikitable \xFFwt>" ).replace( /\|}(?!})/g, "</wikitable \xFFwt>" );
        text = restoreFromRepository ( tmpr, text, "nWT" );
        htmlTagsA.push ("wikitable \xFFwt");
    }

    tmpr = new Array();
    text = storeInRepository ( tmpr, text, new RegExp("\\<\\/?(" + htmlTagsA.join("|") + ")([ \n][^<>]*)?\\/?\\>","gi"), "tag" );

    if ( tmpr.length )
    {
        var tagStack = new Array();
        var tagOpen   = new Array();
        var tagClose  = new Array();
        var tagSingle = new Array();
        var prob = 0;

        for ( var i = 0 ; i < htmlTagsA.length ; i++ )
        {
            tagOpen   [ htmlTagsA[i] ] = 0;
            tagClose  [ htmlTagsA[i] ] = 0;
            tagSingle [ htmlTagsA[i] ] = 0;
        }

        for ( var i = 0 ; i < tmpr.length ; i++ )
        {
            var name = tmpr[i].replace ( /\<\/?([a-z]+)(.|\n)+/i, "$1" ).toLowerCase();

            tmpr[i] = tmpr[i].replace ( /\n+ */g, " " )                                                     // replace linebreaks with spaces
                             .replace ( /(\<\/?)[a-z]+ *( [^<>]+?)? *(\/?\>)/i, "$1" + name + "$2$3" )      // normalize <xxx>, </xxx> and <xxx />
                             .replace ( "/>", " />" );

            if ( name == "wikitable" ) name = "wikitable \xFFwt";

            if ( tmpr[i].indexOf("/>") != -1 ) tagSingle[ name ]++;
             else
                if ( tmpr[i].indexOf("</") != -1 )                                          // closing tag
                {
                    tagClose[ name ]++;
                    if ( !tagStack.length || name != tagStack.pop() ) prob = 1;
                }
                else                                                                        // opening tag
                {
                    tagOpen[ name ]++;
                    tagStack.push ( name );
                }
        }

        for ( var i = 0 ; i < htmlTagsA.length ; i++ )
        {
            if ( htmlTagsA[i] != "ref" && tagSingle[htmlTagsA[i]] ) htmlmsg += ", <" + htmlTagsA[i] + ":" + tagSingle[htmlTagsA[i]] + "/>";
            if ( tagOpen[htmlTagsA[i]] != tagClose[htmlTagsA[i]] )
            {
                if ( htmlTagsA[i] == "wikitable \xFFwt" ) htmlmsg += ", {|wikitable " + tagOpen[htmlTagsA[i]] + "::" + tagClose[htmlTagsA[i]] + "|}";
                 else htmlmsg += ", <" + htmlTagsA[i] + " " + tagOpen[htmlTagsA[i]] + "::" + tagClose[htmlTagsA[i]] + ">\u200F";
                prob = -1;
            }
        }

        if ( prob != -1 && ( tagStack.length || prob ) ) htmlmsg += ", מבנה העץ";

        text = restoreFromRepository ( tmpr, text, "tag" )                                  // return wiki style tables to normal
               .replace( /\<wikitable \xFFwt\>/g, "{|" ).replace( /\<\/wikitable \xFFwt\>/g, "|}" );
    }

    tmpr = new Array();
    text = storeInRepository ( tmpr, text, new RegExp("\\<(" + htmlTagsB.join("|") + ")([ \n][^<>]*)?\\/?\\>","gi"), "tag" );

    if ( tmpr.length )
    {
        for ( var i = 0 ; i < tmpr.length ; i++ )
            tmpr[i] = tmpr[i].replace ( /\n+ */g, " " )                                                // replace linebreaks with spaces
                             .replace ( /\<[a-z]+ *( [^<>]+?)? *\/? *\>/i,
                                        "<" + tmpr[i].replace(/\<([a-z]+).+/i,"$1").toLowerCase() + "$1 />");

        text = restoreFromRepository ( tmpr, text, "tag" );
    }

//********************************************************************************************************
    tmpr = storeInRepository( [], text, /\<math( [^<>]+)?\>(.|\n)*?\<\/math( [^<>]+)?\>/g, "d" )
           .match ( new RegExp("\\<(?!\\/?(" + htmlTagsA.join("|") + "|" + htmlTagsB.join("|") + ")( [^<>]+)?\\/?\\>)[/\\\\]?[a-zA-Z][^<>]{0,256}\\>", "g") );
    if ( tmpr ) htmlmsg += " ***** " + tmpr.join(", ");
//********************************************************************************************************

    reportStandardizeMessage ( flag || originalText != text ? "HTML_TAGS" : "", "" );
    reportStandardizeMessage ( "TAGS_ERROR", htmlmsg );

// ---------------------------------------- stage X: hide special wiki parts --------------------------------------

    text = storeInRepository ( allBitsInPage, text, /\<math( [^<>]+)?\>(.|\n)*?\<\/math( [^<>]+)?\>/g, "m" );
    text = storeInRepository ( allBitsInPage, text, /\<(timeline|noinclude|includeonly)( [^<>]+)?\>(.|\n)*?\<\/\1( [^<>]+)?\>/g, "-" );

// -------------------------- stage X: fix some simple and uninteresting miscellaneous things ---------------------

    text = text.replace ( /(\n[*:#]+)( +(?=[^ ])|(?=[^*:# \n]))/g, "$1 " )                   // make sure there's exactly one space after "*", ":" or "#"
               .replace ( /(\n:+) \{\|/g, "$1{|" )                                           // and then cancel the space between ":" and wiki tables
               .replace ( /(\[\[[| \n]*]]|\{\{[| \n]*}})/g, "" )                             // remove empty brackets and templates
               .replace ( /\<(gallery|imagemap)( [^<>]+)?\>[ \n]*\<\/\1( [^<>]+)?\>/g, "" )  // remove empty gallery and imagemap sections
               .replace ( /\{\{[ \n]*ש[ \n]*}}/g, "{{ש}}" );                                 // normalize {{ש}}

    tmpr = new Array();
    text = storeInRepository ( tmpr, text, /( *(\<br \/\>|\{\{ש}})){2,}/g, "BR" );           // hide subsequent linebreaks
    text = text.replace ( / *(\<br \/\>|\{\{ש}})\n\n/g, "\n\n")                              // remove unnecessary linebreak
               .replace ( /(\n[*:#].*?) *(\<br \/\>|\{\{ש}})(?=\n)/g, "$1" );                // remove unnecessary linebreak at end of list item
    text = restoreFromRepository ( tmpr, text, "BR" );

// - stage X.1: extract [http://], [[files:]], [[brackets]] and {{templates}} from the text, nested and recursive -
// ---------------------------------------------- stage X.2: fix stuff inside -------------------------------------

    var top_index = allBitsInPage.length;
    var index     = allBitsInPage.length;
    var rxHttp      = /\[?\[[ \n]*https?:\/\/[^ \n\[\]\xFF]+([ \n]([^\[\]{}]|\[(?!\[)|\{(?!\{)|\}(?!\}))*)?](](?!]))?/g;
    var numHttp     = 0;
    var rxFile      = /\[\[ *(file|קובץ|image|תמונה) *:[^|\[\]{}\n\xFF]+(\|([^\[\]{}]|\[(?!\[)|\](?!\])|\{(?!\{)|\}(?!\}))*)?]]/gi;
    var numFile     = 0;
    var rxBracket   = /\[\[[^|\[\]{}\n\xFF]+(\|([^\[\]{}\xFF]|\[(?!\[)|\](?!\])|\{(?!\{)|\}(?!\})|\xFF[Tm])*)?]]/g;
    var numBracket  = 0;
    var rxTemplate  = /\{\{([ \n]|\xFFr.?%\d+%)*([^|\[\]{}\n\xFF]+|#[^|:\[\]{}\n\xFF]+:[^|\[\]{}\n\xFF]+)([ \n]|\xFFr.?%\d+%)*(\|([^\[\]{}]|\[(?!\[)|\](?!\])|\{(?!\{)|\}(?!\}))*)?}}/g;
    var numTemplate = 0;
    var miscFlag           = false;
    var httpCounter        = 0;
    var fakeHttpCounter    = 0;
    var spaceCounter       = 0;
    var linkCounter        = 0;
    var selflinkCounter    = 0;
    var catLocationCounter = 0;
    var prepositionCounter = 0;
    var langCounter        = 0;
    var doublePipeStr      = "";

    text = text.replace ( /\[\[\|([^|\[\]{}\n\xFF]+]])/g, "[[$1" );                      // fix a rare syntax problem: "[[xyz]]" --> "[[xyz]]"

    while ( rxHttp.test(text) || rxFile.test(text) || rxBracket.test(text) || rxTemplate.test(text) )
    {
        text = storeInRepository ( allBitsInPage, text, rxHttp, "h" );                   // *********** extract and fix http links *************
        for ( ; index < allBitsInPage.length ; index++, numHttp++ )
        {
            if ( /(^\[\[|]]$)/.test(allBitsInPage[index]) )
            {                                                                                         // [[http://site]  --> [http://site]
                allBitsInPage[index] = allBitsInPage[index].replace( /^\[?(\[.+?])]?$/, "$1" );       // [[http://site]] --> [http://site]
                httpCounter++;                                                                        //  [http://site]] --> [http://site]
            }

            if ( /(\n|^\[ | ]$)/.test(allBitsInPage[index]) )
            {
                if ( /^\[[ \n]/.test(allBitsInPage[index]) )                                          // put a space before the brackets, if needed
                    text = text.replace ( new RegExp("([^ \n])(\xFFh%" + index + "%)"), "$1 $2");

                if ( /[ \n]]$/.test(allBitsInPage[index]) )                                           // put a space after the brackets, if needed
                    text = text.replace ( new RegExp("(\xFFh%" + index + "%)(?!( |\"|'|,|;|\\.|\\?|!|\\)|]|-|\n|\\{\\{ש}}|\\<br \\/\\>))"), "$1 ");

                allBitsInPage[index] = allBitsInPage[index].replace(/\n/g," ").replace(/\[ *(.+?) *]/,"[$1]");   // remove spaces and linebreaks
                spaceCounter++;
            }

            allBitsInPage[index] = allBitsInPage[index].replace( /(\[[^ ]+) +(.+])/, "$1 $2" );

            if ( allBitsInPage[index].toLowerCase().indexOf(wgServer + "/wiki/") == 1 )
            {
                var tmp = "[[" + unescape ( allBitsInPage[index].replace(/\[.*\/wiki\/([^ ]*).*]/i,"$1").replace(/_/g," ") ) +
                          ( allBitsInPage[index].indexOf(" ") != -1 ? "|" + allBitsInPage[index].replace(/[^ ]+ (.+)]/,"$1") : "" ) + "]]";
                if ( /^\[\[ *[^ |\[\]{}][^|\[\]{}]*(\| *[^ |\[\]{}][^|\[\]{}]*)?]]$/.test(tmp) )                 // if wikilink is well formed
                {
                    text = text.replace ( "\xFFh%" + index + "%", tmp.replace(/\[\[([^|]+)\|\1]]/,"[[$1]]") );   // replace the http with the wikilink
                    fakeHttpCounter++;
                    numHttp--;
                }
            }

            if ( index % 25 == 0 ) reportStandardizeMessage ( "PROGRESS", "בודק קישורים (" + numBracket + "), קבצים (" + numFile + ") תבניות (" + numTemplate + ") וקישורים חיצוניים (" + numHttp + ")" );
        }


        text = storeInRepository ( allBitsInPage, text, rxFile, "p" );                   // *********** extract and fix files *************
        for ( ; index < allBitsInPage.length ; index++, numFile++ )
        {
            originalText = allBitsInPage[index];

            allBitsInPage[index] = allBitsInPage[index]
                    .replace( /(\[\[ *)(file|image|תמונה)/i,            "$1קובץ"    )   // "file/תמונה/image" --> "קובץ"
                    .replace( /\|[ \n]*thumb[ \n]*(]]|\|)/gi,           "|ממוזער$1" )   // |thumb|            --> |ממוזער|
                    .replace( /\|[ \n]*border[ \n]*(]]|\|)/gi,          "|גבול$1"   )   // |border|           --> |גבול|
                    .replace( /\|[ \n]*(center|centre)[ \n]*(]]|\|)/gi, "|מרכז$2"   )   // |center|           --> |מרכז|
                    .replace( /\|[ \n]*right[ \n]*(]]|\|)/gi,           "|ימין$1"   )   // |right|            --> |ימין|
                    .replace( /\|[ \n]*left[ \n]*(]]|\|)/gi,            "|שמאל$1"   );  // |left|             --> |שמאל|

            miscFlag = miscFlag || originalText != allBitsInPage[index];
                                                                                                // --- remove excess spaces inside files ---
                                       //  [[:  abc  ]]                   -->  [[:abc]]    ":" is optional
                                       //  [[  :  abc  ]]                 -->  [[ :abc]]
                                       //  [[:  abc  |  xyz  |  qwe ]]    -->  [[:abc|xyz|qwe]]
                                       //  [[  :  abc  |  xyz  | qwe  ]]  -->  [[ :abc|xyz|qwe]]
                                       //  [[  abc  |  [xyz]  ]]          -->  [[abc|[xyz] ]]
                                       //  [[  :  abc  |  [xyz]  ]]       -->  [[ :abc|[xyz] ]]
            allBitsInPage[index] = allBitsInPage[index]
                    .replace( /\[\[ *קובץ *: */, "[[קובץ:" )
                    .replace( /[ \n]*\|[ \n]*/g, "|" )
                    .replace( /\|{2,}/g, "|" )
                    .replace( /[ \n]+]]/, "]]" )
                    .replace( "]]]", "] ]]" );                 // [[(:)קובץ:abc|something here]]] --> [[(:)קובץ:abc|something here] ]]

            if ( index % 25 == 0 ) reportStandardizeMessage ( "PROGRESS", "בודק קישורים (" + numBracket + "), קבצים (" + numFile + ") תבניות (" + numTemplate + ") וקישורים חיצוניים (" + numHttp + ")" );
        }


        text = storeInRepository ( allBitsInPage, text, rxBracket, "B" );                // *********** extract and fix brackets *************
        for ( ; index < allBitsInPage.length ; index++, numBracket++ )
        {
            if ( /\[\[([^|]+\| | [^|]+$)/.test(allBitsInPage[index]) )                          // put a space before the brackets, if needed
                text = text.replace ( new RegExp("([^ \n])(\xFFB%" + index + "%)"), "$1 $2");

            if ( / ]]/.test(allBitsInPage[index]) )                                             // put a space after the brackets, if needed
                text = text.replace ( new RegExp("(\xFFB%" + index + "%)(?!( |\"|'|,|;|\\.|\\?|!|\\)|]|-|\n|\\{\\{ש}}|\\<br \\/\\>))"), "$1 ");

            if ( /\[\[ *:? *(category|קטגוריה) *:/i.test(allBitsInPage[index]) )                // is this a category ?
            {
                if ( /\[\[ *:? *category/i.test(allBitsInPage[index]) )
                {                                                                               // "category" --> "קטגוריה"
                    allBitsInPage[index] = allBitsInPage[index].replace( /(\[\[ *:? *)category/i, "$1קטגוריה" )
                    miscFlag = true;
                }

                if ( !/\[\[ *:/.test(allBitsInPage[index]) )
                {                                                                               // [[xyz| ]] --> [[xyz|*]]
                    originalText = allBitsInPage[index];
                    allBitsInPage[index] = allBitsInPage[index].replace( /(\|[ \n]*)+]]/, "|*]]" );
                    if ( originalText != allBitsInPage[index] ) catLocationCounter++;
                }

                originalText = allBitsInPage[index];                                            // --- remove excess spaces inside categories ---
                                           //  [[:  abc  ]]                   -->  [[:abc]]       ":" is optional
                                           //  [[  :  abc  ]]                 -->  [[ :abc]]
                                           //  [[:  abc  |  xyz  ]]           -->  [[:abc|xyz]]
                                           //  [[  :  abc  |  xyz  ]]         -->  [[ :abc|xyz]]
                                           //  [[  abc  |  ]]                 -->  [[abc]]
                                           //  [[  :  abc  |  ]]              -->  [[ :abc]]
                allBitsInPage[index] = allBitsInPage[index]
                        .replace( /_(?=.*\|)/g, " " )                                           // replace "_" to space before the "|"
                        .replace( /\[\[ *?(( |):)? *קטגוריה *: *([^|]+?) *((\|)[ \n]*((.|\n)+?)[ \n]*)?]]/, "[[$1קטגוריה:$3$5$6]]" );

                if ( originalText != allBitsInPage[index] ) spaceCounter++;
            }
            else                                                                                // it's a normal link
            {
                originalText = allBitsInPage[index];                                            // --- remove excess spaces inside brackets ---
                                           //  [[:  abc  ]]                   -->  [[:abc]]     ":" is optional
                                           //  [[  :  abc  ]]                 -->  [[ :abc]]
                                           //  [[:  abc  |  xyz  ]]           -->  [[:abc|xyz]]
                                           //  [[  :  abc  |  xyz  ]]         -->  [[ :abc|xyz]]
                                           //  [[:  abc  |  xyz  |  qwe ]]    -->  [[:abc|xyz  |  qwe]]
                                           //  [[  :  abc  |  xyz  | qwe  ]]  -->  [[ :abc|xyz  |  qwe]]
                                           //  [[  abc  |  ]]                 -->  [[abc| ]]
                                           //  [[  :  abc  |  ]]              -->  [[ :abc| ]]
                allBitsInPage[index] = allBitsInPage[index]
                        .replace( /_(?=.*\|)/g, " " )                                           // replace "_" to space before the "|"
                        .replace( /\n/g, " " )
                        .replace( /\[\[ *?(( |):)? *([^:|][^|]*?) *((\|) *(.*?) *)?]]/, "[[$1$3$5$6]]" )
                        .replace( /\[\[([^|]*?) *?( ?# ?) *([^|]*)(\|.*)?]]/, "[[$1$2$3$4]]" );

                if ( langlinkRX.test(allBitsInPage[index]) )                                    // normalize links to other languages
                    allBitsInPage[index] = "[[" + allBitsInPage[index].replace(langlinkRX, "$1")                     +
                                                  allBitsInPage[index].replace(langlinkRX, "$2").toLowerCase() + ":" +
                                                  allBitsInPage[index].replace(langlinkRX, "$3")                     + "]]";

                if ( /\[\[[^|]+\|([\"\']+)[^\"\']+\1]]/.test(allBitsInPage[index]) )            // [[abc|"xyz"]]     --> "[[abc|xyz]]"
                {                                                                               // [[abc|'''xyz''']] --> '''[[abc|xyz]]'''
                    text = text.replace ( new RegExp("(\xFFB%" + index + "%)"),
                                          allBitsInPage[index].replace(/\[\[[^|]+\|([\"\']+)[^\"\']+\1]]/,"$1") + "$1" +
                                          allBitsInPage[index].replace(/\[\[[^|]+\|([\"\']+)[^\"\']+\1]]/,"$1")          );
                    allBitsInPage[index] = allBitsInPage[index].replace( /(\[\[[^|]+\|)([\"\']+)[ \n]*([^\"\']+?)[ \n]*\2]]/, "$1$3]]" );
                }

                if ( originalText != allBitsInPage[index] ) spaceCounter++;

                originalText = allBitsInPage[index];                                            // --- fix links ---

                if ( localWikiPrefix && wlinkRXtext.test(allBitsInPage[index]) )   // [[w : xxx]] --> [[en:xxx]],   [[w : fr : xxx]] --> [[fr:xxx]],
                {
                    var linktext = allBitsInPage[index].replace( wlinkRXtext, "$2" );
                    var linkinterwiki = linktext.replace( wlinkRXinternal, "$1" ).toLowerCase();             // get the prefix, if any, from the link
                    if ( linkinterwiki == wgContentLanguage )                                                // if it's a link to the local wiki:
                        allBitsInPage[index] = "[[" + linktext.replace( wlinkRXinternal, "$2" ) + "]]";      // remove the prefixes
                     else
                        if ( linkinterwiki && interwikiNames.indexOf("|" + linkinterwiki + "|") != -1 )      // is there a language interwiki prefix ?
                              allBitsInPage[index] = "[[:" + linkinterwiki + ":" + linktext.replace( wlinkRXinternal, "$2" ) + "]]";
                         else allBitsInPage[index] = "[[:en:" + linktext + "]]";                             // if not then the default is english
                }

                allBitsInPage[index] = allBitsInPage[index].replace ( /\[\[([^|]+)\|\1]]/, "[[$1]]" );       // fix links of the form [[abc|abc]] to [[abc]]

                if ( originalText != allBitsInPage[index] ) linkCounter++;

                                                                                                             // --- fix preposition letters in links ---
                if ( hebPreRX_1.test(allBitsInPage[index]) )  // [[hxxx|bxxx]] --> b[[hxxx|xxx]]  and  [[hxxx|lxxx]] --> l[[hxxx|xxx]]
                {
                    allBitsInPage[index] = allBitsInPage[index].replace ( hebPreRX_1, "$5[[ה$1$2|$1]]" );
                    prepositionCounter++;
                }
                 else
                if ( /^[בכלמהוש]+$/.test(allBitsInPage[index].replace(hebPreRX_2,"$5"))                                                              &&  // check for preposition letters
                     !/\[\[(סחר|סלע|גלוון|אושר|סמל|שקר|זרז|דשן|חוסר הכרה|אור|פחד|נסכים)( \([^|]+\))?( *#[^|]*)?\|.*מ\1]]/.test(allBitsInPage[index]) &&  // but with exceptions for "מ"
                     !/\[\[(נאום|גלות|צחוק|סמל|שקר|דשן|זרז|צום)( \([^|]+\))?( *#[^|]*)?\|.*ל\1]]/.test(allBitsInPage[index])                         &&  // and with exceptions for "ל"
                     !/\[\[(רומנטיקה|פלמ\"ח|קומקון)( \([^|]+\))?( *#[^|]*)?\|.*ה\1]]/.test(allBitsInPage[index])                                       ) // and with exceptions for "ה"
                {
                    allBitsInPage[index] = allBitsInPage[index].replace ( hebPreRX_2, "$5[[$1$2|$9$1]]" ).replace ( /\[\[([^|]+)\|\1]]/, "[[$1]]" );
                    prepositionCounter++;
                }

                if ( selfSubSectionRX.test(allBitsInPage[index]) )                                       // check self link to a sub section
                {
                    allBitsInPage[index] = allBitsInPage[index].replace ( selfSubSectionRX, "[[#$2$3]]" ).replace ( /\[\[([^|]+)\|\1]]/, "[[$1]]" );
                    selflinkCounter++;
                }
            }

            if ( /\|.*\|/.test(allBitsInPage[index]) ) doublePipeStr += (doublePipeStr ? ", " : "") + allBitsInPage[index];

            if ( index % 25 == 0 ) reportStandardizeMessage ( "PROGRESS", "בודק קישורים (" + numBracket + "), קבצים (" + numFile + ") תבניות (" + numTemplate + ") וקישורים חיצוניים (" + numHttp + ")" );
        }


        text = storeInRepository ( allBitsInPage, text, rxTemplate, "T" );               // *********** extract and fix templates *************
        for ( ; index < allBitsInPage.length ; index++, numTemplate++ )
        {                                                                // --- remove excess spaces inside templates and some other stuff ---
            allBitsInPage[index] = allBitsInPage[index]                                  // {{ (תבנית/template : )abc | xyz }}  -->  {{abc| xyz }}
                    .replace( /\{\{( |\n)*((template|תבנית) *: *)?(cite [^ \|\n]+ |[^\|\n ][^\|\n]*?)( |\n)*?((\n|) *(\|)((.|\n)*))?}}/i, "{{$4$7$8$9}}" )
                    .replace( /\{\{DEFAULTSORT *: *([^|]*)}}/i, "{{מיון רגיל:$1}}")
                    .replace( /\{\{(link [FG]A|מיון רגיל:|Coord|ללא בוט)}}/i, "" )          // remove templates without information
                    .replace( /\{\{(link [FG]A|Coord|ללא בוט|קצרמר|תריג|אין בינוויקי|imdb name|שפת קישור|הערות שוליים|הערה)\n?\|[ \n]*((.|\n)*?)[ \n]*}}/i, "{{$1|$2}}" )  // remove excess spaces
                    .replace( /\{\{link FA\|/i, "{{Link FA|" ).replace( /\{\{link GA\|/i, "{{Link GA|" ).replace( /\{\{Coord\|/i, "{{Coord|" )
                    .replace( /\{\{מיון רגיל:[ \n]*(.*?)[ \n]*}}/, "{{מיון רגיל:$1}}" )
                    .replace( /\{\{היאבקות מקצוענית(?=(}}|\n?\|))/ ,"{{היאבקות מקצועית" ).replace( /\{\{אזהרה רפואית(?=(}}|\n?\|))/ ,"{{הבהרה רפואית" );

            if ( /\{\{הערה\|/.test(allBitsInPage[index]) )                               // is thie a reference-template ?
            {
                allBitsInPage[index] = allBitsInPage[index].replace(/\|([ \n]*\|)+/g,"|").replace(/\|[ \n]*}}/,"}}");   // remove empty "| |"
                text = text.replace ( "\xFFT%" + index + "%", "\xFFf%" + index + "%");                                  // replace the marker
            }
             else
                if ( /\{\{(מסגרת תמונה|תמונה רחבה|תמונה תלויה)\n?\|/.test(allBitsInPage[index]) )  // is thie a picture-template ?
                    text = text.replace ( "\xFFT%" + index + "%", "\xFFp%" + index + "%");         // replace the marker
             else
                if ( /\{\{שפת קישור\|/.test(allBitsInPage[index]) &&                         // is thie a language-template ?
                     existingLangTemplates.test( restoreFromRepository ( allBitsInPage, allBitsInPage[index] ) ) )
                    {
                        allBitsInPage[index] = restoreFromRepository(allBitsInPage,allBitsInPage[index]).replace ( existingLangTemplates, "{{$2$3}}" );
                        langCounter++;
                    }

            if ( index % 25 == 0 ) reportStandardizeMessage ( "PROGRESS", "בודק קישורים (" + numBracket + "), קבצים (" + numFile + ") תבניות (" + numTemplate + ") וקישורים חיצוניים (" + numHttp + ")" );
        }
    }

//---                                                                   // if there are any brackets or templates markers left in the text
    if ( /(\[\[|\]\]|\{\{|\}\}|\[[ \n]*https?:\/\/)/.test(text) )       // it could mean that there is a syntax problem. not 100% sure
        return reportStandardizeMessage ( "ERROR", "יתכן שיש טעות בתחביר "                                                  +
                                                   (/(\[\[|\]\])/.test(text)                             ? "הקישורים" : "") +
                                                   (/(\[\[|\]\])/.test(text) && /(\{\{|\}\})/.test(text) ? " ו"       : "") +
                                                   (                            /(\{\{|\}\})/.test(text) ? "התבניות"  : "") +  ": " +
                                                   getTextAround ( text, text.search(/(\[\[|\]\]|\{\{|\}\}|\[[ \n]*https?:\/\/)/), 23 ) );

//---
    for ( index = top_index ; index < allBitsInPage.length ; index++ )
        if ( selfLinkRX.test(allBitsInPage[index]) )                               // is this a self link ?
        {
            allBitsInPage[index] = allBitsInPage[index].replace( /\[\[([^|]*\|)?(.*)]]/, "$2" );  // remove the self reference link, leave only the text

            if ( !new RegExp("''' ?\xFFB%" + index + "% ?'''").test(text) &&
                 new RegExp("^(( |\n)*\xFF(B|T|p|r.?)%\\d+%)*( |\n)*(?!.*'''" + allBitsInPage[index] + "''')[^\.\n]*\xFFB%" + index + "%").test(text) )
                allBitsInPage[index] = "'''" + allBitsInPage[index] + "'''";       // add bold tags if the self link is in the first sentence in the text
                                                                                   // and it's not already bold and it's text in not already bold in the same sentence
            selflinkCounter++;
        }
        else if ( /\{\{(שם שגוי\||כותרת תצוגה:)/.test(allBitsInPage[index]) &&     // is this a "wrong name" template ?
                  text.indexOf("\xFFT%" + index + "%") != -1                   )   // and it's on the document level ?
        {
            pageOpeningPart += allBitsInPage[index] + "\n";                        // save the "wrong name" template
            allBitsInPage[index] = "";
        }

    reportStandardizeMessage ( "PROGRESS", "" );
    reportStandardizeMessage ( "HTTPinBRACKETS", httpCounter );
    reportStandardizeMessage ( "FAKE_HTTP", fakeHttpCounter );
    reportStandardizeMessage ( "LINK", linkCounter );
    reportStandardizeMessage ( "SELFLINK", selflinkCounter );
    reportStandardizeMessage ( "PREPOSITION", prepositionCounter );
    reportStandardizeMessage ( "CATEGORY_LOCATION", catLocationCounter );
    reportStandardizeMessage ( "SPACE", spaceCounter );
    reportStandardizeMessage ( "DOUBLE_PIPE", doublePipeStr );

// ------------------- stage X: fix some simple miscellaneous things inside galleries and imagemaps ---------------

                                                                    // get all gallery and imagemap parts, not nested
    text = storeInRepository ( allBitsInPage, text, /\<(gallery|imagemap)( [^<>]+)?\>(.|\n)*?\<\/\1( [^<>]+)?\>/g, "g" );

    for ( ; index < allBitsInPage.length ; index++ )                // [[file/קובץ/image/תמונה:X]] --> [[קובץ:X]] inside galleries and imagemaps
    {
        originalText = allBitsInPage[index];
        allBitsInPage[index] = allBitsInPage[index].replace( /(\n *)(file|image|תמונה)( *:)/gi, "$1קובץ$3" );
        miscFlag = miscFlag || originalText != allBitsInPage[index];

        allBitsInPage[index] = allBitsInPage[index].replace( /\n *קובץ *: */g, "\nקובץ:" ).replace( /\n{2,}/g, "\n" );
    }

// ----------------------- stage X: collect start-of-page elements and remove them from the text ------------------

    if ( startofpagerx.test(text) )
    {
        pageOpeningPart += text.match(startofpagerx).join("\n").toUpperCase() + "\n";
        text = text.replace ( startofpagerx, "" );
    }

// -------------------------- stage X: restore only document level templates and brackets -------------------------

    text = restoreFromRepository ( allBitsInPage, text, "B|T", true );

    reportStandardizeMessage ( "" );

// ------------------------- stage X: find the last headline section and remove it from the text ------------------

    var endPos = text.split("").reverse().join("").search(/\n={1,6} *.+? *={1,6}\n/);  // find the first headline in reverse
    if ( endPos == -1 ) endPos = 0;                    // if there are no headlines in the text - take all the text
     else endPos = text.length - endPos;               // fix for the reverse order

    var lastHeadlineSection = "\n" + text.substring(endPos) + "\n" ;  // get the last headline section (does not include the headline itself)
    text = text.substring ( 0, endPos );                              // and remove it from the text

// ------- stage X: collect end-of-page elements, remove them from the text and attach to the last headline -------

    var elementsCounter = 0;
    var colonCounter = 0;

    tmpr = new Array();
    text = storeInRepository ( tmpr, text,
        /\{\{((הבהרה רפואית|אזהרת סמים|אזהרת ניקוטין|אזהרה משפטית|אזהרה כימית|ויקימדיה|הלכה|היאבקות מקצועית|הבהרה מקצועית|ערך מומלץ|ערך יתום|פוטנציאל|נ|קצרמר|תריג|Link [FG]A|ללא בוט|אין בינוויקי)(?=(}}|\n?\|))|מיון רגיל:)(.|\n)*?}}/g,
        "xA" );                                                                     // mark special templates
    text = storeInRepository ( tmpr, text, /\[\[קטגוריה:.*?]]/g, "xB" );            // mark category elements
    text = storeInRepository ( tmpr, text, interwikiRX, "xB" );                     // mark interwiki elements

    if ( tmpr.length )
    {
        var endOfPageElements = new Array();
                                                              // --- get special templates / interwikis / categories with remarks ---
                                                                                                                                   // 1 --- full lines
        text = storeInRepository ( endOfPageElements, text, /\n+( *\xFF(x.|r.?)%\d+% *)*\xFFx.%\d+%( *\xFF(x.|r.?)%\d+% *)*(\n+(( *\xFF(x.|r.?)%\d+% *)*\n+)*( *\xFF(x.|r.?)%\d+% *)*\xFFx.%\d+%( *\xFF(x.|r.?)%\d+% *)*)?\n+/g,
                                   "!" );
        text = text.replace ( /\xFF!%\d+%/g, "\n\n" );        //  put back an empty line instead of the one I just took
                                                                                                                                   // 2 --- from beginning of line
        text = storeInRepository ( endOfPageElements, text, /\n( *\xFF(x.|r.?)%\d+% *)*\xFFx.%\d+%( *\xFF(x.|r.?)%\d+% *)*/g, "!" );
        text = text.replace ( /\xFF!%\d+%/g, "\n" );          //  put back a linebreak instead of the one I just took
                                                                                                                                   // 3 --- from end of line
        text = storeInRepository ( endOfPageElements, text, /( *\xFF(x.|r.?)%\d+% *)*\xFFx.%\d+%( *\xFF(x.|r.?)%\d+% *)*(?=\n)/g );

                                                              // --- get special templates, from middle of line, with remarks and adjacent interwiki / category ---
        text = storeInRepository ( endOfPageElements, text, /(\xFF(x.|r.?)%\d+% *)*\xFFxA%\d+%( *\xFF(x.|r.?)%\d+%)*/g );

        if ( endOfPageElements.length )
        {                                                                           // attach found elements at the beginning of the last headline section
            lastHeadlineSection = restoreFromRepository (tmpr, endOfPageElements.join("\n\n"), "x.") + "\n\n" + lastHeadlineSection;
            elementsCounter += endOfPageElements.join().match(/\xFFx.%/g).length;
        }
    }

    reportStandardizeMessage ( "ELEMENTS", elementsCounter );

// ----------- stage X: insert a colon in interwiki and category parts that are actually normal links -------------

    if ( /\xFFxB%/.test(text) )                                 //  are there any document level interwiki or category parts in the text ?
    {                                                           //  if so then they are normal links
        for ( var i = 0 ; i < tmpr.length ; i++ ) tmpr[i] = tmpr[i].replace ( "[[", "[[:" );
        text = restoreFromRepository  ( tmpr, text, "xB" );     // restore the category and interwiki elements to the text
    }

    for ( var i = top_index ; i < allBitsInPage.length ; i++ )  // fix all interwiki and category parts (document level parts were already restored to the text)
        if ( ( interwikiRX.test(allBitsInPage[i]) && !interwikiRX.test("") ) || /\[\[קטגוריה:/.test(allBitsInPage[i]) )
        {
            allBitsInPage[i] = allBitsInPage[i].replace ( "[[", "[[:" );  // [[lang:XX]] -> [[:lang:XX]], same for קטגוריה
            colonCounter++;
        }

    reportStandardizeMessage ( "COLON", colonCounter - getLengthOfMatch ( lastHeadlineSection.match( interwikiRX     ) )
                                                     - getLengthOfMatch ( lastHeadlineSection.match( /\[\[קטגוריה:/g ) ) );

// ---------------------------- stage X: collect all end-of-page elements and format them -------------------------

    var elementsBasket = [ [], [], [], [], [], [], [], [] ];                 // 8 baskets for end-of-page elements
    var betweenElements = new Array();
                                                                             // 1: -- warning templates --
    lastHeadlineSection = storeInRepository ( elementsBasket[1], lastHeadlineSection,
        /\{\{(הבהרה רפואית|אזהרת סמים|אזהרת ניקוטין|אזהרה משפטית|אזהרה כימית|ויקימדיה|הלכה|היאבקות מקצועית|הבהרה מקצועית)(\n?\|(.|\n)*?)?}}/g, "e1");
    deleteDuplicatesAndReport ( elementsBasket[1], "DUPLICATE" );
                                                                             // 1: and also -- stub templates --
    lastHeadlineSection = storeInRepository ( elementsBasket[1], lastHeadlineSection, /\{\{(קצרמר|תריג|פוטנציאל)(\n?\|(.|\n)*?)?}}/g, "e1");
    deleteDuplicatesAndReport ( elementsBasket[1], "DUPLICATE" );
                                                                             // 2: -- recommended article, orphan article template --
    lastHeadlineSection = storeInRepository ( elementsBasket[2], lastHeadlineSection, /\{\{(ערך מומלץ|ערך יתום)(\n?\|(.|\n)*?)?}}/g, "e2");
    deleteDuplicatesAndReport ( elementsBasket[2], "DUPLICATE" );
                                                                             // 3: -- normal sorting template --
    lastHeadlineSection = storeInRepository ( elementsBasket[3], lastHeadlineSection, /\{\{מיון רגיל:(.|\n)*?}}/g, "e3");
    deleteDuplicatesAndReport ( elementsBasket[3], "DUPLICATE", ", מיון רגיל" );
                                                                             // 3: and also -- categories --
    lastHeadlineSection = storeInRepository ( elementsBasket[3], lastHeadlineSection, /\[\[קטגוריה:(.|\n)*?]]/g, "e3");
    deleteDuplicatesAndReport ( elementsBasket[3], "DUPLICATE_CATEGORY" );
                                                                             // 4: -- generic templates --
    lastHeadlineSection = storeInRepository ( elementsBasket[4], lastHeadlineSection, /\{\{(Coord|ללא בוט|נ|ללא הודעת הגנה אוטומטית)(\n?\|(.|\n)*?)?}}/g, "e4");
    deleteDuplicatesAndReport ( elementsBasket[4], "DUPLICATE" );
    elementsBasket[4] = elementsBasket[4].sort();
                                                                             // 5: -- LinkFAs and LinkGAs --
    lastHeadlineSection = storeInRepository ( elementsBasket[5], lastHeadlineSection, /\{\{Link [FG]A(\n?\|(.|\n)*?)?}}/g, "e5");
    sortInterwikiAndReport ( elementsBasket[5], /^(\{\{Link [FG]A\|)(.*)(}})$/, "INTERWIKI_FA" );
                                                                             // 6: -- interwikies --
    lastHeadlineSection = storeInRepository ( elementsBasket[6], lastHeadlineSection, interwikiRX, "e6");
    sortInterwikiAndReport ( elementsBasket[6], /^(\[\[)(.*?)(:.*)$/, "INTERWIKI" );
                                                                             // 7: -- nointerwiki template --
    lastHeadlineSection = storeInRepository ( elementsBasket[7], lastHeadlineSection, /\{\{אין בינוויקי(\n?\|(.|\n)*?)?}}/g, "e7");
    if ( elementsBasket[7].length && elementsBasket[6].length && elementsBasket[6][0].substring(2,elementsBasket[6][0].indexOf(":")) == "en" )
    {
        elementsBasket[7] = new Array();
        reportStandardizeMessage ( "NOINTERWIKI" , elementsBasket[6][0].substring(2,elementsBasket[6][0].indexOf(":")) );
    }
    else deleteDuplicatesAndReport ( elementsBasket[7], "DUPLICATE", ", אין בינוויקי" );

//---
    betweenElements[0] = "";

    for ( var i = 1 ; i < 8 ; i++ )
        if ( elementsBasket[i].length )
        {
            tmpr = new Array(); // remarks after the elements
            lastHeadlineSection = storeInRepository ( tmpr, lastHeadlineSection, new RegExp("\xFFe" + i + "%\\d+%( *\n? *\xFFr.?%\\d+%)+", "g") );
            elementsBasket[i].push ( tmpr.join("\n").replace(/ *\xFFe.%\d+% */g,"") );

            tmpr = new Array(); // remarks before the elements
            lastHeadlineSection = storeInRepository ( tmpr, lastHeadlineSection, new RegExp("\n?(\xFFr.?%\\d+%( |\n)*)+\xFFe" + i + "%\\d+%", "g") );
            betweenElements[i] = tmpr.join("\n").replace(/\n{3,}/g,"\n\n").replace(/ *\xFFe.%\d+% */g,"").replace(/\n?$/,"\n");
        }
        else betweenElements[i] = "";

    lastHeadlineSection = lastHeadlineSection.replace ( /\xFFe.%\d+%\n*/g, "");  // remove the markers

//---
                                                                             // 0: -- navigation templates and remarks from the end --
                                            // mark all *possibly* navigation templates (=templates with no parameters) - not 100% sure
    lastHeadlineSection = storeInRepository ( allBitsInPage, lastHeadlineSection,
        /\{\{(?=((?!([-+]+|הערות שוליים|פיצול|לפצל|בעבודה|להשלים|השלמה))[^|]+}}|((סדרה|ניווט)( .+?)?|ציר זמן לרבנים|שנה בודדת בתולדות עם ישראל|סורות)(}}|\n?\|)))(.|\n)+?}}/g, "n" );

                                                                   // collect galleries, pictures, navigation templates and remarks from the end
    if ( /(^|\n) *(\xFF(g|p|n|r.?)%\d+%( |\n)*)+$/.test(lastHeadlineSection) )
    {
        pageClosingPart += lastHeadlineSection.match ( /(^|\n) *(\xFF(g|p|n|r.?)%\d+%( |\n)*)+$/ )[0];
        lastHeadlineSection = lastHeadlineSection.replace ( /(^|\n) *(\xFF(g|p|n|r.?)%\d+%( |\n)*)+$/, "");
        pageClosingPart = grabSpecialFragments ( pageClosingPart, "n", elementsBasket[0] );            // grab all navigation templates

        if ( !/[^ \n]/.test(lastHeadlineSection) )                       // if the last headline is now empty
        {
            lastHeadlineSection = pageClosingPart;                       // put back the pictures and galleries (if any) in the last headline
            pageClosingPart = "";
        }
    }

    lastHeadlineSection = restoreFromRepository ( allBitsInPage, lastHeadlineSection, "n" );  // restore remaining navigation templates -
                                                                                              // so they can be recognized as regular templates later

// ------------------------------------------ stage X: build the closing part -------------------------------------

    pageClosingPart = removeExcessSpaces ( pageClosingPart, 2 );
    for ( var i = 0 ; i < elementsBasket.length ; i++ )
        pageClosingPart += removeExcessSpaces ( betweenElements[i] + elementsBasket[i].join("\n").replace(/\n{2,}/g,"\n"), 2 );

    text = text + lastHeadlineSection;                                  // attach whatever is left from the last headline

    reportStandardizeMessage ( "" );

// ----------------------------------------------- stage X: format lists ------------------------------------------

    var listCounter = 0;

    tmpr = new Array();
    text = storeInRepository ( tmpr, text, /\n([*:#]).*(\n\n?(\1.*|[*:#]+))*(?=\n)/g, "L" );  // get all lists by type - * : #

    for ( var i = 0 ; i < tmpr.length ; i++ )
    {
        originalText = tmpr[i];
        tmpr[i] = tmpr[i].replace ( /(\n[*:#]+\n?)+(?=(\n|$))/g, "" );           // remove lines with only *:# and no text
        if ( originalText != tmpr[i] ) listCounter++;
    }

    text = restoreFromRepository ( tmpr, text, "L" );

    reportStandardizeMessage ( "LIST", listCounter );

// -------------------------------- stage X: break the text to headlines and textparts ----------------------------

    var headlines = text.match ( /\n={1,6}.+={1,6}(?=\n)/g );     // get all headlines (possible levels are 1 to 6)
    if ( !headlines ) headlines = new Array();                    // or, if there are no headlines - create an empty list
    headlines.splice (0, 0, "");                                  // add an empty headline as the headline of the first textpart
                                                                  // note: don't use unshift() method - it might not work in IE
    var textparts = text.split ( /\n={1,6}.+={1,6}(?=\n)/ );      // break the text to parts without the headlines

// ------------------------------------------- stage X: format the headlines --------------------------------------

    var headlineCounter = 0;

    for ( var i = 0 ; i < headlines.length ; i++ )             /* remove excess line breaks and spaces from headlines */
    {                                                          /* and format them if necessary */
        headlines[i] = headlines[i].replace ( /\n/g, "" )                                                  // remove the linebreak taken from the text
                                   .replace ( /^(={1,6} ?) *(.+?) *?( ?={1,6})$/, "$1$2$3" );              // "==    abc==" --> "== abc=="
        if ( /^={1,6}[^ ].+? ={1,6}$/.test(headlines[i]) || /^={1,6} .+?[^ ]={1,6}$/.test(headlines[i]) )
            headlines[i] = headlines[i].replace( /^(={1,6}) ?(.+?) ?(={1,6})$/, "$1 $2 $3" );              // "== abc==" --> "== abc =="

        originalText = headlines[i];
        headlines[i] = headlines[i].replace ( /^(={1,6} ?)(.+?)( *:)( ?={1,6})$/, "$1$2$4" )   // "abc :" --> "abc"
                                   .replace ( / {2,}/g, " " )                                  // reduce subsequent spaces to one space
                                   .replace ( /\'\'\'/g, "" )                                  // remove '''
                                   .replace ( /קישורים חיצונים/, "קישורים חיצוניים" )          // fix common typo
                                   .replace ( /הערות שולים/, "הערות שוליים" );                 // fix common typo
        if ( originalText != headlines[i] ) headlineCounter++;
    }

    reportStandardizeMessage ( "HEADLINE", headlineCounter );

// ---------------------------------------------- stage X: format the textparts -----------------------------------

    for ( var i = 0 ; i < textparts.length ; i++ )
    {
        textparts[i] = textparts[i]
            .replace ( /^( |\n|\{\{ש}}|\<br \/\>)*(\n|\{\{ש}}|\<br \/\>)/, "\n")                              // remove empty lines from the beginning
            .replace ( /( |\n|\{\{ש}}|\<br \/\>)*((\{\{(-|\+-|-\+)}})*)( |\n|\{\{ש}}|\<br \/\>)*$/, "\n$2");  // remove empty lines from the end and before {{-}} {{+-}} {{-+}}

        tmpr = new Array();
        textparts[i] = storeInRepository ( tmpr, textparts[i], /\{\{.+?}} *( *\{\{כ}})*/g, "tl" );      // mark 1st level line templates, with following {{כ}}
        textparts[i] = storeInRepository ( tmpr, textparts[i], /\{\{(.|\n)+?}} *( *\{\{כ}})*/g, "tm" ); // mark 1st level non-line templates, with following {{כ}}
        textparts[i] = storeInRepository ( tmpr, textparts[i], /(\xFFtl%\d+% *)+(?![\n\xFF])/g, "N" );  // hide line templates that are part of the text

        var pretext = "";
        if ( /^(( |\n|\{\{ש}}|\<br \/\>)*\xFF(p|t.|r.?)%\d+%)+/.test(textparts[i]) )
        {                                                                           // collect pictures, templates and remarks from the beginning
            pretext = textparts[i].match ( /^(( |\n|\{\{ש}}|\<br \/\>)*\xFF(p|t.|r.?)%\d+%)+/ )[0]
                                  .replace ( /(\{\{ש}}|\<br \/\>)/g, "\n" )         // normalize linebreaks
                                  .replace ( /\n* *(\xFF(p|t.)%\d+%)/g, "\n$1" )    // insert linebreak before pictures and templates
                                  .replace ( /\n+ *(\xFFr.?%\d+%)/g, "\n$1" )       // replace one or more linebreaks before a remark with one linebreak
                                  .replace ( /(\xFFrl%\d+%)\n+/g, "$1" )            // remove linebreaks after special line-remarks
                                  .replace ( /\n{2,}/g, "\n" );                     // remove unnecessary linebreaks
            textparts[i] = textparts[i].replace ( /^(( |\n|\{\{ש}}|\<br \/\>)*\xFF(p|t.|r.?)%\d+%)+( |\n|\{\{ש}}|\<br \/\>)*/, ""); // remove from text

            pretext = restoreFromRepository ( tmpr, removeExcessSpaces(pretext), "t." );  // restore templates and remove excess spaces
        }

        if ( i == 0 )                                                                     // only in the first textpart
        {
            pretext = pretext.replace ( /(\{\{כותרת נושא(\n?\|.+)?}}\n$)/, "$1\n" );      // (wikiquote:) insert a linebreak after {{כותרת נושא}}

            if ( new RegExp("^\n*" + wgTitle.replace(/(\^|\[|\.|\$|\{|\*|\(|\\|\+|\)|\?|\<|\>)/g,"\\$1") + "[ ,;\\-\n]").test(textparts[0]) )
            {                                                                                         // if the article name is the first word:
                textparts[0] = textparts[0].replace ( wgTitle, "'''" + wgTitle + "'''" );             // make it bold
                miscFlag = true;
            }
        }
                                                                        // remove excess linebreaks and spaces, attach the opening part
        textparts[i] = restoreFromRepository ( tmpr, pretext + removeHardExcessSpaces(textparts[i]), "t.|N" );  // and restore templates
    }

    reportStandardizeMessage ( miscFlag ? "MISC" : "", "" );

// ---------- stage X: position the sisterlinks template in the "external links" section and sub-sections ---------

    var sisternum = 0;                                                             // number of sisterlinks-templates

    for ( index = headlines.length - 1 ; index >= 0 ; index-- )                    // find "external links" section
        if ( /^==(?!=).*קישורים חיצוניים.*==/.test(headlines[index]) )
        {
            do {
                tmpr = new Array();
                textparts[index] = removeExcessSpaces ( grabTemplatesInSection ( tmpr, textparts[index], "מיזמים" ) ) ;  // get sisterlinks-template(s)
                if ( tmpr.length ) textparts[index] = tmpr.join("\n") + "\n" + textparts[index];                         // attach the template(s) in the beginning
                sisternum += tmpr.length;
                index++;
            } while ( index < headlines.length && /^===/.test(headlines[index]) );
            break;
        }

// ---------- stage X: put the text back together and break it again to 2nd level headlines and textparts ---------

    text = "\n";                                            // start with a linebreak
    for ( var i = 0 ; i < headlines.length ; i++ )          // and connect headlines and text parts
        text += removeExcessSpaces ( headlines[i] + "\n" + textparts[i], 2 );

    headlines = text.match ( /\n==?(?!=).+=?=(?=\n)/g );    // get all headlines in levels 1 and 2
    if ( !headlines ) headlines = new Array();              // or, if there are no headlines - create an empty list
    headlines.splice (0, 0, "");                            // add an empty headline as the headline of the first textpart
                                                            // note: don't use unshift() method - it might not work in IE
    textparts = text.split ( /\n==?(?!=).+=?=(?=\n)/ );     // break the text to parts without the headlines

    reportStandardizeMessage ( "" );

// ------------------------------ stage X: move certain templates in end-of-page sections -------------------------
// ------------------------- stage X: insert language templates in the "external links" section -------------------

    var hdRx = [ /^\n== ?ראו גם/             ,     // 0 - see also         <-- the correct headline order
                 /(לקריאה נוספת|לעיון נוסף)/ ,     // 1 - further reading
                 /קישורים חיצוניים/          ,     // 2 - external links
                 /הערות שוליים/                ];  // 3 - references
    var hdPos = [ -1, -1, -1, Infinity ];

    for ( var i = 0 ; i < headlines.length ; i++ )                             // find end-of-page sections
    {
        for ( var h = 0 ; h < 4 ; h++ )
            if ( hdRx[h].test(headlines[i]) )
            {
                hdPos[h] = i;
                break;
            }
        if ( h == 4 && /(\<references \/\>|\{\{הערות שוליים(}}|\|))/.test(textparts[i]) ) hdPos[3] = i;
    }

    var templatesMovedCounter = 0;

    if ( hdPos[0] != -1 )                                                 // "see also" section exists ?
    {
        tmpr = new Array();
        for ( var h = 1 ; h < 4 ; h++ )
            if ( textparts[hdPos[h]] ) textparts[hdPos[h]] = grabTemplatesInSection ( tmpr, textparts[hdPos[h]], "(קישורי פורטל|פורטל)" );

        if ( tmpr.length )
        {
            textparts[hdPos[0]] = "\n" + tmpr.join("\n") + textparts[hdPos[0]];
            templatesMovedCounter += tmpr.length;
        }
    }

    if ( hdPos[2] != -1 )                                                 // "external links" section exists ?
    {
        tmpr = new Array();
        for ( var h = 0 ; h < 4 ; h++ )
            if ( h != 2 && textparts[hdPos[h]] ) textparts[hdPos[h]] = grabTemplatesInSection ( tmpr, textparts[hdPos[h]], "(מיזמים|ויקישיתוף בשורה)" );

        if ( tmpr.length )
        {
            textparts[hdPos[2]] = "\n" + tmpr.join("\n") + textparts[hdPos[2]];
            templatesMovedCounter += tmpr.length;
            sisternum += tmpr.length;
        }

        textparts[hdPos[2]] = insertLanguageTemplates ( restoreFromRepository ( allBitsInPage, textparts[hdPos[2]], "h|B|T|g|p" ) );
    }

    reportStandardizeMessage ( "TEMPLATES_MOVED", templatesMovedCounter );
    if ( sisternum > 1 ) reportStandardizeMessage ( "MORE_THAN_ONE", ", מיזמים" );

// -------------------------------------- stage X: standardize headline order -------------------------------------

    var orderFlag = false;

    if ( hdPos[2] != -1 && hdPos[1] > hdPos[2] )
    {
        orderFlag = true;                             // "further reading" is after "external links"

        tmpr.push ( headlines[hdPos[1]], headlines[hdPos[2]], textparts[hdPos[1]], textparts[hdPos[2]] );
        textparts[hdPos[1]] = tmpr.pop();
        textparts[hdPos[2]] = tmpr.pop();
        headlines[hdPos[1]] = tmpr.pop();
        headlines[hdPos[2]] = tmpr.pop();
    }

    if ( ( hdPos[1] != -1 && hdPos[0] > hdPos[1] ) || ( hdPos[2] != -1 && hdPos[0] > hdPos[2] ) )
    {
        orderFlag = true;                             // "see also" is after "further reading" and/or "external links"

        tmpr.push ( headlines[hdPos[0]], textparts[hdPos[0]] );
        headlines[hdPos[0]] = "";
        textparts[hdPos[0]] = "";
        hdPos[0] = Math.min(hdPos[1],hdPos[2]) != -1 ? Math.min(hdPos[1],hdPos[2]) : Math.max(hdPos[1],hdPos[2]);
        if ( hdPos[3] > hdPos[0] ) hdPos[3]++;
        textparts.splice ( hdPos[0], 0, tmpr.pop() );
        headlines.splice ( hdPos[0], 0, tmpr.pop() );
    }

    if ( hdPos[3] <= Math.max(hdPos[0],hdPos[1],hdPos[2]) )
    {
        orderFlag = true;                             // "references" is not the last section

        headlines.push ( headlines[hdPos[3]] );
        headlines[hdPos[3]] = "";
        textparts.push ( textparts[hdPos[3]] );
        textparts[hdPos[3]] = "";
    }

    reportStandardizeMessage ( orderFlag ? "ORDER" : "", "" );

// --------- stage X: put the text back together, attach opening and closing parts and restore wiki parts ---------

    text = "";                                                  // start empty
    for ( var i = 0 ; i < headlines.length ; i++ )              // and connect headlines and text parts
        text += removeExcessSpaces ( headlines[i] + textparts[i], 2 );

    text = removeExcessSpaces(pageOpeningPart) + text + removeHardExcessSpaces(pageClosingPart);  // attach opening and closing parts
    text = restoreFromRepository ( allBitsInPage, text, "h|B|T|g|p|n" );                          // restore wiki parts

    reportStandardizeMessage ( "" );

// -------------------------------------------- stage X: fix references -------------------------------------------

    text = storeInRepository ( allBitsInPage, text, /\<ref( [^<>]+)?\/\>/g, "f" );                       // get <ref xyz /> parts
    text = storeInRepository ( allBitsInPage, text, /\<ref( [^<>]+)?\>(.|\n)*?\<\/ref[ \n]*\>/g, "f" );  // get <ref>....</ref> parts

    var refCounter = 0;
    var ro = text.match ( /\xFFf%\d+%/g );              // references order in the document

    if ( ro )                                           // are there any references ?
    {
        var refName = new Array();
        var ref = "";
        var name = "";

        for ( var i = 0 ; i < ro.length ; i++ )
        {
            ro[i] = ro[i].replace ( /\xFFf%(\d+)%/, "$1" );
            ref = "";
            name = "";

            if ( /^\<ref[^<>]*\/\>$/.test(allBitsInPage[ro[i]]) )        // <ref name="name"/>
            {
                name = allBitsInPage[ro[i]].replace ( /\<ref[^<>]* name[ \n]*=[ \n]*((\"|\')([^\n<>]+?)\2|([^\n<>]+))[^<>]*\/\>/i, "$3$4" );
                if ( /[<>]/.test(name) ) name = "";
            }
            else if ( /^\<ref/.test(allBitsInPage[ro[i]]) )               // <ref name="name"> reference body </ref>
            {
                ref = allBitsInPage[ro[i]].replace ( /^\<ref[^<>]*\>( |\u200F|\n)*((.|\n)*?)( |\u200F|\n)*\<\/ref[ \n]*\>/, "$2" );
                if ( ref ) allBitsInPage[ro[i]] = allBitsInPage[ro[i]].replace ( ref, "\xFFrb%" + allBitsInPage.length + "%" );

                name = allBitsInPage[ro[i]].replace ( /^\<ref[^<>]* name[ \n]*=[ \n]*((\"|\')([^\n<>]+?)\2|([^\n<>]+))[^<>]*\>(.|\n)*/i, "$3$4" );
                if ( /[<>]/.test(name) ) name = "";
            }
            else                                                          // {{הערה| reference body | שם = name}}
            {
                if ( /\|(?![ \n]*(שמאל|שם)[ \n]*=)(.|\n)+?(?=(\||}}))/.test(allBitsInPage[ro[i]]) )
                {
                    ref = allBitsInPage[ro[i]].match ( /\|(?![ \n]*(שמאל|שם)[ \n]*=)(.|\n)+?(?=(\||}}))/ )[0];
                    allBitsInPage[ro[i]] = allBitsInPage[ro[i]].replace ( ref, "|\xFFrb%" + allBitsInPage.length + "%" );
                    ref = ref.replace(/^\|([ \n]*1[ \n]*=)?[ \n]*/,"").replace(/[ \n]+$/,"");
                }

                while ( /\|[ \n]*שם[ \n]*=[ \n]*(\||}})/.test(allBitsInPage[ro[i]]) )
                    allBitsInPage[ro[i]] = allBitsInPage[ro[i]].replace ( /\|[ \n]*שם[ \n]*=[ \n]*(\||}})/, "$1" );     // remove empty name

                if ( /\|[ \n]*שם[ \n]*=/.test(allBitsInPage[ro[i]]) )
                {
                    name = allBitsInPage[ro[i]].match ( /\|[ \n]*שם[ \n]*=[^|]+?(?=(\||}}))/ )[0]                       // get name
                                               .replace ( /^\|[ \n]*שם[ \n]*=[ \n]*(.+?) *(\n(.|\n)*)?$/, "$1" )
                                               .replace ( /^([\"\']+)[ \n]*(.+?)[ \n]*\1$/, "$2" );                     // "xyz" --> xyz
                    allBitsInPage[ro[i]] = allBitsInPage[ro[i]].replace ( allBitsInPage[ro[i]].match(/\|[ \n]*שם[ \n]*=[^|]+?(?=(\||}}))/)[0], "|שם=" + name );
                }
            }

            if ( ref )
            {
                ref = restoreFromRepository ( allBitsInPage, insertLanguageTemplates ( restoreFromRepository ( allBitsInPage, ref, "h|B|T|g|p" ) ) );
                allBitsInPage.push  ( ( /^\{\{/.test(allBitsInPage[ro[i]]) && ref.indexOf("=") != -1 ? "1=" : "" ) + ref );
            }

            refName[i] = name.replace ( /(^[ \n]+|[ \n]+$)/g, "" );                 // remove surrounding spaces from the name
        }

        var rduplicate = new Array();
        var allRefNames = "|" + refName.join("|") + "|";
        var rLetter = "א";

        for ( var i = 0 ; i < ro.length ; i++ )
            if ( /\xFFrb%\d+%/.test(allBitsInPage[ro[i]]) )
            {
                ref = allBitsInPage[allBitsInPage[ro[i]].replace(/(.|\n)*?\xFFrb%(\d+)%(.|\n)*/,"$2")]   // get the matching reference body
                          .replace(/(\u200F|&lrm;|&rlm;|\{\{[כש]}}|\<br \/\>|\'{2,})/g,"")               // remove invisible \u200F, directional markers and more
                          .replace(/(^((ה?מקור|ה?מקורות|ראו|ראה|ראי) *:?| |\.|,|;|\n)+|( |\.|,|;|\n)+$)/g,"")
                          .replace(/\|([ \n]*\|)+/g,"|").replace(/\|[ \n]*}}/,"}}")                      // remove empty "| |"
                          .replace(/[ \n]{2,}/g," ");                                                    // replace subsequent spaces and linebreaks to one space

                if ( ref && !refName[i] && !/(^| |,|;|\.|-)שם( |,|;|\.|-|$)/.test(ref) && typeof(rduplicate[ref]) != "undefined" )
                {
                    refCounter++;

                    name = refName[rduplicate[ref]];
                    if ( !name )
                    {
                        name = "הערה_" + rLetter;
                        while ( allRefNames.indexOf("|" + name + "|") != -1 ) name += "_" + i;           // fix accidental identical names
                        refName[rduplicate[ref]] = name;

                        if ( rLetter.indexOf("ת") != -1 ) rLetter = "ת" + i;                             // advance reference-letter for next iteration
                         else do { rLetter = String.fromCharCode(rLetter.charCodeAt(0)+1); } while ( /[םןץףך]/.test(rLetter) );

                        if ( /^\<ref/.test(allBitsInPage[ro[rduplicate[ref]]]) )                         // add the newly created "name" to the reference
                              allBitsInPage[ro[rduplicate[ref]]] = allBitsInPage[ro[rduplicate[ref]]].replace ( '<ref', '<ref name="' + name + '"' );
                         else allBitsInPage[ro[rduplicate[ref]]] = allBitsInPage[ro[rduplicate[ref]]].replace ( "{{הערה", "{{הערה|שם=" + name );
                    }

                    if ( /^\<ref/.test(allBitsInPage[ro[i]]) )                                           // use "name" and remove the reference body
                          allBitsInPage[ro[i]] = allBitsInPage[ro[i]].replace ( /\>(.|\n)*/, ' name="' + name + '" />' );
                     else allBitsInPage[ro[i]] = allBitsInPage[ro[i]].replace ( /\xFFrb%\d+%/, "שם=" + name );
                }
                else rduplicate[ref] = i;
            }
    }

    reportStandardizeMessage ( "DOUBLE_REF", refCounter );
    reportStandardizeMessage ( "LANG_TEMPLATES", langCounter );

// -------------------------------- stage X: restore all hidden parts and output text -----------------------------

    if ( autoStandardizeTextBox )
    {
        text = removeExcessSpaces ( restoreFromRepository ( allBitsInPage, text ) );
        if ( xFFreplacement ) text = text.replace ( new RegExp(xFFreplacement,"g"), "\xFF" );  // put the special character back, if needed
        autoStandardizeTextBox.value = text;
    }

    return reportStandardizeMessage ( "DONE", "" );
  }
  catch(e)
  {
    return reportStandardizeMessage ( "CRASH", "CRASH" );
  }

}   //  ********************** end of autoStandardizePage() function ********************

if ( wgContentLanguage == "he" && wgNamespaceNumber >= 0 && wgNamespaceNumber % 2 == 0 && ( wgAction == "edit" || wgAction == "submit" ) )
    addOnloadHook ( autoStandardizeButton );

/*
known issues:
    1. interwiki elements are identified by a list in interwikiNames - whenever a new language is added this list must be updated.
    2. remarks handling is far from perfect. for example:
          headlines with remarks in the same line are not identified: <!--remark-->==headline==

highly unlikely situations:
    1. the bracket-template-file-http identification is very good but not perfect. for example:
          "[[abc|[xyz]]]" is a good link, but is recognized as [[abc|[xyz]] ]
    2. 2nd level bad interwiki links are not fixed ([[en:abc]] --> [[:en:abc]])
    3. galleries/imagemaps inside templates are not processed
*/