User:Frietjes/findargdups.js

jQuery(document).ready(function($) {var myContent = document.getElementsByName('wpTextbox1')[0];// -------------------------------------------------------------------------------- //var mysummary = "Clean up [[:Category:Pages using duplicate arguments in template calls|duplicate template arguments]] using [[:en:User:Frietjes/findargdups|findargdups]]";if(typeof findargdupseditsummary == 'string') {mysummary = findargdupseditsummary;}var morefound = "More duplicates found, fix some and run again!";if(typeof findargdupsmorefound == 'string') {morefound = findargdupsmorefound;}var linktext = "Find dups";if(typeof findargdupslinktext == 'string') {linktext = findargdupslinktext;}var showresultsbox = 0;if(typeof findargdupsresultsbox == 'string') { showresultsbox = 1;}var showalertbox = 1;if(typeof findargdupsnoalertbox == 'string') { showalertbox = 0; showresultsbox = 1;}var nonefound = 'No duplicates were found!';if(typeof findargdupsnonefound == 'string') { nonefound = findargdupsnonefound;}// -------------------------------------------------------------------------------- //if(mw.config.get('wgNamespaceNumber') != -1 && myContent) {mw.loader.using(['mediawiki.util']).done( function() {  var portletlink = mw.util.addPortletLink('p-tb', '#', linktext, 't-fdup');  $(portletlink).click(function(e) {    e.preventDefault();    wpFindDuplicateArgs(0);  });});}// -------------------------------------------------------------------------------- //function wpAddResultsBox(text, num){var div = document.getElementById('wpSummaryLabel').parentNode;if( div ) {if( num < 2 ) {if( document.getElementById('FindArgDupsResultsBox') ) {document.getElementById('FindArgDupsResultsBox').innerHTML = '';} else {div.innerHTML = '<div id="FindArgDupsResultsBox"></div>' + div.innerHTML;}}div1 = document.getElementById('FindArgDupsResultsBox');if( div1 ) {text = text.replace(/</g, '&lt;');text = text.replace(/>/g, '&gt;');div1.innerHTML = div1.innerHTML + '<div class="FindArgDupsResultsBox" ' +  'id="FindArgDupsResultsBox-' + num + '" ' +  'style="max-height:5em; overflow:auto; padding:5px; border:#aaa 1px solid; ' +  'background-color:cornsilk;">' + text + '</div>' + "\n";}}}function wpClearResultsBox(){var div = document.getElementById('wpSummaryLabel').parentNode;if( div ) {if( document.getElementById('FindArgDupsResultsBox') ) {document.getElementById('FindArgDupsResultsBox').innerHTML = '';}}}// -------------------------------------------------------------------------------- //function wpFindDuplicateArgs(debugflag){  // Flag used to determine if we have issued an alert popup  var alertissued=0;  // Flag used to determine if we've selected one of the problem templates yet  var selectedone=false;  // 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 = [];   // Regular expression which matchs a template arg  var argexp = new RegExp("\\|[\\s]*([^\\s=\\|\\[\\]\\{\\}][^=\\|\\[\\]\\{\\}]*[^\\s=\\|\\[\\]\\{\\}]|[^\\s=\\|\\[\\]\\{\\}]|)[\\s]*=", "gm");    // Copy the contents of the text window so we can modify it without problems  var mytxt = myContent.value;  // Remove some includeonly, noinclude, and onlyinclude tags  mytxt = mytxt.replace(/<\/?[ ]*(?:includeonly|noinclude|onlyinclude)[ ]*>/gi, '');  // Remove PAGENAME, BASEPAGENAME, ... nested inside of triple braces  mytxt = mytxt.replace(/\{\{\{[^\{\}]*\|[ ]*\{\{[A-Z]+\}\}\}\}\}/g, '');  // Mangle some ref tags  mytxt = mytxt.replace(/(<ref[^<>=]*name[ ]*)=/gi, '$1&#61;');  mytxt = mytxt.replace(/(<ref[^<>=]*group[ ]*)=/gi, '$1&#61;');  // Mangle some math tags  loopcount = 0;  while((mytxt.search(/<[\s]*math[^<>]*>[^<>=]*=/gi) >= 0) && (loopcount < 10)) {  mytxt = mytxt.replace(/(<[\s]*math[^<>]*>[^<>=]*)=/gi, '$1&#61;');  loopcount++;  }  // Remove some triple braces and parserfunctions inside of triple braces  loopcount = 0;   while((mytxt.search(/\{\{\{[^\{\}]*\}\}\}/g) >= 0) && (loopcount < 5) ) {    mytxt = mytxt.replace(/\{\{\{[^\{\}]*\}\}\}/g, '');    mytxt = mytxt.replace(/\{\{#[a-z]+:[^{}=]*\}\}/gi, '');    loopcount++;  }  // Replace some bare braces with HTML equivalent  mytxt = mytxt.replace(/([^\{])\{([^\{])/g, '$1&#123;$2');  mytxt = mytxt.replace(/([^\}])\}([^\}])/g, '$1&#125;$2');  // Remove newlines and tabs which confuse the regexp search  mytxt = mytxt.replace(/[\s]/gm, ' ');  // Compress whitespace  mytxt = mytxt.replace(/[\s][\s]+/gm, ' ');  // Remove some nowiki and pre text  mytxt = mytxt.replace(/<nowiki[^<>]*>(?:<[^\/]|[^<])*<\/nowiki[^<>]*>/gi, '');  mytxt = mytxt.replace(/<pre[^<>]*>(?:<[^\/]|[^<])*<\/pre[^<>]*>/gi, '');  // Remove some HTML comments  mytxt = mytxt.replace(/<!--(?:[^>]|[^\-]>|[^\-]->)*-->/gm, '');  // Modify some = inside of file/image/wikilinks which cause false positives  loopcount = 0;  while((mytxt.search(/\[\[[^\[\]\{\}]*=/gi) >= 0) && (loopcount < 5) ) {    mytxt = mytxt.replace(/(\[\[[^\[\]\{\}]*)=/gi, '$1&#61;');    loopcount++;  }  // 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] = '';      }    }    // Join the chunks back together for the next iteration    mytxt = strlist.join('');    loopcount++;  }    // Preprocess some = signs inside of non-citation-templated citations  for(i=0; i < tlist.length; ++i) {  j=0;  while( (tlist[i].search(/<ref[^<>\/]*>(?:<[^\/]|[^<])*=/gi) >= 0)   && (j < 50) ) {  tlist[i] = tlist[i].replace(/(<ref[^<>\/]*>(?:<[^\/]|[^<])*)=/gi, '$1&#61;');}  }  // Now find duplicates in the list of unnested templates  for(i=0; i < tlist.length; ++i) {    // Add numbers for unnamed parameters    var unp=0;    tlist[i] = tlist[i].replace(/(\{\{[\s_]*#invoke[\s ]*:[^{}\|]*)\|([^{}\|=]*\|)/gi, '$1|0=$2');    while((tlist[i].search(/(\{\{(?:[^{}\[\]]|\[\[[^\[\]]*\]\])*?\|)((?:[^{}\[\]=\|]|\[[^\[\]=]*\]|\[\[[^\[\]]*\]\])*(?:\||\}\}))/) >= 0)          && (unp < 25)) {      unp++;      tlist[i] = tlist[i].replace(/(\{\{(?:[^{}\[\]]|\[\[[^\[\]]*\]\])*?\|)((?:[^{}\[\]=\|]|\[[^\[\]=]*\]|\[\[[^\[\]]*\]\])*(?:\||\}\}))/, '$1' + unp + '=$2');    }    // Array to hold any found duplicate args (reduce number of alerts)    var f = [];    // Split the template into an array of | arg = ... strings    var p = tlist[i].match(argexp);    if( p ) {      for(j=0; j < p.length; ++j) {        p[j] = p[j].replace(argexp, '$1');      }      p = p.sort();      for(j=0; j < p.length - 1; ++j) {        if( p[j] == p[j+1]) {          f.push(p[j]);        }      }    }    if(f.length > 0) {      alertissued = alertissued + 1;      if(alertissued < 5) {      if(!selectedone) {      var selectmatch = myContent.value.match(tlist[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\s+/g, '\\s*'));      if(selectmatch !== null) {      myContent.setSelectionRange(selectmatch.index, selectmatch.index + selectmatch[0].length);      selectedone = true;      }      }        if(showresultsbox > 0) {        wpAddResultsBox('Duplicate \"' + f.join('\", \"') + '\" in\n' + tlist[i], alertissued);        }        if(showalertbox > 0) {        alert('\"' + f.join('\", \"') + '\" in\n' + tlist[i]);        }      } else if(alertissued == 6) {      alert(morefound);      }    }  }  if (alertissued) {    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;        }      }    }  if(selectedone) {  setTimeout(function() {myContent.focus();}, 0);  }  } else if(nonefound.trim().length > 0) {mw.notify(nonefound);  } else {  if(showresultsbox > 0) { wpClearResultsBox(); }  }}// -------------------------------------------------------------------------------- //});