User:Sanmosa/findargdups.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
jQuery(document).ready(function($) {
var myContent = document.getElementsByName('wpTextbox1')[0];
// -------------------------------------------------------------------------------- //
var mysummary = "經[[User:Sanmosa/findargdups|檢查調用重複模板參數工具]]清理[[:Category:调用重复模板参数的页面|調用重複模板參數的頁面]]";
if(typeof findargdupseditsummary == 'string') {mysummary = findargdupseditsummary;}
var morefound = "發現更多重複調用的模板參數。請修正相關參數,然後重新運行此工具。";
if(typeof findargdupsmorefound == 'string') {morefound = findargdupsmorefound;}
var linktext = "尋找重複調用的模板參數";
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;}
// -------------------------------------------------------------------------------- //
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, '<');
text = text.replace(/>/g, '>');
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=');
mytxt = mytxt.replace(/(<ref[^<>=]*group[ ]*)=/gi, '$1=');
// Mangle some math tags
loopcount = 0;
while((mytxt.search(/<[\s]*math[^<>]*>[^<>=]*=/gi) >= 0) && (loopcount < 10)) {
mytxt = mytxt.replace(/(<[\s]*math[^<>]*>[^<>=]*)=/gi, '$1=');
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{$2');
mytxt = mytxt.replace(/([^\}])\}([^\}])/g, '$1}$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=');
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=');
}
}
// 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(showresultsbox > 0) { wpClearResultsBox(); }
}
}
// -------------------------------------------------------------------------------- //
});