/// 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 <nowiki /> and <span />
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(/<noinclude>(?:[^<>]|<\/?[^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.length; ++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<!-- UNPROCESSED HERE -->$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 = '<table class="wikitable sortable">\n<tr>\n<th scope=col>Parameter</th>\n';
for(i=0; i< templates.length; i++) {
cp += '! scope=col | [[' + templates[i] + '|' + templates[i].replace(/^Template:/gi, '') + ']]\n';
cphtml += '<th scope=col><a href="/w/index.php?title=' + encodeURIComponent(templates[i])
+ '" title="' + templates[i] + '">' + templates[i].replace(/^Template:/gi, '') + '</a></th>';
}
for (var key in mparameters) {
var p = mparameters[key].join('<br>');
var r = '|-\n! scope=row | ' + p + '\n';
var rhtml = '<tr>\n<th scope=row>' + p + '</th>\n';
var hiderow = true;
for (j=0; j<templates.length; j++) {
var mpk = mparameters[key];
var hasparam = false;
for (k=0; k<mpk.length; k++) {
if (params[j].indexOf(String(mpk[k])) >= 0) {
hasparam = true;
}
}
if (hasparam) {
r += '| {{ya}}\n';
rhtml += '<td data-sort-value="Yes" style="background:#D2FFD2; text-align:center;" class="table-yes2">Yes</td>\n'
} else {
r += '| {{na}}\n';
rhtml += '<td data-sort-value="No" style="background:#FFD2D2; text-align:center;" class="table-no2">No</td>'
hiderow = false;
}
}
rhtml += '</tr>\n'
if (showall || (hiderow === false)) {
cp += r;
cphtml += rhtml;
}
}
cp += '|}';
cphtml += '</table>';
cp = cphtml + '\n<pre>\n' + cp + '\n</pre>';
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 = '<h3 id="siteSub">From Wikipedia, the free encyclopedia</h3><br /><br />'
+ '<form id="wpTemplateCompare" name="wpTemplateCompare">'
+ '<b>If you abuse this tool, it\'s <i>your</i> fault, not mine.</b>'
+ '<p></p>'
+ 'Templates to compare (one on each line, with namespace prefix):<br />'
+ '<textarea tabindex="1" name="wpTemplateCompareTemplates" id="wpTemplateCompareTemplates" rows="3" cols="80"></textarea>'
+ '<input type="checkbox" name="wpTemplateCompareAll" id="wpTemplateCompareAll"> Show all parameters<br>'
+ '<input type="checkbox" name="wpTemplateCompareMerge" id="wpTemplateMerge"> Merge similar parameters<br>'
+ '<input type="button" id="wpTemplateCompareSubmit" name="wpTemplateCompareSubmit" value="Compare" onclick="doTemplateCompare()" />'
+ '</form>\n'
+ '<div id="wpTemplateCompareResultsContainer"></div>';
}
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 );
}