User:Mesidast/Tidy citations.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Mesidast/Tidy citations. |
// <nowiki>
// Forked from [[User:Meteor sandwich yum/Tidy citations.js]] by [[User:Meteor sandwich yum]]
// Forked by [[User:Mesidast]]. For full list of changes see [[User:Mesidast/Tidy citations]]
// 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 = / *\| *([a-zA-Z1-9-]+) *= */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(/{{[_\s]*[Cc]it(?:ation|e[A-Za-z_ ]*)[_\s]*\|(?:{{[^}]*}}|[^}])+}}/g) || [];
var newTemplates = oldTemplates.slice();
//var archiveTemplates = txt.match(/{{[_\s]*[Ww]eb(?:\.|[_ ]*)archive[_\s]*\|(?:{{[^}]*}}|[^}])+}}/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
// /{{[_\s]*[Ll]ondon[_ ]*[Gg]azette[_\s]*\| (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[i])) {
newTemplates[i] = newTemplates[i].replace(deprecatedRegex, "|" + deprecatedParams[key] + "=");
hyphenToggle = true;
}
}
}
}
//Remove "|url-status=live" if there is no archive link
if (gTidyCiteRemoveLive && /\|\s*url-?status\s*=\s*live/.test(newTemplates[i])) { //Fix .test
if (!(/\|\s*archive-?url\s*=\s*http/.test(newTemplates[i]))) {
newTemplates[i] = newTemplates[i].replace(/\|\s*url-?status\s*=\s*live/,"");
statusToggle = true;
}
}
// standard, crammed, roomy & custom
if (mode !== "vertical") {
// Remove newlines
newTemplates[i] = newTemplates[i].replace(/\n/g, "");
switch (mode) { // Normalize spaces around the pipes and equal signs
case "standard":
newTemplates[i] = newTemplates[i].replace(paramRegex, " |$1=");
break;
case "crammed":
newTemplates[i] = newTemplates[i].replace(paramRegex, "|$1=");
break;
case "roomy":
newTemplates[i] = newTemplates[i].replace(paramRegex, " | $1 = ");
break;
case "custom":
newTemplates[i] = newTemplates[i].replace(paramRegex, customRegex);
break;
}
// Remove potential extra spaces before template ends
newTemplates[i] = newTemplates[i].replace(/\s*}}$/, "}}");
txt = txt.replace(oldTemplates[i], newTemplates[i]);
// vertical
} else {
// Fill an array with one entry per each parameter for this citation template
var oldParams = oldTemplates[i].match(/ *\n? *\| *\n? *([a-zA-Z1-9-]+) *= */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[j] = oldParams[j].match(/[a-zA-Z1-9-]+/)[0];
// Calculate the length of the longest parameter
maxWidth = (newParams[j].length > maxWidth) ? newParams[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 < oldParams.length; k++) {
var numSpaces = maxWidth - newParams[k].length;
var alignedParam = "\n | " + newParams[k] + new Array(numSpaces).join(" ") + " = ";
// Replace the original parameters with the tweakes ones
newTemplates[i] = newTemplates[i].replace(oldParams[k], alignedParam);
}
// Also align the }}
newTemplates[i] = newTemplates[i].replace(/ *\n? *}}/g, "\n}}");
// Replace the original templates with the tweaked versions
txt = txt.replace(oldTemplates[i], newTemplates[i]);
}
}
// 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[Math.floor(Math.random() * chars.length)];
}
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([subText, commentMatches[i]]);
citeTemplate = citeTemplate.replace(commentMatches[i], 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[key]);
}
}
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 [[User:Mesidast/Tidy citations|a script]]";
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[0].indexOf(hyphenSum) !== -1;
statusToggle = statusToggle || currentSum[0].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][^\/\s]?\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>