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 code will be executed when previewing this page.
Documentation for this user script can be added at User:Frietjes/indent.
jQuery(document).ready(function($) {
var myContent = document.getElementsByName('wpTextbox1')[0];
// -------------------------------------------------------------------------------- //
//var mysummary = "Indent templates using [[:en:User:Frietjes/indent.js|indent]]";
var mysummary = "";
//var mysmallsummary = "Indent templates and remove small tags per [[MOS:SMALL]] using [[:en:User:Frietjes/indent.js|indent]]";
var mysmallsummary = "Remove small tags per [[MOS:SMALL]]";
// List of labels that should not be indented
var long_labels = [
"construction_start_date",
"construction_stop_date",
"[a-z]+cup[0-9][\\t ]*qualifiers?",
"resting[_ ]*place[\\t _]*coordinates",
"conventional[\\t _]*long_name",
"population_density[\\t _]*[a-z]+[0-9]*_[a-z0-9]+",
"pushpin_label_position"
];
if(typeof indenteditsummary == 'string') {mysummary = indenteditsummary;}
var linktext = "Indent";
// -------------------------------------------------------------------------------- //
if(mw.config.get('wgNamespaceNumber') != -1 && myContent && (mw.config.get('wgUserName') == 'MB' || mw.config.get('wgUserName') == 'Hhkohh' || mw.config.get('wgUserName') == 'Frietjes')) {
mw.loader.using(['mediawiki.util']).done( function() {
var portletlink = mw.util.addPortletLink('p-tb', '#', linktext, 't-fdup');
$(portletlink).click(function(e) {
e.preventDefault();
wpIndentTemplates(0);
});
});
}
// -------------------------------------------------------------------------------- //
function wpIndent(s)
{
var alignflag = 0;
// Mangle file/image link
while(s.search(/(\[\[[\t _]*(?:image|file)[\t _]*:[^\[\]=]*)=/gi) >=0 ) {
s = s.replace(/(\[\[[\t _]*(?:image|file)[\t _]*:[^\[\]=]*)=/gi, '$1<!-- FIX EQ MARKER -->');
}
// Mangle html tags
while(s.search(/(<[\t \r\n]*[a-z]+[^<>]*)=/gi) >=0 ) {
s = s.replace(/(<[\t \r\n]*[a-z]+[^<>]*)=/gi, '$1<!-- FIX EQ MARKER -->');
}
// Election box
s = s.replace(/(\{\{[_ ]*[Ee]lection[_ ]*box[^{}\|\r\n]*[a-z])[\t ]*\|[\t ]*([\r\n][\t ]*\|)/g, '$1$2');
// Mark some spacing
s = s.replace(/(= ) (\|)/g, '$1<!-- SPACE MARKER -->$2');
// Some fixes for the case where infoboxes have the pipes at the end of the line
var old = '';
while(s != old) {
old = s;
s = s.replace(/(\{\{[_\t\r\n ]*(?:[Ii]nfobox|[Ss]peciesbox|[Ff]ootball[_ ]*box)(?:\{\{(?:\{\{(?:\{\{[^{}]*\}\}|[^{}])*\}\}|[^{}])*\}\}|[^{}])*)(\|)[\t ]*([\r\n])/gim, '$1$3$2');
}
s = s.replace(/(\{\{[_\t\r\n ]*(?:[Ii]nfobox|[Ss]peciesbox|[Ff]ootball[_ ]*box)(?:\{\{(?:\{\{(?:\{\{[^{}]*\}\}|[^{}])*\}\}|[^{}])*\}\}|[^{}])*)[\t\r\n ]*\|[\t ]*([\r\n][\t ]*\}\})/gi, '$1$2');
s = s.replace(/(\{\{[_\t\r\n ]*(?:[Ii]nfobox|[Ss]peciesbox|[Ff]ootball[_ ]*box)(?:\{\{(?:\{\{(?:\{\{[^{}]*\}\}|[^{}])*\}\}|[^{}])*\}\}|[^{}])*[\r\n])[\t\r\n ]*\|[\t ]*(\}\})/gi, '$1$2');
// Space before end of line
while(s.search(/([^=])[\t ]+[\r\n]/g) >= 0) {
s = s.replace(/([^=])[\t ]+([\r\n])/g, '$1$2');
}
// Unroll infobox
if(s.search(/\{\{[_\t\r\n ]*(?:[Ii]nfobox|[Ss]peciesbox|[Ff]ootball[_ ]*box)/g) >=0 ) {
s = s.replace(/([^\t \r\n])([\t ]*\|[\t ]*[^=\|\[\]\{\]\t ][^=\|\[\]\{\]]*=)/g, '$1\n$2');
s = s.replace(/(=)([\t ]*\|[\t ]*[^=\|\[\]\{\]\t ][^=\|\[\]\{\]]*=)/g, '$1\n$2');
s = s.replace(/([^\t \r\n])[\t \r\n]*(\}\})/g, '$1\n$2'); // put trailing braces on a newline
}
// Add some markers
s = s.replace(/(\|[ ]*(?:[a-z_ ]+)[\t ]*=[^\r\n]*(?:[\r\n][\t ]*♦§[0-9][0-9]*§♦[\t ]*|)*)[\r\n]([\t ]*\|[\t ]*(?:pattern|left|right|body|shorts|socks))/g, '$1<!-- UNGAP MARKER -->\n\n$2');
s = s.replace(/(\|[ ]*(?:league|cup[0-9]+)(?:[ ]*result|)[\t ]*=[^\r\n]*(?:[\r\n][\t ]*♦§[0-9]+§♦[\t ]*|))[\r\n]([\t ]*\|[ ]*(?:[a-z]+ attendance|[a-z]+ topscorer|league scorer))/g, '$1<!-- UNGAP MARKER -->\n\n$2');
s = s.replace(/[\r\n]([\t ]*\|[ ]*prevseason[ ]*=)/g, '<!-- UNGAP MARKER -->\n\n$1');
s = s.replace(/[\t ]*[\r\n][\t ]*([\r\n][\t ]*\|[\t ]*[A-Za-z0-9_\-\t ]*=)/g, '\n<!--\n GAP MARKER\n -->$1');
s = s.replace(/[\r\n][\t ]*[\r\n]/g, '\n<!-- GAP MARKER -->\n');
// Labels that should not be indented
for(var i=0; i < long_labels.length; i++) {
var re = new RegExp('(\\|[\\t ]*)(' + long_labels[i] + ')[\\t ]*=[\\t ]*', 'g');
s = s.replace(re, '$1_FIX_ = <!-- _THIS_LONG_LABEL_ $2 -->');
}
// uniform pre-pipe indentation
var c0 = s.split(/[\r\n]\|/g).length;
var c1 = s.split(/[\r\n][\t ]\|/g).length;
var c2 = s.split(/[\r\n][\t ][\t ][\t ]*\|/g).length;
if (c0 >= c1 && c0 >= c2) {
s = s.replace(/([\r\n])[\s]*(\|)/g, '$1$2');
} else if (c1 >= c0 && c1 >= c2 ) {
s = s.replace(/([\r\n])[\s]*(\|)/g, '$1 $2');
} else {
s = s.replace(/([\r\n])[\s]*(\|)/g, '$1 $2');
}
// uniform post-pipe indentation
c0 = s.split(/[\r\n][\t ]*\|[^=\|\[\]\{\]\t ]/g).length;
c1 = s.split(/[\r\n][\t ]*\|[\t ][\t ]*[^=\|\[\]\{\]\t ]/g).length;
if (c1 >= c0) {
s = s.replace(/([\r\n][\t ]*\|)[\t ]*([^=\|\[\]\{\]\t ])/g, '$1 $2');
} else {
s = s.replace(/([\r\n][\t ]*\|)[\t ]*([^=\|\[\]\{\]\t ])/g, '$1$2');
}
// flip space and =
s = s.replace(/(\|[^=\|\[\]\{\]\t ][\t ]*)(=)([\t ][\t ][\t ]*)/g, '$1$3$2');
var two_or_more_space_before_equal_count = s.split(/[^=\|\[\]\{\}][\s][\s][\s]*=/g).length - 1;
if (two_or_more_space_before_equal_count > 1) {
// Unalign
s = s.replace(/[\s]*\|[\s]*[\r\n]([\s]*[^=\|\[\]\{\]]*?=)[\t ]*/g, '\n|$1 ');
s = s.replace(/(\|[\s ]*[^=\|\[\]\{\]]*?)[\s]*=[\t ]*/g, '$1 = ');
s = s.replace(/[\r\n]([\s]*[^\s\|])/g, '<!-- ♦§NEWLINE§♦ -->$1');
s = s.replace(/<!--[\s]*<!-- ♦§NEWLINE§♦ -->[\s]*GAP MARKER[\s]*<!-- ♦§NEWLINE§♦ -->[\s]*-->/g, '<!--\n GAP MARKER\n -->');
// Realign
for(var i=40; i>1; i--) {
var r1 = new RegExp('([\\r\\n][\\s]*\\|[^=\\|\\[\\]\\{\\}]{'+(i)+'}=[^\\r\\n]*[\\r\\n][\\s]*\\|[^=\\|\\[\\]\\{\\}]{0,'+(i-1)+'})(=)','g');
while( s.search(r1) > -1) {
s = s.replace(r1, '$1 $2');
}
var r2 = new RegExp('([\\r\\n][\\s]*\\|[^=\\|\\[\\]\\{\\}]{0,'+(i-1)+'})(=[^\\r\\n]*[\\r\\n][\\s]*\\|[^=\\|\\[\\]\\{\\}]{'+(i)+'}=)','g');
while( s.search(r2) > -1) {
s = s.replace(r2, '$1 $2');
}
}
} else if (two_or_more_space_before_equal_count > 0) {
s = s.replace(/([^=\|\[\]\{\}][\s])[\s][\s]*(=)/g, '$1$2');
}
s = s.replace(/<!-- ♦§NEWLINE§♦ -->/g, '\n');
s = s.replace(/<!-- FIX EQ MARKER -->/g, '=');
s = s.replace(/<!-- SPACE MARKER -->/g, ' ');
s = s.replace(/<!--[\s]*GAP MARKER[\s]*-->/g, '');
s = s.replace(/<!--[\s]*UNGAP MARKER[\s]*-->[\t ]*[\r\n][\t ]*[\r\n]*([\s]*)/g, '\n$1');
s = s.replace(/_FIX_[\t ]*=[\t ]*<!--[\t ]* _THIS_LONG_LABEL_ [\t ]*([^<>]*?)[\t ]*-->[\t ]*/g, '$1 = ');
s = s.replace(/([^\|\{\t ])[\t ]*(\|)[\t ]*([\r\n])([^\*:;\{\|])/g, '$1$3$2$4');
s = s.replace(/(\{\{cite[^{}\r\n]*)[\t ][\t ]+([^{}\r\n]*\}\})/g, '$1 $2');
return s;
}
// -------------------------------------------------------------------------------- //
function wpUnsmall(s)
{
var strlist = s.split(/(\{\{[\t \r\n]*(?:[Ii]nfobox|[Ff]ootball[_ ]*box)(?:[^{}]|\{\{(?:(?:[^{}]|\{\{(?:[^{}]|\{\{(?:[^{}]|\{\{[^{}]*\}\})*\}\})*\}\})*|\{\{[^{}]*\}\})*\}\})*\}\})/);
for (i = 0; i < strlist.length; i++) {
s = strlist[i];
if(s.search(/\{\{[_\t\r\n ]*(?:[Ii]nfobox|[Ff]ootball[_ ]*box)/g) >=0 ) {
var stmp = '';
while( stmp != s ) {
stmp = s;
s = s.replace(/(\|[ ]*name[ ]*=[^\[\]\|\{\}]*sm)(all)/gi, '$1<!--MARKER DO NOT FIX MARKER-->$2');
}
s = s.replace(/<[\t ]*\/?[\t ]*small[^<>]*>/gi, '');
s = s.replace(/\{\{small(?:er|)[\t ]*\|[\t ]*1[\t ]*=[\t ]*((?:[^{}]|\{\{(?:(?:[^{}]|\{\{(?:[^{}]|\{\{(?:[^{}]|\{\{[^{}]*\}\})*\}\})*\}\})*|\{\{[^{}]*\}\})*\}\})*?)[\t ]*\}\}/gi, '$1');
s = s.replace(/\{\{small(?:er|)[\t ]*\|((?:[^{}]|\{\{(?:(?:[^{}]|\{\{(?:[^{}]|\{\{[^{}]*\}\})*\}\})*|\{\{[^{}]*\}\})*\}\})*)\}\}/gi, '$1');
s = s.replace(/<!--[ ]*MARKER DO NOT FIX MARKER[ ]*-->/g, '');
strlist[i] = s;
}
}
return strlist.join('');
}
// -------------------------------------------------------------------------------- //
function wpIndentTemplates(debugflag)
{
// Regular expression which matchs a template arg
var argexp = new RegExp("(\\|[\\s]*[^=\\|\\[\\]\\{\\}]*=[\\s]*)", "gm");
// Internal for and while loop variables
var i=0; var j=0; var loopcount=0;
// Array used to hold the list of unnested templates
var tlist = [];
// Copy the contents of the text window so we can modify it without problems
var mytxt = myContent.value;
// Mark dollar signs which are problematic for regexp
mytxt = mytxt.replace(/\$/g, '♦§DOLLAR§♦');
// Remove comments
loopcount = 0;
while( (mytxt.search(/<!--.*?-->/g) >= 0) && (loopcount < 20) ) {
// Split into chunks, isolating the comments
var strlist = mytxt.split(/(<!--.*?-->)/);
// Loop through the chunks, removing the comments templates
for (i = 0; i < strlist.length; i++) {
if( strlist[i].search(/^<!--.*?-->$/) >= 0 ) {
tlist.push(strlist[i]);
strlist[i] = '♦§' + (tlist.length - 1) + '§♦';
}
}
// Join the chunks back together for the next iteration
mytxt = strlist.join('');
loopcount++;
}
var istart = tlist.length;
// Now start unnesting the templates
loopcount = 0;
while( (mytxt.search(/(?:\{\{|\}\})/g) >= 0) && (loopcount < 20) ) {
// Split into chunks, isolating the unnested templates
var strlist = mytxt.split(/(\{\{[^\{\}]*\}\})/);
// Loop through the chunks, removing the unnested templates
for (i = 0; i < strlist.length; i++) {
if( strlist[i].search(/^\{\{[^\{\}]*\}\}$/) >= 0 ) {
tlist.push(strlist[i]);
strlist[i] = '♦§' + (tlist.length - 1) + '§♦';
}
}
// Join the chunks back together for the next iteration
mytxt = strlist.join('');
loopcount++;
}
// Now start indenting the list of unnested templates
for(i=istart; i < tlist.length; ++i) {
tlist[i] = wpIndent(tlist[i]);
}
// Reassemble the article
while(mytxt.search(/♦§[0-9][0-9]*§♦/g) >= 0) {
var n = mytxt.match(/♦§[0-9][0-9]*§♦/)[0].replace(/♦§([0-9]*)§♦/, '$1');
mytxt = mytxt.replace(new RegExp('♦§' + n + '§♦', 'g'), tlist[Number(n)]);
}
mytxt = mytxt.replace(/[\t ]*[\r\n]*[\t ]*[\r\n][\t ]*(\{\{)[\t ]*((?:[Ii]nfobox|[Ss]peciesbox))/g, '\n$1$2');
mytxt = mytxt.replace(/(\{\{[^{}=\|\r\n]*)([\r\n])(\|)[\t ]*(\{\{)/g, '$1$3$2$4');
// Unmark dollar signs which are problematic for regexp
mytxt = mytxt.replace(/♦§DOLLAR§♦/g, '\$');
// Remove small tags (if opt-in)
if(typeof removesmalltags == 'string' && removesmalltags == 'yes') {
var oldtxt = mytxt;
mytxt = wpUnsmall(mytxt);
if (oldtxt != mytxt) {
mysummary = mysmallsummary;
}
}
myContent.value = mytxt;
var editsummary = document.getElementsByName('wpSummary')[0];
if(typeof editsummary == 'object') {
if (editsummary.value.indexOf(mysummary) == -1) {
if (editsummary.value.match(/[^\*\/\s][^\/\s]?\s*$/)) {
editsummary.value += '; ' + mysummary;
} else {
editsummary.value += mysummary;
}
}
}
}
// -------------------------------------------------------------------------------- //
});