مدیاویکی:Gadget-Extra-Editbuttons-persianwikitools.js: تفاوت میان نسخه‌ها

از ویکی پاسخ
بدون خلاصۀ ویرایش
(اگر صفحه‌ای حاوی نویسه‌های خاص مثل پرانتز باشد، اینجا خطای عبارات باقاعده می‌دهد؛ راه حل آن است که در عنوان صفحه ابتدا از نویسه رهایی استفاده شود)
خط ۸۳: خط ۸۳:
urlArchive: /\/\/web\.archive\.org[^\|\}\n\<\>]+/gi,
urlArchive: /\/\/web\.archive\.org[^\|\}\n\<\>]+/gi,
mediawikiFunctions: /\{\{\#(?:\{\{.*?\}\}|[^\}])*\}\}/gi,
mediawikiFunctions: /\{\{\#(?:\{\{.*?\}\}|[^\}])*\}\}/gi,
articleTitleParts: new RegExp('\\s' + mw.config.get('wgTitle').split(' ').join('\\s|\\s') + '\\s', 'g'),
articleTitleParts: new RegExp('\\s' + escapeRegExp(mw.config.get('wgTitle')).split(' ').join('\\s|\\s') + '\\s', 'g'),
catgories: /\[\[(?:رده|[Cc]ategory)\:[^\]]+\]\]/gi
catgories: /\[\[(?:رده|[Cc]ategory)\:[^\]]+\]\]/gi
};
};
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}


function escapeRE(s) {
function escapeRE(s) {
خط ۶۶۷: خط ۶۷۱:
.replace(/\=\s*(?:[Ss]ee [Aa]lso|همچنین ببینی[مد]|بیشتر ببینی[مد]|همچنین نگاه کنید|بیشتر بدانی[مد]|مراجعات مرتبط|جستار وابسته|مطلب مرتبط|مطالب مرتبط|جستارهای مشابه|جستارهای دیگر)\s*\=/g, '= جستارهای وابسته =')
.replace(/\=\s*(?:[Ss]ee [Aa]lso|همچنین ببینی[مد]|بیشتر ببینی[مد]|همچنین نگاه کنید|بیشتر بدانی[مد]|مراجعات مرتبط|جستار وابسته|مطلب مرتبط|مطالب مرتبط|جستارهای مشابه|جستارهای دیگر)\s*\=/g, '= جستارهای وابسته =')
.replace(/\=\s*(?:منبع|منبع[‌ ]?ها|رفرنس|رفرنس[‌ ]?ها|ارجاع[‌ ]?ها|ارجاع|مرجع[‌ ]?ها|رفرنس|برگرفته از|مراجع|منابع و یادداشت[‌ ]?ها|منبع|مرجع|م[آا]خذ|منابع و م[آا]خذ|منابع و پانویس‌ها|فهرست مراجع|لیست مراجع|فهرست ارجاع[‌ ]?ها|فهرست ارجاع|[rR]eferences)\s*\=/g, '= منابع =')
.replace(/\=\s*(?:منبع|منبع[‌ ]?ها|رفرنس|رفرنس[‌ ]?ها|ارجاع[‌ ]?ها|ارجاع|مرجع[‌ ]?ها|رفرنس|برگرفته از|مراجع|منابع و یادداشت[‌ ]?ها|منبع|مرجع|م[آا]خذ|منابع و م[آا]خذ|منابع و پانویس‌ها|فهرست مراجع|لیست مراجع|فهرست ارجاع[‌ ]?ها|فهرست ارجاع|[rR]eferences)\s*\=/g, '= منابع =')
//.replace(/\=\s*(?:مطالعه بیشتر|بیشتر بخوانی[مد])\s*\=/g, '= برای مطالعهٔ بیشتر =')
.replace(/\=\s*(?:مطالعه بیشتر|بیشتر بخوانی[مد])\s*\=/g, '= برای مطالعهٔ بیشتر =')
.replace(/^\={3,}\s*(جستارهای وابسته|پانویس|منابع)\s*\={3,}$/g, '== $1 ==');
.replace(/^\={3,}\s*(جستارهای وابسته|پانویس|منابع)\s*\={3,}$/g, '== $1 ==');
}
}

نسخهٔ ‏۱۴ نوامبر ۲۰۲۰، ساعت ۲۱:۰۸

// <nowiki> // DO NOT REMOVE THIS LINE EVER
/**
 * Wikipedia specific Persian text style improvement tools
 * Tests: [[مدیاویکی:Gadget-Extra-Editbuttons-tests.js]] [[وپ:تست]]
 * See also: [[مدیاویکی:Gadget-Extra-Editbuttons-persiantools.js]]
 */
/*global persianTools, persianToolsDictionary, autoEd*/
var persianWikiTools = (function () {
	'use strict';
	var persianMonths = ["فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند"];
	//http://www.entitycode.com/
	var htmlEntityCodes = {
		"&iexcl;": "¡", "&cent;": "¢", "&pound;": "£", "&curren;": "¤",
		"&yen;": "¥", "&brvbar;": "¦", "&sect;": "§", "&copy;": "©",
		"&middot;": "·", "&times;": "×", "&rdquo;": "”", "&dagger;": "†",
		"&Dagger;": "‡", "&euro;": "€", "&laquo;": "«", "&reg;": "®",
		"&deg;": "°", "&plusmn;": "±", "&sup2;": "²", "&sup3;": "³",
		"&para;": "¶", "&sup1;": "¹", "&raquo;": "»", "&frac14;": "¼",
		"&frac12;": "½", "&frac34;": "¾", "&iquest;": "¿", "&divide;": "÷",
		"&ndash;": "–", "&mdash;": "—", "&lsquo;": "‘", "&rsquo;": "’",
		"&ldquo;": "“", "&trade;": "™", "&bull;": "•", "&hellip;": "…",
		"&permil;": "‰", "&lsaquo;": "‹", "&rsaquo;": "›", "&larr;": "←",
		"&uarr;": "↑", "&rarr;": "→", "&darr;": "↓", "&harr;": "↔",
		"&crarr;": "↵", "&minus;": "−", "&radic;": "√", "&infin;": "∞",
		"&loz;": "◊", "&spades;": "♠", "&rfloor;": "⌋", "&nbsp;": " ",
		"&ne;": "≠", "&ap;": "≈", "&approx;": "≈", "&asymp;": "≈",
		"&rceil;": "⌉", "&lfloor;": "⌊", "&diams;": "♦", "&auml;": "ä",
		"&ouml;": "ö", "&uuml;": "ü", "&szlig;": "ß", "&aring;": "å",
		"&oline; ": "‾ ", "&aelig;": "æ", "&ccedil;": "ç", "&ntilde;": "ñ",
		"&acirc;": "â", "&aacute;": "á", "&agrave;": "à", "&#36;": "$",
		"&clubs;": "♣", "&hearts;": "♥", "&Prime;": "″", "&prime;": "′",
		"&lceil;": "⌈", "&mldr;": "…", "&bullet;": "•", "&grave;": "`",
		"&pm;": "±", "&acute;": "´", "&centerdot;": "·", "&half;": "½",
		"&Auml;": "Ä", "&Ouml;": "Ö", "&Uuml;": "Ü", "&rsquor;": "’",
		"&lsquor;": "‚", "&sbquo;": "‚", "&rdquor;": "”", "&bdquo;": "„",
		"&ldquor;": "„", "&ddagger;": "‡", "&div;": "÷", "&leq;": "≤",
		"&geq;": "≥", "&le;": "≤", "&ge;": "≥"
	}; // &quot; , &amp; &lt; &gt; &#124;
	var patterns = {
		arabicDigitsEnglishContext: /[a-z]([\|a-z %"'\._:\;,\-\\\/\(\)\#\^\+\d><–\[\]&?{}](?!\|\|))*\d|(\d|[a-z])[a-z %"'\._:\;\|,\-\\\/\(\)\#\^\+\d><–\[\]&?{}]*[a-z]\d*/gi,
		arabicTagEnclosed: /\{\{(?:عربی|شروع عربی|آغاز عربی)\}\}([\s\S]*?)\{\{(?:پایان عربی)\}\}/g,
		LtRTagEnclosed: /\{\{(?:چپ چین|چپ‌چین)\}\}([\s\S]*?)\{\{(?:پایان چپ‌چین|پایان چپ چین|پایان)\}\}/g,
		argumentsBlacklist: /(?:accessdate|namespace|legend1start|image|تصویر|doi|style|شابک|عرض|bibcode|isbn|issn|pmid|arxiv|upright|upleft|padding|spacing|border|filename|نام پرونده|ایستاده)\s*\=\s*[^\|\}\]]*/gi,
		color: /#(?:[abcdef0-9]{8}|[abcdef0-9]{6}|[abcdef0-9]{3})/gi,
		//colorAsParameter: /\=\s*(?:[abcdef0-9]{8}|[abcdef0-9]{6}|[abcdef0-9]{3})(?:[\s\|\}]|$)/gi,
		// space, ", \t, \n, {, |, }, ... they will interfere with wiki markup
		decodeUriBlacklist: /(?:%20|%27|%5C|%5E|%60|%23|%25|%3C|%3E|%5B|%5D|%22|%09|%0A|%7B|%7C|%7D)/gi,
		diffLink: /\[\[(?:ویژه|Special):(?:تفاوت|Diff)\/[^\|\]]*/gi,
		englishDate: /\d{1,2},? [a-z]{3,} \d{2,4}/gi, // 3, May 2013
		fileNames: /(?:پرونده|File|تصویر|Image)\:.*?(?=\||\]|\n|$)|=.*\.(?:flac|gif|jpeg|jpg|mid|mp3|mpeg|mpg|ogg|pdf|png|svg|wav|webm)$/mgi, // don't capture | after
		fileParameter: /\|\s*(image|تصویر)\s*\=\s*.*/g,
		ipSign: /\[\[ویژه:مشارکت\u200cها.*?\]\]/g,
		isbn: /(?:ISBN|ISSN|PMID) [\d\-]*/gi,
		galleryTag: /<gallery.*?>[\s\S]*?<\/gallery>/g,
		htmlAttributes: /(?:style|perrow|colspan|color|rowspan|cellpadding|cellspacing|height|width|size|border|thumbtime|name|perrow|upright|upleft)\s*[\=\:]\s*(?:['\"].*?['\"]|[\da-z]+)/gi,
		htmlEntity: /&#\d+;/,
		imagePixelSize: /[\|=] *[x\d]+?(px|پیکسل)[\]\|\s]/g, // means it will capture |10px| and |10x10px|
		insideQuote: /[^ا]".*?"/g,
		wikilinkTargets: /\[[^\[|\]]+/g,
		nowikiTag: /<nowiki>.+?<\/nowiki>/g,
		preTag: /<pre.*?>.*?<\/pre>/g,
		insideHtmlComment: /<\!\-\-[\s\S]*?\-\->/g,
		linksOnEnglishContext: /[a-z][\:\,\. ]*\[\[[\da-z\-\, ]*/gi,
		mathTag: /<math.*?>[\s\S]*?<\/math>/g,
		otherLanguagesInline: /\{\{(?:به .+?|پم|به انگلیسی|انگلیسی|عربی|متن عربی|عبارت عربی|حدیث|به عربی|به اردو|اردو|lang\-[au]r|پینگ|ping)[\s\S]*?\}\}/g,
		parameter: /\{\{\{\d+/gi,
		parenthesesAfterDigits: /\w\s?\([\w\s\.\-]*?\)/g,
		parenthesesHa: /\)ها/g,
		ref: /(?:<ref[^\/]*?>[\s\S]*?<\/ref>|<ref[^\/]*?\/>)/g, // inside <ref></ref> and <ref/>
		refname: /\<ref name\=.*?\>/g,
		citation: /\{\{\s*(?:[Cc]it|یادکرد).*?[_\s]*(?:\{\{.*?\}\}|[^\}])*\}\}/g,
		signatures: /\[\[(?:کاربر|User|بحث[ _]کاربر|User[_ ]talk)\:.*?\]\]/gi,
		sourceTag: /(<source.*?>[\s\S]*?<\/source>|<syntaxhighlight.*?>[\s\S]*?<\/syntaxhighlight>|<code.*?>[\s\S]*?<\/code>|<timeline.*?>[\s\S]*?<\/timeline>)/g,
		tagNames: /<\/?[a-zA-Z\d]*/g,
		graphTemplate: /(?:\<div[^\>]+>)?\{\{[ \_]*(?:الگو|Template)?(?:[Gg]raph\:?[^\|\}]+).*?[_\s\n]*(?:\{\{.*?\}\}|[^\}])*\}\}(?:\<\/div\>)/g,
		templateEnglishName: /(الگو|Template):[a-z][a-z\d\-\+_]+/gi,
		templateWithEnglishName: /\{\{[ \_]*(?:الگو|Template)?[\x00-\x7a~]*\|.*?\}\}/gi,
		templateParameterName: /\|\s*(?=[a-z_]*\d)[a-z_\d]*\s*\=/gi,
		globalExceptionTag: /(<nowiki>.+?<\/nowiki>|<!--[\s]*ابر[\s]*-->.+?<!--[\s]*\/[\s]*ابر[\s]*-->|\{\{استثنای ابرابزار\|[\s\S]*?\}\})/gi,
		translatedUrl: /.(کام|نت|آی‌آر)/g,
		boxVar: /([a-zA-Z][۱۲۳۴۵۶۷۸۹۰]+) *\=/g,
		url: /\/\/.*?(?=[\s\n\|\}\]<]|$)/gi,	 // بدون https?: هم ممکن است
		urlArchive: /\/\/web\.archive\.org[^\|\}\n\<\>]+/gi,
		mediawikiFunctions: /\{\{\#(?:\{\{.*?\}\}|[^\}])*\}\}/gi,
		articleTitleParts: new RegExp('\\s' + escapeRegExp(mw.config.get('wgTitle')).split(' ').join('\\s|\\s') + '\\s', 'g'),
		catgories: /\[\[(?:رده|[Cc]ategory)\:[^\]]+\]\]/gi
	};
	
	function escapeRegExp(string) {
		return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
	}

	function escapeRE(s) {
		return s.replace(/([$()*+\-.?[\\\]^{|}])/g, '\\$1');
	}

	function descendingFromComparetor(x, y) {
		return x.from - y.from;
	}
	function removeCheckDict(text) {
		// رفع مشکل [[Special:Permalink/25174868#متن هایلایت‌شده]]
		var otext = ''
		while (otext != text) {
			otext = text
			text = text.replace(/\<span[^>]+CheckDictation\-marked[^>]+\>([^<>]+)\<\/span\>/g, '$1')
		}
		return text
	}
	function replaceExcept(text, callback, excepts) {
		var match, result = [], i, ranges, minRange, to, min, max;
		while (text !== '') {
			ranges = [];

			for (i in excepts) {
				if (excepts.hasOwnProperty(i)) {
					// a global regex should be reset before calls
					excepts[i].lastIndex = 0;
					match = excepts[i].exec(text);
					if (match !== null) {
						ranges.push({
							from: match.index,
							to: match.index + match[0].length
						});
					}
				}
			}

			// so nothing is matched
			if (ranges.length === 0) {
				result.push(callback(text));
				break;
			}

			minRange = ranges.sort(descendingFromComparetor)[0];
			min = minRange.from;

			to = [];
			for (i in ranges) {
				if (ranges.hasOwnProperty(i)) {
					if (ranges[i].from <= minRange.to) {
						to.push(ranges[i].to);
					}
				}
			}
			max = Math.max.apply(null, to);

			result.push(callback(text.substr(0, min)));
			result.push(text.substr(min, max - min));
			// console.log('Excepted: "' + text.substr(min, max - min) + '"');
			text = text.substr(max);
		}
		return result.join('');
	}

	function wikiConvertToPersianCharacters(text) {
		return replaceExcept(
			text,
			persianTools.toStandardPersianCharacters,
			[patterns.globalExceptionTag, patterns.otherLanguagesInline, patterns.arabicTagEnclosed, patterns.fileNames, patterns.signatures, patterns.url, patterns.fileParameter]
		);
	}

	if (!String.prototype.trim) { // if is not available currently
		String.prototype.trim = function () {
			return this.replace(/^\s+|\s+$/g, '');
		};
	}

	function autoFormatCleanReferences(str) {
		// تمیزکاری autoFormater.js > cleanReferences
		str = str.replace(
			/<\s*references\s*(\s\b[^<>]*?)?\s*(?:\/|>\s*<\s*\/\s*references)\s*>/gi,
			'<references$1/>'
		);
		if (mw.config.get('wgNamespaceNumber') === 0) {
			//ویکی‌پدیای فارسی منبع برای ارجاع نیست  
			str = str.replace(/\<ref[^>]*\>\[?(?:https?:)?\/\/fa.(?:m\.)?wikipedia.org\/[^\<\n\}\]\[]+\]?\<\/ref\>/gi, '')
		};
		str = str.replace(/<\s*references\s*(\s\b[^<\/>]*?)?\s*>/gi, '<references$1>');
		str = str.replace(/<\s*\/\s*references\s*>/gi, '<\/references>');
		var re = /(<references[^<\/>]*)>/g, m;
		while (m = re.exec(str)) {
			if (str.indexOf('<\/references>', m.index) < 0) {
				str = str.slice(0, m.index) + m[1] + '/>' + str.slice(m.index + m[0].length);
			}
		}
		str = str.replace(/< *ref\s*(\s\b[^<>]*?)\s*(?:\/+|>\s*<\s*\/+\s*ref) *>/gi, '<ref$1/>');

		/* remove line breaks with assays only the top of the article */
		var i = str.indexOf('<references'),
			slice;
		if (i > 0) {
			slice = str.slice(i);
			slice = slice.replace(/< *ref\s*(\s\b[^<\/>]*?)?\s*>[\t ]*/gi, '<ref$1>');
			slice = slice.replace(/(?:(\n[\t ]*)|[\t ]*)<\s*\/+\s*ref\s*>/gi, '$1<\/ref>');
			str = str.slice(0, i);
		}
		str = str.replace(/< *ref\s*(\s\b[^<\/>]*?)?\s*>\s*/gi, '<ref$1>');
		str = str.replace(/\s*<\s*\/+\s*ref\s*>/gi, '<\/ref>');
		if (slice) {
			str += slice;
		}

		/* Space between the end of block and remove <ref> or two <ref> */
		str = str.replace(/([!,.;?]|<ref\b[^<>]*(?:\/|>[^<>]*<\/ref)>) +(?=<ref[ >])/gi, '$1');
		/* Two identical punctuation before and cut after a <ref> on one */
		str = str.replace(/([!,.:;?])(<ref\b[^<>]*(?:\/|>[^<>]*<\/ref)>)\1/gi, '$1$2');
		/* ref inside small */
		return str.replace(/\<small\> *(\<ref[^\<]+\<\/ref\>)<\/small\>/gi, '$1');
	}

	function autoFormatCleanTags(str) {
		str = str.replace(/(<\/?s)trike\b/gi, '$1');
		str = str.replace(
			/\<u\>([^\<]+)\<\/u\>/gi,
			"''$1''"
		);
		str = str.replace(
			/\<center\>/gi,
			"{{وسط‌چین}}"
		);
		str = str.replace(
			/\<\/center\>/gi,
			"{{پایان}}"
		);
		str = str.replace(
			/<sub\s*(>[^<>]*<)\s*(?:su[bp]\s*[.\/\\]+|[.\/\\]+\s*su[bp])\s*>/gi,
			'<sub$1/sub>'
		);
		str = str.replace(
			/<sup\s*(>[^<>]*<)\s*(?:su[bp]\s*[.\/\\]+|[.\/\\]+\s*su[bp])\s*>/gi,
			'<sup$1/sup>'
		);

		/* Drop default font attributes */
		str = str.replace(
			/(<font\b[^<>]*?)\s+fa\w+(?:[\s"',=]*(?:Arial|Helvetica(?:\W?N\w*)?|sans\W?serif)\b)+[\s"';]*(?=\s\w+\s*=|>)/gi,
			'$1'
		);
		str = str.replace(
			/(<font\b[^<>]*?)\s+size[\s"',=]*(?:-1\b|2\b|100\b[ ,.]*\d*%|1(?:\.0*)?em\b)["';]*/gi,
			'$1'
		);
		/* Remove inline elements with no attributes */
		while (/<(font|span)\s*>\s*(?:<(?!\1)|[^<])*?\s*<\/\1[^<>]*>/i.test(str)) {
			str = str.replace(/<(font|span)\s*>[ \n]*((?:<(?!\1)|[^<])*?)[ \n]*<\/\1[^<>]*>/gi, '$2');
		}
		str = str.replace(
			/<font\s+color[\s"',=]*(#[\dA-F]{3,6}|[a-z]{3,20})[\s"';]*>((?:<(?!font)|[^<])*?)<\/font[^<>]*>/gi,
			'<span style="color:$1;">$2<\/span>'
		);
		str = str.replace(
			/<font\s+size[\s"',=]*(?:-[2-9]|[01])[\s"';]*>((?:<(?!font)|[^<])*?)<\/font[^<>]*>/gi,
			'<small>$1<\/small>'
		);
		str = str.replace(
			/<font\s+size[\s"',=]*(?:[+-]0|3)[\s"';]*>((?:<(?!font)|[^<])*?)<\/font[^<>]*>/gi,
			'<span style="font-size:larger;">$1<\/span>'
		);
		/* Merge nested inline tags */
		str = str.replace(
			/<(abbr|cite|mark|q|s|small|u)\s*><(font|span)\s+style\s*=\s*["']?([^\n"<>]*?);?["']?\s*>([^<>]*)<\/\2\s*>\s*(?=<\/\1\s*>)/gi,
			'<$1 style="$3;">$4'
		);
		str = str.replace(
			/(<span\b[^<>]*?)\s+style\s*=\s*["']?([^\n"<>]*?);?["']?\s*><span\s+style\s*=\s*["']?([^\n"<>]*?);?["']?\s*>([^<>]*)<\/span\s*>\s*(?=<\/span\s*>)/gi,
			'$1 style="$2; $3;">$4'
		);

		/* Verschiedenste Formen von HTML-Zeilenumbrüchen durch einheitliche ersetzen */
		str = str.replace(/<(?:[\s\/\\]*br\b)+\s*(\s\w[^<>]*?)?[\s.\/\\]*>/gi, '<br$1/>');
		/* Unnötige HTML-Zeilenumbrüche entfernen, wenn sowieso ein Absatz folgt */
		str = str.replace(/ *(?:{{سخ}}|<br \/>)(?=[\r\n][\n#*:;\|}\]])/gi, '');
		str = str.replace(
			/<(ref|small|su[bp])\b\s*(\s\w[^<>]*?)?\s*><small\s*>([^<>]*)<\/small\s*><\/\1\s*>/gi,
			'<$1$2>$3<\/$1>'
		);
		str = str.replace(
			/<small\s*><(ref|small|su[bp])\b\s*(\s\w[^<>]*?)?\s*?( ?\/|>[^<>]*<\/\1)\s*><\/small\s*>/gi,
			'<$1$2$3>'
		);
		/* Drop old navigation bar wrapper, see [[Template:NaviBlock]] */
		return str.replace(
			/<div\s+class[^<>\w]*BoxenVerschmelzen[^<>\w]*>\s*(\{\{[^#:<>{}]*\}\})\s*<\/div>/gi,
			'$1'
		);
	}

	function autoFormatCleanDuplicateLinks(str) {
		/* Exclude files and infoboxes from the start of the article */
		var m = /^(?:\s*\[\[\w+:(?:\[\[[^\n\]]*\]\]|[^\n\]])*\]\])*(?:\s*\{\{(?:\{\{[^}]*\}\}|[^}])*\}\})+/.exec(str),
			start = m ? m[0].length : 0,
			found = [],
			a = [];
		/* Unlink years that are linked more than one time */
		var re = /\[\[ *([۱۲][۱۲۳۴۵۶۷۸۹۰]{3}|[۱۲][۱۲۳۴۵۶۷۸۹۰]{3} \((میلادی|قمری)\)) *\]\]/g;
		/* In each case the first discovery of a year noted entlinken thereafter */
		while (m = re.exec(str)) {
			if (m.index >= start) {
				found[m[1]] ? a.push(m) : found[m[1]] = true;
			}
		}
		var r = '',
			p = 0;
		for (var i = 0; i < a.length; i++) {
			r += str.slice(p, a[i].index) + a[i][1];
			p = a[i].index + a[i][0].length;
		}
		return p ? r + str.slice(p) : str;
	}

	function autoFormatCleanDates(str) {
		var months = ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"].concat(persianMonths);

		/* Add missing space between day and month */
		str = str.replace(new RegExp('([\\s!\'(>|„](?:3[01]|[12]\\d|0?[1-9])\\.?)(?=(?:' +
			months.join('|') + ')\\b)', 'g'), '$1 ');
		/* No non-breaking space between month and year */
		str = str.replace(new RegExp('(\\b(?:3[01]|[12]\\d|0?[1-9])\\.?(?:[\\s\\xA0]|&nbsp;)+(?:' +
			months.join('|') + '))(?:\xA0|&nbsp;)(?=[12]\\d{3}\\b)', 'g'), '$1 ');
		/* Missverständliches deutsches Datumsformat durch Langform ersetzen */
		var separator = ' ';
		str = str.replace(
			/([\s'(>„])(3[01]|[12]\d|0?[1-9])\. *(1[012]|0?[1-9])\. *(?=[12]\d{3}[!,.:;?]?[\s')<\]“])/g,
			function ($0, $1, $2, $3) {
				return $1 + ($2 | 0) + separator + months[$3 | 0] + ' ';
			}
		);
		// عدد فارسی
		str = str.replace(new RegExp('([\\s!\'(>|„](?:۳[۰۱]|[۱۲][۱۲۳۴۵۶۷۸۹]|۰?[۱۲۳۴۵۶۷۸۹])\\.?)(?=(?:' +
			months.join('|') + ')[\\s\')<\\]»}|])', 'g'), '$1 ');
		/* No non-breaking space between month and year */
		str = str.replace(new RegExp('([\\s\'(>«](?:۳[۰۱]|[۱۲][۱۲۳۴۵۶۷۸۹]|۰?[۱۲۳۴۵۶۷۸۹])\\.?(?:[\\s\\xA0]|&nbsp;)+(?:' +
			months.join('|') + '))(?:\xA0|&nbsp;)(?=[۱۲][۱۲۳۴۵۶۷۸۹]{3}[\\s\')<\\]»}|])', 'g'), '$1 ');
		/* Missverständliches deutsches Datumsformat durch Langform ersetzen */
		var separator = ' ';
		str = str.replace(
			/([\s'(>«])(۳[۰۱]|[۱۲][۱۲۳۴۵۶۷۸۹]|۰?[۱۲۳۴۵۶۷۸۹])\. *(۱[۰۱۲]|۰?[۱۲۳۴۵۶۷۸۹])\. *(?=[۱۲][۱۲۳۴۵۶۷۸۹]{3}[!,.:;?]?[\s')<\]»}|])/g,
			function ($0, $1, $2, $3) {
				return $1 + ($2 | 0) + separator + months[$3 | 0] + ' ';
			}
		);
		return str
	}

	function quotationReplace(line) {
		[
			['“', '”'], ['”', '“'], ['‘', '’'], ['’', '‘'], ['‚', '’'], ['„', '”'], ['\\<\\<', '\\>\\>'], ['\\(\\(', '\\)\\)']
		].forEach(function(qs) {
			line = line.replace(new RegExp(
				'(^|[' + persianTools.persianCharacters + '\\:>،»؛\\s\\n\\}\\]\\.]+)'
				+ qs[0] + '((?:\\[\\[|).*?[' + persianTools.persianCharacters + '\\n]+?(?:\\]\\]|\\.|\\<|\\:|\\{|\\[|…|))' + qs[1]
				+ '([' + persianTools.persianCharacters + '،«؛\\s\\n\\.\\[\\{]|$)', 'g'
			), '$1«$2»$3');
		});
		return line;
	}

	function quotation(text) {
		// این تابع زمانی گیومه را به فارسی تیدیل می‌کند که در پاراگراف مورد نظر تعداد گیومهٔ لاتین زوج باشد.
		var lines = text.split(/\n\n/);
		var result = [];
		for (var i = 0; i < lines.length; ++i) {
			var line = lines[i];
			if ((line.match(/"/g) || []).length % 2 === 0) { // count of quote marks
				// تبدیل گیومهٔ لاتین به فارسی
				// این دستور در ابتدا باشد تا فاصله‌های قبل و بعد گیومه هم اصلاح شود
				line = line.replace(
					new RegExp('(^|[' + persianTools.persianCharacters + '\\:>،»؛\\s\\n\\}\\]\\.\\)]+)"((?:\\[\\[|).*?[' + persianTools.persianCharacters + '؛\\n،]+?(?:\\]\\]|\\.|\\<|\\:|…|))"([' + persianTools.persianCharacters + '،«؛\\s\\n\\.\\[\\{\\(]|$)', 'g'),
					'$1«$2»$3'
				);
				// if some of quote marks are remained from conversion, something might wrong, revert
				var testline = line.replace(/(?:<ref[^\/]*?>[\s\S]*?<\/ref>|<ref[^\/]*?\/>)/g, '')

				if (testline.match(/"/g)) {
					line = lines[i];
				}
			}
			// رفع مشکل استفاده از ـً به جای گیومه لاتین در متن فارسی
			line = line.replace(new RegExp('ا\\"([ ]*[' + persianTools.persianCharacters + '])', 'g'), 'اً$1')
			line = line.replace(new RegExp('ا\\”([ ]*[' + persianTools.persianCharacters + '])', 'g'), 'اً$1')
			line = quotationReplace(line);
			result.push(line);
		}
		return result.join('\n\n');
	}
	/**
	 * افزودن ستون به الگوی پانویس
	 * @param {string} text محتوا
	*/
	function addColumnToRefTemplate(text) {
		var refTemplate = /\{\{پانویس([^\}\{]+)?\}\}/i.exec(text), needChange = false;
		if (refTemplate) {
			if ((text.match(/<ref/gi) || []).length >= 6) {
				if (refTemplate[1] !== undefined) {
					var refParams = refTemplate[1].split('|');
					for (var i = refParams.length - 1; i >= 0; i--) {
						// اگر از پیش ستون یا پارامتر عرض تعریف شده‌باشد تغییری ایجاد نمی‌شود.
						if (refParams[i].length == 1 || refParams[i].indexOf('عرض') > -1) {
							needChange = true;
							break;
						}
					}
				}
				if (refTemplate[1] === undefined || !needChange) {
					return text.replace(refTemplate[0], refTemplate[0].replace('}}', '|۲}}'));
				}
			}
		} else {
			if ((mw.config.get('wgNamespaceNumber') === 0 && mw.config.get("wgEditMessage") === 'editing') || mw.config.get('wgPageName') === "ویکی‌پدیا:ویکی‌پروژه_ابزارها/آزمایش_واحد") {
				if ((text.match(/<ref/gi) || []).length > 0 && /\{\{پانویس([^\}\{]+)?\}\}/i.exec(text) != null) {
					var text2 = text.replace('== منابع ==', '== منابع ==\n{{پانویس}}')
					if (text2 == text) {
						text2 = text.replace('== پانویس ==', '== پانویس ==\n{{پانویس}}')
					}
					if (text2 == text) {
						text2 = text.replace('[[رده:', '== منابع ==\n{{پانویس}}\n\n[[رده:')
					}
					if (text2 == text) {
						text2 = text + '\n== منابع ==\n{{پانویس}}'
					}
					text = text2
				}
			}
		}
		return text;
	}

	/**
	 * اصلاح پیوندها
	 * @param  {string} text محتوا
	 * @return {string}
	 */
	function fixBadLinks(text) {
		// حذف متن جایگزین پیوند اگر با نشانی پیوند برابر باشد؛ مانند [[سلام|سلام]]
		text = text.replace(/\[{2}([^\|]+)\|\1\]{2}/gi, '[[$1]]');

		// حذف پیوند سال و روز ماه
		text = text.replace(/\[{2}([۰-۹]+|[۰-۹]+ [\)\(\u0621-\u0655\u067E\u0686\u0698\u06AF\u06A9\u0643\u06AA\uFED9\uFEDA\u06CC\uFEF1\uFEF2]+)(?:\|([^\]\|\[]+))?\]{2}/g, function (match, p1, p2) {
			// اگر فقط سال پیوند شده‌باشد یا به شکل [[سال|همان سال]] باشد فقط سال را می‌گرداند.
			var calendar_type = / \((میلادی|قمری|خورشیدی|شمسی|پیش از میلاد|قبل از میلاد)\)/g;
			if (p1 !== p2 && p1.replace(calendar_type, '') === p2) {
				return p2;
			}//[[Special:Permalink/19908981#حذف پیوند تاریخ‌ها]]
			if (p2 === undefined || p1 === p2) {
				// اگر پیوند به روز و ماه بود، برای جلوگیری از اشتباه و تداخل، بررسی می‌شوند که حتما یکی از ماه‌ها داخل رشته باشد.
				if (p1.indexOf(" ") > -1) {
					var
						months = [
							"محرم", "صفر", "ربیع‌الاول", "ربیع‌الثانی", "جمادی‌الاول", "جمادی‌الثانی", "رجب", "شعبان", "رمضان", "شوال", "ذیقعده", "ذیحجه"
						].concat(persianMonths),
						i;
					for (i = months.length - 1; i >= 0; i--) {
						if (p1.indexOf(months[i]) > -1) {
							return p1.replace(calendar_type, '');
						}
					}
					return "[[" + p1 + "]]";
				}
				return p1;
			}
			// اگر متن جایگزین پیوند مخالف پیوند سال بود، متن جایگزین را برمی‌گرداند.
			return p2;
		});

		return text;
	}

	function wikiPunctuation(text) {
		text = autoFormatCleanReferences(text)
		text = autoFormatCleanTags(text)
		text = autoFormatCleanDuplicateLinks(text)
		text = replaceExcept(
			text,
			function (text) {
				return quotation(text);
			},
			[patterns.ref]
		);
		if (mw.config.get('wgNamespaceNumber') === 0) {
			var old_text = text.replace(/\=\=/g, '')
			if (old_text == text) {//در صورتی که در مقاله بخش‌بندی وجود نداشته باشد
				text = text.replace(/(\n\{\{سخ\}\}|\n\n)(\s|_|)\'\'\'(.*?)\'\'\'(\s|_|)(\{\{سخ\}\}|\n)([\n\#\*])/g, '\n\n== $3 ==\n$6')
			}
		}
		text = replaceExcept(
			text,
			function (text) {
				text = text.replace(
					new RegExp('([' + persianTools.persianCharactersNoVowels + '])ـ+([' + persianTools.persianCharactersNoVowels + '])', 'g'),
					'$1$2'
				);
				return text.replace(new RegExp('([' + persianTools.persianCharacters + '])(\\]\\]|), (\\[\\[|)?(?=[' + persianTools.persianCharacters + "])", 'g'), '$1$2، $3');
			},
			[patterns.globalExceptionTag, patterns.fileNames, patterns.url, patterns.galleryTag, patterns.sourceTag, patterns.translatedUrl, patterns.parenthesesHa]
		);
		text = replaceExcept(
			text,
			function (text) {
				return text.replace(/(<\/ref>)\s+(<ref)/g, '$1$2').replace(/([^=])\s+<ref(?!erences)/g, '$1<ref');
			},
			[/\{\{(پانویس|پانویس‌ها|پی‌نوشت)\s*\|[\s\S]*/]
		);
		return replaceExcept(
			text,
			function (text) {
				return persianTools.punctuation(text)
					.replace(/^([*#]+)([^*#\:\s])/mg, '$1 $2') // Adds a space after the # or * for lists
					.replace(/^([*#]+) {2,}([^*#\:\s])/mg, '$1 $2'); // Trim more that one space after the # or * for lists
			},
			[patterns.globalExceptionTag, patterns.mathTag, patterns.fileNames, patterns.url, patterns.wikilinkTargets,
			patterns.galleryTag, patterns.sourceTag, patterns.translatedUrl, patterns.parenthesesHa]
		)
			.replace(/\u00A0/g, ' ') // convert implicit nbsp to space, probably is being added by some bug on ContentTranslation
			.replace(/٬ /g, '، ')
			.replace(new RegExp('([' + persianTools.persianCharacters + '\]])٬', 'g'), '$1،')
			.replace(new RegExp('([' + persianTools.persianCharacters + '])(\]\]|»|)[ ]*[,]', 'g'), '$1$2، ')
			.replace(/\[\[([^\|\]]+)\|(\'{2,3})\1'{2,3}\]\]/g, '$2[[$1]]$2') // for [[foo|'''foo''']] > '''[[foo]]'''
			.replace(new RegExp('\\[\\[(' + escapeRE(mw.config.get('wgPageName')) + ')\\]\\]', 'g'), '$1') // پیوندزدایی از خود صفحه
			//برگرفته از https://checkwiki.toolforge.org/cgi-bin/checkwikin.cgi?project=fawiki&view=project
			.replace(/\[\[([^\|\]]+)\|\1([\u200c ]*(های?))\]\]/g, '[[$1]]$2')//[[Special:Diff/17515365/17865938]]
			.replace(/([\S]*)[\s\u200c]*-[\s\u200c]*(تاکنون)(?![ ]+)/g, '$1-اکنون')//[[Special:Diff/17515365/17865938]]
			//مشکل در نشانی اینترنتی
			.replace(/(\<ref.*?\>) *(\[|)\www(6|3|)\./gi, '$1$2http://www$3.')
			.replace(/\[\[ *(https?\:\/\/.*?) *\]\]/g, '[$1]')
			.replace(/\[\[ *(\/\/.*?) *\]\]/g, '[$1]')
			.replace(/(https?:\/?\/?){2,}/g, '$1')
			// تمیزکاری autoFormatter.js > cleanExternalLinks
			.replace(/\b(?:http(s?)(?::+\/*|\/\/+:*)\b)+/gi, 'http$1://')
			// repair links with vertical stroke
			.replace(/(\[https?:\/\/[^\s[\]|]*?) *\| *(?=[^\s=[\]|]+\])/gi, '$1 ')
			// supplement slashes at the end easier Domains
			.replace(/(\[https?:\/\/\w[\w.-]*\w\.\w+) +/gi, '$1/ ')
			// Domains lowercase, whether labeled or not
			.replace(/\bhttps?:\/\/\b[0-9a-z.-]*[A-Z][\w.-]*/g, function ($0) {
				return $0.toLowerCase();
			})
			// پیوند به بیرون‌هایی که در میان پیوند نویسهٔ رفتن به خط بعد، وجود داشته باشد
			.replace(/\[(?:https?\:|)\/\/[^\]\[]+\]/g, function (x) {
				x = x.replace(/[\n\r]/g, '');
				return x
			})
			// فاصله اول زیربخش
			.replace(/پیوند\n\=/, 'پیوند=')// [[Special:Diff/20238012/20244702]]
			.replace(/^ +(\=+[^\=]+\=+)/mg, '$1')
			.replace(/\[\[\|/g, '[[')
			.replace(/(\< *\/ *br *\>|\< *br *\\ *\>|\< *br *\. *\>)/g, '<br/>')
			.replace(/(\<br *\/\>|\{\{سخ\}\})([\r\n])(\*|\#|\=\=)/g, '$2$3')
			.replace(/(\<br *\/\>|\{\{سخ\}\}) *\]\]/g, ']]')
			.replace(/\[\[ *(\<br *\/\>|\{\{سخ\}\})/g, '[[')
			.replace(/(\< *span *\/ *\>|\< *\/ *span *\/ *\>)/gi, '</span>')
			.replace(/(\< *center *\/ *\>|\< *\/ *center *\/ *\>)/gi, '</center>')
			.replace(/(\< *b *\/ *\>|\< *\/ *b *\/ *\>)/gi, '</b>')
			.replace(/(\< *div *\/ *\>|\< *\/ *div *\/ *\>)/gi, '</div>')
			.replace(/(\< *p *\/ *\>|\< *\/ *p *\/ *\>)/gi, '</p>')
			.replace(/(\< *td *\/ *\>|\< *\/ *td *\/ *\>)/gi, '</td>')
			.replace(/(\< *small *\/ *\>|\< *\/ *small *\/ *\>)/gi, '</small>')
			.replace(/\[\[([^\]]+)\{\{\!\}\}([^\]]+)\]\]/g, '[[$1|$2]]')//وجود {{!}} درون پیوند
			.replace(/\[{2}([^\|]+)\|\1\]{2}/gi, '[[$1]]')//زمانی که بخش هدف و نمایه پیوند یکی باشند
			.replace(/\[\[(.+)\|('+)(.+\b)('+)\]\]/gi, '$2[[$1|$3]]$4')// انتقال ''' به بیرون پیوند
			// تمیزکاری autoFormatter.js > CleanGalleries
			.replace(/<gallery\b([^<>]*)>([^<>]+)<\/gallery\b[^<>]*>/gi,
				function ($0, $1, $2) {
					return '<gallery' + $1 + '>' + $2
						.replace(/^(\s*)\[+([^[\]]*)\]\]?\s*$/gm, '$1$2')
						.replace(/^(\s*)\[+/gm, '$1') + '<\/gallery>';
				}
			)
			// تمیزکاری پرونده‌ها
			// زمانی که برچسب کوچک در توضیحات تصویر می‌آید برای دستگاه‌های با مانیتور کوچک خواندن متن مشکل می‌شود
			//https://checkwiki.toolforge.org/cgi-bin/checkwiki.cgi?project=fawiki&view=only&id=77
			.replace(/\[\[(پرونده|[Ff]ile)\:((?:\[\[.*?\]\]|[^\]])*)\]\]/g, function ($0, $1, $2) {
				$2 = $2.replace(/\<\/?(big|center|small)>/g, '');
				return '[[' + $1 + ':' + $2 + ']]'
			})
			.replace(/\[\[ *تصو[يی]ر\:/gi, '[[پرونده:')
			// تمیزکاری الگو autoFormater.js > cleanTemplates
			.replace(/\{\{\s*:?\s*(?:الگو|Template)\s*:\s*/gi, '{\{')
			// حذف خط زیر از عنوان الگو
			.replace(/(?:^|[^{])\{\{[ 0-9a-z\xC0-\u024F-]*_[ \w\xC0-\u024F-]*/gi,
				function ($0) {
					return $0.replace(/_+$/, '').replace(/[ _]+/g, ' ').replace(/\{ +/, '{');
				}
			)
			//سایر موارد
			.replace(/\[\[(رده|الگو|ویکی\u200cپدیا)\: +/g, '[[$1:')
			.replace(/\{\{\*\}\}/g, '{{•}}')
			.replace(/[\n\s]*\{\{[•·ن](w?)\}\}\s*/g, '{{•$1}} ')
			.replace(/\=\{\{[•·ن](w?)\}\}\s*/g, '=\n{{•$1}} ')//رفع باگ [[Special:Diff/14799178/16387261]] در خط بالا 
			.replace(/ *(<\/? ?br ?\/?>|\{\{بر\}\}) */g, '{{سخ}}')
			.replace(/\{\{سخ\}\}\n\n/g, '\n\n')
			.replace(/\n\n\{\{سخ\}\}/g, '\n\n')
			.replace(/\{\{سخ\}\}\]/g, ']')
			.replace(/\[\{\{سخ\}\}/g, '[')
			.replace(/\n\n(\*|\#)/g, '\n$1')
			.replace(/\n(\#|\*)( |)\n/g, '\n$1')
			.replace(/\n(\*|\#)( |)(\={2,})/g, '\n$3')
			.replace(/(\n?)\s+?<\/ref>/g, '$1</ref>')
			.replace(/\{ *\|/g, '{|')
			.replace(/\| *\}/g, '|}')
			.replace(/\{\| *\{\|/g, '{|')
			.replace(/\|\} *\|\}/g, '|}')
			.replace(/^=.*&nbsp;.*=$/gim, function ($0) {
				return $0.replace(/(?:&nbsp;|\s)+/gi, ' ');
			})
			.replace(/([^=])\n+(\=.*?\=\n+)/g, '$1\n\n$2')
			.replace(/^(=+([^=].*?)=+)[\t\s]{1,}\n/g, '$1\n')
			.replace(/^(\={2,}) +[\:,;>&\^#@•→←↔↑↓—–…~٫،؛ٔ]/mg, '$1') // Cleanup headers
			.replace(/[\:,;<&\^#@•→←↔↑↓—–…~٫،؛ٔ] +(\={2,})$/mg, '$1')
			.replace(/^(\={2,}\s*)(«)([^\n«»]*?)(»)(\s*\={2,})/mg, '$1 $3 $5')
			.replace(/^(\={2,}) *'+(.*?)'+ *(\={2,})/mg, '$1 $2 $3')
			.replace(/^[•●⚫⬤]/mg, '*') // Wikify bullets in start of lines
			.replace(/^#\s*(REDIRECT|تغییر[ _]?مسیر)/gi, '#تغییرمسیر')
			.replace(/^#تغییرمسیر(?=\S)/g, '#تغییرمسیر ') // Adds a space after #REDIRECT
			.replace(/(\={2,}) *([^\n\r]*?) *(\={2,})/g, '$1 $2 $3') // Format headings level 2 and above
			// زیربخش نیازی به برچسب بزرگ و کوچک ندارد
			.replace(/(\=+) \<(?:small|big)\>([^\=\n\r]+)\<\/(?:small|big)\> (\=+)/g, '$1 $2 $3')
			// فاصله‌های اضافی را از داخل پیوند به بیرون منتقل کند تا اگر اضافه بودند در کدهای دیگر حذف شوند
			.replace(/\[\[(\s*)(.*?)(\s*)\]\]/g, '$1[[$2]]$3')
			//حذف فاصلهٔ اضافی درون {{}}
			.replace(/\{\{(\s*)(.*?)(\s*)\}\}/g, '{{$2}}')
			// تبدیل به نویسه / یکی کردن فاصله های مجازی پشت سرهم
			.replace(/(\{\{فم\}\}|\&zwnj\;|\u200c+)/g, '\u200c')
			// Full stop and comma should be before citation. See en:WP:REFPUNC
			.replace(/ *((?:<ref[^\/]*?>.*?<\/ref>)+)([\.،,:])?/g, '$2$1')
			.replace(/([^.])([\.،,:]){2}((?:<ref[^\/]*?>.*?<\/ref>)+)/g, '$1$2$3')
			.replace(/ *((?:<ref[^\/]*?\/>)+)([\.،,:])/g, '$2$1')
			.replace(/([^.])([\.،,:]){2}(((?:<ref[^\/]*?\/>)+)+)/g, '$1$2$3')
			/* هر رده در یک خط */
			.replace(/([^\s>-]) *(\[\[رده:[^\n[\]]*\]\])/gi, '$1\n$2')
			.replace(/(\[\[رده:[^\n[\]]*\]\]) *(?![\s<-]|$)/gi, '$1\n')
			.replace(/(\[\[رده:[^\n[\]]*\]\]\n) *(?!\[\[رده:|[\s<-]|$)/gi, '$1\n')
			//ترتیب‌پیش‌فرض
			.replace(/\{\{(?:DEFAULTSORT|[Dd]efaultsort|ترتیب|ترتیب[‌ ]پیش[‌ ]?فرض) *[|:] *(?=.*?}})/g, '{{ترتیب‌پیش‌فرض:')
			.replace(/\{\{(ترتیب‌پیش‌فرض|DEFAULTSORT)\:[-\w,\s\(\)]+\}\}\n?/g, '')
			.replace(/(\{\{(?:ترتیب‌پیش‌فرض|DEFAULT\w*SORT\w*):[^\n{}]*\}\})\s*(?=\[\[رده:)/gi, '$1\n')
			.replace(/(\{\{ترتیب‌پیش‌فرض\:)\s/g, '$1')
			.replace(/(==\n)\n+(?=<references[^\n<>]*\/>\n\n)/gi, '$1')
			//نچسبیدن و+فاصله به براکت که محصول اشتباه در تایپ کردن است
			.replace(/\]\]و /g, ']] و ')
			.replace(/(\s|^)\'\'\'(\s|)(.*?)(\s|)\'\'\'(\s)/g, "$1'''$3'''$5") // حذف فاصلهٔ اضافی درون ویکی کد
			.replace(/'''\{\{به /g, "''' {{به ")
			.replace(/\*(\s+|\n)?\{\{پانویس/g, "{{پانویس")
			.replace(/((?:^|\n\s)\=+\s+\=+(?:\s+|)\n)/g, "\n\n")
			.replace(/\n{3,}/g, '\n\n')
			.replace(/(\[{1,2})([^\[\]\n]+) +(\]{1,2})/g, "$1$2$3")
			.replace(/(\[{1,2}) +([^\[\]\n]+)(\]{1,2})/g, "$1$2$3")
			//تبدیل بندهای ترتیبی به قالب‌بندی ویکی [[Special:Permalink/19923598#تبدیل بندهای ترتیبی به قالب‌بندی ویکی]]
			.replace(/(?:(?:^(?:\* ?)?[۱۲۳۴۵۶۷۸۹۰0-9]{1,2} ?[\.\-\)]) ?[^۱۲۳۴۵۶۷۸۹۰0-9\n]+\n+){2,}/gm, function (x) {
				var x2 = x.replace(/((?:\* ?)?[۱۲۳۴۵۶۷۸۹۰0-9]{1,2} ?[\.\-\)]) ?([^۱۲۳۴۵۶۷۸۹۰0-9\n]+)\n+/gm, '# $2\n')
				if (x2.replace(/[۱۲۳۴۵۶۷۸۹۰0-9]/g, '') === x2) {
					return x2;
				}
				return x;
			})
			.trim();
	}

	function wikiSubsection(text) {
		return text.replace(/\<(?:\s*)references?(?:\s*\/|\s*\/\s*)\>/g, '{{پانویس}}')
			.replace(/\{\{(?:[Rr]eflist|[Rr]eferences?|پانویس[‌ ]?ها)(?=\||\})/g, '{{پانویس')
			.replace(/\{\{راست(| |‌)چین\}\}\s*\{\{پانویس(.*?)\}\}\s*\{\{(پایان راست(| |‌)چین|پایان)\}\}/g, '{{پانویس$2}}')
			.replace(/\{\{چپ(| |‌)چین\}\}\s*\{\{پانویس(.*?)\}\}\s*\{\{(پایان چپ(| |‌)چین|پایان)\}\}/g, '{{پانویس$2|چپ‌چین=بله}}')
			.replace(/\<small\>\s*\{\{پانویس(.*?)\}\}\s*\<\/small\>/g, '{{پانویس$1|اندازه=کوچک}}')
			.replace(/(({\{پانویس.*?\}\})(\n|)){1,}/g, '$1')
			.replace(/\=\s*لیست\s*\=/g, '= فهرست =')
			.replace(/\=\s*(?:[gG]allery|نگارستان|گالری (تصویر|عکس|))\s*\=/g, '= نگارخانه =')
			.replace(/\=\s*(?:بیوگرافی|زندگینامه)\s*\=/g, '= زندگی‌نامه =')
			.replace(/\=\s*(?:[eE]xternal links|لینک‌?های بیرونی|پیوندهای خارجی|لینک‌?های خارجی|پیوندهای بیرونی)\s*\=/g, '= پیوند به بیرون =')
			.replace(/\=\s*(?:[nN]otes|[fF]ootnotes?|پاورقی|پاورقی‌ها|پانوشت|پانویس‌ها)\s*\=/g, '= پانویس =')
			.replace(/\=\s*(?:[Ss]ee [Aa]lso|همچنین ببینی[مد]|بیشتر ببینی[مد]|همچنین نگاه کنید|بیشتر بدانی[مد]|مراجعات مرتبط|جستار وابسته|مطلب مرتبط|مطالب مرتبط|جستارهای مشابه|جستارهای دیگر)\s*\=/g, '= جستارهای وابسته =')
			.replace(/\=\s*(?:منبع|منبع[‌ ]?ها|رفرنس|رفرنس[‌ ]?ها|ارجاع[‌ ]?ها|ارجاع|مرجع[‌ ]?ها|رفرنس|برگرفته از|مراجع|منابع و یادداشت[‌ ]?ها|منبع|مرجع|م[آا]خذ|منابع و م[آا]خذ|منابع و پانویس‌ها|فهرست مراجع|لیست مراجع|فهرست ارجاع[‌ ]?ها|فهرست ارجاع|[rR]eferences)\s*\=/g, '= منابع =')
			.replace(/\=\s*(?:مطالعه بیشتر|بیشتر بخوانی[مد])\s*\=/g, '= برای مطالعهٔ بیشتر =')
			.replace(/^\={3,}\s*(جستارهای وابسته|پانویس|منابع)\s*\={3,}$/g, '== $1 ==');
	}
	function wikiUrlMinifier(text) {
		return text
			.replace(patterns.url, function (x) {
				return replaceExcept(
					x,
					function (x) {
						try {
							x = decodeURI(x);
						} catch (e) {
							try {
								x = decodeURIComponent(unescape(x));
							} catch (e) { mw.notify(e); }
						}
						return x;
					},
					[patterns.globalExceptionTag, patterns.decodeUriBlacklist, patterns.refname, patterns.urlArchive]
				);
			})

			// Strip the http(s) prefix
			.replace(/\[(https?\:)(?=\/\/(?:[\w\-]+)\.(?:m\.)?(wiki(pedia|media|data|source|news|oyage|quote)|wiktionary)\.org\/[^\s\]]*)/g, '[')
			.replace(/[\[\=](?:https?\:|)\/\/[\w\-]{2,}\.(?:m\.)?wikipedia\.org\/w(?:iki)?\/([^\n?]*?)[\]\|]/g, function (x) {
				x = x.replace(/\[(?:https?\:|)\/\/([\w\-]{2,})\.(?:m\.)?wikipedia\.org\/w(?:iki)?\/(.*?) (.*?)\]/g, '[[:$1:$2|$3]]')
				x = x.replace(/\[(?:https?\:|)\/\/([\w\-]{2,})\.(?:m\.)?wikipedia\.org\/w(?:iki)?\/(.*?)\]/g, '[[:$1:$2]]')
				//x = x.replace(/\=(?:https?\:|)\/\/([\w\-]{2,})\.(?:m\.)?wikipedia\.org\/w(?:iki)?\/(.*?)\|/g,'=[[:$1:$2]]|') // در الگو یادکرد مشکل ایجاد می‌کند
				x = x.replace(/\[\[\:fa\:/g, '[[').replace(/\%20/g, ' ').replace(/٪۲۰/g, ' ').replace(/\[\[[a-zA-Z\'0-9 ]+\|/g, '[[')
				x = x.replace(/\[\[.*?\]\]/g, function (y) {
					y = y.replace(/\_/g, ' ')
					return y
				})
				return x
			}).replace(/\[{2}([^\|]+)\|\1\]{2}/gi, '[[$1]]');
	}
	function SubSectionLeveling(text) {
		// تنظیم سطح زیربخش‌ها
		text = text.replace(/^(\={2,}) *(.*?) *(\={2,})/mg, '$1 $2 $3')
		if ((mw.config.get('wgNamespaceNumber') === 0 && mw.config.get("wgEditMessage") === 'editing') || mw.config.get('wgPageName') === "ویکی‌پدیا:ویکی‌پروژه_ابزارها/آزمایش_واحد") {
			//مقاله‌ای که فقط زیربخش سطح ۱ دارد
			if (text.replace(/\=\=/g, '') === text) {
				var text2 = text.replace(new RegExp('^\=([^\=\r\n]+)\=$', 'gm'), "== $1 ==")
				if (text !== text2) {
					text = text2.replace(/\n\=  /g, '\n= ').replace(/  \=\n/g, ' =\n')
				};
			};
			//مقاله‌ای که فقط زیربخش سطح ۳ یا ۴ دارد
			var text_test = text.replace(/^\=+ (منابع|جستارهای وابسته|پیوند به بیرون|پانویس|نگارخانه) \=+\n/gm, '')
			if (text_test.replace(/^\=\= /gm, '') === text_test) {
				if (text_test.replace(/^\=\=\= /gm, '') !== text_test) {
					//سطح ۳
					text = text.replace(new RegExp('^\=\=\=([^\=\r\n]+)\=\=\=$', 'gm'), "== $1 ==")
					text = text.replace(new RegExp('^\=\=\=\=([^\=\r\n]+)\=\=\=\=$', 'gm'), "=== $1 ===")
				} else if (text_test.replace(/^\=\=\=\= /gm, '') !== text_test) {
					//سطح ۴
					text = text.replace(new RegExp('^\=\=\=\=([^\=\r\n]+)\=\=\=\=$', 'gm'), "== $1 ==")
				} else {
					text = text.replace(/===/g, '==')
				};
			};
			text = text.replace(/==  /g, '== ').replace(/  ==/g, ' ==')
		};
		return text;
	};
	function decimalPointToPersian(text) {
		//Decimal point [[Special:Permalink/25438370#جمع‌بندی_بدون_رسیدگی]]
		return text.replace(new RegExp('([۰۱۲۳۴۵۶۷۸۹])\\.(?=[۰۱۲۳۴۵۶۷۸۹])', 'g'), '$1٫')
	};
	function wikiTextDigitsToPersian(text) {
		text = replaceExcept(
			text,
			toEnglishDigits,
			[patterns.argumentsBlacklist, patterns.fileNames, patterns.fileParameter]);
		text = replaceExcept(
			text,
			persianTools.toPersianDigits,
			[patterns.globalExceptionTag, patterns.url, patterns.argumentsBlacklist, patterns.mathTag, patterns.imagePixelSize, patterns.fileNames, patterns.ref,
			patterns.sourceTag, patterns.arabicDigitsEnglishContext, patterns.signatures, patterns.htmlEntity, patterns.diffLink,
			patterns.htmlAttributes, patterns.fileParameter, patterns.templateParameterName, patterns.ipSign,
			patterns.parenthesesAfterDigits, patterns.otherLanguagesInline, patterns.preTag, patterns.isbn, patterns.englishDate,
			patterns.parameter, patterns.color, patterns.templateEnglishName, patterns.linksOnEnglishContext, patterns.citation, patterns.refname,
			patterns.LtRTagEnclosed, patterns.boxVar, patterns.mediawikiFunctions, patterns.graphTemplate]
		);
		text = replaceExcept(
			text,
			decimalPointToPersian,
			[patterns.catgories, patterns.graphTemplate]
		);
		return text
			//  thousands' separator
			.replace(/([۱۲۳۴۵۶۷۸۹۰]),([۱۲۳۴۵۶۷۸۹۰])/g, '$1٬$2')
			.replace(/([۱۲۳۴۵۶۷۸۹۰])( |)\u0652/g, '$1°')//تبدیل نویسه سکون+عدد فارسی به نویسه درجه و عدد فارسی
			.replace(/\u0652( |)([۱۲۳۴۵۶۷۸۹۰])/g, '°$2')
			//فاصله بین نویسه درجه و حروف الفبای فارسی به جز عدد فارسی
			.replace(/([\u0621-\u064A\u0653-\u0655\u067E\u0686\u0698\u06AF\u06A9\u0643\u06AA\uFED9\uFEDA\u06CC\uFEF1\uFEF2])°/g, '$1 °');
	}

	function dictationReplace(x, y, extensions, text) {
		return text.replace(
			new RegExp(
				'(^|[^' + persianTools.persianCharacters + '])(\\s|\u200c|_|)(' + x + ')(\\s|_)(' + y + ')(\\s|\u200c|_|)(' +
				extensions + ')($|[^' + persianTools.persianCharacters + '])',
				'g'
			),
			'$1$2$3\u200c$5$6$7$8'
		);
	}

	// it has dependency to MediaWiki:Gadget-Extra-Editbuttons-Dictionary.js
	function dictation(text) {
		var i,
			dictionary = persianToolsDictionary,
			NASB = '\u064b', // ًـ
			ZAMM = '\u064c'; // ُـ
		for (i in dictionary.complexes) {
			if (dictionary.complexes.hasOwnProperty(i)) {
				text = dictationReplace(
					i,
					dictionary.complexes[i],
					'ی|یی|ها|های|هایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|',
					text
				);
			}
		}
		// for last name
		text = dictationReplace(
			dictionary.personNames,
			'ی|یی|زاده|نیا|گان|فر|نژاد|یان|ی\u200cها|یها',
			'ی|',
			text
		);
		// for 'آباد's
		text = dictationReplace(
			dictionary.personNames + '|' + dictionary.addToAbad,
			'آباد',
			'زاده|نیا|پور|گان|فر|نژاد|ی|یان|ها|های|یی|هایی|ی\u200cها|یها|',
			text
		);
		// for first names
		for (i in dictionary.firstNameComplex) {
			if (dictionary.firstNameComplex.hasOwnProperty(i)) {
				text = text.replace(
					new RegExp(
						'(^|[^' + persianTools.persianCharacters + ']|\\s|_)(' + i + ')(\\s|_)(' +
						dictionary.firstNameComplex[i] + ')(\\s|_)($|[^' + persianTools.persianCharacters + ']|[^' +
						persianTools.persianCharacters + '])',
						'g'
					),
					'$1$2\u200c$4$5$6'
				);
			}
		}
		// for colors
		text = dictationReplace(
			dictionary.colorsNames,
			'فام|گون',
			'زاده|نیا|پور|گان|فر|نژاد|ی|یی|ها|های|هایی|ی\u200cها|یها|هایم|هایت|هایش|هایمان|هایتان|هایشان|',
			text
		);
		// for numbers
		text = dictationReplace(
			dictionary.persianNumbers,
			'گانه|ماهه',
			'زاده|نیا|پور|گان|فر|نژاد|ی|یی|ها|های|هایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|',
			text
		);
		// wrong dictation
		for (i in dictionary.forReplace) {
			if (dictionary.forReplace.hasOwnProperty(i)) {
				text = text.replace(
					new RegExp(
						'(^|[^' + persianTools.persianCharacters + '])(\\s|\\(|\u200c|_|)(' + i + ')(\\s|\\)|\u200c|_|)($|[^' +
						persianTools.persianCharacters + '])',
						'g'
					),
					'$1$2' + dictionary.forReplace[i] + '$4$5'
				);
			}
		}

		var preword = "(^|\\s|_|«|»|\\[|\\(|\\<|\\>|\\')(";
		// کلماتی که آ دارند
		text = text.replace(
			new RegExp(preword + dictionary.wordsWithA + ")(ی|ئی|یی|ٔ|)(?= |«|»|\\.|،|_|\\]|\\s|\\:|\\)|\\<|\\>|؟|\\'|\\!|$)", 'g'),
			function (x) { return x.replace(/ا/i, 'آ'); } // 'i' is just to trick bidi algorithm on code view
		);
		// بن مضارع که آ دارند
		text = text.replace(
			new RegExp("(^|\u200c|\\s|_|«|»|\\[|\\(|\\<|\\>|\\')(" + dictionary.PresentVerbsWithA + ")(م|ی|د|یم|ید|ند)(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'),
			function (x) { return x.replace(/ا/i, 'آ'); } // 'i' is just to trick bidi algorithm on code view
		);

		// بن ماضی که آ دارند
		text = text.replace(
			new RegExp("(^|\u200c|\\s|_|«|»|\\[|\\(|\\<|\\>|\\')(" + dictionary.PastVerbsWithA + ")(م|ی|یم|ید|ند|ه|)(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'),
			function (x) { return x.replace(/ا/i, 'آ'); } // 'i' is just to trick bidi algorithm on code view
		);

		// همزه ضم
		text = text.replace(
			new RegExp(preword + dictionary.HamzehZam + ")(‌ها|ها|ین|ان|ی|ئی|یی|ٔ|)(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'),
			function (x) { return x.replace(/وء/, 'ؤ').replace(/و/i, 'ؤ'); } // 'i' is just to trick bidi algorithm on code view
		);
		//همزه نصب
		text = text.replace(
			new RegExp(preword + dictionary.HamzehNasb + ")(ی|ئی|یی|ٔ|)(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'),
			function (x) { return x.replace(/ا/i, 'أ'); } // 'i' is just to trick bidi algorithm on code view
		);

		//همزه وسط کلمه
		for (i in dictionary.HamzehAtInside) {
			text = text.replace(new RegExp(
				preword + i + ')(| )(' + dictionary.HamzehAtInside[i] + ")(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)",
				'g'
			), '$1$2ء$4');
		}

		// در مورد افزودن یا حذف همزهٔ پایانی اجماعی وجود ندارد.
		/* text = text.replace(new RegExp(preword + dictionary.HamzehAtEnd + ")(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'),'$1$2ء'); */

		//الف مقصوره
		text = text.replace(
			new RegExp(preword + dictionary.AlefMaghsooreh + ")(?= |«|»|\\.|،|_|\\s|\\]|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'),
			function (x) { return x.replace(/ا/i, 'ی'); } // 'i' is just to trick bidi algorithm on code view
		);

		// صفت+تر
		text = text.replace(new RegExp("(^|\\s|_|«|»|\\]|\\[|\\(|\\<|\\>|\\')(" + dictionary.adjective + ")( |_)تر(?= |«|»|\\.|\\[|\\]|،|_|\\s|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'), '$1$2\u200cتر');

		// اسامی رنگ‌ها (به‌عنوان صفت)+تر
		text = text.replace(new RegExp("(^|\\s|_|«|»|\\]|\\[|\\(|\\<|\\>|\\')(" + dictionary.colorsNames + ")( |_)تر(?= |«|»|\\.|\\[|\\]|،|_|\\s|\\:|\\)|\\<|\\>|؟|\\!|\\'|$)", 'g'), '$1$2\u200cتر');

		text = text.replace(/به دست\u200cآورد/g, 'به دست آورد'); // Solving a bug!
		text = persianTools.normalizeZwnj(text);
		return text.replace(new RegExp("(^|[؛\\s\\n\\.،«»\'\\<\\>؟])(" + dictionary.needsNasb + ')[' + NASB + ZAMM + ']?([؛؟\\s\\n\\.،«»\'"\\<\\>]|$)', 'g'), function (match) {
			return match
				.replace(new RegExp('ا([\\s\\n\\.،«»؟؛"\'\\>\\<' + ZAMM + '])', 'i'), 'ا' + NASB + '$1')
				.replace(new RegExp(NASB + '["' + NASB + ZAMM + ']'), NASB);
		});
	}

	function wikiDictation(text) {
		return replaceExcept(
			text,
			dictation,
			[patterns.globalExceptionTag, patterns.fileNames, patterns.signatures, patterns.url, patterns.galleryTag, patterns.insideQuote, patterns.argumentsBlacklist, patterns.articleTitleParts]
		);
	}
	function wikiApplyOrthography(text) {
		text = text //en:Wikipedia:HTML5
			//big
			.replace(/((?:\<big\>){5})([^<]+)((?:\<\/big\>){5})/g, '<span style="font-size: 56px;">$2</span>')
			.replace(/((?:\<big\>){4})([^<]+)((?:\<\/big\>){4})/g, '<span style="font-size: 38px;">$2</span>')
			.replace(/((?:\<big\>){3})([^<]+)((?:\<\/big\>){3})/g, '{{خیلی بزرگ|$2}}')
			.replace(/((?:\<big\>){2})([^<]+)((?:\<\/big\>){2})/g, '{{بزرگ|$2}}')
			.replace(/((?:\<big\>){1})([^<]+|[\s\S]+)((?:\<\/big\>){1})/g, '{{درشت|$2}}')
			//center
			.replace(/<center><gallery>([\S\s]+?)\<\/gallery><\/center>/g, '<gallery class="center">$1</gallery>')
			//.replace(/<center>([\S\s]+?)<\/center>/g,'{{وسط|$1}}')
			//empty tag
			.replace(/<span style="font-size: [^>]+"><\/span>/g, '')
			.replace(/{{(?:درشت|خیلی بزرگ|بزرگ|وسط)\|}}/g, '')

		//حذف برچسب‌های خالی نرم‌افزار مدیاویکی
		var tags = ['math', 'div', 'grammarly\\-btn', 'code', 'nowiki', 'pre', 'syntaxhighlight', 'source', 's', 'noinclude', 'includeonly', 'big', 'small', 'gallery'];// has bug for sub , sup [[Special:Diff/19450140/19490903]]
		text = replaceExcept(
			text,
			function (text) {
				for (var i = 0; i < tags.length; ++i) {
					for (var b = 0; b < 5; ++b) {//خیلی از برچسب‌های خالی تو در تو هستند مانند [[Special:PermaLink/19223877]]
						text = text.replace(new RegExp('\<' + tags[i] + '[^\>]*\>(\\n|\\s|\u200c)*?\<\\/' + tags[i] + '\>', 'g'), '');
					}
					// remove the tags if they occurred multiple times consequently
					if (mw.config.get('wgNamespaceNumber') === 0 || mw.config.get('wgNamespaceNumber') === 4) {
						text = text.replace(new RegExp('(\<' + tags[i] + '\>){2,}', 'g'), '$1')
							.replace(new RegExp('(\<\\/' + tags[i] + '\>){2,}', 'g'), '$1');
					}
				}
				if (mw.config.get('wgNamespaceNumber') === 0) {
					text = text.replace(/\<ref\>[\s\n]*\<\/ref\>/g, '').replace(/\<ref\>[\s\n]*\<ref\>/g, '<ref>').replace(/\<\/ref\>[\s\n]*\<\/ref\>/g, '</ref>').replace(/\<ref\/\>/g, '</ref>');
				};
				return text
			},
			[patterns.insideHtmlComment]
		);
		return replaceExcept(
			text,
			persianTools.applyOrthography,
			[patterns.globalExceptionTag, patterns.fileNames, patterns.signatures, patterns.url, patterns.galleryTag, patterns.wikilinkTargets]
		).replace(patterns.galleryTag, function (gallery) {
			// apply `applyOrthography` on gallery descriptions separately
			return gallery.replace(/^([^\|]*?\|)(.*)$/mg, function (x, y, z) {
				return y + persianTools.applyOrthography(z);
			});
		});
	}

	// probably should be exactly same above but for applyZwnj
	function wikiApplyZwnj(text) {
		return replaceExcept(
			text,
			persianTools.applyZwnj,
			[patterns.globalExceptionTag, patterns.fileNames, patterns.signatures, patterns.url, patterns.galleryTag]
		).replace(patterns.galleryTag, function (gallery) {
			// apply `applyOrthography` on gallery descriptions separatly
			return gallery.replace(/^([^\|]*?\|)(.*)$/mg, function (x, y, z) {
				return y + persianTools.applyZwnj(z);
			});
		});
	}

	function replaceEnMonth(text) {
		var enMonth = {
			'آگست': 'اوت',
			'آگوست': 'اوت',
			'جولای': 'ژوئیه',
			'مارچ': 'مارس',
			'آپریل': 'آوریل',
			'فوریوری': 'فوریه',
			'january': 'ژانویه',
			'jan': 'ژانویه',
			'february': 'فوریه',
			'feb': 'فوریه',
			'march': 'مارس',
			'mar': 'مارس',
			'april': 'آوریل',
			'apr': 'آوریل',
			'may': 'مه',
			'june': 'ژوئن',
			'jun': 'ژوئن',
			'july': 'ژوئیه',
			'august': 'اوت',
			'aug': 'اوت',
			'september': 'سپتامبر',
			'sept': 'سپتامبر',
			'sep': 'سپتامبر',
			'october': 'اکتبر',
			'oct': 'اکتبر',
			'november': 'نوامبر',
			'nov': 'نوامبر',
			'december': 'دسامبر',
			'dec': 'دسامبر'
		};
		for (var i in enMonth) {
			var text_new = text.replace(new RegExp(i, 'ig'), enMonth[i])
			if (text_new != text) {
				return text_new
			}
		}
		return text
	};
	function autoFormatCleanDatesException(text) {
		return replaceExcept(
			text,
			autoFormatCleanDates,
			[patterns.globalExceptionTag, patterns.fileNames, patterns.galleryTag, patterns.mathTag, patterns.sourceTag, patterns.templateWithEnglishName, patterns.citation, patterns.argumentsBlacklist, patterns.ref]
		)
	}
	function wikitranslateEnMonth(text) {
		text = autoFormatCleanDatesException(text)
		return replaceExcept(
			text,
			function translateEnMonth(text) {
				var enMonthRegex = '(آگست|آگوست|جولای|مارچ|آپریل|january|jan|february|feb|march|mar|april|apr|may|jun|june|july|august|aug|sep|sept|september|oct|october|nov|november|december|dec)';
				return text.replace(new RegExp('([^a-zA-Z])(\^|\\||\\s|\\=|\\n|\\(|«|\\:)' + enMonthRegex + ' (\\d{1,2}|[۱۲۳۴۵۶۷۸۹۰]{1,2})\\, (\\d{3,4}|[۱۲۳۴۵۶۷۸۹۰]{3,4})(\\||\\s|\\n|\$|\\)|\\}|»)([\^a\-zA\-Z])', 'ig'),
					function (x) {
						x = x.replace(new RegExp('([\^a\-zA\-Z])(\^|\\||\\s|\\=|\\n|\\(|«|\\:)' + enMonthRegex + ' (\\d{1,2}|[۱۲۳۴۵۶۷۸۹۰]{1,2})\\, (\\d{3,4}|[۱۲۳۴۵۶۷۸۹۰]{3,4})(\\||\\s|\\n|\$|\\)|\\}||»)([^a-zA-Z])', 'ig'),
							'$1$2$4 $3 $5$6$7')
						x = persianTools.toPersianDigits(x);
						x = replaceEnMonth(x);
						return x;
					})
					.replace(new RegExp('([\^a\-zA\-Z])(\^|\\||\\s|\\=|\\n|\\(|«)((\\d{1,2}|[۱۲۳۴۵۶۷۸۹۰]{1,2}) |)' + enMonthRegex + ' (\\d{3,4}|[۱۲۳۴۵۶۷۸۹۰]{3,4})(\\||\\s|\\n|$|\\)|\\}|»|\\:)([\^a\-zA\-Z])', 'ig'),
						function (x) {
							x = persianTools.toPersianDigits(x);
							x = replaceEnMonth(x);
							return x;
						}
					);
			}, [patterns.globalExceptionTag, patterns.fileNames, patterns.ref, patterns.fileParameter, patterns.galleryTag, patterns.mathTag, patterns.sourceTag, patterns.templateWithEnglishName, patterns.citation, patterns.argumentsBlacklist]
		)
	}

	var arabicDigits = '0123456789', persianDigits = '۰۱۲۳۴۵۶۷۸۹', arabicIndicDigits = '٠١٢٣٤٥٦٧٨٩';
	function robustToEnglishDigits(text) {
		var i = 0;
		for (i = 0; i <= 9; i = i + 1) {
			text = text.replace(new RegExp('[' + persianDigits[i] + arabicIndicDigits[i] + ']', 'g'), arabicDigits[i]);
		}
		return text;
	}

	function toEnglishDigits(text) {
		text = text.replace(/[a-zA-Z]([\_\s\:\.\,\;\]\[\"\'\)\(\}\{\/\\ ]+|)([۱۲۳۴۵۶۷۸۹۰٪\.٫\-\—\–°÷×\+\,\s\_\:،»«؛]+)([\_\s\:\.\,\;\]\[\"\'\)\(\}\{\/\\\<\> ]+|)([a-zA-Z\>]|$)/g, function (x) {
			var i = 0;
			for (i = 0; i <= 9; i = i + 1) {
				x = x.replace(new RegExp('[' + persianDigits[i] + arabicIndicDigits[i] + ']', 'g'), arabicDigits[i]);
			}
			return x.replace(/،/g, ',').replace(/»/g, '"').replace(/«/g, '"').replace(/؛/g, ';');
		});
		// bug [[Special:Diff/17760890/17760898]]
		text = text.replace(/([a-zA-Z][۱۲۳۴۵۶۷۸۹۰]+) *\=/g, function (x) {
			var i = 0;
			for (i = 0; i <= 9; i = i + 1) {
				x = x.replace(new RegExp('[' + persianDigits[i] + arabicIndicDigits[i] + ']', 'g'), arabicDigits[i]);
			}
			return x;
		});
		// ISBN, ISSN and PMID's numbers should in english
		text = text.replace(/\b(ISBN|ISSN|PMID|PubMed) *:? *([۱۲۳۴۵۶۷۸۹۰0-9–—−ـ_\-]+)([^۱۲۳۴۵۶۷۸۹۰0-9–—−ـ_\-]|$)/gi, function (x) {
			x = x.replace(/[–—−ـ_\-]+/g, '-')
			var i = 0;
			for (i = 0; i <= 9; i = i + 1) {
				x = x.replace(new RegExp('[' + persianDigits[i] + arabicIndicDigits[i] + ']', 'g'), arabicDigits[i]);
			}
			x = x.replace(/\b(ISBN|ISSN|PMID|PubMed) *:? *([۱۲۳۴۵۶۷۸۹۰\-0-9]+)([^۱۲۳۴۵۶۷۸۹۰\-0-9]|$)/gi, '$1 $2$3')
			x = x.replace('PubMed', 'PMID')
			return x;
		});
		text = text.replace(/ISBN \-note/g, 'ISBN-note');
		// تبدیل عددهای فارسی در عدد ترتیبی انگلیسی
		text = text.replace(/(?:^|["\'\s_«\(\[\{])([۱۲۳۴۵۶۷۸۹۰]+)(st|nd|rd|th)[\s_\.,»"\'\)\]\}]/g, function (x) {
			var i = 0;
			for (i = 0; i <= 9; i = i + 1) {
				x = x.replace(new RegExp('[' + persianDigits[i] + arabicIndicDigits[i] + ']', 'g'), arabicDigits[i]);
			}
			return x;
		});
		return text
			.replace(new RegExp('([' + arabicDigits + ']) ?٪', 'g'), '$1%')
			.replace(new RegExp('([' + arabicDigits + '])٫(?=[' + arabicDigits + '])', 'g'), '$1.') // English decimal separator
	}
	function cleanTemplateBracesFromArticle(text, alwaysRun) { // like [[Special:Diff/18828723]]
		if (mw.config.get('wgNamespaceNumber') !== 0 && !alwaysRun) {
			return text;
		}
		var i = 0
		for (i = 0; i <= 5; i = i + 1) {
			text = text.replace(/\{\{\{[^\|\}]+\|([^\}]+)\}\}\}/g, '$1')
				.replace(/\{\{\{[^\|\}]+\| *\}\}\}/g, '')
		}

		return text.replace(/\{\{\#(?!invoke)/ig, '{{جا:#')
			.replace(/\{\{ *(PAGENAME|FULLPAGENAMEE|SITENAME|NAMESPACE) *\}\}/g, '{{جا:$1}}')
			.replace('{{ترتیب‌پیش‌فرض:}}', '');
	}
	function decodeHTMLSymbolEntitiesCodes(text) {
		//&copy; > ©
		return replaceExcept(
			text,
			function decodeEntitiesCodes(text) {
				if(!text) return '';
				for (var i in htmlEntityCodes) {
					var entityInput = i;
					var entityoutput = htmlEntityCodes[i];
					text = text.replace(new RegExp(entityInput, 'g'), entityoutput);
				}
				return text;
			}, [patterns.globalExceptionTag, patterns.fileNames, patterns.ref, patterns.fileParameter,
			patterns.galleryTag, patterns.mathTag, patterns.sourceTag, patterns.templateWithEnglishName,
			patterns.citation, patterns.url]
		)
	}
	function removeWikiSigne(text) {
		return replaceExcept(
			text,
			function (text) {
				text = text.replace(/\[\[([^\|\]]+)\|([^\]]+)\]\]/g, '$2');
				text = text.replace(/\[\[([^\|\]]+)\]\]/g, '$1');
				return text;
			}, [patterns.globalExceptionTag, patterns.fileNames, patterns.fileParameter,
			patterns.mathTag, patterns.sourceTag, patterns.templateWithEnglishName, patterns.nowikiTag, patterns.preTag,
			patterns.insideHtmlComment]
		)
	}
	function autoEdHTMLtoWikitextWikiTools(text) {
		return replaceExcept(
			text,
			autoEd.autoEdHTMLtoWikitext,
			[patterns.fileParameter, patterns.mathTag, patterns.sourceTag]
		)
	}
	function superTool(text) {
		text = decodeHTMLSymbolEntitiesCodes(text);
		text = cleanTemplateBracesFromArticle(text);
		text = persianWikiTools.wikiConvertToPersianCharacters(text);
		text = persianWikiTools.wikiApplyZwnj(text);
		text = persianWikiTools.wikiApplyOrthography(text);
		text = persianWikiTools.wikitranslateEnMonth(text);
		if (mw.config.get('wgNamespaceNumber') !== 10) {
			text = persianWikiTools.wikiTextDigitsToPersian(text);
		}
		text = persianWikiTools.wikiUrlMinifier(text);
		text = persianWikiTools.wikiDictation(text);
		text = persianWikiTools.wikiPunctuation(text);
		text = persianWikiTools.wikiSubsection(text);
		text = persianWikiTools.SubSectionLeveling(text)
		//ابزارهای بیشتر برگرفته از ویکی‌پدیای انگلیسی [[Mediawiki:Gadget-Extra-Editbuttons-autoed.js]]
		text = autoEd.autoEdISBN(text);
		text = autoEd.autoEdWhitespace(text);
		text = autoEdHTMLtoWikitextWikiTools(text);
		text = autoEd.autoEdHeadlines(text);
		text = autoEd.autoEdTablestoWikitext(text);
		text = autoEd.autoEdExtraBreaks(text);
		text = persianWikiTools.addColumnToRefTemplate(text);
		text = persianWikiTools.removeCheckDict(text);
		return text;
	}

	function superToolMove(text) {
		text = ' ' + text + ' '; // بعضی از کدها اگر فاصله در انتها یا اول نباشد عمل نمی‌کنند مانند افزودن تنوین به کلمه بعدا
		text = persianWikiTools.wikiConvertToPersianCharacters(text);
		text = persianTools.applyZwnj(text);
		text = persianWikiTools.wikiApplyOrthography(text);
		text = persianWikiTools.wikiTextDigitsToPersian(text);
		text = persianWikiTools.wikiUrlMinifier(text);
		text = persianWikiTools.wikiDictation(text);
		text = persianWikiTools.wikiPunctuation(text);
		return text.trim();
	}

	return {
		removeWikiSigne: removeWikiSigne,
		superTool: superTool,
		superToolMove: superToolMove,
		dictation: dictation,
		wikiApplyOrthography: wikiApplyOrthography,
		wikiApplyZwnj: wikiApplyZwnj,
		wikiConvertToPersianCharacters: wikiConvertToPersianCharacters,
		wikiDictation: wikiDictation,
		wikiPunctuation: wikiPunctuation,
		wikiSubsection: wikiSubsection,
		SubSectionLeveling: SubSectionLeveling,
		wikiUrlMinifier: wikiUrlMinifier,
		wikiTextDigitsToPersian: wikiTextDigitsToPersian,
		wikitranslateEnMonth: wikitranslateEnMonth,
		addColumnToRefTemplate: addColumnToRefTemplate,
		fixBadLinks: fixBadLinks,
		robustToEnglishDigits: robustToEnglishDigits,
		toEnglishDigits: toEnglishDigits,
		cleanTemplateBracesFromArticle: cleanTemplateBracesFromArticle,
		removeCheckDict: removeCheckDict
	};
}());
if (typeof window !== "undefined") {
	window.persianWikiTools = persianWikiTools;
}
// </nowiki>