User:Lightmouse/Lightbot/javascript conversion

//

        WikiFunctions.Parse.HideText ht = new WikiFunctions.Parse.HideText(true, false, true);

        public string ProcessArticle(string ArticleText, string ArticleTitle, int wikiNamespace, out string Summary, out bool Skip)
        {
            Skip = false;
            Summary = "";

ArticleText = ht.Hide(ArticleText);

//year: temporary change to protect band '4AD' and comic '2000AD'. Undone below
            ArticleText = Regex.Replace(ArticleText, @"\[\[4AD\]\]", "[[xx4ADxx]]");
            ArticleText = Regex.Replace(ArticleText, @"\[\[2000AD\]\]", "[[xx2000ADxx]]");
            ArticleText = Regex.Replace(ArticleText, @"\[\[2000 AD\]\]", "[[xx2000 ADxx]]");

// century
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|twenty(?: |-)first)(?: |-))century\]\]", "$1century");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|twenty(?: |-)first)(?: |-))century (AD|BC|CE|BCE)\]\]", "$1century $2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(\d{1,2}(?:st|nd|rd|th)(?: |-))century\]\]", "$1century");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(\d{1,2}(?:st|nd|rd|th)(?: |-))centuries\]\]", "$1centuries");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2}(?:st|nd|rd|th)(?: |-)century\|(\d{1,2}(?:st|nd|rd|th))\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2}(?:st|nd|rd|th)(?: |-)century\|(\d{1,2}(?:st|nd|rd|th)(?: |-))century\]\]", "$1century");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2}(?:st|nd|rd|th)(?: |-)century\|(\d{1,2}(?:st|nd|rd|th)(?: |-))centuries\]\]", "$1centuries");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(\d{1,2}(?:st|nd|rd|th)(?: |-))century (AD|BC|CE|BCE)\]\]", "$1century $2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2}(?:st|nd|rd|th)(?: |-)century\|(\d{1,2}(?:st|nd|rd|th)(?: |-))century (AD|BC|CE|BCE)\]\]", "$1century $2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2}(?:st|nd|rd|th)(?: |-)century\|(\d{1,2}(?:st|nd|rd|th)(?: |-))centuries (AD|BC|CE|BCE)\]\]", "$1centuries $2");

// decades and years
            ArticleText = Regex.Replace(ArticleText, @"\[\[((?:\d{1,3}|[12]\d{3}))\'?s\]\]", "$1s");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:\d{1,3}|[12]\d{3}))\'?(s) ?(AD|BC|CE|BCE)\]\]", "$1$2 $3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:\d{1,3}|[12]\d{3})\'?s? ?(?:AD|BC|CE|BCE)\|((?:\d{1,3}|[12]\d{3}))\'?(s)?\]\]", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:\d{1,3}|[12]\d{3})\'?s? ?(?:AD|BC|CE|BCE)\|((?:\d{1,3}|[12]\d{3}))\'?(s)? ?(AD|BC|CE|BCE)\]\]", "$1$2 $3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:\d{1,3}|[12]\d{3})\'?s?\|((?:\d{1,3}|[12]\d{3}))\'?(s)? ?(AD|BC|CE|BCE)\]\]", "$1$2 $3");
            ArticleText = Regex.Replace(ArticleText, @"\[\[(?:\d{1,3}|[12]\d{3})\'?s?\|((?:\d{1,3}|[12]\d{3}))\'?(s)?\]\]", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d\d?(?:st|nd|rd|th) centur(?:y|ies)\|((?:\d{1,3}|[12]\d{3}))\'?(s)?\]\]", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\w{5,12} centur(?:y|ies)\|((?:\d{1,3}|[12]\d{3}))\'?(s)?\]\]", "$1$2");

// solitary day_numbers
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2}(?:st|nd|rd|th))\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\|(\d{1,2}(?:st|nd|rd|th))\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(\d{1,2}(?:st|nd|rd|th))\]\]", "$1");

//Month+day_number "March 7th" -> "March 7"
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(January|February|March|April|May|June|July|August|September|October|November|December) (\d?\d)(?:st|nd|rd|th)\]\]", "[[$1 $2]]");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\](?:st|nd|rd|th)", "[[$1]]");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(\d?\d)(?:st|nd|rd|th) (January|February|March|April|May|June|July|August|September|October|November|December)\]\]", "[[$1 $2]]");

//'present'
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Present \(time\)\|(Present)\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(Present)\]\]", "$1");

//Season
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(spring \(season\)|summer|winter|autumn)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[spring \(season\)\|(spring)\]\]", "$1");

//Identify surprise or 'Easter egg' diversions linking months to year articles.
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:\d{1,3}|[12]\d{3})#[^\|]{1,30}\|(January|February|March|April|May|June|July|August|September|October|November|December)\]\]", "$1");

// months
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(January|February|March|April|May|June|July|August|September|October|November|December)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December)\|(January|February|March|April|May|June|July|August|September|October|November|December)\]\]", "$1");
//Treat 'Sept' (i.e. month abbreviation) differently from 'sept' (i.e. family)
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(Sept)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[January\|(Jan)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[February\|(Feb)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[March\|(Mar)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[April\|(Apr)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[May\|(May)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[June\|(Jun)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[July\|(Jul)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[August\|(Aug)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[September\|(Sep)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[October\|(Oct)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[November\|(Nov)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[December\|(Dec)\]\]", "$1");

//month piped to number
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December)\|((?:\d{1,3}|[12]\d{3}))\]\]", "$1");

//month piped to number
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December)\|((?:\d{1,3}|[12]\d{3}))\]\]", "$1");

//Month+day_number piped into number. Preferences do not work. They don't work in sequence because digits in the two dates must be adjacent
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\]( ?\-? ?)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1$2$3$4");
//same again but with ndash or mdash instead of hyphen
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\]( ?&[nm]dash; ?)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1$2$3$4");
//same again but with slash instead of hyphen
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\](\/)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1$2$3$4");

//            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\]( ?\-? ?)\[\[(\d{1,2})\]\]", "$1$2$3$4");
//same again but with ndash instead of hyphen
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\]( ?&[nm]dash; ?)\[\[(\d{1,2})\]\]", "$1$2$3$4");
//same again but with slash instead of hyphen
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d?\d)\]\](\/)\[\[(\d{1,2})\]\]", "$1$2$3$4");

            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[(\d?\d) (?:January|February|March|April|May|June|July|August|September|October|November|December)\]\]( ?\-? ?)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1$2$3$4");
//same again but with ndash instead of hyphen
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[(\d?\d) (?:January|February|March|April|May|June|July|August|September|October|November|December)\]\]( ?&[nm]dash; ?)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1$2$3$4");
//same again but with slash instead of hyphen
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\[]{4})\[\[(\d?\d) (?:January|February|March|April|May|June|July|August|September|October|November|December)\]\](\/)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1$2$3$4");

            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2})\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\|(\d{1,2})\]\]", "$1");

            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|((?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2})\]\]", "$1");
//month+day piped into month+day or vice versa
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\|((?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2})\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December))\]\]", "$1");

//month+day piped into iso8601 month and day
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\|(\d\d\-\d\d)\]\]\-\[\[([12]\d{3})\]\]", "$1-$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d\d\-\d\d)\]\]\-\[\[([12]\d{3})\]\]", "$1-$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[([12]\d{3})\]\]\-\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\|(\d\d\-\d\d)\]\]", "$1-$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[([12]\d{3})\]\]\-\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d\d\-\d\d)\]\]", "$1-$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\|(\d\d\-\d\d)\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\|(\d\d\-\d\d)\]\]", "$1");

//Month + year
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:January|February|March|April|May|June|July|August|September|October|November|December) \d{3,4})\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(\d{3,4} (?:January|February|March|April|May|June|July|August|September|October|November|December))\]\]", "$1");


// days of the week in full. Optional plurals
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(Mondays?|Tuesdays?|Wednesdays?|Thursdays?|Fridays?|Saturdays?|Sundays?)\]\]", "$1");
// days of the week abbreviated. Leave out 'Sun' as potentially valid link to the Sun. Leave out 'SAT' in upper case as potential link to 'Scholastic achievement/aptitude test'.
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(Mon|Tue|Tues|Wed|Thu|Thur|Thurs|Fri)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"\[\[(Sat)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Mondays?\|(Mondays?|Mon)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Tuesdays?\|(Tuesdays?|Tues?)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Wednesdays?\|(Wednesdays?|Wed)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Thursdays?\|(Thursdays?|Thur?)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Fridays?\|(Fridays?|Fri)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Saturdays?\|(Saturdays?|Sat)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Sundays?\|(Sundays?|Sun)\]\]", "$1");

//4 digit years piped into 2
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:\d{1,3}|[12]\d{3})\|(\d{1,2})\]\]", "$1");

//fix autoformatted dates broken by piped years
//ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(January|February|March|April|May|June|July|August|September|October|November|December) ([0-3][\d]|[\d])(?:st|nd|rd|th|)\]\](?:st|nd|rd|th|), \[\[(\d{1,4}) in [^\]]{1,32}\]\]", "[[$1 $2]], [[$3]]");
//ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(January|February|March|April|May|June|July|August|September|October|November|December) ([0-3][\d]|[\d])(?:st|nd|rd|th|)\]\](?:st|nd|rd|th|), {{(?:avyear|by|ly|scy|sdy)\|(\d{1,4})}}", "[[$1 $2]], [[$3]]");

//ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[([0-3][\d]|[\d])(?:st|nd|rd|th|) (January|February|March|April|May|June|July|August|September|October|November|December)\]\] \[\[(\d{1,4}) in [^\]]{1,32}\]\]", "[[$1 $2]] [[$3]]");
//ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[([0-3][\d]|[\d])(?:st|nd|rd|th|) (January|February|March|April|May|June|July|August|September|October|November|December)\]\] {{(?:avyear|by|ly|scy|sdy)\|(\d{1,4})}}", "[[$1 $2]] [[$3]]");


//remove piped years
//protect some
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[(?:\d{1,3}|[12]\d{3}) in) ((?:baseball|film|literature|comics|aviation|ireland)\|(?:\d{1,3}|[12]\d{3})\]\])",  "$1xx$2");
//now removed the piped years
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:\d{1,3}|[12]\d{3}) in [^\|\]]+\|((?:\d{1,3}|[12]\d{3}))\]\]",  "[[$1]]");

//removed piped years when in full date
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[\d{1,2} (?:January|February|March|April|May|June|July|August|September|October|November|December)\]\],? ?\[\[)[^\|\]]+\|((?:\d{1,3}|[12]\d{3})\]\])", "$1$2");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}\]\],? ?\[\[)[^\|\]]+\|((?:\d{1,3}|[12]\d{3})\]\])", "$1$2");


//unprotect baseball and film
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[(?:\d{1,3}|[12]\d{3}) in)xx((?:baseball|film|literature|comics|aviation|ireland)\|(?:\d{1,3}|[12]\d{3})\]\])",  "$1 $2");

//year: temporary change to protect accessyear. Undone below at #1
            ArticleText = Regex.Replace(ArticleText, @"(?i)(accessyear ?= ?)\[\[((?:\d{1,3}|[12]\d{3}))\]\]", "$1xx$2xx");
//Year: temporary change to protext preference dates - y?y?y?. Needed to handle 'year in' piped links
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[\d\d? (?:January|February|March|April|May|June|July|August|September|October|November|December)\]\],? ? ?)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?",  "$1xx$2xx");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[\d\d? (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\]\],? ? ?)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?",  "$1xx$2xx");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d\d?\]\],? ? ?)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?",  "$1xx$2xx");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\[\[(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?\]\],? ? ?)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?",  "$1xx$2xx");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?(,? ?\-? ?\[\[(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?\]\])",  "xx$1xx$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?(,? ?\-? ?\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December) \d\d?\]\])",  "xx$1xx$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?(,? ?\-? ?\[\[\d\d? (?:January|February|March|April|May|June|July|August|September|October|November|December)\]\])",  "xx$1xx$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:\d{1,3}|[12]\d{3}))\]\]y?y?y?(,? ?\-? ?\[\[\d\d\-\d\d\]\]y?y?y?)",  "xx$1xx$2");

//year: now remove unprotected linked years
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[((?:\d{1,3}|[12]\d{3}))\]\]", "$1");

//year: now remove unprotected linked years of a limited range
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(2\d{3}|19[456789]\d)\]\]", "$1");

//year: #1. Undo temporary change to protect accessyear and date preference dates
            ArticleText = Regex.Replace(ArticleText, @"(?i)xx((?:\d{1,3}|[12]\d{3}))xx", "[[$1]]");

//year: unprotect band '4AD' and comic '2000AD'.
            ArticleText = Regex.Replace(ArticleText, @"\[\[xx4ADxx\]\]", "[[4AD]]");
            ArticleText = Regex.Replace(ArticleText, @"\[\[xx2000ADxx\]\]", "[[2000AD]]");
            ArticleText = Regex.Replace(ArticleText, @"\[\[xx2000 ADxx\]\]", "[[2000 AD]]");

//change dash in year ranges
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\w\w )([12]\d{3}) ?- ?([12]\d{3})(|,|\.)( \w\w)", "$1$2–$3$4$5");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\()([12]\d{3}) ?- ?([12]\d{3})(\))", "$1$2–$3$4");


//remove flagicons from birth and death
            ArticleText = Regex.Replace(ArticleText, @"(?i)(birth ?= ?)\{\{flagicon\|[^\}]{1,30}\}\}", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(death ?= ?)\{\{flagicon\|[^\}]{1,30}\}\}", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(birth_?place ?= ?)\{\{flagicon\|[^\}]{1,30}\}\}", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(death_?place ?= ?)\{\{flagicon\|[^\}]{1,30}\}\}", "$1");


            //aviation specifications: protect "main=" and "alt=" - undone below
            ArticleText = Regex.Replace(ArticleText, @"(?i)((?:main|alt) ?= ?)(\d)", "$1xx$2");

            // Celsius spelling errors

            //metre
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(metres|meters|metre|meter)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:metres|meters|metre|meter)\|(m)\]\]", "$1");
            //convert "metres" to "m" when in parentheses
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\(\d[\d,\.]{0,16})(?: |-|)(?:metres|meters|metre|meter)(\))", "$1 m$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\(\d[\d,\.]{0,16}) (?:metres|meters|metre|meter)(\))", "$1 m$2");
//            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}\|(?:m|ft)\|[^\}]{0,16})\|lk=(?:on|in|out)", "$1");


            // millimetre
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(milli(?:metres|meters|metre|meter))\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[milli(?:metres|meters|metre|meter)\|(mm)\]\]", "$1");

            // centimetre, cubic centimetre
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(centi(?:metres|meters|metre|meter))\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[centi(?:metres|meters|metre|meter)\|(cm)\]\]", "$1");

            // kilometre
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(kilo(?:metres|meters|metre|meter))\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[kilo(?:metres|meters|metre|meter)\|(km)\]\]", "$1");
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}\|(?:mi|km)[^\}]{0,16})\|lk=(?:on|in|out)", "$1");

            //square kilometre
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(km²)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[square kilomet..\|(km²)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}\|(?:sqkm|sqmi|km2|mi2)[^\}]{0,16})\|lk=(?:on|in|out)", "$1");

            //kilometre per second
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)(?:km\/second|km\/sec)([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 km/s$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16}) (?:km\/second|km\/sec)([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 km/s$3");

            // kilometre per hour
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)(?:km\/hr|km\/ph|kph|kmph|kmh)([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 km/h$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16}) (?:km\/hr|km\/ph|kph|kmph|kmh)([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 km/h$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)\[\[(?:km\/hr|km\/ph|kph|kmph|kmh)\]\]([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 km/h$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16}) \[\[(?:km\/hr|km\/ph|kph|kmph|kmh)\]\]([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 km/h$3");

            // ensure spaces and correct case in kilowatt
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)kW([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 kW$3");

            // ensure spaces and correct case in hertz
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)Hz([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 Hz$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)kHz([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 kHz$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)GHz([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 GHz$3");
            // ensure spaces in megahertz. Must be upper case to avoid clashing with millihertz
            ArticleText = Regex.Replace(ArticleText, @"([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)MHz([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 MHz$3");

            // kilogram
            ArticleText = Regex.Replace(ArticleText, @"(?i)kilogrammes", "kilograms");
            ArticleText = Regex.Replace(ArticleText, @"(?i)kilogramme", "kilogram");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(kilograms?)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[kilograms?\|(kg|kilograms?)\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)grammes([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 grams$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)gramme([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 gram$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)(?:kgs?|\[\[kg\]\])([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 kg$3");
//            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}\|(?:kg|lb)\|[^\}]{0,16})\|lk=(?:on|in|out)", "$1");

            //foot
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(foot|feet|ft)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(?:foot|feet|ft|foot)\|(foot|feet|ft)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[foot \((?:unit|length|unit of length)\)\|(foot|feet|ft)\]\]", "$1");

            //convert "foot" to "ft" when in parentheses
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\(\d[\d,\.]{0,16})(?: |-|)(?:feet|foot)(\))", "$1 ft$2");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)(\(\d[\d,\.]{0,16}) (?:feet|foot)(\))", "$1 ft$2");

            //remove trailing period when in parentheses
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\(\d[\d,\.]{0,16})(?: |-|)ft\.(\))", "$1 ft$2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\(\d[\d,\.]{0,16}) ft\.(\))", "$1 ft$2");

            // square foot
            //convert "sq foot" to "sq ft"
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d)( |-)sq\.?( |-|)(feet|foot|ft)", "$1 sq ft");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d) sq\.? (feet|foot|ft)", "$1 sq ft");
            //convert "square ft" to "sq ft"
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d)( |-)square( |-)ft", "$1 sq ft");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d) square ft", "$1 sq ft");

            //convert excessive zeros for cubic foot
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000000000\|cuft\|", "$1|Tcuft|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000000\|cuft\|", "$1|Gcuft|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000\|cuft\|", "$1|Mcuft|");

            //convert excessive zeros for cubic feet
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000000000\|cuft\|", "$1|Tcuft|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000000\|cuft\|", "$1|Gcuft|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000\|cuft\|", "$1|Mcuft|");


            //convert excessive zeros for oil
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000000000\|oilbbl\|", "$1|Toilbbl|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000000\|oilbbl\|", "$1|Goilbbl|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,16})000000\|oilbbl\|", "$1|Moilbbl|");


            //feet per second
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16})(?: |-|)(?:ft\/second|ft\/sec)([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 ft/s$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d[\d,\.]{0,16}) (?:ft\/second|ft\/sec)([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2 ft/s$3");

            //foot - remove period when followed by parentheses
            ArticleText = Regex.Replace(ArticleText, @"(\d ft)\.( \(\d)", "$1$2");

            // foot and inch
            ArticleText = Regex.Replace(ArticleText, @"(?i)(ength[.]{1,3})((?:\d{1,3}|[12]\d{3})) ?[""’] ?(\d{1,3}) ?[""”]", "$1$2 ft $3 in");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(idth[.]{1,3})((?:\d{1,3}|[12]\d{3})) ?[""’] ?(\d{1,3}) ?[""”]", "$1$2 ft $3 in");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([\(\|:] ?(?:\d{1,3}|[12]\d{3})) ?[""’] ?(\d{1,3}) ?[""”]([^NESW])", "$1 ft $2 in$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d) ?ft ?(\d{1,3}) ?in", "$1$2 ft $3 in");

            // knot
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d)( |-| )(?:kts|kt|knt) ([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1$2knots$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d)( |-| )(?:kts|kt|knt)([^²³\w\d-\(\)\/\\] )", "$1$2knots$3");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[knot \(unit\)\|", "[knot (speed)|");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[kts\]\]", "[[knot (speed)|knots]]");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\|kts\]\]", "|knots]]");

            //convert knot template to kn to match km
            //ArticleText = Regex.Replace(ArticleText, @"(?i)({{convert\|[\d\.]{1,16})\|knot\|", "$1|kn|");

            //nautical mile - rename "miles" as "nautical miles" when followed by knots or conversion code
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\d)(?: |-| |)miles (?:at|@) ([\d\.]{1,9}(?: |-| |)knots|{{convert)", "$1 nautical miles at $2");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(\d)( |-| )(?:mi|nm|nmi) (?:at|@) ([\d\.]{1,9}(?: |-| |)knots|{{convert)", "$1$2nmi at $3");

            //mile - lower case to avoid proper names like "Five Mile Road"
            //delink this common unit
//            ArticleText = Regex.Replace(ArticleText, @"\[\[(mi|mile|miles)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"\[\[(?:mile|miles)\|(mi|mile|miles)\]\]", "$1");

            // square mile
            ArticleText = Regex.Replace(ArticleText, @"(?i)([^\d\(\)\/\\] )(\d)(?: |-)sq(?: |\. |-)mi([^²³\w\d-\(\)\/\\][^\d\(\)\/\\])", "$1 sq mi$2");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[(square mile)\]\]", "$1");
//            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[square mile\|(sq mi)\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)(sq)(?: |-| |)(mile)", "$1uare $2");

            //remove commas from numerical values in convert template
            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}),(\d)", "$1$2");

            //pound weight
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[pound \(weight\)\|([^\]]{1,30})\]\]", "[[pound (mass)|$1]]");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\|lbs?\.\]\]", "|lb]]");

            //aviation specifications: unprotect "main=" and "alt="
            ArticleText = Regex.Replace(ArticleText, @"(?i)((?:main|alt) ?= ?)xx(\d)", "$1$2");

            //replace other templates with convert template
            ArticleText = Regex.Replace(ArticleText, @"(?i){{mi to km\|(\d{1,9})}}", "{{convert|$1|mi|km}}");
            ArticleText = Regex.Replace(ArticleText, @"(?i){{mi to km\|(\d{1,9})\|round[^\}]{1,5}}}", "{{convert|$1|mi|km}}");
            ArticleText = Regex.Replace(ArticleText, @"(?i){{mi2 to km2\|(\d{1,9})}}", "{{convert|$1|mi|km}}");
            ArticleText = Regex.Replace(ArticleText, @"(?i){{mi2 to km2\|(\d{1,9})\|round[^\}]{1,5}}}", "{{convert|$1|mi|km}}");

            //remove commas from numerical values in convert template
            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}),(\d)", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}),(\d)", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}),(\d)", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}),(\d)", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"({convert\|\d{1,16}),(\d)", "$1$2");

            //remove leading zeros from convert template
            ArticleText = Regex.Replace(ArticleText, @"({convert\|)0(\d)", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"({convert\|)0(\d)", "$1$2");
            ArticleText = Regex.Replace(ArticleText, @"({convert\|)0(\d)", "$1$2");

            //Remove surprise or "Easter egg" diversions linking unit name to orders of magnitude articles
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[1 ?_?E ?[\-\+]?\d{1,2} ?..?\|([^\]]{1,50})\]\]", "$1");
            ArticleText = Regex.Replace(ArticleText, @"(?i)\[\[Orders of magnitude \([^\)]{1,30}\)\|([^\]]{1,50})\]\]", "$1");

            //convert squares and cubes
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqmm\|", "$1|mm2|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqcm\|", "$1|cm2|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqm\|", "$1|m2|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqkm\|", "$1|km2|");

            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqmm}", "$1|mm2}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqcm}", "$1|cm2}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqm}", "$1|m2}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqkm}", "$1|km2}");

            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cumm\|", "$1|mm3|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cucm\|", "$1|cm3|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cum\|", "$1|m3|");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cukm\|", "$1|km3|");

            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cumm}", "$1|mm3}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cucm}", "$1|cm3}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cum}", "$1|m3}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|cukm}", "$1|km3}");

            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqmi sqkm}", "$1|sqmi km2}");
            ArticleText = Regex.Replace(ArticleText, @"({{convert\|[^}]{1,30})\|sqmi sqkm\|", "$1|sqmi km2|");


            //delink common units of measurement in convert template
//            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,30}\|)(mm|mm2|mm3|cm|cm2|cm3|m|m2|m3|km|km2|km3|in|ft|sqft|mi|sqmi)\|lk=on", "$1$2");
//            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,30}\|)(mm|mm2|mm3|cm|cm2|cm3|m|m2|m3|km|km2|km3|in|ft|sqft|mi|sqmi)(\|\d)\|lk=on", "$1$2$3");
//            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,30}\|)(mm|mm2|mm3|cm|cm2|cm3|m|m2|m3|km|km2|km3|in|ft|sqft|mi|sqmi)\|(mm|mm2|mm3|cm|cm2|cm3|m|m2|m3|km|km2|km3|in|ft|sqft|mi|sqmi)\|lk=on", "$1$2|$3");
//            ArticleText = Regex.Replace(ArticleText, @"({{convert\|\d{1,30}\|)(mm|mm2|mm3|cm|cm2|cm3|m|m2|m3|km|km2|km3|in|ft|sqft|mi|sqmi)\|(mm|mm2|mm3|cm|cm2|cm3|m|m2|m3|km|km2|km3|in|ft|sqft|mi|sqmi)(\|\d)\|lk=on", "$1$2|$3$4");

            return ht.AddBack(ArticleText);
        }
//