MediaWiki:Gadget-ToolsRedirect.js

参阅Help:绕过浏览器缓存以获取更多帮助。

// <nowiki>'use strict';(function ($) {var nsNumber = mw.config.get('wgNamespaceNumber'),origPageName = mw.config.get('wgPageName'),scriptPath = mw.config.get('wgScriptPath');var SUFFIX_APPEND = 0,SUFFIX_REPLACE = 1,SUFFIX_SETDEFAULT = 2,isCategory = nsNumber === 14;if (nsNumber === -1) {var chainNoop = function () { return this; };var noop = function () {};mw.toolsRedirect = {SUFFIX_APPEND,SUFFIX_REPLACE,SUFFIX_SETDEFAULT,findRedirectCallback: chainNoop,findRedirectBySelector: chainNoop,setRedirectTextSuffix: noop};return;}var _TR,_findRedirectCallbacks = [],_pageWithRedirectTextSuffix = {},_redirectExcludes = {};var _nsCanonPrefix = origPageName.split(':')[0] + ':',_nsPrefixPattern = $.map(mw.config.get('wgNamespaceIds'), function (nsid, text) {return nsid === nsNumber ? text : null;}).join('|');_nsPrefixPattern = new RegExp('^(' + _nsPrefixPattern + '):', 'i');if (nsNumber === 0) {// articles_nsCanonPrefix = '';_nsPrefixPattern = /^/;}function fixNamespace(title) {if (nsNumber === 0) {// do nothing if it's articlesreturn title;} else if (_nsPrefixPattern.test(title)) {// canonize the namespacereturn title.replace(_nsPrefixPattern, _nsCanonPrefix);} else {// don't have a namespacereturn _nsCanonPrefix + title;}}mw.toolsRedirect = {SUFFIX_APPEND: SUFFIX_APPEND,SUFFIX_REPLACE: SUFFIX_REPLACE,SUFFIX_SETDEFAULT: SUFFIX_SETDEFAULT,findRedirectCallback: function (callback) {/* Add new custom callback for finding new * potential redirect titles. * * @param {function} callback( pagename, $content, titles ) -> title list */if (arguments.length === 1) {_findRedirectCallbacks.push(callback);} else {$.merge(_findRedirectCallbacks, arguments);}return this;},findRedirectBySelector: function (selector) {/* A shortcut to add CSS selectors as rule to find new potential * redirect titles. * * @param {string} selector */_findRedirectCallbacks.push(function () {return $(selector).map(function () {var title = $(this).text();return title || null;});});return this;},setRedirectTextSuffix: function (title, suffix, flag) {var flag_set = false,flag_append = false;flag = flag || SUFFIX_APPEND; // default appendflag_set = flag === SUFFIX_REPLACE;title = fixNamespace(title);if (title in _pageWithRedirectTextSuffix) {flag_append = flag === SUFFIX_APPEND;} else {// if not exist, every flag can setflag_set = true;}if (flag_set) {_pageWithRedirectTextSuffix[title] = suffix;} else if (flag_append) {_pageWithRedirectTextSuffix[title] = _pageWithRedirectTextSuffix[title] + suffix;}},};_TR = {msg: null,tabselem: null,tagselem: null,variants: ['zh-hans', 'zh-hant', 'zh-cn', 'zh-hk', 'zh-mo', 'zh-sg', 'zh-tw'],init: function () {if (!this.msg) {return;} // not setup correctlyvar self = this,btn = $(mw.util.addPortletLink('p-views', '#', this.msg.btntitle, 'ca-redirect', this.msg.btndesc, null, '#ca-watch')).addClass('collapsible').css('cursor', 'pointer');btn.click(function (evt) {evt.preventDefault();self.dialog();});mw.config.get('skin') === 'vector-2022' ? $('#p-cactions ul').append(btn) : $('li#ca-history').after(btn);},dialog: function () {var dlg = $('<div class="dialog-redirect" title="' + this.msg.dlgtitle + '">').dialog({bgiframe: true,resizable: false,modal: true,width: 600,});this.tabselem = $('<div class="tab-redirect">').appendTo(dlg);this.tagselem = $('<ul>').appendTo(this.tabselem);this.addTabs();this.tabselem.tabs();},addTabs: function () {for (var kname in this.tabs) {if (this.tabs[kname] === null) {this.tabs[kname] = this['_initTab' + kname[0].charAt(0).toUpperCase() + kname.slice(1)]();}var tab = this.tabs[kname];this.tagselem.append(tab.tag);this.tabselem.append(tab.cont);}// default tab, autoload when dialog initiatethis.loadView();},createTab: function (tabname, tabtitle, onClick) {var self = this,tag = $('<li><a href="#tab-' + tabname + '">' + tabtitle + '</a></li>'),cont = $('<div id="tab-' + tabname + '"/>');$('a', tag).on('click', function () {onClick.call(self);});return {tag: tag, cont: cont, loaded: false};},_initTabView: function () {return this.createTab('view', this.msg.tabviewtitle, this.loadView);},_initTabCreate: function () {return this.createTab('create', this.msg.tabcreatetitle, this.loadCreate);},tabs: {view: null,create: null,},fix: function (pagenames) {var self = this;$('p.desc', this.tabs.view.cont).text(this.msg.fixloading);$('p[class!=desc]', this.tabs.view.cont).remove();this.loading(this.tabs.view.cont);this.bulkEditByRegex(pagenames, / \[\[.*?\]\]/, ' [['+origPageName+']]', this.msg.fixsummary).done(function () {// delay load before the asynchronous tasks on server finishedsetTimeout(function () {self.loaded(self.tabs.view.cont);self.loadView(true);}, 3000);});},create: function (pagenames) {var self = this;$('p.desc', this.tabs.create.cont).text(this.msg.createloading);$('p[class!=desc]', this.tabs.create.cont).remove();this.loading(this.tabs.create.cont);this.bulkEdit(pagenames, this.msg.createtext.replace('$1', origPageName), this.msg.createsummary.replace('$1', origPageName)).done(function () {// delay load before the asynchronous tasks on server finishedsetTimeout(function () {self.loaded(self.tabs.create.cont);self.tabs.view.loaded = false;self.loadCreate(true);}, 500);});},addRedirectTextSuffix: function (title, text) {if (title in _pageWithRedirectTextSuffix) {text = text + _pageWithRedirectTextSuffix[title];}return text;},bulkEdit: function (titles, text, summary) {var self = this;titles = titles.filter(function (v, i, arr) {return arr.indexOf(v) === i;});titles = titles.join('|');return $.ajax(this.buildQuery({action: 'query', prop: 'info', titles: titles, meta: 'tokens'})).then(function (data) {var deferreds = [];$.each(data.query.pages, function (idx, page) {deferreds.push($.ajax(self.buildQuery({action: 'edit',title: page.title,token: data.query.tokens.csrftoken,text: self.addRedirectTextSuffix(page.title, text),summary: summary,tags: 'ToolsRedirect',})));});return $.when.apply($, deferreds);});},bulkEditByRegex: function (titles, r, t, summary) {var self = this;titles = titles.filter(function (v, i, arr) {return arr.indexOf(v) === i;});titles = titles.join('|');return $.ajax(this.buildQuery({ action: 'query', prop: 'revisions', titles: titles, rvprop: 'content', meta: 'tokens' })).then(function (data) {var deferreds = [];$.each(data.query.pages, function (idx, page) {var content = page.revisions[0]['*'];var newContent = content.replace(r, t);deferreds.push($.ajax(self.buildQuery({action: 'edit',title: page.title,token: data.query.tokens.csrftoken,text: newContent,summary: summary,tags: 'ToolsRedirect',basetimestamp: page.revisions[0].timestamp,})));});return $.when.apply($, deferreds);});},loadTabCont: function (tabname, callback, reload) {var self = this,tab = this.tabs[tabname];if (reload) {tab.loaded = false;}if (!tab.loaded) {tab.cont.html('');var $desc = $('<p class="desc"><span class="desc-text">' + this.msg.rediloading + '</span></p>').appendTo(tab.cont),$text = $desc.find('> .desc-text');callback.apply(this).done(function () {$text.text(self.msg['tab' + tabname + 'desc']);}).fail(function () {$text.text(self.msg['tab' + tabname + 'notfound']);}).always(function () {self.addMethods($desc, [{href: '#refresh',title: self.msg.refresh,click: function (evt) {evt.preventDefault();self.loadTabCont(tabname, callback, true);},},]);});tab.loaded = true;}},loading: function (container) {if (container.prop('tagName').toLowerCase() === 'span') {container.addClass('mw-ajax-loader');} else if ($('span.mw-ajax-loader', container).length === 0) {$('<span class="mw-ajax-loader"></span>').appendTo(container);}},loaded: function (container) {if (container.prop('tagName').toLowerCase() === 'span') {container.removeClass('mw-ajax-loader');} else {$('span.mw-ajax-loader', container).remove();}},selectAll: function (cont) {$('input[type=checkbox]:not(:disabled)', cont).prop('checked', true);},selectInverse: function (cont) {$('input[type=checkbox]:not(:disabled)', cont).each(function () {var e = $(this);e.prop('checked', !e.prop('checked'));});},selectAction: function (cont, cb) {var pagenames = [];$('input[type=checkbox]:checked', cont).each(function () {pagenames.push($(this).data('page-title'));});if (pagenames.length) {cb.call(this, pagenames);}},clickAction: function (cont, cb) {var pagename = $('input[type="checkbox"]', cont).data('page-title');cb.call(this, [pagename]);},buildLink: function (attr) {var a = $('<a href="' + attr.href + '" title="' + attr.title + '" target="blank">' + attr.title + '</a>');if (attr.click) {a.on('click', attr.click);}if (attr.classname) {a.addClass(attr.classname);}return $('<span class="tools-redirect_link">').append(a);},addMethods: function ($parent, methods) {var self = this,$container = $parent.find('> .tools-redirect_methods');function methodExist(method) {return $container.find('a[href=' + JSON.stringify(method.href) + ']').length > 0;}if ($container.length === 0) {$container = $('<span class="tools-redirect_methods">').appendTo($parent);}$.each(methods, function (idx, method) {if (!methodExist(method)) {self.buildLink(method).appendTo($container);}});},buildSelection: function (main, metd, mt, dsab) {var cont = $('<span>'),sele = $('<input type="checkbox"/>').appendTo(cont);this.buildLink(main).appendTo(cont);this.addMethods(cont, metd);sele.data('page-title', mt);if (dsab) {sele.attr('disabled', true);}return cont;},loadView: function (reload) {var $container = this.tabs.view.cont;this.loadTabCont('view',function () {return this.loadRedirect(origPageName, $container, 0);},reload);},loadCreate: function (reload) {this.loadTabCont('create',function () {return this.findRedirect(origPageName);},reload);},loadRedirect: function (pagename, container, deep, loaded) {this.loading(container);var self = this,deferObj = $.Deferred(),top = deep ? $('<dl>').appendTo(container) : container;if (!loaded) {loaded = {};loaded[pagename] = true;}function onClickFix(evt) {/* jshint validthis: true */var entry = $(this).parents('dd, p').first();evt.preventDefault();self.clickAction(entry, self.fix);}$.ajax(this.buildQuery({action: 'query', prop: 'redirects', titles: pagename, rdlimit: 'max'})).done(function (data) {self.loaded(container);var has_redirect = false,desc = $('p.desc', self.tabs.view.cont),maximumRedirectDepth = mw.config.get('toolsRedirectMaximumRedirectDepth', 10);$.each(data.query.pages, function (_, page) {if (!('redirects' in page)) {return;}$.each(page.redirects, function (_, rdpage) {var $container,isCycleRedirect,rdtitle = rdpage.title,ultitle = rdtitle.replace(/ /g, '_'),baseuri = scriptPath + '/index.php?title=' + encodeURIComponent(ultitle),entry = (deep ? $('<dd>') : $('<p>')).appendTo(top),methods = [{href: baseuri + '&action=edit',title: self.msg.rediedit,},];isCycleRedirect = rdtitle in loaded;loaded[rdtitle] = true;if (!isCycleRedirect && deep) {methods.push({href: '#fix-redirect',title: self.msg.tabviewfix,click: onClickFix,});}$container = self.buildSelection({href: baseuri + '&redirect=no', title: rdtitle}, methods, ultitle, !deep).appendTo(entry);if (isCycleRedirect) {$container.append('<span class="error">' + self.msg.errcycleredirect + '</span>');} else if (deep < maximumRedirectDepth) {deferObj.done(function () {return self.loadRedirect(rdtitle, entry, deep + 1, loaded);});}has_redirect = true;});});if (has_redirect && deep === 1) {self.addMethods(desc, [{href: '#select-all',title: self.msg.selectall,click: function (evt) {evt.preventDefault();self.selectAll(self.tabs.view.cont);},},{href: '#select-inverse',title: self.msg.selectinverse,click: function (evt) {evt.preventDefault();self.selectInverse(self.tabs.view.cont);},},{href: '#fix-selected',title: self.msg.tabviewfix,click: function (evt) {evt.preventDefault();self.selectAction(self.tabs.view.cont, self.fix);},},]);}if (has_redirect) {deferObj.resolveWith(self);} else {deferObj.rejectWith(self);}});return deferObj.promise();},findVariants: function (pagename, titles) {var self = this,suffixReg = /^.+?( \(.+?\))$/,retTitles = [],deferreds = [],simpAndTrad = {'zh-hans': true, 'zh-hant': true};$.each(this.variants, function (_, variant) {var xhr = $.ajax(self.buildQuery({action: 'parse',page: pagename,prop: 'displaytitle',variant: variant,})).then(function (data) {var title = fixNamespace(data.parse.displaytitle);if (variant in simpAndTrad) {mw.toolsRedirect.setRedirectTextSuffix(title, '\n{{簡繁重定向}}', SUFFIX_APPEND);}return title;});if (isCategory) {xhr = xhr.then(function (origTitle) {return $.ajax(self.buildQuery({action: 'parse',text: pagename,prop: 'text',variant: variant,})).then(function (data) {var tmpTitle = $(data.parse.text['*']).text().replace(/(^\s*|\s*$)/g, '');// should not create redirect categories// if the conversion is already in global table,// or it will mess up a lot_redirectExcludes[tmpTitle] = true;return origTitle;});});}deferreds.push(xhr);});return $.when.apply($, deferreds).then(function () {var suffixes = [];$.each(arguments, function () {var suffix,title = this;// find title suffix,// for example " (济南市)" to "市中区 (济南市)"suffix = suffixReg.exec(title);if (suffix && suffix.length === 2) {suffix = suffix[1];} else {suffix = '';}retTitles.push(title);suffixes.push(suffix);});// append suffixes$.each($.uniqueSort(suffixes), function (_, suffix) {$.merge(retTitles,$.map(titles, function (title) {title = fixNamespace(title);return suffixReg.test(title) ? title : title + suffix;}));});return self.findNotExists($.uniqueSort(retTitles));});},findNotExists: function (titles) {var self = this,deferreds = [],alltitles = [],excludes = ['用字模式'];titles = titles.join('|');$.each(['zh-hans', 'zh-hant'], function (idx, variant) {deferreds.push($.ajax(self.buildQuery({action: 'parse', text: titles, prop: 'text', variant: variant})));});return $.when.apply($, deferreds).then(function () {$.each(arguments, function () {alltitles = alltitles.concat($(this[0].parse.text['*']).text().replace(/(^\s*|\s*$)/g, '').split('|'));});alltitles = alltitles.filter(function (v, i, arr) {return arr.indexOf(v) === i;});alltitles = alltitles.join('|');return $.ajax(self.buildQuery({action: 'query',prop: 'info',titles: alltitles,})).then(function (data) {titles = [];$.each(data.query.pages, function (pageid, page) {var title = page.title;if (pageid < 0 && excludes.indexOf(title) === -1) {if (title in _redirectExcludes) {// exclude special titlesreturn;}titles.push(title);if (isCategory) {var target = origPageName.replace(/^Category:/, '');mw.toolsRedirect.setRedirectTextSuffix(title, '\n{{分类重定向|$1}}'.replace('$1', target));}// only set default suffixmw.toolsRedirect.setRedirectTextSuffix(title, '\n{{別名重定向}}', SUFFIX_SETDEFAULT);}});return titles;});});},findRedirect: function (pagename) {var self = this,titles = [],frcDeferreds = [],container = this.tabs.create.cont,$content = $('#mw-content-text > div.mw-parser-output'),deferObj = $.Deferred();this.loading(container);$.each(_findRedirectCallbacks, function (_, callback) {var ret = callback(pagename, $content, titles);if (typeof ret === 'string') {titles.push(ret);} else if ('done' in ret) {// is DeferredfrcDeferreds.push(ret);} else {$.merge(titles, ret);}});// remove all empty titlestitles = $.map(titles, function (title) {return title || null;});function onClickCreate(evt) {/* jshint validthis: true */var entry = $(this).parents('p:first');evt.preventDefault();self.clickAction(entry, self.create);}// handles the deferred callbacks$.when.apply($, frcDeferreds).then(function () {$.each(arguments, function (_, ret) {if (typeof ret === 'string') {titles.push(ret);} else {$.merge(titles, ret);}});return self.findVariants(pagename, titles);}).done(function (titles) {// build HTMLself.loaded(container);$.each(titles, function (_, title) {var ultitle = title.replace(' ', '_'),baseuri = scriptPath + '/index.php?title=' + encodeURIComponent(ultitle),entry = $('<p>').appendTo(container);self.buildSelection({href: baseuri + '&action=edit&redlink=1',title: title,classname: 'new',},[{href: '#create-redirect',title: self.msg.tabcreatetitle,click: onClickCreate,},],ultitle,false).appendTo(entry);});var desc = $('p.desc', container);if (titles.length > 0) {self.addMethods(desc, [{href: '#select-all',title: self.msg.selectall,click: function (evt) {evt.preventDefault();self.selectAll(container);},},{href: '#select-inverse',title: self.msg.selectinverse,click: function (evt) {evt.preventDefault();self.selectInverse(container);},},{href: '#create-selected',title: self.msg.tabcreatetitle,click: function (evt) {evt.preventDefault();self.selectAction(container, self.create);},},]);deferObj.resolveWith(self, [titles]);} else {deferObj.rejectWith(self, [titles]);}});return deferObj.promise();},buildQuery: function (data) {var query = {url: scriptPath + '/api.php', dataType: 'json', type: 'POST'};query.data = data;query.data.format = 'json';return query;},};$.when(mw.loader.getScript('/w/index.php?title=MediaWiki:Gadget-ToolsRedirect-msg-' + wgULS('zh-hans', 'zh-hant') + '.js&action=raw&ctype=text/javascript'), $.ready).done(function () {_TR.msg = window.tools_redirect_msg;_TR.init();});})(jQuery);// </nowiki>