تفصیل کے لیے کھولیں کے بٹن پر کلک کریں یاددہانی: محفوظ کرنے کے بعد تازہ ترین تبدیلیوں کو دیکھنے کے لیے آپ کو اپنے براؤزر کا کیش صاف کرنا ہوگا۔

  • فائرفاکس/ سفاری: جب Reload پر کلک کریں تو Shift دبا کر رکھیں، یا Ctrl-F5 یا Ctrl-R دبائیں (Mac پر R- )
  • گوگل کروم: Ctrl-Shift-R دبائیں (Mac پر Shift-R-⌘)
  • انٹرنیٹ ایکسپلورر: جب Refresh پر کلک کریں تو Ctrl یا Ctrl-F5 دبائیں
  • اوپیرا: Tools → Preferences میں جائیں اور کیش صاف کریں

/***************************************************************************************************
 extra.js --- by Evad37
 > Common helper functions, stored in the window.extraJs object.
 > Version 1.3.1
----------------------------------------------------------------------------------------------------
 Take care to load approriate resource loader modules, as specified for each function. Or just load
 all that may be required, like this:
 
 mw.loader.using( ['mediawiki.util', 'mediawiki.api', 'mediawiki.Title', 'mediawiki.RegExp',
	'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'], function () {

 // ... your code goes here...

 });
 
***************************************************************************************************/
// <nowiki>

window.extraJs = {};

/**
 * makeApiErrorMsg
 *
 * Makes an error message, suitable for displaying to a user, from the values
 * that the MediaWiki Api passes to the failure callback function, e.g.
 * `new mw.Api.get(queryObject}).done(successCallback).fail(failureCallback)`
 *
 * @param {string} code
 *  First paramater passed to failure callback function.
 * @param {jQuery.jqXHR} jqxhr
 *  Second paramater passed to failure callback function.
 * @return {string} Error message details, with in a format like
 *  "(API|HTTP) error: details"
 */
extraJs.makeErrorMsg = function(code, jqxhr) {
	var details = '';
	if ( code === 'http' && jqxhr.textStatus === 'error' ) {
		details = 'HTTP error ' + jqxhr.xhr.status;
	} else if ( code === 'http' ) {
		details = 'HTTP error: ' + jqxhr.textStatus;
	} else if ( code === 'ok-but-empty' ) {
		details = 'Error: Got an empty response from the server';
	} else {
		details = 'API error: ' + code;
	}
	return details;
};

/**
 * makeLink
 *
 * Makes a link to a ur.Wikipedia page that opens in a new tab/window.
 * 
 * @requires {Module} mediawiki.util
 * @param {string} linktarget
 *  The target page.
 * @param {string} linktext
 *  Text to display in the link. Optional, if not provided the target will be used.
 * @return {jQuery} jQuery object containing the `<a>` element.
 */
extraJs.makeLink = function(linktarget, linktext) {
	if ( linktext == null ) {
		linktext = linktarget;
	}
	return $('<a>').attr({
		'href':'https://ur.wikipedia.org/wiki/'+mw.util.wikiUrlencode(linktarget),
		'target':'_blank'
	}).text(linktext);
};

/**
 * makeRcatCapsuleMultiselect
 * 
 * Creates an OOjs UI CapsuleMultiselect with Rcat templates as options,
 * grouped as per https://ur.wikipedia.org/wiki/Template:R_template_index
 *
 * @requires {Modules} oojs-ui-core, oojs-ui-widgets
 * @param {function} onChangeCallback({String[]} datas)
 *  Callback function for when the selected rcats change, is passed an array of Strings
 *  each of which is a selected rcat template (including  braces `{{` and `}}`). When all
 *  prior selections are removed, an empty array is passed.
 * @param {object} context
 *  The context to be used as the `this` value when executing the callback function
 * @param {jQuery} overlay
 *  Overlay element. If ommited, element with id `ejs-rcats-overlay` will be emptied and used
 *  if it exists, or else a div with that id will be created and used.
 * @return {OO.ui.CapsuleMultiselectWidget}
 */
extraJs.makeRcatCapsuleMultiselect = function(onChangeCallback, context, overlay) {

	// Extend OO.ui.MenuSelectWidget and OO.ui.CapsuleMultiselectWidget to use a more intuitive
	// lookup system, such that e.g. typing "section" brings up `{{R to section}}` as a match
	LookupMenuSelectWidget = function(config) {
		OO.ui.MenuSelectWidget.call(this, config);
	};
	LookupMenuSelectWidget.prototype = Object.create(OO.ui.MenuSelectWidget.prototype);
	LookupMenuSelectWidget.prototype.getItemMatcher = function ( s, exact ) {
		var re;
		if ( s.normalize ) {
			s = s.normalize();
		}
		s = exact ? s.trim() : s.replace( /^\s+/, '' );
		re = s.replace( /([\\{}()|.?*+\-^$[\]])/g, '\\$1' ).replace( /\s+/g, '\\s+' );
		if ( exact ) {
			re = '^\\s*' + re + '\\s*$';
		}
		re = new RegExp( re, 'i' );
		return function ( item ) {
			var matchText = item.getMatchText();
			if ( matchText.normalize ) {
				matchText = matchText.normalize();
			}
			return re.test( matchText );
		};
	};
	var LookupCapsuleMultiselectWidget = function ( config ) {
		OO.ui.CapsuleMultiselectWidget.call(this, config);
		// Override menu widget
		this.menu = new LookupMenuSelectWidget( $.extend(
			{
				widget: this,
				$input: this.$input,
				$floatableContainer: this.$element,
				filterFromInput: true,
				disabled: this.isDisabled()
			},
			config.menu
		) );
		this.menu.connect( this, {
			choose: 'onMenuChoose',
			toggle: 'onMenuToggle',
			add: 'onMenuItemsChange',
			remove: 'onMenuItemsChange'
		} );
		if ( this.$input ) {
			this.$input.prop( 'disabled', this.isDisabled() );
			this.$input.attr( {
				role: 'combobox',
				'aria-owns': this.menu.getElementId(),
				'aria-autocomplete': 'list'
			} );
		}
		if ( !this.popup ) {
			this.$content.append( this.$input );
			this.$overlay.append( this.menu.$element );
		}
		this.onMenuItemsChange();
	};
	LookupCapsuleMultiselectWidget.prototype = Object.create(OO.ui.CapsuleMultiselectWidget.prototype);
	
	// Define new overlay, or use/reuse already defined element
	if ( overlay == null ) {
		if ( $('#ejs-rcats-overlay').length ) {
			overlay = $('#ejs-rcats-overlay').first().empty();
		} else {		
			overlay = $('<div>')
			.attr('id', 'ejs-rcats-overlay')
			.css({'z-index':'2000', 'position':'fixed', 'top':'0px', 'font-size':'85%'})
			.prependTo('body');
		}
	}
	
	// Make menu option widgets based on template name
	var newRcatOption = function(val) {
		return new OO.ui.MenuOptionWidget( {data: '{{'+val+'}}', label: '{{'+val+'}}'} );
	};
	
	// Make the widget
	var rcatCapsuleMultiselect = new LookupCapsuleMultiselectWidget( {
		allowArbitrary: true,
		$overlay: overlay,
		popup: false,
		menu: {
			items: [
				// Common Rcats
				new OO.ui.MenuSectionOptionWidget({label:'Common'}),
					newRcatOption('R to related topic'),
					newRcatOption('R from subtopic'),
					newRcatOption('R to list entry'),
					newRcatOption('R to section'),
				new OO.ui.MenuSectionOptionWidget({label:'Related information'}),
					newRcatOption('R from album'),
					newRcatOption('R to article without mention'),
					newRcatOption('R from book'),
					newRcatOption('R to decade'),
					newRcatOption('R from domain name'),
					newRcatOption('R from top-level domain'),
					newRcatOption('R from film'),
					newRcatOption('R from gender'),
					newRcatOption('R from list topic'),
					newRcatOption('R from member'),
					newRcatOption('R to related topic'),
					newRcatOption('R from related word'),
					newRcatOption('R from phrase'),
					newRcatOption('R from school'),
					newRcatOption('R from song'),
					newRcatOption('R from subtopic'),
					newRcatOption('R to subtopic'),
					newRcatOption('R from Unicode'),
				new OO.ui.MenuSectionOptionWidget({label:'Fiction'}),
					newRcatOption('R from fictional character'),
					newRcatOption('R from fictional element'),
					newRcatOption('R from fictional location'),
					newRcatOption('R to TV episode list entry'),
				// Grammar, punctuation, and spelling
				new OO.ui.MenuSectionOptionWidget({label:'Abbreviation'}),
					newRcatOption('R to acronym'),
					newRcatOption('R from acronym'),
					newRcatOption('R to initialism'),
					newRcatOption('R from initialism'),
				new OO.ui.MenuSectionOptionWidget({label:'Capitalisation'}),
					newRcatOption('R from CamelCase'),
					newRcatOption('R from other capitalisation'),
					newRcatOption('R from miscapitalisation'),
				new OO.ui.MenuSectionOptionWidget({label:'Grammar & punctuation'}),
					newRcatOption('R from modification'),
					newRcatOption('R from plural'),
					newRcatOption('R to plural'),
				new OO.ui.MenuSectionOptionWidget({label:'Parts of speech'}),
					newRcatOption('R from adjective'),
					newRcatOption('R from adverb'),
					newRcatOption('R from common noun'),
					newRcatOption('R from gerund'),
					newRcatOption('R from proper noun'),
					newRcatOption('R from verb'),
				new OO.ui.MenuSectionOptionWidget({label:'Spelling'}),
					newRcatOption('R from alternative spelling'),
					newRcatOption('R from ASCII-only'),
					newRcatOption('R to ASCII-only'),
					newRcatOption('R from diacritic'),
					newRcatOption('R to diacritic'),
					newRcatOption('R from misspelling'),
					newRcatOption('R from stylization'),
				// Alternative names
				new OO.ui.MenuSectionOptionWidget({label:'Alternative names (general)'}),
					newRcatOption('R from alternative language'),
					newRcatOption('R from alternative name'),
					newRcatOption('R from former name'),
					newRcatOption('R from historic name'),
					newRcatOption('R from incorrect name'),
					newRcatOption('R from long name'),
					newRcatOption('R from portmanteau'),
					newRcatOption('R from short name'),
					newRcatOption('R from sort name'),
					newRcatOption('R from less specific name}'),
					newRcatOption('R from more specific name'),
					newRcatOption('R from synonym'),
					newRcatOption('R from antonym'),
				new OO.ui.MenuSectionOptionWidget({label:'Alternative names (people)'}),
					newRcatOption('R from birth name'),
					newRcatOption('R from given name'),
					newRcatOption('R to joint biography'),
					newRcatOption('R from married name'),
					newRcatOption('R from name with title'),
					newRcatOption('R from personal name'),
					newRcatOption('R from pseudonym'),
					newRcatOption('R from surname'),
				new OO.ui.MenuSectionOptionWidget({label:'Alternative names (technical)'}),
					newRcatOption('R from Java package name'),
					newRcatOption('R from molecular formula'),
					newRcatOption('R from technical name'),
					newRcatOption('R to technical name'),
					newRcatOption('R from trade name'),
				new OO.ui.MenuSectionOptionWidget({label:'Alternative names (organisms)'}),
					newRcatOption('R from scientific name'),
					newRcatOption('R from alternative scientific name'),
					newRcatOption('R to scientific name'),
				new OO.ui.MenuSectionOptionWidget({label:'Alternative names (geography)'}),
					newRcatOption('R from name and country'),
					newRcatOption('R from more specific geographic name'),
					newRcatOption('R from postal code'),
				// Navigation aids
				new OO.ui.MenuSectionOptionWidget({label:'Navigation'}),
					newRcatOption('R to anchor'),
					newRcatOption('R avoided double redirect'),
					newRcatOption('R from file metadata link'),
					newRcatOption('R to list entry'),
					newRcatOption('R mentioned in hatnote'),
					newRcatOption('R to section'),
					newRcatOption('R from shortcut'),
					newRcatOption('R from template shortcut'),
				new OO.ui.MenuSectionOptionWidget({label:'Disambiguation'}),
					newRcatOption('R from ambiguous term'),
					newRcatOption('R to anthroponymy page'),
					newRcatOption('R to disambiguation page'),
					newRcatOption('R from incomplete disambiguation'),
					newRcatOption('R from incorrect disambiguation'),
					newRcatOption('R from other disambiguation'),
					newRcatOption('R from unnecessary disambiguation'),
				new OO.ui.MenuSectionOptionWidget({label:'Merge, duplicate & move'}),
					newRcatOption('R from duplicated article'),
					newRcatOption('R with history'),
					newRcatOption('R from merge'),
					newRcatOption('R from move'),
					newRcatOption('R with old history'),
				new OO.ui.MenuSectionOptionWidget({label:'To namespaces'}),
					newRcatOption('R to category namespace'),
					newRcatOption('R to draft namespace'),
					newRcatOption('R to help namespace'),
					newRcatOption('R to main namespace'),
					newRcatOption('R to portal namespace'),
					newRcatOption('R to project namespace'),
					newRcatOption('R to talk page'),
					newRcatOption('R to template namespace'),
					newRcatOption('R to user namespace'),
				// Miscellaneous
				new OO.ui.MenuSectionOptionWidget({label:'ISO codes'}),
					newRcatOption('R from ISO 4'),
					newRcatOption('R from ISO 639 code'),
					newRcatOption('R from ISO 3166 code'),
					newRcatOption('R from ISO 4217 code'),
					newRcatOption('R from ISO 15924 code'),
				new OO.ui.MenuSectionOptionWidget({label:'Miscellaneous'}),
					newRcatOption('R printworthy'),
					newRcatOption('R unprintworthy'),
					newRcatOption('Wikidata redirect')
			]
		}
	} );
	
	// Execute callback when selector data changes
	rcatCapsuleMultiselect.on('change', function(d) {
		// Only care about the sring data (or no data), not the widgets
		if ( typeof d[0] === 'string' ) {
			onChangeCallback.call(context, d);
		} else if ( d.length === 0 ) {
			onChangeCallback.call(context, ['']);
		}
	});
	
	return rcatCapsuleMultiselect;
	
};

/**
 * makeTooltip
 *
 * Make a question mark in a circle that shows a 'tooltip' when hovered over
 *
 * @param {string} tipText
 *  The text for the tooltip.
 * @return {jQuery} jQuery object containing the tooltip element
 */
extraJs.makeTooltip = function(tipText) {
	// Add css rule, if not already added
	if ( !extraJs.tooltipStyle ) {
		var s = mw.loader.addStyleTag('.ejs-tooltip { border:1px solid #33a; border-radius:10px; '+
		'font-weight:bold; font-size:80%; color:#22a; padding:0px; cursor:help }');
		extraJs.tooltipStyle = s.sheet || s.styleSheet || s;
	}
	return $('<span>').attr({'title':tipText, 'class':'ejs-tooltip'}).html('&thinsp;?&thinsp;');
};

/**
 * multiButtonConfirm
 *
 * Uses OOjs UI to create a multi-button confirm dialogue.
 *
 * @requires {Modules} oojs-ui-core, oojs-ui-windows, mediawiki.util
 * @param {string} title
 *  Title for the dialogue.
 * @param {string} message
 *  Message for the dialogue. Certain HTML tags can be escaped, newline characters are ignored.
 * @param {object[]} buttons
 *  Array of objects which each represent a buttons to show at the bottom of the prompt.
 *  Each object can be of the form
 *  `{
 *    label: {string},
 *    action: {string|null},
 *    flags: {string|null},
 *   }`
 *  where `label` is the label to show on the button, `action` is the value passed to the callback
 *  function if that button is selected by the user, and `flags` is one of "safe", "primary",
 *  "progressive", or "destructive", per https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged
 * @param {function} callback
 *  callback function executed after a button is selected (passed that button's `action` value)
 * @param {object} options
 *  Display options:
 *   @param {boolean} options.verbose
 *    Display verbose message formatting (left- instead of center-aligned)
 *   @param {boolean} options.unescape
 *    Unescape the following simple HTML tags (no attributes) in the message:
 *    <br>, <p>, <ul>, <li>, <pre> (and matching closing tags or self-closed tags).
 *    Tags within <pre> tags will not be unescaped.
 *   @param {boolean} options.wikilinks
 *    Convert [[wikilinks]] into actual links. If `options.unescape` is set to `true`, wikilinks
 *    within <pre> tags will not be converted.
 */
extraJs.multiButtonConfirm = function(title, message, buttons, callback, options) {
	// If needed, create array of deferreds
	if ( !extraJs.multiButtonConfirm.dfd ) {
		extraJs.multiButtonConfirm.dfd = [$.Deferred().resolve()];
	}
	
	// Add Deferred, to be resoved when previous window is done
	var dfdIndex = extraJs.multiButtonConfirm.dfd.push($.Deferred()) - 1;
	
	// Open window when previous window's Deferred is resolved
	extraJs.multiButtonConfirm.dfd[dfdIndex-1].done(function(){
		extraJs.multiButtonConfirm.windowManager = new OO.ui.WindowManager();
		var windowManager = extraJs.multiButtonConfirm.windowManager;
		var messageDialog = new OO.ui.MessageDialog();
		$('body').append( windowManager.$element );
		windowManager.addWindows( [ messageDialog ] );
		var instance = windowManager.openWindow( messageDialog, {
			title: title,
			message: message,
			verbose: options && options.verbose,
			actions: buttons
		} );
		instance.opened.then( function() {
			if ( options && ( options.unescape || options.wikilinks ) ) {
				// Escaped message text
				var msg = $('label.oo-ui-messageDialog-message')
					.filter(':visible')
					.text();
				
				// Unescape escaped html - pre tags			
				if ( options.unescape ) {
					// Process pre tags first (this way the only unescaped `<`s will be for pre tags)
					msg = msg.replace(/&lt;(\/?pre\s?\/?)&gt;/g,'<$1>');
				}
				
				// Make wikilinks into real links
				if ( options.wikilinks ) {
					var path = 'https:' + mw.config.get('wgServer') + '/wiki/';
					// First piped links, then simple links (unless inside <pre> tags)
					msg = msg.replace(
						/\[\[([^\|\]]*?)\|([^\|\]]*?)\]\](?![^<]*?<\/pre>)/g,
						'<a href="' + path + mw.util.wikiUrlencode('$1') + '" target="_blank">$2</a>'
					).replace(
						/\[\[([^\|\]]+?)]\](?![^<]*?<\/pre>)/g,
						'<a href="' + path + mw.util.wikiUrlencode('$1') + '" target="_blank">$1</a>'
					);
				}
				
				// Unescape escaped html - other tags			
				if ( options.unescape ) {
					// Process other tags, unless inside <pre> tags
					msg = msg.replace(/&lt;(\/?(?:br|p|ul|li)\s?\/?)&gt;(?![^<]*?<\/pre>)/g,'<$1>');
				}
				
				// Replace message
				$('label.oo-ui-messageDialog-message')
				.filter(':visible')
				.html(msg);
				
				// Resize dialogue to fit
				messageDialog.updateSize();
			}
		} );
		instance.closed.then( function ( data ) {
			if ( data && data.action ) {
				callback(data.action);
			} else {
				callback(null);
			}
			windowManager.destroy();
			// Resolve this window's Deferred
			extraJs.multiButtonConfirm.dfd[dfdIndex].resolve();
		} );
	});
};

/**
 * toSentenceCase
 *
 * Capitalises the first letter of a string.
 *
 * @param {String} input
 *  The string to be transformed.
 * @param {Boolean} lc
 *  Transform the characters following the first character to lowercase
 * @returns {String} Transformed string.
 */
extraJs.toSentenceCase = function(input, lc) {
	return input.slice(0,1).toUpperCase() +
		(( lc ) ? input.slice(1).toLowerCase() : input.slice(1));
};

/**
 * uniqueArray
 *
 * Filters out possible duplicate values from an array.
 *
 * @param {array} a
 *  Array to be filtered.
 * @return {array} Filtered array.
 */
extraJs.uniqueArray = function(a) {
	return a.filter(function(val, i, arr){ return arr.indexOf(val) === i; });
};

/**
 * unlink
 *
 * Function to unlink and/or remove links and file usages from a block of wikitext.
 * Derived from XFDcloser < https://en.wikipedia.org/wiki/User:Evad37/XFDcloser.js >
 *
 * @requires {Module} mediawiki.RegExp
 * @param {string} wikitext
 *  Wikitext in which to search for links or file usages.
 * @param {string[]} unlinkThese
 *  Array of page titles to be unlinked.
 * @param {number} ns
 *  Number of the namespace which the wikitext is in.
 * @param {boolean} isDab
 *  Wikitext is of a disambiguation page.
 * @return {string} Updated wikitext. If no links or file usages were found, this will be
 *  the same as the input wikitext.
 */
extraJs.unlink = function(wikitext, unlinkThese, ns, isDab) {
	// Remove image/file usages, if any titles are files
	var unlinkFiles = unlinkThese.filter(function(t){ return /^File:/i.test(t); });
	if ( unlinkFiles.length > 0 ) {
		// Start building regex strings
		var normal_regex_str = "(";
		var gallery_regex_str = "(";
		var free_regex_str = "(";
		for ( var i=0; i<unlinkFiles.length; i++ ) {
			// Take off namespace prefix
			filename = unlinkFiles[i].replace(/^.*?:/, "");
			// For regex matching: first character can be either upper or lower case, special
			// characters need to be escaped, spaces/underscores can be either spaces or underscores
			filename_regex_str = "[" + mw.RegExp.escape(filename.slice(0, 1).toUpperCase()) +
			mw.RegExp.escape(filename.slice(0, 1).toLowerCase()) + "]" +
			mw.RegExp.escape(filename.slice(1)).replace(/(?: |_)/g, "[ _]");
			// Add to regex strings
			normal_regex_str += "\\[\\[\\s*(?:[Ii]mage|[Ff]ile)\\s*:\\s*" + filename_regex_str +
			"\\s*\\|?.*?(?:(?:\\[\\[.*?\\]\\]).*?)*\\]\\]";
			gallery_regex_str += "^\\s*(?:[Ii]mage|[Ff]ile):\\s*" + filename_regex_str + ".*?$";
			free_regex_str += "\\|\\s*(?:[\\w\\s]+\\=)?\\s*(?:(?:[Ii]mage|[Ff]ile):\\s*)?" +
			filename_regex_str;
			
			if ( i+1 !== unlinkFiles.length ) {
				normal_regex_str += "|";
				gallery_regex_str += "|";
				free_regex_str += "|";				
			}
		}
		// Close off regex strings
		normal_regex_str += ")(?![^<]*?-->)";
		gallery_regex_str += ")(?![^<]*?-->)";
		free_regex_str += ")(?![^<]*?-->)";

		// Check for normal file usage, i.e. [[File:Foobar.png|...]]
		var normal_regex = new RegExp( normal_regex_str, "g");
		wikitext = wikitext.replace(normal_regex, "");
		
		// Check for gallery usage, i.e. instances that must start on a new line, eventually
		// preceded with some space, and must include File: or Image: prefix
		var gallery_regex = new RegExp( gallery_regex_str, "mg" );
		wikitext = wikitext.replace(gallery_regex, "");
		
		// Check for free usages, for example as template argument, might have the File: or Image:
		// prefix excluded, but must be preceeded by an |
		var free_regex = new RegExp( free_regex_str, "mg" );
		wikitext = wikitext.replace(free_regex, "");
	}
	
	// Remove links
	// Start building regex strings
	var simple_regex_str = "\\[\\[\\s*:?\\s*(";
	var named_regex_str = "\\[\\[\\s*:?\\s*(?:";
	for ( var ii=0; ii<unlinkThese.length; ii++ ) {
		// For regex matching: first character can be either upper or lower case, special
		// characters need to be escaped, spaces/underscores can be either spaces or underscores
		var unlink_regex_str = "[" + mw.RegExp.escape(unlinkThese[ii].slice(0, 1).toUpperCase()) +
			mw.RegExp.escape(unlinkThese[ii].slice(0, 1).toLowerCase()) + "]" +
			mw.RegExp.escape(unlinkThese[ii].slice(1)).replace(/(?: |_)/g, "[ _]");
		// Add to regex strings
		simple_regex_str += unlink_regex_str;
		named_regex_str += unlink_regex_str;
		if ( ii+1 !== unlinkThese.length ) {
			simple_regex_str += "|";
			named_regex_str += "|";			
		}
	}
	// Close off regex strings
	simple_regex_str += ")(?:#[^\\|\\]]*?)?\\s*\\]\\](?![^<]*?-->)";
	named_regex_str += ")(?:#[^\\|\\]]*?)?\\s*\\|([^\\[\\]\\n\\r]+?)\\]\\](?![^<]*?-->)";
	var simple_regex = new RegExp( simple_regex_str, "g" );
	var named_regex = new RegExp( named_regex_str, "g" );
	
	// Set index articles for names, which should be treated like disambiguation pages, will contain
	// one of these templates
	var name_set_index_regex = /\{\{\s*(?:[Gg]iven[ _]name|[Ss]urnames?|[Nn]ickname|[Ff]irst[ _]name|[Ff]orename|[Dd]isambigN(?:ame|m)?)\s*(?:\|.*?)*?\}\}/g;
	if ( name_set_index_regex.test(wikitext) ) {
		isDab = true;
	}
	
	// List items removals:
	if ( ns === 10 ) {
		//Within navbox templates, remove links entirely, including the preceding *'s and the following newline
		var navbox_regex = new RegExp("\\{\\{[Nn]avbox(?: with collapsible groups| with columns)?\\s*\\|" +
			"(?:.|\\n)*?(?:(?:\\{\\{" +			// accounts for templates within the navbox
				"(?:.|\\n)*?(?:(?:\\{\\{" +		// accounts for templates within templates within the navbox
					"(?:.|\\n)*?" +
				"\\}\\})(?:.|\\n)*?)*?" +
			"\\}\\})(?:.|\\n)*?)*" +
		"\\}\\}", "g");
		var navbox_simple_regex = new RegExp( "\\*+\\s*" + simple_regex_str + "[\\r\\t\\f\\v ]*\\n", "g" );
		var navbox_named_regex = new RegExp( "\\*+\\s*" + named_regex_str + "[\\r\\t\\f\\v ]*\\n", "g" );
		//Find navbox templates
		var navboxes = wikitext.match(navbox_regex);
		if ( navboxes ) {
			// remove regex matches from wikitext
			for ( var jj=0; jj<navboxes.length; jj++ ) {
				replacement = navboxes[jj].replace(navbox_simple_regex, "").replace(navbox_named_regex, "");
				wikitext = wikitext.replace(navboxes[jj], replacement);
			}
		}
	} else if ( isDab ) {
		// For disambiguation pages, entirely remove list items containing a backlink, including the
		// preceding *'s and the following newline (but skiping list items with multiple links)
		var dab_simple_regex = new RegExp( "\\*+[^\\[\\]\\n\\r]*" + simple_regex_str + "[^\\[\\]\\n\\r]*\\n", "g" );
		var dab_named_regex = new RegExp( "\\*+[^\\[\\]\\n\\r]*" + named_regex_str + "[^\\[\\]\\n\\r]*\\n", "g" );	
		wikitext = wikitext.replace(dab_simple_regex, "").replace(dab_named_regex, "");
	} else {
		// For See also sections, entirely remove list items containing a backlink, including the
		// preceding *'s and the following newline (but skiping list items with multiple links)
		var seealso_regex = /==+\s*[Ss]ee [Aa]lso\s*==+\n+(?:^.*\n*)*?(?:(?===+)|$)/gm;
		var seealso_simple_regex = new RegExp( "\\*+[^\\[\\]\\n\\r]*" + simple_regex_str + "[^\\[\\]\\n\\r]*\\n", "g" );
		var seealso_named_regex = new RegExp( "\\*+[^\\[\\]\\n\\r]*" + named_regex_str + "[^\\[\\]\\n\\r]*\\n", "g" );
		var seealso = wikitext.match(seealso_regex);
		if ( seealso ) {
			// remove regex matches from wikitext
			for ( var kk=0; kk<seealso.length; kk++ ) {
				replacement = (seealso[kk]+"\n").replace(seealso_simple_regex, "").replace(seealso_named_regex, "");
				wikitext = wikitext.replace(seealso[kk].trim(), replacement.trim());
			}
		}
		// For other lists, entirely remove list items if the only content is a single backlink,
		// including the preceding *'s and the following newline
		var list_simple_regex = new RegExp( "\\*+[\\t ]*" + simple_regex_str + "[\\t ]*\\n", "g" );
		var list_named_regex = new RegExp( "\\*+[\\t ]*" + named_regex_str + "[\\t ]*\\n", "g" );	
		wikitext = wikitext.replace(list_simple_regex, "").replace(list_named_regex, "");
	}
	// Mark any other list items with backlinks for manual review, using {{subst:void}}
	var manual_review_regex = new RegExp( '^\\*+.*(?:' + simple_regex_str + '|' +
		named_regex_str + ').*$', 'gm' );
	wikitext = wikitext.replace(manual_review_regex, '{{subst:void}}$&');

	// For all other links, replace with unlinked text
	wikitext = wikitext.replace(simple_regex, "$1").replace(named_regex, "$1");

	return wikitext;
};

/**
 * val2key
 *
 * For an object `obj` with key:value pairs, return a value's corresponding key.
 *
 * @param {string|number} val
 *  Value to seach for.
 * @param {object} obj
 *  Object to search in.
 * @return {string|number} Key corresponding to the input value.
 */
extraJs.val2key = function(val, obj) {
    for ( var k in obj ) {
        if ( obj[k] === val ) {
            return k;
        }
    }
};

// </nowiki>