Jump to content

User:Dl2000/DateFix2.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <syntaxhighlight lang=javascript>
// This script aligns dates, currencies and potentially other formatting e.g. international format
// for many nations per [[WP:MOSNUM]] or {{A$}} template for Australian dollar.
// PLEASE READ THE DOCUMENTATION at [[User:Dl2000/DateFix]] (click on the link above) before using.
 
// Feedback and constructive criticism are welcome
// -- disable - some bugs in the general formatting, and much of this was not related
// -- to date fixing e.g. lowercasing "Career" in headings or removing word "Notable" in hdgs

function Dl2_DebugColourStart(clrcod) {
    var startfont = '<font color="';
    var fontlist = new Array("000000", "00ff00", "ff0000", "0000ff", "888800", "008888", "880088", "777777",
                             "ff8888", "88ff88", "8888ff" );
    if (clrcod >= fontlist.length)
        clrcod = 0;

    startfont += fontlist[clrcod];
    startfont += '">';
    return startfont;
}

function Dl2_DebugColourEnd() {
    return "</font>";
}

function Dl2_formatgeneral(){
// reserved for any future general formatting
}

// Only fix errors which can apply globally through the article
// Does not include fixes that do not apply in some cases e.g. quotation or template

function Dl2_fix_common_errors(intxt) {
        var txt = intxt;
 
// straighten non-standard "curly" quotations
        //txt=txt.replace(/“/g, '"'); // lquote - Unicode 201c
        //txt=txt.replace(/”/g, '"'); // rquote - Unicode 201d

//underscore in linked dates - dmy
	txt=txt.replace(/(\[\[[0-3]?\d)_(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))(\]\])/gi, '$1 $2$3');
//underscore in linked dates - mdy
	txt=txt.replace(/(\[\[)(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))_([0-3]?\d\]\])/gi, '$1$2 $3');
 
//remove leading zero from linked date
	txt=txt.replace(/(\[\[)(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s0(\d)(?:th|st|nd|rd|)(\]\])/gi, '$1$2 $3$4');
	txt=txt.replace(/(\[\[)0(\d)(?:th|st|nd|rd|)\s(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))(\]\])/gi, '$1$2 $3$4');
 
//fix 'bda' template redirect
	txt=txt.replace(/{{bda\|([^}]+)}}/gi, '{{birth date and age|$1}}');
 
//fix 'startdate' template redirect
	txt=txt.replace(/{{startdate\|([^}]+)}}/gi, '{{start date|$1}}');

//zap redundant templates ('date', 'as of', 'English', '#dateformat:') 
	txt=txt.replace(/\{\{date\|([^\}\|]+)(?:[^\}]+)?\}\}/gi, '$1');
	txt=txt.replace(/{{#dateformat:([^\}\|]+)(?:\|dmy|\|mdy)?}}/gi,'$1'); 
 
//Replace Image:
        txt=txt.replace(/\[\[Image:/gi, '[[File:');

        return txt;
}

// capitalise month names
function Dl2_cap_month_names(intxt)
{
        var txt = intxt;

	txt=txt.replace(/(\s)jan(|uary|\.)(\s)/g, '$1Jan$2$3');
	txt=txt.replace(/(\s)feb(|ruary|\.)(\s)/g, '$1Feb$2$3');
	txt=txt.replace(/(\d\s)mar(|ch|\.)(\s)/g, '$1Mar$2$3');
	txt=txt.replace(/(\s)mar(|ch|\.)(\s\d)/g, '$1Mar$2$3');
	txt=txt.replace(/(\s)apr(|il|\.)(\s)/g, '$1Apr$2$3');
	txt=txt.replace(/(\d\s)may(,|\.)(\s)/g, '$1May$2$3');
	txt=txt.replace(/(\s)may(|\.)(\s\d)/g, '$1May$2$3');
	txt=txt.replace(/(\s)jun(|e|\.)(\s)/g, '$1Jun$2$3');
	txt=txt.replace(/(\s)jul(|y|\.)(\s)/g, '$1Jul$2$3');
	txt=txt.replace(/(\s)aug(|ust|\.)(\s)/g, '$1Aug$2$3');
	txt=txt.replace(/(\s)sep(|tember|\.)(\s)/g, '$1Sep$2$3');
	txt=txt.replace(/(\d{1,2}\s)sept(\s)/g, '$1Sep$2');
	txt=txt.replace(/(\s)oct(|ober|\.)(\s)/g, '$1Oct$2$3');
	txt=txt.replace(/(\s)nov(|ember|\.)(\s)/g, '$1Nov$2$3');
	txt=txt.replace(/(\s)dec(|ember|\.)(\s)/g, '$1Dec$2$3');

        return txt; 
}

// Protection mechanism replaced in favour of skipping conversions on sections to be "protected" such as quotations or file names.

function Dl2_code_delink_dates(intext) {
 var txt=intext;

//delink ISO8601 dates
	txt=txt.replace(/\[\[([12]\d{3}-[0-1]\d-[0-3]\d)\]\]/gi, '$1');
	txt=txt.replace(/\[\[([12]\d{3})\]\]-\[\[([0-1]\d-[0-3]\d)\]\]/gi, '$1-$2');
	txt=txt.replace(/([12]\d{3})-\[\[([0-1]\d-[0-3]\d)\]\]/gi, '$1-$2');
	txt=txt.replace(/\[\[([12]\d{3})\]\]-([0-1]\d-[0-3]\d)/gi, '$1-$2');
 
//delink full dates
	txt=txt.replace(/\[\[([1-3]?\d)(?:th|st|nd|rd|)[\s_](?:of[\s_])?(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))(?:\]\] \[\[| )([12]\d{3})\]\]/gi, '$1 $2 $3');  
 
	txt=txt.replace(/\[\[(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|)) (?:the\s)?([1-3]?\d)(?:th|st|nd|rd|)(?:\]\],? \[\[|, )([12]\d{3})\]\]/gi, '$1 $2, $3');  
 
//delink single dm or 'dth the m'
	txt=txt.replace(/(?:the\s)?\[\[([1-3]?\d)(?:th|st|nd|rd|)[\s_](?:of[\s_])?(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\]\]/gi, '$1 $2');  
 
//delink single md or 'm the dth'
	txt=txt.replace(/\[\[(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))[\s_](?:the[\s_])?([1-3]?\d)(?:th|st|nd|rd|)\]\]([^\w\d])/gi, '$1 $2$3');
 
//Month+day_number "[[March 7]]th" -> "March 7"
	txt=txt.replace(/\[\[((?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s[1-3]?\d)\]\](?:th|st|nd|rd)/gi, '$1');
 
//month+day+year piped pseudo-ISO dates
	txt=txt.replace(/\[\[(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))( [0-2]?\d|30|31)\|[0-3]?\d-[0-3]?\d\]\]-(?:\[\[)?([1-2]\d\d\d)(\|\d{2,4})?(?:\]\])?/gi, '$1$2, $3');
	txt=txt.replace(/\[\[([0-3]\d\s(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|)))\|[0-3]?\d-[0-3]?\d\]\]-(?:\[\[)?([1-2]\d{3})(\]\])?/gi, '$1 $2');
 
//month+day piped
	txt=txt.replace(/(?:the\s)?\[\[\d{1,2}(?:th|st|nd|rd|)[\s_](?:of[\s_])?(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\|([^\]]{1,30})\]\]/gi, '$1');
 
 //'[[month day|xxXxx]]Xyyyy ' to 'month day, year'
	txt=txt.replace(/\[\[(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s(\d{1,2})(?:th|st|nd|rd|)\|\d?\d\.\d?\d\]\].(\d{3,4})/gi, '$1 $2, $3'); 
 //'[[day month|xxXxx]]Xyyyy' to 'day month year'
	txt=txt.replace(/\[\[(\d{1,2})(?:th|st|nd|rd|)\s(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\|\d?\d\.\d?\d\]\].(\d{3,4})/gi, '$1 $2 $3'); 
 
// century
	txt=txt.replace(/\[\[((?:first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|twenty(?:\s|-)first)(?:\s|-))(century|centuries)(\sAD|\sBC|\sCE|\sBCE|)\]\]/gi, '$1$2$3');
	txt=txt.replace(/\[\[(?:first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|thirteenth|fourteenth|fifteenth|sixteenth|seventeenth|eighteenth|nineteenth|twentieth|twenty(?:\s|-)first)[\s-_](?:century|centuries)(?:\sAD|\sBC|\sCE|\sBCE|)\|([^\]]{1,30})\]\]/gi, '$1');
	txt=txt.replace(/\[\[(\d{1,2}(?:st|nd|rd|th)[\s-_])(century|centuries)(\sAD|\sBC|\sCE|\sBCE|)\]\]/gi, '$1$2$3');
	txt=txt.replace(/\[\[\d{1,2}(?:st|nd|rd|th)[\s-_](?:century|centuries)(?:\sAD|\sBC|\sCE|\sBCE|)\|([^\]]{1,30})\]\]/gi, '$1');
 
// months
	txt=txt.replace(/\[\[(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\]\]/gi, '$1');
	txt=txt.replace(/\[\[(?:January|February|March|April|May|June|July|August|September|October|November|December)\|([^\]]{1,30})\]\]/gi, '$1');
 
// decades and years -- disabling for now due to potential inappropriate delinks
	// txt=txt.replace(/\[\[(\d{1,3}0)\'?s\]\]/g, '$1s');
	// txt=txt.replace(/\[\[\d{1,3}0\'?s?\|([^\]]{1,30})\]\]/g, '$1');
	// txt=txt.replace(/\[\[(\d{1,3}0)\'?(s)?\s(AD|BC|CE|BCE)\]\]/gi, '$1$2 $3');
	// txt=txt.replace(/\[\[(\d{1,4}[\s_]?)(AD|BC|CE|BCE|)\]\]/gi, '$1$2');
	// txt=txt.replace(/\[\[(AD|BC|CE|BCE|)([\s_]?)(\d{1,4})\]\]/gi, '$3$2$1');
	// txt=txt.replace(/\[\[\d{1,3}0\'?s?\s(?:AD|BC|CE|BCE)\|([^\]]{1,30})\]\]/gi, '$1');
	// txt=txt.replace(/\[\[\d{1,3}0\'?s?\s\(decade\)\|([^\]]{1,30})\]\]/gi, '$1');
	// txt=txt.replace(/\[\[([MDCLXVI]{3,10})\]\]/g, '$1'); -- disabled - would delink things like [[DVD]]
 
//month+year
//Identify surprise or 'Easter egg' diversions linking month+years to year articles. Turn them into month+year links to be dealt with below
	txt=txt.replace(/\[\[\d{1,4}#[^\|\]]+\|((?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s\d{3,4})\]\]/gi, '$1');
	txt=txt.replace(/\[\[((?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s\d{3,4})\]\]/gi, '$1');
	txt=txt.replace(/\[\[(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s\d{3,4}\|([^\]]{1,30})\]\]/gi, '$1');
 
//removed piped years when in full date
	txt=txt.replace(/(\[\[\d{1,2}\s(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\]\],?\s?\[\[)[^\|\]]{1,32}\|(\d{1,4}\]\])/gi, '$1$2');
	txt=txt.replace(/(\[\[(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s\d{1,2}\]\],?\s?\[\[)[^\|\]]{1,32}\|(\d{1,4}\]\])/gi, '$1$2');
 
//Identify surprise or 'Easter egg' diversions linking months to year articles.
	txt=txt.replace(/\[\[\d{1,4}#[^\|\]]+\|(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\]\]/gi, '$1');
 
// month and day piped
	txt=txt.replace(/(\d{4,4}-)\[\[(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))[\s_]\d{1,2}(?:th|st|nd|rd|)\|(\d-)(\d)\]\]/gi, '$10$20$3');
	txt=txt.replace(/(\d{4,4}-)\[\[(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))[\s_]\d{1,2}(?:th|st|nd|rd|)\|(\d\d-)(\d)\]\]/gi, '$1$20$3');
	txt=txt.replace(/(\d{4,4}-)\[\[(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))[\s_]\d{1,2}(?:th|st|nd|rd|)\|(\d-)(\d\d)\]\]/gi, '$10$2$3');
	txt=txt.replace(/\[\[(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))[\s_]\d{1,2}(?:th|st|nd|rd|)\|([^\]]{1,30})\]\]/gi, '$1');
	txt=txt.replace(/\[\[\d{1,2}(?:th|st|nd|rd|)[\s_](?:of[\s_])?(?:Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.?|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\|([^\]]{1,30})\]\]/gi, '$1');
	txt=txt.replace(/\[\[(\d{1,2}(?:st|nd|rd|th))\]\]/gi, '$1');
 
// spaces and commas - mdy birth and death date ranges
	txt=txt.replace(/([^\d][^\w\d])(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s([0-2]?\d|30|31),? (\d{1,3}|[12]?\d{3})(?:[ ]*[-–][ ]*)(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s([0-2]?\d|30|31),? (\d{1,3}|[12]?\d{3})([^\d][^\w\d])/gi, '$1$2 $3, $4 – $5 $6, $7$8');
//dmy birth and death date ranges)
	txt=txt.replace(/([^\d][^\w\d])([0-2]?\d|30|31)\s(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|)),? (\d{1,3}|[12]?\d{3})(?:\s?[-–]\s?)([0-2]?\d|30|31)\s(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|)),? (\d{1,3}|[12]?\d{3})([^\d][^\w\d])/gi, '$1$2 $3 $4 – $5 $6 $7$8');

    return txt;
}
 
function Dl2_delink_ISO_to_dmy() {
    var txt = document.editform.wpTextbox1;
 
// disable in-citation temporarily
//    txt.value = yyyymmdd_to_dmy(txt.value);  // adapted from User:Plastikspork/datetools.js

	txt.value=txt.value.replace(/([^\d\w\/\-%,])([12]\d{3}-\d\d-\d\d)(<\s?\/ref.*?>)/g, '$1$2 $3');

//code to convert ref ISO-dates in citation templates for certain cases

// -([1-3]\d)([^
// -0(\d)([^

// replace date=<ISO8601> within refs
	txt.value=txt.value.replace(/(<\s?ref.*?>[^<]+)(\|\s?date\s?=)([12]\d{3})-(0[0-9]|1[012])-([0-3]\d)([^\d\w\/\-%,])([^<]*?<\s?\/ref.*?>)/gm, 
            function(zz, start1, start2, yyyy, mm, dd, end1, end2)
            {
                return (start1 + start2 + dd + ' ' + Dl2_Monthname(mm) + ' ' + yyyy + end1 + end2);
            } );

    // txt.value = Dl2_remove_leading_zeros_from_nonlinked_dates (txt.value);
 
}
 
//protect certain dates 
//	txt.value=txt.value.replace(/(\[\[4)(AD)/gi, '$1♫$2');
//	txt.value=txt.value.replace(/(March )((?:8|14) Alliance)/gi, '$1♫$2');
//	txt.value=txt.value.replace(/(movement 2) (June)/gi, '$1♫$2');
//	txt.value=txt.value.replace(/(6th\sof\s)(October City)/gi, '$1♫$2');
//	txt.value=txt.value.replace(/(19th\sof\s)(April movement)/gi, '$1♫$2');
//	txt.value=txt.value.replace(/(\[\[May\s1968)(\]\])/gi, '$1 in France|May 1968$2');
//	txt.value=txt.value.replace(/(\[\[June )(1, 1974\]\])/gi, '$1♫$2'); //June 1, 1974 is the name of an album
//	txt.value=txt.value.replace(/(\'\'June )(1, 1974\'\')/gi, '$1♫$2'); 
//	txt.value=txt.value.replace(/(\[\[)((?:2300|2000)\s?AD\]\])/gi, '$1:$2');
 
function Dl2_remove_leading_zeros_from_nonlinked_dates (intext) {

 var txt=intext;
//remove leading zero from nonlinked date
	txt=txt.replace(/([^\d][^\w\d])(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s0(\d)(?:th|st|nd|rd|),?\s([12]\d{3})([^\w\d][^\d]|\b)/gi, '$1$2 $3, $4$5');
	txt=txt.replace(/([^\d][^\w\d])0(\d)(?:th|st|nd|rd|)\s(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s([12]\d{3})([^\w\d][^\d]|\b)/gi, '$1$2 $3 $4$5');
 
	txt=txt.replace(/([^\d][^\w\d])(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))\s0(\d)(?:th|st|nd|rd|)([^\w\d][^\d]|\b)/gi, '$1$2 $3$4');
	txt=txt.replace(/([^\d][^\w\d])0(\d)(?:th|st|nd|rd|)\s(Jan(?:uary|\.|)|Feb(?:ruary|\.|)|Mar(?:ch|\.|)|Apr(?:il|\.|)|May\.?|Jun(?:e|\.|)|Jul(?:y|\.|)|Aug(?:ust|\.|)|Sep(?:tember|\.|t\.|)|Oct(?:ober|\.|)|Nov(?:ember|\.|)|Dec(?:ember|\.|))([^\w\d][^\d]|\b)/gi, '$1$2 $3$4');
 
	return txt;
}

// Tag only
function Dl2_Monthname(monthcode) {
    var myMonths = new Array("0", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

    return myMonths[parseInt(monthcode, 10)]; // the , 10 avoids the jscript cootie where "08" is translated to "0"
}

function Dl2_Monthcode(monthname) {
    var myMonths = ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"];

    var mthcode = myMonths.indexOf(monthname.toLowerCase()) + 1;

    return mthcode;
}

function Dl2_CurrMY() {
// current month-year
    var currentDate = new Date();
    var currmonth = currentDate.getMonth();
    var curryear  = currentDate.getFullYear();
    var myMonths = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
    var curryyyymm = myMonths[currmonth] + ' ' + curryear;

    return curryyyymm;
}

function Dl2_IntlTag1() {
    var txt=document.editform.wpTextbox1;
    Dl2_IntlTag(txt);
}

function Dl2_IntlTag(txta){
// leave an existing tag alone
    var rxpd1 = new RegExp("{{Use dmy dates(\\|[^}]*)?}}", "gi");
    var ddfound = txta.value.search(rxpd1);
    if (ddfound >= 0)
    {
        return;
    }

// current month-year
    var curryyyymm = Dl2_CurrMY();

// insert or update 'dmy' template
    txta.value=txta.value.replace(/{{(use (dmy|mdy) dates|dmy|mdy)(\|[^}]*)?}}/gi, '{{Use dmy dates|date='+curryyyymm+'}}');

    var rxpdd = new RegExp("{{Use dmy dates\\|date="+curryyyymm+"}}", "gi");
    var dflagfound = txta.value.search(rxpdd);
    if (dflagfound == -1)
    {
        txta.value='{{Use dmy dates|date='+curryyyymm+'}}\r\n'+txta.value;
    }
}
 
function Dl2_BDA() {
  var txt=document.editform.wpTextbox1;

  var case1handled = 0;

  // case 1: birth_date = dd MMM yyyy
	txt.value=txt.value.replace(/(birth_date[\s]*=[\s]*)([0-3]?[0-9])[\s]*([a-zA-Z]+)[\s]*([1-2][0-9][0-9][0-9])([\s]*\(age.*\))?/gi,
            function(zz, start1, dd, mmm, yyyy, end1)
            {
                var newbda;
                var andage = '';
                if (parseInt(yyyy) > 1920)
                {
                    andage = ' and age';
                }
                newbda =  (start1 + '{{birth date' + andage + '|' + yyyy + '|' + Dl2_Monthcode(mmm) + '|' + dd + '|df=y}}' );
                case1handled = 1;
                return newbda;
            } );

  // case 2: existing {{birth date| - but only if not handled in case 1, and then only for sensible years
  if (case1handled == 0)
  {
    txt.value=txt.value.replace(/{{birth date\|(19[3-9][0-9])\|/gi, '{{birth date and age|$1|');
  }

  var txtsumm=document.editform.wpSummary;
  var summary = "bda";
  if (txtsumm.value.indexOf(summary) == -1) {
    if (txtsumm.value.match(/[^\*\/\s][^\/\s]?\s*$/)) {
      txtsumm.value += " | ";
    }
    txtsumm.value += summary;
  }
  document.forms.editform.wpMinoredit.checked = true;

  document.editform.wpDiff.click();
}

function Dl2_Fdate() {
  var txt=document.editform.wpTextbox1;

  var case1handled = 0;

  // case 1: released = dd MMM yyyy
	txt.value=txt.value.replace(/(released[\s]*=[\s]*)([0-3]?[0-9])[\s]*([a-zA-Z]+)[\s]*([1-2][0-9][0-9][0-9])([\s]*)?/gi,
            function(zz, start1, dd, mmm, yyyy, end1)
            {
                var newrel;
                newrel =  (start1 + '{{film date|' + yyyy + '|' + Dl2_Monthcode(mmm) + '|' + dd + '|df=y}}' );
                case1handled = 1;
                return newrel;
            } );

  var txtsumm=document.editform.wpSummary;
  var summary = "film date";
  if (txtsumm.value.indexOf(summary) == -1) {
    if (txtsumm.value.match(/[^\*\/\s][^\/\s]?\s*$/)) {
      txtsumm.value += " | ";
    }
    txtsumm.value += summary;
  }
  document.forms.editform.wpMinoredit.checked = true;

  document.editform.wpDiff.click();
}


// Section types:
// 0: normal article text
// 1: [[..]] e.g. image, link, category
// 2: {{..}} e.g. template
// 3: <!--..--> comment
// 4: <blockquote>
// 5: <gallery>
// 6: <timeline>
// 7: ".." e.g. nondirectional double quotation
//
// (single quotations not handled - sometimes these can be used for abbrevation e.g. '76)

function Dl2_process_text_section(sectext, sectype) {

    var newtext;

    switch (sectype)
    {
    case 0:
        newtext = Dl2_process_text_section_normal(sectext)
        break;

    case 1:
        newtext = Dl2_process_text_section_link(sectext)
        break;

    case 2:
        newtext = Dl2_process_text_section_template(sectext)
        break;

    // comment, quotation, gallery, timeline - always keep intact
    default:
        newtext = sectext;
        break;
    }

    return newtext;
}

function Dl2_process_text_section_normal(intext) {
    var txt = intext;

    // Fix common normal text non-date items
    txt = Dl2_cap_month_names(txt);

    // lc and tidy any "- present" range
    txt=txt.replace(/(\d)(?:-|–|&ndash;)P(resent)/g, '$1 – p$2');

    //Fix curly-directional double-quotes which are discouraged at [[WP:PUNCT]] - these often get mismatched with straight d-quotes anyway
    txt=txt.replace(/“/g, '"'); // lquote - Unicode 201c
    txt=txt.replace(/”/g, '"'); // rquote - Unicode 201d

    // common regex elements
    var matchmonth = "(Jan(?:uary|\\.|)|Feb(?:ruary|\\.|)|Mar(?:ch|\\.|)|Apr(?:il|\\.|)|May\\.?|Jun(?:e|\\.|)|Jul(?:y|\\.|)|Aug(?:ust|\\.|)|Sep(?:tember|\\.|t\\.|)|Oct(?:ober|\\.|)|Nov(?:ember|\\.|)|Dec(?:ember|\\.|))";
    var matchday = "([0-2]?\\d|30|31)";
    var matchdwd = "([^\\d][^\\w\\d])";
    var matchwdb = "([^\\w\\d][^\\d]|\\b)";
    var nmatchord = "(?:<sup>|<small>)?(?:th|st|nd|rd|)(?:</sup>|</small>)?"; // strip ordinals (and any superscripts) out with a non-match
    var nmatchthe = "(?:the\\s?)?"; // strip spurious "the" prefixing
    var nmatchconj = "(?:and|[-–&]|to|or)"; // strip spurious conjunctions

    if (txt.search(matchmonth) >= 0)
    {
// dmy cleanups...

//rem redundant spaces (and commas) in date formats (moved from fix common errors, to avoid refactoring file names)
        var rx = new RegExp("([^\\d][^\\w\\d]\[?\\[?[0-3]?\\d)[ ]+" + matchmonth + "(\\]\\])?[ ]*,[ ]*(\\[?\\[?\\d{3,4}(\\sAD|\\sBC|\\sCE|\\sBCE|)\\]?\\]?[^\\w\\d][^\\d])", 'gi');
	txt=txt.replace(rx, '$1 $2$3 $4');

        rx = new RegExp("([^\\d][^\\w\\d]\\[?\\[?)" + matchmonth + "[ ]+" + matchday + "(\\]?\\]?)(?:[ ]*,[ ]*)(\\[?\\[?\\d{3,4}(\\sAD|\\sBC|\\sCE|\\sBCE|)\\]?\\]?[^\\w\\d][^\\d])", 'gi');
	txt=txt.replace(rx, '$1$2 $3$4, $5');

        rx = new RegExp("([^\\d][^\\w\\d]\\[?\\[?)" + matchmonth + "[ ]+" + matchday + "(\\]?\\]?)[ ]+(\\[?\\[?\\d{3,4}(\\sAD|\\sBC|\\sCE|\\sBCE|)\\]?\\]?[^\\w\\d][^\\d])", 'gi');
	txt=txt.replace(rx, '$1$2 $3$4, $5'); 

        // comma/of cleanup
        rx = new RegExp(matchmonth + "(?:, | of )(\d{3,4}[\w\d])", 'gi'); //repeat after delinking
        txt=txt.replace(rx, '$1 $2');

//remove unlinked ordinal date formats
        // dth, dth&dth m -> d, d&dm
        rx = new RegExp(nmatchthe + matchday + nmatchord + ", " + matchday + nmatchord + "(\\s?" + nmatchconj + "\\s?)" + matchday + nmatchord + "(?:\\sof\\s?)?\\s" + matchmonth + "([^\\w\\d])", 'g');
        txt=txt.replace(rx,  '$1, $2$3 $4$5 $6');

        // dth&dth m -> d&dm
        rx = new RegExp(nmatchthe + matchday + nmatchord + "(\\s?" + nmatchconj + "\\s?)" + matchday + nmatchord + "(?:\\sof\\s?)?\\s" + matchmonth + "([^\\w\\d])", 'g');
	txt=txt.replace(rx, '$1$2$3 $4$5');

        rx = new RegExp(nmatchthe + matchday + nmatchord + "(?:\\sof\\s?)?\\s" + matchmonth + "([^\\w\\d])", 'g');
        txt=txt.replace(rx, '$1 $2$3');

        rx = new RegExp(matchmonth + "\\s" + nmatchthe + matchday + nmatchord + ",\\s" + nmatchthe + matchday + nmatchord + "(\\s?" + nmatchconj + "\\s?)" + nmatchthe + matchday + nmatchord + "([^\\]\\|\\w\\d][^\\d])", 'g');
        txt=txt.replace(rx, '$1 $2, $3$4 $5$6');

        rx = new RegExp(matchmonth + "\\s" + nmatchthe + matchday + nmatchord + "(\\s?" + nmatchconj + "\\s?)" + nmatchthe + matchday + nmatchord + "([^\\]\\|\\w\\d][^\\d])", 'g');
	txt=txt.replace(rx, '$1 $2$3$4$5');

        rx = new RegExp(matchmonth + "\\s" + nmatchthe + matchday + nmatchord + "([^\\]\\|\\w\\d][^\\d])", 'g');
        txt=txt.replace(rx, '$1 $2$3');

// mdy conversions...

// A. convert mdy-mdy to dmy-dmy (birth and death date ranges)
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + ", ([12]?\\d{0,3})(?:\\s?[-–]\\s?)" + matchmonth + "\\s" + matchday + ", ([12]?\\d{0,3})" + matchdwd, 'g');
	txt=txt.replace(rx, '$1$3 $2 $4 – $6 $5 $7$8');

// B1. m{d}*,y to {d}my
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + "((?:,\\s[0-3]?\\d" + nmatchord + "){0,6}),?(\\s?" + nmatchconj + "\\s+?)" + matchday + nmatchord + ",?\\s(?:of\\s)?(\\d{3,4}[^\\w\\d][^\\d])", 'g');
	txt=txt.replace(rx, '$1$3$4$5$6 $2 $7');

// B2. md-mdy to dm-dmy
        rx = new RegExp(matchdwd + matchmonth + "\\s+" + matchday + nmatchord + "\\s*" + nmatchconj + "\\s*" + matchmonth + "\\s+" + matchday + nmatchord + ",?\\s(?:of\\s)?(\\d{3,4}[^\\w\\d][^\\d])", 'g');
	txt=txt.replace(rx, '$1$3 $2 – $5 $4 $6');

// C. md-md to dm-dm (mdy-mdy or md-mdy cases being caught above)
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + "(?:\\s?[-–]\\s?)" + matchmonth + "\\s" + matchday + matchdwd, 'g');
	txt=txt.replace(rx, '$1$3 $2 – $5 $4$6');

// D. md,d,d -> d,d,dm
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + "((?:,\\s[0-3]?\\d" + nmatchord + "){0,6}), " + matchday + nmatchord + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3$4, $5 $2$6');

// E. convert md,d,d, date ranges to d,d,dm  (multiple, separated by commas)
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + "((?:,?\\s[0-3]?\\d" + nmatchord + "){0,6}),?(\\/|\\s?[-–]\\s?|\\s" + nmatchconj + "\\s+?)" + matchday + nmatchord + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3$4$5$6 $2$7');

// F. md&d -> d&dm
        rx = new RegExp(matchdwd + matchmonth + "((?:\\s[1-3]?\\d" + nmatchord + ",?){1,6})(\\s" + nmatchconj + "\\s+?)" + matchday + nmatchord + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3$4$5 $2$6');

// G. md,d -> d,dm
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + "((?:,?\\s[1-3]?\\d" + nmatchord + "){1,6})" + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3$4 $2$5');

// H. convert md-d date ranges to d-dm  (simple, separated by hyphens and dashes  or 'to')
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + "(\\s?[-–]\\s?|\\sto\\s)" + matchday + nmatchord + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3 $4$5 $2$6');

// I. 'md, md,' to 'dm, dm,'
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + ",\\s?" + matchmonth + "\\s" + matchday + "([,\\.\\s])" + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3 $2, $5 $4$6$7');

// J. convert simple mdy dates to dmy
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + ",?\\s(\\d{1,4}\\s?(?:AD|BC|CE|BCE)[^\\w\\d][^\\d])", 'g');
	txt=txt.replace(rx, '$1$3_$2_$4');

        // test - previous word checks will miss basic cases
        //rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + ",?\\s([12]\\d{3})" + matchwdb, 'g');
	//txt=txt.replace(rx, '$1 $3 $2 $4$5');

// K. md,y -> dmy - ending with \D or end of string
        rx = new RegExp("\\b" + matchmonth + "\\s" + matchday + nmatchord + ",?\\s([12]\\d{3})(\\D|$)", 'g');
	txt=txt.replace(rx, '$2 $1 $3$4');

// L. md -> dm
        // 11De2011 - also allow starting pipe to cover table entry case
        rx = new RegExp("([^\\d][^\\w\\d]|\\|\\s*)" + matchmonth + "\\s" + matchday + nmatchord + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3 $2$4');

// M. Repeat line to capture some instances that get missed first time 
// (needed because the date component 'September 19, 1881' within the string 'March 4-September 19, 1881' is blocked from conversion by the '4')
        rx = new RegExp(matchdwd + matchmonth + "\\s" + matchday + nmatchord + ",?\\s(\\d{1,4})" + matchwdb, 'g');
	txt=txt.replace(rx, '$1$3 $2 $4$5');

// ordinal strip-outs
// N. dth m y -> dmy
        rx = new RegExp(matchdwd + matchday + nmatchord + "\\s" + matchmonth + "\\s(\\d{1,4})" + matchwdb, 'g');
	txt=txt.replace(rx, '$1$2 $3 $4$5');

// O. dth m -> dm
        rx = new RegExp(matchdwd + matchday + nmatchord + "\\s" + matchmonth + matchwdb, 'g');
	txt=txt.replace(rx, '$1$2 $3$4');

// P. dth-dth m -> d-dm
        rx = new RegExp(matchdwd + matchday + nmatchord + "(\\s?[-–]\\s?)" + matchday + nmatchord + "\\s" + matchmonth + matchwdb, 'g');
	txt=txt.replace(rx, '$1$2$3$4 $5$6');
    }
 
    txt = Dl2_remove_leading_zeros_from_nonlinked_dates (txt);

//cleanup any residual commas in International date format
    rx = new RegExp(matchday + nmatchord + "\\s" + matchmonth + ",\\s?(\\d{3,4})([^\\w\\d])", 'g');
    txt=txt.replace(rx, '$1 $2 $3$4');

    return txt;
}

function Dl2_process_text_section_link(intext) {

        var txt = intext;

        // process any date texts within a File: (except in the filename itself)
	txt=txt.replace(/(File:[^\|\]]+)(\|[^\]]*)(\]\])/gi,
            function(zz, start1, body1, end1)
            {
                var newfile = start1 + Dl2_process_text_section_normal(body1) + end1;
                return newfile;
            } );

        // reserved for link processing

        // ??? 9/11 attacks?

        return txt;
}

function Dl2_process_text_section_template(sectext) {
	var txt = sectext;

        var template_key = "";
        var arr_template_key = txt.match(/^(\{\{[\s]*)([^\|\}]*)/);
        if (arr_template_key != null)
        {
            if (arr_template_key.length >= 2)
            {
                template_key = arr_template_key[2];
            }
        }
        template_key = template_key.toLowerCase();
        

//change start and end templates
	txt=txt.replace(/({{(start\sdate|end\sdate)[^|]*\|)df=ye?s?\|([^}]*df=ye?s?)/gi, '$1$2');
 
//change deprecated birth and death templates, start/end and wayback templates
	txt=txt.replace(/({{(?:Birth|Death|release|film date|start date|end date|wayback)[^}]*)\|mf=ye?s?/gi, '$1');
	txt=txt.replace(/({{(?:Birth|Death|release|film date|start date|end date|wayback)[^|]*\|)/gi, '$1df=yes|');
	txt=txt.replace(/({{(?:Birth|Death|release|film date|start date|end date|wayback)[^|]*\|)df=ye?s?\|([^}]*df[ ]?=[ ]?ye?s?)/gi, '$1$2');
 
// dts - format=dmy in this case
        // per {{dts}} doc, remove the obsolete link=off param
	txt=txt.replace(/({{dts[^}]*)(\|link=off)/gi, '$1');
        // clean up existing format...
	txt=txt.replace(/({{dts[^}]*)(\|format=(dmy|mdy))/gi, '$1');
        // then ensure format=dmy is applied if year is first (bugfix courtesy Ohconfucius)
        // txt=txt.replace(/({{dts[^|]*\|)/gi, '$1format=dmy|'); - false pos when date not yr first
        txt=txt.replace(/(\{\{dts[^|]*\|)(?=\d{4}[-\|])/gi, '$1format=dmy|');

// do not attempt to refactor dates for certain parameters, or within certain templates
        var arrSkipParamKeys = new Array("title", "journal", "quote", "source",
             "image", "image_name", "image_file", "work", "filename", "Ship image", "chapter",
             "photo", "contribution" );

// clean up params except for certain cases where a title or quote should remain intact
        var arrParam = txt.split("|");
        var arrParamLength = arrParam.length;
        if (arrParamLength > 0)
        {
            var newtxt = "";

            var skip_all_param = 0;
            
            // don't refactor cquotes, as contained in non-keyed params
            if ((template_key == "cquote") || (template_key == "bquote") ||
               (template_key == "quote") || (template_key == "quotation") ||
               (template_key == "blockquote") ||
               (template_key == "not a typo") || (template_key == "gallery"))
            {
                skip_all_param = 1; // leave all params intact for these cases
            }
            // don't refactor defaultsorts
            var match_ds = template_key.match("^defaultsort:");
            if (match_ds != null)
            {
                skip_all_param = 1; // leave all params intact for these cases
            }
            
			for (ii = 0; ii < arrParamLength; ii++)
            {
                var newParam = arrParam[ii];
                var param_key = newParam.match("^(?:\\s*)([^=]+)(?:=)");
                var skip_this_param = skip_all_param;
                if ((param_key != null) && (skip_all_param == 0))
                {
                    param_key1 =  param_key[1].replace(/\s*$/, ""); // trim any trailing spaces
                    if (arrSkipParamKeys.indexOf(param_key1) >= 0)
                    {
                    	skip_this_param = 1;
                    }
                }

				if (skip_this_param == 0)
                {
                    newtxt = newtxt + Dl2_process_text_section_normal(newParam);
                }
                else
                {
                    newtxt = newtxt + newParam;
                }
                     
                if (ii < (arrParamLength - 1))
                {
                    newtxt = newtxt + "\|";
                }
            }
            txt=newtxt;
        }

        return txt;
}

// Concept is to avoid "protection" mechanism - instead of string replacements across the entire
// article, parse the article into separate sections according to whether they are templates, quotations,
// images, links, or formattable article text. This may actually be less efficient than global
// substitutions, but will tend to avoid false positives by skipping those portions of an article
// which should not be refactored.

function Dl2_dates_to_dmy(isdebug){

    var txt=document.editform.wpTextbox1;

    Dl2_IntlTag(txt);

    txt.value = Dl2_fix_common_errors(txt.value);

    txt.value = Dl2_code_delink_dates(txt.value);

    // Parse article text into arrSectionText elements, each idenified with arrSectionType
    var arrSectionText = new Array();
    var arrSectionType = new Array();

    // define corresponding start and end markers for sections...
    var arrSectStarts = new Array('', '[[', '{{', '<!--', '<blockquote>',  '<gallery',  '<timeline>',  "\"", '<div', "''" );
    var arrSectEnds   = new Array('', ']]', '}}', '-->',  '</blockquote>', '</gallery>', '</timeline>', "\"", '</div>', "''" );

    var numDigits = "0123456789";

    var currSectionType = 0;
    var currSectionIndex = 0;
    var currSectionError = 0;
    var hasQMismatch = 0;
    var hasUTmismatch = 0;

    var currpos = 0;
    var last_currpos = 0;

    // Initial pass to parse out the text sections...
    // Set up local variables for text content and length to slightly improve efficiency - txt won't change in this first loop

    var txtValue = txt.value;
    var txtValueLength = txt.value.length;

    while (currpos < txtValueLength)
    {
        if (currSectionType == 0)
        {
            // assume normal text - look for the start of another type e.g. [[, {{, "
            var nextSectionType = 0;
            var ixNext = txtValueLength;
            for (ii = 1; ii < arrSectStarts.length; ii++)
            {
                var ixPos = txtValue.indexOf(arrSectStarts[ii], currpos);
                if (ixPos < 0)
                {
                    ixPos = txtValueLength + 1;
                }
                if (ixPos < ixNext)
                {
                    ixNext = ixPos;
                    nextSectionType = ii;
                }
            }

            if (ixNext < txtValueLength)
            {
                // special case for double quote - stay in normal section type if this is not a starting
                // double quote (generally inches designation e.g. 7", as immediately preceded by digit(s))

                if (nextSectionType == 7) // double quotation per arrSectStarts[]
                {
                    var beforequote = txtValue.slice(ixNext - 1, ixNext);
                    if (beforequote)
                    {
                        if (numDigits.indexOf(beforequote) >= 0)
                        {
                            nextSectionType = 0; // start another normal section
                            ixNext++;
                        }
                    }
                }

                if (ixNext > currpos)
                {
                    arrSectionText[currSectionIndex] = txtValue.slice(currpos, ixNext);
                    arrSectionType[currSectionIndex] = 0;
                    currSectionIndex++;
                }
                currSectionType = nextSectionType;
                currpos = ixNext;
            }
            else
            {
                // no more sections found - write out to the end
                arrSectionText[currSectionIndex] = txtValue.slice(currpos);
                arrSectionType[currSectionIndex] = 0;
                currpos = txtValueLength;
            }
        }
        else
        {
            if (currSectionType >= arrSectEnds.length)
            {
                currpos++; // fail-safe trap
                currSectionType = 0;
            }
            else
            {
                var levels_in = 1; // up a level for each {{, down for each }} - outer template ends when level gets to 0
                var ixEnd = currpos + 1;
                var sStarter = arrSectStarts[currSectionType];
                var sTerminator = arrSectEnds[currSectionType];
                var identical_ends = 0;
                if (sStarter == sTerminator)
                {
                    identical_ends = 1;
                }

                while ((levels_in > 0) && (ixEnd < txtValueLength))
                {
                    var chk = txtValue.slice(ixEnd, ixEnd + sTerminator.length);

                    // if starter == terminator, this is only one level, only watch for the terminator!
                    if ((chk == sStarter) && (identical_ends == 0))
                    {
                        levels_in++;
                        ixEnd = ixEnd + sStarter.length;
                    }
                    else
                    {
                        if (chk == sTerminator)
                        {
                            levels_in--;
                            ixEnd = ixEnd + sTerminator.length;
                        }
                        else
                        {
                            var nxtStarter = txtValue.indexOf(sStarter, ixEnd + 1);
                            var nxtTerminator = nxtStarter;
                            if (identical_ends == 0)
                            {
                                nxtTerminator = txtValue.indexOf(sTerminator, ixEnd + 1);
                            }
                            if ((nxtStarter < nxtTerminator) && (nxtStarter >= 0))
                            {
                                ixEnd = nxtStarter;
                            }
                            else
                            {
                                if (identical_ends == 1)
                                {
                                    // in quotation sections, automatically terminate at the end of the para and reset section scan
                                    var nxtPara = txtValue.indexOf("\n", ixEnd + 1);
                                    if (nxtPara < 0)
                                    {
                                        nxtPara = txtValueLength;
                                    }
                                    if (nxtTerminator > nxtPara)
                                    {
                                        // alert("unterminated quote (" + sTerminator + ") at end of para:\n" + txtValue.slice(currpos, nxtPara) + " ixEnd=" + ixEnd);
                                        ixEnd = nxtPara;
                                        levels_in = 0;
                                        currSectionError = nxtPara;
                                    }
                                }

                                if (nxtTerminator < 0)
                                {
                                    ixEnd = txtValueLength;
                                }
                                else
                                {
                                    ixEnd = nxtTerminator;
                                }
                            }
                        }
                    }
                }

                if (levels_in > 0)
                {
                    var err_pos = currpos + 100;
                    if (err_pos > txtValueLength)
                    {
                        err_pos = txtValueLength - 1;
                    }

                    // alert('unterminated section of text! (missing ' + arrSectEnds[currSectionType] +
                    //       ')\nCheck from start of this section:\n' +  txtValue.slice(currpos, err_pos) + '...');

                    hasUTmismatch = hasUTmismatch + 1;
                    arrSectionText[currSectionIndex] = '{{check quotation}}<!-- MISSING ' +
                               arrSectEnds[currSectionType] + ' following: -->' +
                               txtValue.slice(currpos);
                    arrSectionType[currSectionIndex] = currSectionType;
                    currpos = txtValueLength;
                }
                else
                {
                    // write out section
                    var nextSectionText;
                    if (currSectionError > 0)
                    {
                        nextSectionText = txtValue.slice(currpos, currSectionError + 1) +
                                          '{{check quotation}}';
                        if (ixEnd > currSectionError + 2)
                        {
                            nextSectionText = nextSectionText + txtValue.slice(currSectionError + 1, ixEnd);
                        }
                        hasQMismatch++;
                    }
                    else
                    {
                        nextSectionText = txtValue.slice(currpos, ixEnd);
                    }
                    arrSectionText[currSectionIndex] = nextSectionText;
                    arrSectionType[currSectionIndex] = currSectionType;
                    currSectionError = 0;
                    currSectionIndex++;
                    currpos = ixEnd;
                }
                currSectionType = 0;
            }
        }
    }

    // Second pass - now refactor each section of text according to its type
    var newtxt = "";

    for (j = 0; j < arrSectionText.length; j++)
    {
        if (isdebug == 1)
        {
            newtxt += Dl2_DebugColourStart(arrSectionType[j]);
        }
        newtxt += Dl2_process_text_section(arrSectionText[j], arrSectionType[j]);
        if (isdebug == 1)
        {
            newtxt += Dl2_DebugColourEnd();
        }
    }

    txt.value = newtxt;

// ??? to re-do
//change start and end templates
//change deprecated birth and death templates

}
 
function Dl2_MOSNUM_edit_summary(nation){
// Add a tag to the summary box
 var txt=document.editform.wpSummary;
    var summary = "unify formatting per [[WP:MOSNUM|MoS]], script-assisted (" + nation + " subject)";
	if (txt.value.indexOf(summary) == -1) {
		if (txt.value.match(/[^\*\/\s][^\/\s]?\s*$/)) {
			txt.value += ", ";
		}
		txt.value += summary;
	}
//	document.forms.editform.wpMinoredit.checked = true;
	document.editform.wpDiff.click();
}
 
function Dl2_ADollar() {
  var txt=document.editform.wpTextbox1;

  txt.value=txt.value.replace(/{{AUD\|([^}]+)}}/gi, '{{A\$|$1}}');
  txt.value=txt.value.replace(/\[\[Australian\sdollar\|AU\$\]\]/gi, '{{A\$}}');
  txt.value=txt.value.replace(/AU\$/gi, 'A\$');
}

// type - the full word of the English variant type to be tagged to
function Dl2_EngTag(type) {
    var txt=document.editform.wpTextbox1;

    // If there's an existing tag, prompt to override
    langvars = new Array("American", "Australian", "British (Oxford)", "British", "Canadian", "Hong Kong", "Indian", "Irish", "Jamaican", "New Zealand", "Pakistani", "South African" );
    var curryyyymm = Dl2_CurrMY();

    for (i = 0; i < langvars.length; i++)
    {
        var rxTemp = new RegExp('{{[_ ]*(?:[Uu]se[_ ]+' + langvars[i] + '[_ ]+English|[Ee]ngvarB)[_ ]*(?:|\\|[ ]*date[ ]*=[^{}\\|]*)[ ]*}}', 'gi');
        if ((langvars[i] != type) && (txt.value.search(rxTemp) >= 0))
        {
            if (confirm(langvars[i] + ' English tag already exists - override?'))
            {
                var newtag='{{Use ' + type + ' English|date='+curryyyymm+'}}';
                txt.value=txt.value.replace(rxTemp, newtag);
            }
            else
            {
                return;
            }
        }
    }

    // add tag if not already present (or changed above)
    var rxpdd = new RegExp("{{Use " + type + " English", "gi");
    var dflagfound = txt.value.search(rxpdd);
    if (dflagfound == -1)
    {
        txt.value='{{Use ' + type + ' English|date='+curryyyymm+'}}\r\n'+txt.value;
    }
}

function Dl2_nobots_check() {
    var txt=document.editform.wpTextbox1;
    var rxnobot = new RegExp("\{\{bots *\| *deny=all", "i");
 
    // If there's an existing nobots tag, prompt and return 1

    if (txt.value.search(rxnobot) >= 0)
    {
        alert("Article is flagged to deny all bots");
        return 1;
    }
 
    return 0;
}


 
function Dl2_all_dates_to_dmy(nation, isdebug) {
  Dl2_formatgeneral();
  Dl2_dates_to_dmy(isdebug);
  // Dl2_delink_ISO_to_dmy();
  Dl2_MOSNUM_edit_summary(nation);
}

function Dl2_CommonStyleFix(engtag, countrycode, isdebug)
{
  if (Dl2_nobots_check() == 0)
  {
    if (engtag != "")
    {
      Dl2_EngTag(engtag);
    }
    Dl2_all_dates_to_dmy(countrycode, isdebug);
  }
}

function Dl2_Australianate() {
  Dl2_ADollar();
  Dl2_CommonStyleFix("Australian", "AUS", 0);
}

function Dl2_NewZealandate() {
  Dl2_CommonStyleFix("New Zealand", "NZL", 0);
}

function Dl2_UKanate() {
  Dl2_CommonStyleFix("British", "UK", 0);
}

function Dl2_IntlDate() {
  if (Dl2_nobots_check() == 0)
  {
    Dl2_all_dates_to_dmy("international", 0);
  }
}

function Dl2_Debugged_Intl() {
  Dl2_all_dates_to_dmy("international", 1);
}

function Dl2_AusNZate() {
  Dl2_all_dates_to_dmy("AUS/NZL", 0);
}

function Dl2_IEanate() {
  Dl2_CommonStyleFix("Irish", "IRL", 0);
}

function Dl2_HKanate() {
  Dl2_CommonStyleFix("Hong Kong", "HKG", 0);
}

function Dl2_JAManate() {
  Dl2_CommonStyleFix("Jamaican", "JAM", 0);
}

function Dl2_ZAanate() {
  Dl2_CommonStyleFix("South African", "ZAF", 0);
}
 
function Dl2_Indianate() {
  Dl2_CommonStyleFix("Indian", "IND", 0);
}
 
$(function () {
 if(document.forms.editform) {
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_Australianate()', 'Australianate', 'ca-unitfixer', 'Format for Australia', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_NewZealandate()', 'New Zealandate', 'ca-unitfixer', 'Format for New Zealand', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_AusNZate()', 'AUS/NZ', 'ca-unitfixer', 'Format for Australia/New Zealand', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_UKanate()', 'UKanate', 'ca-unitfixer', 'Format for UK', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_IEanate()', 'Irelandate', 'ca-unitfixer', 'Format for Ireland', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_ZAanate()', 'South Africanate', 'ca-unitfixer', 'Format for South Africa', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_Indianate()', 'Indianate', 'ca-unitfixer', 'Format for India', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_JAManate()', 'Jamaicanate', 'ca-unitfixer', 'Format for Jamaica', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_HKanate()', 'HKandate', 'ca-unitfixer', 'Format for Hong Kong', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_IntlDate()', 'International dates', 'ca-unitfixer', 'International date formatting', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_IntlTag1()', 'Intl tag', 'ca-unitfixer', 'International dmy date tag', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_BDA()', 'BDA', 'ca-unitfixer', 'Standardise infobox birth dates', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_Fdate()', 'FDate', 'ca-unitfixer', 'Standardise infobox film date', '', '');
  mw.util.addPortletLink('p-tb', 'javascript:Dl2_Debugged_Intl()', '(Debug Test)', 'ca-unitfixer', 'Debug test', '', '');

  }
});
// </syntaxhighlight>