User:Mesidast/Tidy citations.js

Nowadays, User:Mesidast/Tidy citations.js is a widely discussed and debated topic in society. Its relevance has become increasingly evident as the years go by, and its impact has been felt in a variety of areas, from politics to technology, culture and economics. User:Mesidast/Tidy citations.js has captured the attention of experts and the general population, generating growing interest in understanding its implications and seeking solutions to the challenges it presents. In this article, we will explore User:Mesidast/Tidy citations.js in depth, analyzing its impact, implications, and possible avenues to address this issue effectively.
// <nowiki>
// Forked from ] by ]
// Forked by ]. For full list of changes see ]
// Version 2.3.2

// Retrieve and Set Global variables
if (gTidyCiteEditSum == null) var gTidyCiteEditSum = true; //generate a short summary
if (gTidyCiteShowDiff == null) var gTidyCiteShowDiff = true; //show diff after
if (gTidyCiteMarkMinor == null) var gTidyCiteMarkMinor = true; //mark edit as minor
if (gTidyCiteReplaceParams == null) var gTidyCiteReplaceParams = true; //replace deprecated parameters
if (gTidyCiteRemoveLive == null) var gTidyCiteRemoveLive = true; //remove url-status=live on unarchived refs
if (gTidyCiteReplacementParams == null) var gTidyCiteReplacementParams = {}; //initialise empty object if no user values found

mw.loader.using("mediawiki.util", function () {
	// Only run script if user is editing an article
	if (!document.forms.editform || (mw.config.get("wgAction") !== "edit" && mw.config.get("wgAction") !== "submit")) {
		return;
	}

	// Deprecated parameters to replace
	var deprecatedParams = { //gTidyCiteReplacementParams
		"accessdate": "access-date",
		"archiveurl": "archive-url",
		"archivedate": "archive-date",
		"urlstatus": "url-status",
		"urlaccess": "url-access",
		"transcripturl": "transcript-url",
		"authorlink": "author-link"
	};
	// If custom user list exists, append to and supersede the default param replace list
	deprecatedParams = Object.assign(deprecatedParams, gTidyCiteReplacementParams);

	function TidyCitations(mode) {
		// WikEd compatibility
		const useWikEd = window.wikEd && window.wikEd.useWikEd;
		if (useWikEd) {
			window.wikEd.UpdateTextarea();
		}

		// Get and check textbox and summary field
		var textbox = $("#wpTextbox1");
		var summary = $("#wpSummary");
		if (!textbox) {
			mw.notify("Textbox not found | Tidy Citations");
			return false;
		}
		if (!summary) {
			mw.notify("Summary box not found | Tidy Citations");
			return false;
		}
		var txt = textbox.val();
		const original = txt;
		var hyphenToggle = false;
		var statusToggle = false;

		const paramRegex = / *\| *(+) *= */g;
		var customRegex;
		if (mode === "custom") {
			customRegex = prompt("Please enter your custom format, using the following examples: ' |$1=' or '|$1=' or ' | $1 = '");
			console.log(customRegex);
			if ((customRegex.match(/?(\s*\|\s*\$1\s*=\s*)?/g) || ).length !== 1) {
				mw.notify("Invalid custom format entered | Tidy Citations");
				return false;
			}
			customRegex = customRegex.replace(//g, "");
		}

		// Fill an array with one entry per each recognized citation template
		var oldTemplates = txt.match(/{{*it(?:ation|e*)*\|(?:{{*}}|)+}}/g) || ;
		var newTemplates = oldTemplates.slice();
		//var archiveTemplates = txt.match(/{{*eb(?:\.|*)archive*\|(?:{{*}}|)+}}/g) || ; //TODO : Tie in
		//var allReferences = txt.match(/<ref(?:\s+name\s*=.+?)?\s*>.*?<\/ref\s*>|<ref\s+name\s*=.+?\/>/gsi); // Get full text within ref tags
		// /{{*ondon*azette*\|	(London Gazette)

		for (var i = 0; i < oldTemplates.length; i++) {

			// Replace deprecated non-hyphenated parameters
			if (gTidyCiteReplaceParams) {
				for (let key in deprecatedParams) {
					if (deprecatedParams.hasOwnProperty(key)) {
						let deprecatedRegex = new RegExp("\\| *" + key + " *=", "gi");
						if (deprecatedRegex.test(newTemplates)) {
							newTemplates = newTemplates.replace(deprecatedRegex, "|" + deprecatedParams + "=");
							hyphenToggle = true;
						}
					}
				}
			}

			//Remove "|url-status=live" if there is no archive link
			if (gTidyCiteRemoveLive && /\|\s*url-?status\s*=\s*live/.test(newTemplates)) { //Fix .test
				if (!(/\|\s*archive-?url\s*=\s*http/.test(newTemplates))) {
					newTemplates = newTemplates.replace(/\|\s*url-?status\s*=\s*live/,"");
					statusToggle = true;
				}
			}

			// standard, crammed, roomy & custom
			if (mode !== "vertical") {
				// Remove newlines
				newTemplates = newTemplates.replace(/\n/g, "");
				
				switch (mode) { // Normalize spaces around the pipes and equal signs
					case "standard":
						newTemplates = newTemplates.replace(paramRegex, " |$1=");
						break;
					case "crammed":
						newTemplates = newTemplates.replace(paramRegex, "|$1=");
						break;
					case "roomy":
						newTemplates = newTemplates.replace(paramRegex, " | $1 = ");
						break;
					case "custom":
						newTemplates = newTemplates.replace(paramRegex, customRegex);
						break;
				}
				// Remove potential extra spaces before template ends
				newTemplates = newTemplates.replace(/\s*}}$/, "}}");
				txt = txt.replace(oldTemplates, newTemplates);
				// vertical
			} else {
				// Fill an array with one entry per each parameter for this citation template
				var oldParams = oldTemplates.match(/ *\n? *\| *\n? *(+) *= */g);
				var newParams = ;
				var maxWidth = 0;
				for (var j = 0; j < oldParams.length; j++) {
					// Get rid of the delimiters and spaces, keep only the parameter string
					newParams = oldParams.match(/+/);
					// Calculate the length of the longest parameter
					maxWidth = (newParams.length > maxWidth) ? newParams.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 < oldParams.length; k++) {
					var numSpaces = maxWidth - newParams.length;
					var alignedParam = "\n  | " + newParams + new Array(numSpaces).join(" ") + " = ";
					// Replace the original parameters with the tweakes ones
					newTemplates = newTemplates.replace(oldParams, alignedParam);
				}

				// Also align the }}
				newTemplates = newTemplates.replace(/ *\n? *}}/g, "\n}}");
				// Replace the original templates with the tweaked versions
				txt = txt.replace(oldTemplates, newTemplates);
			}
		}
		// Only insert the text if something has changed
		if (txt !== original) {
			textbox.val(txt); //update text
			if (useWikEd) wikEd.UpdateFrame(); //wikEd compatibility
			if (gTidyCiteEditSum) summary.val(EditSummary(summary.val(), hyphenToggle, statusToggle)); //edit summary
			if (gTidyCiteMarkMinor) document.editform.wpMinoredit.checked = true; //mark as minor
			if (gTidyCiteShowDiff) $("#wpDiff").click(); //show changes
		} else {
			mw.notify("No changes made | Tidy Citations");
		}
	}

	// Generate a random alphanumeric ID of set length
	function GetUniqueID(length) {
		const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
		var result = "";
		for (let i = 0; i < length; i++) {
			result += chars;
		}
		return result;
	}

	// Substitute comments with placeholders
	function RemoveComments(citeTemplate) {
		const commentText = ;
		const commentMatches = citeTemplate.match(/<!--.*?-->/gs); //Get all comments
		for (let i = 0; i < commentMatches.length; i++) {
			var subText = GetUniqueID(10);
			while (citeTemplate.indexOf(subText) !== -1) {
				subText = GetUniqueID(10);
			}
			commentText.push(]);
			citeTemplate = citeTemplate.replace(commentMatches, subText);
		}
		return { commentText, citeTemplate };
	}
	// a = RemoveComments("Test")
	// b = a.commentText
	// c = a.newTemplates

	// Restore comments from placeholders
	function RestoreComments(citeTemplate, commentText) {
		for (let key in commentText) {
			if (commentText.hasOwnProperty(key)) {
				citeTemplate = citeTemplate.replace(key, commentText);
			}
		}
		return citeTemplate;
	}

	// Get array of parameters split by "|" and then split by "="
	function SplitParams(citeTemplate) {
		var paramList = citeTemplate
			.split("|")
			.map(element => element.split(/=(.*)/s)
				.map(element => element.trim())
				.filter(element => element !== ""));
		return paramList;
	}

	// Append custom message unto the end of the current edit dummary
	function EditSummary(sum, hyphenToggle, statusToggle) {
		// Define edit summary messages
		const spaceSum = "Standardise citation spacing";
		const hyphenSum = " replace deprecated fields";
		const statusSum = " remove 'url-status=live' from non-archived refs";
		const linkSum = " using ]";
		
		var repeatSummary = sum.indexOf(linkSum) !== -1;
		var currentRegex;
		if (repeatSummary) {
			// Merge toggles from previous edit summary
			currentRegex = new RegExp(spaceSum + ".*?" + linkSum.replace(/(\/\|])/g, "\\$1"), "gs");
			var currentSum = sum.match(currentRegex) || ;
			hyphenToggle = hyphenToggle || currentSum.indexOf(hyphenSum) !== -1;
			statusToggle = statusToggle || currentSum.indexOf(statusSum) !== -1;
		}
		
		// Build edit summary
		var firstAppend = true;
		var appendSum = linkSum;
		if (statusToggle === true) {
			appendSum = " and" + statusSum + appendSum;
			firstAppend = false;
		}
		if (hyphenToggle === true) {
			appendSum = (firstAppend ? " and" : ",") + hyphenSum + appendSum;
			firstAppend = false;
		}
		appendSum = spaceSum + appendSum;
		
		// Merge script summary and existing summary
		if (repeatSummary) {
			// Script re-run
			sum = sum.replace(currentRegex, appendSum);
		} else {
			// First time
			if (/?\s*$/.test(sum)) {
				sum += " | " + appendSum;
			} else {
				sum = appendSum;
			}
		}
		return sum;
	}

	var tidyButton1 = mw.util.addPortletLink("p-tb", "#", "{{Tidy}}", "t-tidyCiteDefault", "Format citations: tidy whitespace");
	var tidyButton2 = mw.util.addPortletLink("p-tb", "#", "{{Tidy}} (Vertical)", "t-tidyCiteVertical", "Formats citations & tidy whitespace (vertically)");
	var tidyButton3 = mw.util.addPortletLink("p-tb", "#", "{{Crammed}}", "t-tidyCiteCrammed", "Formats citations without any whitespace whatsoever");
	var tidyButton4 = mw.util.addPortletLink("p-tb", "#", "{{Roomy}}", "t-tidyCiteRoomy", "Formats citations with a lot of whitespace");
	var tidyButton5 = mw.util.addPortletLink("p-tb", "#", "{{Custom}}", "t-tidyCiteCustom", "Formats citations with custom format");
	$(tidyButton1).click(function () { TidyCitations("standard"); });
	$(tidyButton2).click(function () { TidyCitations("vertical"); });
	$(tidyButton3).click(function () { TidyCitations("crammed"); });
	$(tidyButton4).click(function () { TidyCitations("roomy"); });
	$(tidyButton5).click(function () { TidyCitations("custom"); });

});
// </nowiki>