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.
// local copy of [[User:Meteor sandwich yum/Tidy citations.js]]
//   which as per [[User:Meteor sandwich yum/Tidy citations]]
//   is a modified version of [[User:Waldir/formatcitations.js]]
// 2015-12-26: handle parameter names containing hyphen (access-date) or underscore (doi_brokendate)

if (autosummary == null) var autosummary = true; //generate a short summary
if (showdiff == null) var showdiff = false; //show diff after pressing button
if (markminor == null) var markminor = true; //mark as minor

function tidy(str) {
    var txt = document.editform.wpTextbox1;
    
    // Fill an array with one entry per each recognized citation template
    var originalTemplates = txt.value.match(/\{\{[Cc]it(ation|e [A-Za-z ]+) *\n? *\|[^}]+\}\}/g);
    // Duplicate the array, for editing. We need to keep the original strings for the replacement step
    var tweakedTemplates  = originalTemplates.slice();
	
    for(var i = 0; i < originalTemplates.length; i++) {
		
		// Fill an array with one entry per each parameter for this citation template
        var originalParams = originalTemplates[i].match(/ *\n? *\| *\n? *([a-zA-Z1-9-_]+|[a-zA-Z1-9-_]+ [a-zA-Z1-9-_]+) *= */g);
        // Create array to be filled with the cleaned-up parameters.
        // We need to keep the original strings for the replacement step.
        var tweakedParams = [];
		
		if(str == "horizontal" || str == "crammed" || str == "roomy") {
            // Remove newlines
            tweakedTemplates[i] = tweakedTemplates[i].replace(/\n/g, "");
            // Normalize spaces around the pipes and equal signs
			switch(str) {
				case "horizontal":
					tweakedTemplates[i] = tweakedTemplates[i].replace(/ *\| *([a-zA-Z1-9-_]+|[a-zA-Z1-9-_]+ [a-zA-Z1-9-_]+) *= */g," |$1=");
					break;
				case "crammed":
            		tweakedTemplates[i] = tweakedTemplates[i].replace(/ *\| *([a-zA-Z1-9-_]+) *= */g,"|$1=");
            		break;
            	case "roomy":
            		tweakedTemplates[i] = tweakedTemplates[i].replace(/ *\| *([a-zA-Z1-9-_]+) *= */g," | $1 = ");
            		break;
            }
            // Remove potential extra spaces before template ends
            tweakedTemplates[i] = tweakedTemplates[i].replace(/ *\}\}$/,"}}");
            txt.value = txt.value.replace(originalTemplates[i], tweakedTemplates[i]);                                      
        }
        else if (str == "vertical") {
			
            var maxWidth = 0;
            for(var j = 0; j < originalParams.length; j++) {
                // Get rid of the delimiters and spaces, keep only the parameter string
                tweakedParams[j] = originalParams[j].match(/[a-zA-Z1-9-_]+/)[0];
                // Calculate the length of the longest parameter
                maxWidth = (tweakedParams[j].length>maxWidth) ? tweakedParams[j].length : maxWidth;
            }
            maxWidth++; // We need an extra one because Array(n).join(' ') will produce a string with n-1 chars
			
            // Generate the aligned versions of the parameters (with padding before the equal signs)
            for(var k = 0; k < originalParams.length; k++) {
                var numSpaces = maxWidth - tweakedParams[k].length;
                var alignedParam = "\n  | " + tweakedParams[k] + new Array(numSpaces).join(" ") + " = ";
                // Replace the original parameters with the tweakes ones
                tweakedTemplates[i] = tweakedTemplates[i].replace (originalParams[k], alignedParam);
       		}
			
            // Also align the }}
            tweakedTemplates[i] = tweakedTemplates[i].replace(/ *\n? *\}\}/g,"\n}}"); 
            // Replace the original templates with the tweaked versions
            txt.value = txt.value.replace(originalTemplates[i], tweakedTemplates[i]); 
        }
	
    if(autosummary) edit_summary();
    if(showdiff) 	diff();
    if(markminor)   document.editform.wpMinoredit.checked = true;
    
    }
}

function edit_summary() {
	var sum = document.editform.wpSummary;
	var summary = "Harmonize whitespace in citation templates";
	summary += " (using [[User:Meteor sandwich yum/Tidy citations.js|a script]])";
	if (sum.value.indexOf(summary) == -1) {
    	if (sum.value.match(/[^\*\/\s][^\/\s]?\s*$/)) {
            	sum.value += " | ";
    	}
    			sum.value += summary;
	}	
}

function diff() {
	document.editform.wpDiff.click();
}

$(function () {
    if(document.forms.editform) {
        mw.util.addPortletLink('p-tb', 'javascript:tidy("horizontal")', '\{\{Tidy\}\}', 'ca-formatcitations', 'Format citations: tidy whitespace');
        mw.util.addPortletLink('p-tb', 'javascript:tidy("vertical")', '\{\{Tidy\}\} (vertically)', 'ca-formatcitations-vertical', 'Formats citations & tidy whitespace (vertically)');
        mw.util.addPortletLink('p-tb', 'javascript:tidy("crammed")', '\{\{Crammed\}\}', 'ca-formatcitations-crammed', 'Formats citations without any whitespace whatsoever');
        mw.util.addPortletLink('p-tb', 'javascript:tidy("roomy")', '\{\{Roomy\}\}', 'ca-formatcitations-roomy', 'Formats citations with a lot of whitespace');
    }
});
//for dummy edits add more or less to end of this line