User:Frietjes/templatecompare.js

/// Template Compare Tool

/// Once installed, go to Special:TemplateCompare and provide a templates

function getTemplateText(title){

// This function was taken from User:Timotheus Canens/massedit.js

var req = new XMLHttpRequest();

req.open("GET", mw.config.get('wgScriptPath') + "/api.php?action=query&prop=revisions&rvprop=content&format=json&indexpageids=1&titles="+encodeURIComponent(title), false);

req.send();

var response = JSON.parse(req.responseText);

pageid = response.query.pageids[0];

if (pageid == "-1") {

return '';

}

var pagetext = response.query.pages[pageid].revisions[0]['*'];

return pagetext;

}

function expandtemplates(text){

var req = new XMLHttpRequest();

req.open("GET", mw.config.get('wgScriptPath') + "/api.php?action=parse&contentmodel=wikitext&format=json&text="+encodeURIComponent(text),false);

req.send();

var response = JSON.parse(req.responseText);

var pagetext = response.parse.text['*'];

return pagetext;

}

function getparams(mytxt, templatename) {

// This function was taken from User:Frietjes/addcheckforunknownparameters.js

var plist = [];

var mytxt2 = mytxt;

// Remove {PAGENAME}, {BASEPAGENAME}, ...

mytxt = mytxt.replace(/\{\{(?:PAGENAME|BASEPAGENAME|FULLPAGENAME|CURRENTYEAR)\}\}/g, '');

// Remove and

mytxt = mytxt.replace(/<(?:span|nowiki)[ ]*\/>/gi, '');

// Excaped table markup

mytxt = mytxt.replace(/([\r\n])\{(\{\{)(!\}\})/g, '$1$2($3');

mytxt = mytxt.replace(/([\r\n]\{\{!)(\}\})\}[\t ]*([\r\n])/g, '$1)$2$3');

// Replace some braces

mytxt = mytxt.replace(/([^\{])\{([^\{])/g, '$1{$2');

mytxt = mytxt.replace(/([^\}])\}([^\}])/g, '$1}$2');

// Replace some equal signs

mytxt = mytxt.replace(/(<(?:span|div)[^<>]*)=/gi, '$1=');

// Remove newlines and tabs which confuse the regexp search

mytxt = mytxt.replace(/[\s]/gm, ' ');

// Compress whitespace

mytxt = mytxt.replace(/[\s][\s]+/gm, ' ');

// Remove some HTML comments

mytxt = mytxt.replace(//gm, '');

// Remove some includeonly tags

mytxt = mytxt.replace(/<\/?includeonly>/gm, '');

// Remove some noinclude sections

mytxt = mytxt.replace(/(?:[^<>]|<\/?[^n][^<>]*>)*<\/noinclude>/gm, '');

// Compress more whitespace

mytxt = mytxt.replace(/\|[\s]+/g, '|');

mytxt = mytxt.replace(/(\{\{[^\{\}\|]*)[\s]+(\||\}\})/g, '$1$2');

// Add a leading and trailing newline to make pattern matches less complicated

mytxt = '\n' + mytxt + '\n';

// Avoid false matches

mytxt2 = mytxt2.replace(/(\{\{\{[^\{\}\|]*)/g, '$1₳₳');

mytxt2 = mytxt2.replace(/[\s]+₳/g, '₳');

// Now start extracting the parameters

var klist = {}; var loopcount = 0;

while( (mytxt.search(/[^{}]/gm) >= 0) && (loopcount < 15) ) {

var p = mytxt.match(/(\{\{\{[^{}\|]*\|?[^\{\}\|=]*\}\}\})/g);

if( p ) {

for(var j=0; j

p[j] = p[j].replace(/\{\{\{([^{}\|]*)\|?[^\{\}\|=]*\}\}\}/g, '$1');

p[j] = p[j].replace(/^[\s]+/, '');

p[j] = p[j].replace(/[\s]+$/, '');

p[j] = p[j].replace(/([\(\)])/g, '\\$1');

var r = new RegExp("\\{\\{\\{[\\s]*" + p[j].replace(/\?/g, '\\?') + "\\|?[^\\{\\}\\|=]*\\}\\}\\}", 'g');

mytxt= mytxt.replace(r, '');

p[j] = p[j].replace(/\\/g, '');

if( klist[p[j]] === undefined ) {

klist[p[j]] = mytxt2.indexOf('{{{' + p[j] + '₳₳');

plist.push(p[j]);

}

}

// Remove templates, parserfunctions, and other double brace expressions

mytxt = mytxt.replace(/([^\{])\{\{[^{}]*\}\}/gm, '$1');

mytxt = mytxt.replace(/\{\{[^{}]*\}\}([^\}])/gm, '$1');

mytxt = mytxt.replace(/([^\{])\{\{(?:[^{}]|\{\{[^{}]*\}\})*\}\}/gm, '$1');

mytxt = mytxt.replace(/\{\{(?:[^{}]|\{\{[^{}]*\}\})*\}\}([^\}])/gm, '$1');

// Remove file links

mytxt = mytxt.replace(/\[\[(?:File|Image):(?:[^\[\]]|\[\^\[\*)*\]\]/g, '');

}

loopcount++;

}

if( mytxt.search(/[\{\}]/gm) >= 0 ) {

mytxt = mytxt.replace(/([\{\}])/gm, '\n$1');

alert('Did not finish processing '+ templatename + ': ' + mytxt);

}

// Sort

plist.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()) });

// Return as an = delimited string

return plist.join('=');

}

function doTemplateCompare() {

document.getElementById("wpTemplateCompareSubmit").disabled = true;

var templates = document.getElementById("wpTemplateCompareTemplates").value.split("\n");

var showall = document.getElementById("wpTemplateCompareAll").checked;

var mergeparams = document.getElementById("wpTemplateMerge").checked;

if(templates.length > 0) {

if(templates[0].search(/[^\s]/g) < 0) {

templates.shift();

}

}

var params = new Array(templates.length);

var allparams = '';

var i=0; var j=0;

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

templates[i] = templates[i].replace(/[\u200e\s]*\((?:redirect|transclusion)\)[\u200e\s]*\(links[\t ]*\|[\t ]*edit\)[\u200e\s]*$/, '');

alert('Processing ' + templates[i]);

var mytxt = getTemplateText(templates[i]);

var p = getparams(mytxt);

if (i > 0) {

allparams += '=' + p;

} else {

allparams = p;

}

params[i] = p.split('=');

}

// Split into a table

var allparameters = allparams.split('=');

// Sort

allparameters.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()) });

// Remove duplicates

allparameters = allparameters.filter( function( item, index, inputArray ) {

return inputArray.indexOf(item) == index;

});

// Merged parameters

var mparameters = {};

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

var key = allparameters[i];

if (mergeparams) {

key = key.toLowerCase();

key = key.replace(/[_ ]/g, '');

}

if (key in mparameters) {

mparameters[key].push(allparameters[i]);

} else {

mparameters[key] = [allparameters[i]];

}

}

// Report results

document.getElementById("wpTemplateCompareSubmit").value = "Done (" + templates.length + ")";

alert('Found a total of ' + allparameters.length + ' unique parameters.');

var cp = '

class="wikitable sortable"\n
\n! scope=col | Parameter\n';

var cphtml = '

\n\n\n';

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

cp += '! scope=col | ' + templates[i].replace(/^Template:/gi, '') + '\n';

cphtml += '

';

}

for (var key in mparameters) {

var p = mparameters[key].join('
');

var r = '

\n\n';

var hiderow = true;

for (j=0; j

var mpk = mparameters[key];

var hasparam = false;

for (k=0; k

if (params[j].indexOf(String(mpk[k])) >= 0) {

hasparam = true;

}

}

if (hasparam) {

r += '| {{ya}}\n';

rhtml += '

\n'

} else {

r += '| {{na}}\n';

rhtml += '

'

hiderow = false;

}

}

rhtml += '

\n'

if (showall

Parameter ' + templates[i].replace(/^Template:/gi, '') + '
\n! scope=row | ' + p + '\n';

var rhtml = '

' + p + ' Yes No
(hiderow === false)) {

cp += r;

cphtml += rhtml;

}

}

cp += '

';

cphtml += '

';

cp = cphtml + '\n

\n' + cp + '\n
';

document.getElementById("wpTemplateCompareResultsContainer").innerHTML = cp;

}

function templatecompareform() {

var bodyContent = 'bodyContent';

switch (mw.config.get('skin')) {

case 'modern':

bodyContent = 'mw_contentholder';

break;

case 'cologneblue':

bodyContent = 'article';

break;

case 'vector':

case 'monobook':

case 'vector':

default:

bodyContent = 'bodyContent';

break;

}

document.getElementsByTagName("h1")[0].textContent = "Template compare tool";

document.title = "Template compare tool - Wikipedia, the free encyclopedia";

document.getElementById(bodyContent).innerHTML = '

From Wikipedia, the free encyclopedia



'

+ '

'

+ 'If you abuse this tool, it\'s your fault, not mine.'

+ '

'

+ 'Templates to compare (one on each line, with namespace prefix):
'

+ ''

+ ' Show all parameters
'

+ ' Merge similar parameters
'

+ ''

+ '

\n'

+ '

';

}

if(mw.config.get('wgNamespaceNumber') === -1 && (mw.config.get('wgPageName') === "Special:Templatecompare" || mw.config.get('wgPageName') === "Special:TemplateCompare")

) {

$.when( $.ready, mw.loader.using(['mediawiki.util'])).done( templatecompareform );

}