MediaWiki:Gadget-SearchPages.js

/* jshint esversion: 6, forin: true, immed: true, indent: 4, latedef: true, newcap: true, noarg: true, undef: true, undef: true, unused: true, browser: true, jquery: true, onevar: true, eqeqeq: true, multistr: true, maxerr: 999999, -W082, -W084 /* global mw, ace */ mw.loader.using(['mediawiki.util', 'mediawiki.api']).then(function {		var api = new mw.Api;	var aceShown = false;	var contentEditor, titleEditor;	mw.loader.load('ext.codeEditor.ace');	ace.define('ace/mode/regex', [], function { var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var RegexHighlightRules = function { this.$rules = { "start": [{ // escapes token: "regexp.keyword.operator", regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" }, {					// flag token: "string.regexp", regex: "/[sxngimy]*", }, {					// invalid operators token : "invalid", regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ }, {					// operators token : "constant.language.escape", regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[$^+*?.]/ }, {					token : "constant.language.delimiter", regex: /\|/ }, {					token: "constant.language.escape", regex: /\[\^?/, next: "regex_character_class" }, {					defaultToken: "string.regexp" }],			};		};		oop.inherits(RegexHighlightRules, TextHighlightRules); exports.RegexHighlightRules = RegexHighlightRules; });

function setupEditor(id) { var aceEditor = ace.edit(id); var mode = new (ace.require("ace/mode/javascript").Mode); mode.HighlightRules = ace.require('ace/mode/regex').RegexHighlightRules; aceEditor.session.setMode(mode);

if (id === "SP-ContentRegex") { aceEditor.setOptions({				wrapBehavioursEnabled: true,				wrap: true,			}); aceEditor.session.on('change', function {				var height = aceEditor.session.getScreenLength					* aceEditor.renderer.lineHeight					+ aceEditor.renderer.scrollBar.getWidth + 'px';				$(id).css({ height: height });				aceEditor.resize;			}); }		return aceEditor; }	function generateNamespaces { var o = mw.config.get('wgFormattedNamespaces'), ret = [];

Object.keys(o).forEach(function(key) {			var value = o[key];

ret.push($(' ', { value: key, text: value, }));		});

ret.unshift($(' ', { value: 0, text: "(Main)", selected: true, }));

return $(' ', {			id: "SP-namespace",			html: ret,		}); }

function getData { var def = new $.Deferred;

api.get({			action: "query",			format: "json",			list: "allpages",			aplimit: 5000,			apnamespace: $('#SP-namespace').val || 0,			apfilterredir: !$('#showredir').prop('checked') ? 'nonredirects' : null,		}).always(function(d) {			var pages = d.query.allpages.map(function(v) { return v.title; });			var titles = ;

var counter = 0; var calls = 0; pages.forEach(function(page) {				counter++;				if (counter >= 250) {					titles.push([page]);					counter = 0;					calls++;				} else {					titles[calls].push(page);				}			});

$.when.apply($, titles.map(function(v) { return api.get({					action: "query",					format: "json",					prop: "revisions",					titles: v.join('|'),					formatversion: "2",					rvprop: "content",					rvslots: "*",				}); })).always(function {				var revs = [];

Array.from(arguments).forEach(function(query) {					query[0].query.pages.forEach(function(v) { revs.push(v); });				});

revs = revs.map(function(v) {					return { 						pageid: v.pageid,						ns: v.ns,						title: v.title,						content: v.revisions[0].slots.main.content,						contentformat: v.revisions[0].slots.main.contentformat,						contentmodel: v.revisions[0].slots.main.contentmodel,					};				}); def.resolve(revs); });		});		return def; }

function filterMatch(data, titleSearch, contentSearch, caseInsensitive, regex, regexFlags) { if (regexFlags.match(/[^gmisuy]/)) return error("Invalid regular expression flags \"" + regexFlags + "\""); if (regex) { try { titleSearch = new RegExp(titleSearch, regexFlags + (caseInsensitive && !regexFlags.includes('i') ? "i" : "")); contentSearch = new RegExp(contentSearch, regexFlags + (caseInsensitive && !regexFlags.includes('i') ? "i" : "")); } catch(e) { return error(e.message); }		}

function testMatch(testString, matcher, caseInsensitive) { if (matcher instanceof RegExp) { return !!matcher.test(testString); } else { if (caseInsensitive) { testString = testString.toLowerCase; matcher = matcher.toLowerCase; }				return !!testString.includes(matcher); }		}		return data.filter(function(page) {			var pass = true;			if (titleSearch && !testMatch(page.title, titleSearch, caseInsensitive)) {				pass = false;			}			if (contentSearch && !testMatch(page.content, contentSearch, caseInsensitive)) {				pass = false;			}			return pass;		}); }

function error(msg) { $('#SP-results').html($("", { html: "Error in getting data: " + msg.replace(/\/(.+?)\//, $(' ', { style: "font-family: consolas;", text: '$1' }).prop('outerHTML')), class: "error", }));	}

function createCheckbox(label, title, id, click) { return $(' ', {			class: "SP-checkbox",			html: [				$(' ', { id: "SP-" + id, name: "SP-" + id, type: "checkbox", title: title, }),				' ',				$(' ', {					for: "SP-" + id, id: "SP-" + id + "-label", text: label, type: "checkbox", title: title, click: click, }),			],		});	}	function createLinks(title) { return $(' ', {			html: [				$('', { href: mw.util.getUrl(title), title: title, text: title, }),				' (',				$('', {					href: mw.util.getUrl(title, { action: "edit" }),					title: mw.util.getUrl(title, { action: "edit" }),					text: "edit",				}), ' | ',				$('', {					href: mw.util.getUrl(title, { action: "hist" }),					title: mw.util.getUrl(title, { action: "hist" }),					text: "hist",				}), ' | ',				$('', {					href: mw.util.getUrl('Special:Log', { page: title }),					title: mw.util.getUrl('Special:Log', { page: title }),					text: "logs",				}), ')',			],		});	}	function toggleEditors { aceShown = !aceShown; $('#SP-ContentRegex, #SP-TitleRegex, #SP-title-search, #SP-content-search').slideToggle; if (aceShown) { contentEditor.setValue($('#SP-content-search').val); titleEditor.setValue($('#SP-title-search').val); } else { $('#SP-content-search').val(contentEditor.getValue); $('#SP-title-search').val(titleEditor.getValue); }	}	function initInterface { document.getElementById('firstHeading').innerHTML = 'Search Pages'; document.title = 'Search Pages | ' + mw.config.get('wgSiteName') + ' | Fandom';

$('#mw-content-text').html($(' ', { html: [ 'Namespace to search: ', generateNamespaces, createCheckbox("Show Redirects", "Show redirects in the results", "showredir"), createCheckbox("Case insensitive", "Make the matchers case insensitive", "case-insensitive"), createCheckbox("Regex", "Make the matchers use regular expressions", "regex", function {					$('#SP-regex-flags-wrapper').fadeToggle;				}), $(' ', {					id: "SP-regex-flags-wrapper",					style: "display: none;",					html: [						$('', { title: "Regular expression flags to use", id: "SP-regex-flags-label", text: "Regex Flags: ", }),						$(' ', {							id: "SP-regex-flags", title: "Regular expression flags to use", }),					],				}),				'Page title to match: ', $(' ', { type: "text", id: "SP-title-search" }).attr({ size: 100 }), $(' ', { id: "SP-TitleRegex", style: "display: none;" }), ' ',				'Page content to match: ', ' ',				$(' ', { cols: 100, rows: 6, id: "SP-content-search", resizable: true }), $(' ', { id: "SP-ContentRegex", style: "display: none;" }), ' ',				' ',				$(' ', {					html: ["Search Results", " ".repeat(2), $(' ', { id: "SP-submit", text: "Submit", click: function { $('#SP-results').addClass('mw-ajax-loader').empty; getData.then(function(d) {								$('#SP-results').removeClass('mw-ajax-loader');								d = filterMatch( d, (aceShown ? titleEditor.getValue : $('#SP-title-search').val).trim, ( aceShown ? contentEditor.getValue : $('#SP-content-search').val).trim, $("#SP-case-insensitive").prop('checked'), $("#SP-regex").prop('checked'), $('#SP-regex-flags').val );								if (!d) return;								var oldD = d;								d = d.map(function(v) { return $('', {										html: createLinks(v.title),									}); });								if (!d.length) return $('#SP-results').html($(' ', { text: 'No pages matched your search.' }));								$('#SP-results').html([ $('', {										html: [											"Total Results: " + d.length,											' (', $('', {												style: "cursor: pointer",												text: "copy pages",												click: function {													window.navigator.clipboard.writeText(oldD.map(function(v) {														return v.title;														}).join('\n'));													return alert('Copied!');												},											}), ')',										],									}),									$('', {										html: d,									}) ]);							});						},					})],				}), 				' ',				$(' ', { id: "SP-results", html: $(' ', { text: "Submit inputs to see pages.", }) }), ],		}));		contentEditor = setupEditor("SP-ContentRegex"); titleEditor = setupEditor("SP-TitleRegex"); }

function initSpecialPages { var listItem = $('', {			html: $('', { text: "Search Pages", href: mw.util.getUrl('Special:SearchPages'), }),		});		$('#AdminDashboardAdvanced').find('h2').parent.slice(1, 2).next.find('ul').first.append(listItem); }

function init { if (window.searchPagesLoaded || mw.config.get('wgNamespaceNumber') !== -1) return; window.searchPagesLoaded = true;

mw.util.addCSS('#SP-title-search, #SP-content-search { font-family: consolas; } .SP-checkbox > * { cursor: pointer !important; }'); switch(mw.config.get('wgTitle')) { case('SearchPages'): return initInterface; case('AdminDashboard'): case('AllPages'): initSpecialPages; }	}	init; });