نکته: پس از انتشار ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
// <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, console*/ if (!String.prototype.trim) { // if is not available currently 	String.prototype.trim = function () { 		return this.replace(/^\s+|\s+$/g, ''); 	}; }  window.persianWikiTools = { 	descendingFromComparetor: function(x, y) { 		return x.from - y.from; 	}, 	replaceExcept: function(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(persianWikiTools.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(''); 	},  	patterns: { 		arabicDigitsEnglishContext: /[a-z][a-z %"'\._:\|,\-\\\/\(\)\#\^\+\d><–\[\]&?{}]*\d|(\d|[a-z])[a-z %"'\._:\|,\-\\\/\(\)\#\^\+\d><–\[\]&?{}]*[a-z]\d*/gi, 		arabicTagEnclosed: /\{\{(?:عربی|شروع عربی|آغاز عربی)\}\}([\s\S]*?)\{\{(?:پایان عربی)\}\}/g, 		argumentsBlacklist: /(?:accessdate|namespace|doi|style|شابک|عرض|bibcode|isbn|pmid|arxiv)\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|%5C|%5E|%60|%23|%25|%3C|%3E|%5B|%5D|%22|%09|%0A|%7B|%7C|%7D)/gi, 		englishDate: /\d{1,2},? [a-z]{3,} \d{2,4}/gi, // 3, May 2013 		fileNames: /(?:پرونده|File|تصویر|Image)\:.*?(?=\||\]|\n|$)/gi, // don't capture | after 		fileParameter: /\|\s*(image|تصویر)\s*\=\s*.*/g, 		templates: /\{\{.*\}\}/gi, 		ipSign: /\[\[ویژه:مشارکت\u200cها.*?\]\]/g, 		isbn: /ISBN [\d\-]*/gi, 		galleryTag: /<gallery.*?>[\s\S]*?<\/gallery>/g, 		htmlAttributes: /(?:style|colspan|color|rowspan|cellpadding|cellspacing|height|width|size|border|thumbtime|name|perrow)\s*[\=\:]\s*(?:['\"].*?['\"]|[\da-z]+)/gi, 		htmlEntity: /&#\d+;/, 		imagePixelSize: /[\|=] *[x\d]+?(px|پیکسل)[\]\|\s]/g, // means it will capture |10px| and |10x10px| 		insideQuote: /".*?"/g, 		wikilinkTargets: /\[[^\[|\]]+/g, 		linksOnEnglishContext: /[a-z][\:\,\. ]*\[\[[\da-z\-\, ]*/gi, 		mathTag: /<math.*?>[\s\S]*?<\/math>/g, 		otherLanguagesInline: /\{\{(?:به .+?|به انگلیسی|انگلیسی|عربی|حدیث|به عربی)[\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/> 		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, 		templateEnglishName: /(الگو|Template):[a-z][a-z\d\-\+_]+/gi, 		templateParameterName: /\|\s*(?=[a-z_]*\d)[a-z_\d]*\s*\=/gi, 		translatedUrl: /.(کام|نت|آی‌آر)/g, 		url: /\/\/.*?(?=[\s\n\|\}\]<]|$)/gi	 // بدون https?: هم ممکن است 	}, 	wikiConvertToPersianCharacters: function(text) { 		return persianWikiTools.replaceExcept( 			text, 			persianTools.toStandardPersianCharacters, 			[persianWikiTools.patterns.otherLanguagesInline, persianWikiTools.patterns.arabicTagEnclosed, persianWikiTools.patterns.fileNames, persianWikiTools.patterns.signatures, persianWikiTools.patterns.url] 		); 	}, 	quotation: function(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 				if (line.match(/"/g)) { 					line = lines[i]; 				} 			} 			// ”“ تبدیل  			line = line.replace( 				new RegExp('(^|[' + persianTools.persianCharacters + '،»؛\\s\\n]+)“((?:\\[\\[|).*?[' + persianTools.persianCharacters + '\\n]+?(?:\\]\\]|))”([' + persianTools.persianCharacters + '،«؛\\s\\n$\.])', 'g'), 				'$1«$2»$3' 			); 			result.push(line); 		} 		return result.join('\n\n'); 	}, 	wikiPunctuation: function(text) { 		text = persianWikiTools.quotation(text); 		text = persianWikiTools.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'); 			}, 			[persianWikiTools.patterns.fileNames, persianWikiTools.patterns.url, persianWikiTools.patterns.galleryTag, persianWikiTools.patterns.sourceTag, persianWikiTools.patterns.translatedUrl, persianWikiTools.patterns.parenthesesHa] 		); 		return persianWikiTools.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 			}, 			[persianWikiTools.patterns.fileNames, persianWikiTools.patterns.url, persianWikiTools.patterns.wikilinkTargets, persianWikiTools.patterns.galleryTag, persianWikiTools.patterns.sourceTag, persianWikiTools.patterns.translatedUrl, persianWikiTools.patterns.parenthesesHa] 		) 			.replace(/\n{3,}/g, '\n\n') // Cosmetic changes bot replaces 			.replace(/\[\[(رده|الگو|ویکی\u200cپدیا)\: +/g, '[[$1:') 			.replace(/[\n\s]*\{\{[•·ن](w?)\}\}\s*/g, '{{•$1}} ') 			.replace(/ *(<\/? ?br ?\/?>|\{\{بر\}\}) */g, '{{سخ}}') 			.replace(/(<\/ref>)\s+(<ref)/g, '$1$2') 			.replace(/([^=])[\s\n]+<ref(?!erences)/g, '$1<ref') 			.replace(/(\n?)[\s\n]+?<\/ref>/g, '$1</ref>') 			.replace(/([^=])\n+(\=.*?\=\n+)/g, '$1\n\n$2') 			.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(/\[\[(\s*)(.*?)(\s*)\]\]/g, '$1[[$2]]$3') 			// تبدیل به نویسه / یکی کردن فاصله های مجازی پشت سرهم 			.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(/\{\{(?:DEFAULTSORT|[Dd]efaultsort|ترتیب|ترتیب[‌ ]پیش[‌ ]?فرض) *[|:] *(?=.*?}})/g, '{{ترتیب‌پیش‌فرض:') 			.replace(/\{\{(ترتیب‌پیش‌فرض|DEFAULTSORT)\:[-\w,\s\(\)]+\}\}\n?/g, '') 			.replace(/(\{\{ترتیب‌پیش‌فرض\:)\s/g, '$1') 			//نچسبیدن و+فاصله به براکت که محصول اشتباه در تایپ کردن است 			.replace(']]و ', ']] و ') 			.trim(); 	}, 	wikiUrlMinifier: function(text) { 		return text 			.replace(persianWikiTools.patterns.url, function (x) { 				return persianWikiTools.replaceExcept( 					x, 					function (x) { 						try { 							x = decodeURI(x); 						} catch (e) { mw.notify(e); } 						return x; 					}, 					[persianWikiTools.patterns.decodeUriBlacklist] 				); 			})  			// Strip the http(s) prefix 			.replace(/\[(https?\:)(?=\/\/(?:[\w\-]+)\.(wiki(pedia|media|data|source|news|oyage|quote)|wiktionary)\.org\/[^\s\]]*)/g, '['); 	}, 	wikiTextDigitsToPersian: function(text) { 		text = persianWikiTools.replaceExcept( 			text, 			persianTools.toPersianDigits, 			[persianWikiTools.patterns.url, persianWikiTools.patterns.argumentsBlacklist, persianWikiTools.patterns.mathTag, persianWikiTools.patterns.imagePixelSize, persianWikiTools.patterns.fileNames, persianWikiTools.patterns.ref, 				persianWikiTools.patterns.sourceTag, persianWikiTools.patterns.arabicDigitsEnglishContext, persianWikiTools.patterns.signatures, persianWikiTools.patterns.htmlEntity, 				persianWikiTools.patterns.htmlAttributes, persianWikiTools.patterns.fileParameter, persianWikiTools.patterns.templateParameterName, persianWikiTools.patterns.ipSign, 				persianWikiTools.patterns.parenthesesAfterDigits, persianWikiTools.patterns.otherLanguagesInline, persianWikiTools.patterns.isbn, persianWikiTools.patterns.englishDate, 				persianWikiTools.patterns.parameter, persianWikiTools.patterns.color, persianWikiTools.patterns.templateEnglishName, persianWikiTools.patterns.linksOnEnglishContext, 				persianWikiTools.patterns.colorAsParameter, persianWikiTools.patterns.tagNames, persianWikiTools.patterns.templates] 		); 		return text 			// Decimal point, and thousands' separator 			.replace(/([۱۲۳۴۵۶۷۸۹۰])\.([۱۲۳۴۵۶۷۸۹۰])/g, '$1٫$2') 			.replace(/([۱۲۳۴۵۶۷۸۹۰]),([۱۲۳۴۵۶۷۸۹۰])/g, '$1٬$2'); 	}, 	dictationReplace: function (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 	dictation: function(text) { 		var i, dictionary = persianToolsDictionary, NASB = '\u064b'; // ًـ 		for (i in dictionary.complexes) { 			if (dictionary.complexes.hasOwnProperty(i)) { 				text = persianWikiTools.dictationReplace( 					i, 					dictionary.complexes[i], 					'ی|ها|های|هایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|', 					text 				); 			} 		} 		// for last name 		text = persianWikiTools.dictationReplace( 			dictionary.personNames, 			'ی|زاده|نیا|گان|فر|نژاد|یان|ی\u200cها|یها', 			'ی|', 			text 		); 		// for 'آباد's 		text = persianWikiTools.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 = persianWikiTools.dictationReplace( 			dictionary.colorsNames, 			'فام|گون', 			'زاده|نیا|پور|گان|فر|نژاد|ی|ها|های|هایی|ی\u200cها|یها|هایم|هایت|هایش|هایمان|هایتان|هایشان|', 			text 		); 		// for numbers 		text = persianWikiTools.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' 				); 			} 		}   		// کلماتی که آ دارند 		text = text.replace( 			new RegExp('(^| |_|«|»)(' + dictionary.wordsWithA + ')(ی|ئی|یی|)(?= |«|»|\\.|،|_|$)', 'g'), 			function (x) { return x.replace(/ا/i, 'آ'); } // 'i' is just to trick bidi algorithm on code view 		); 		 		text = text.replace(/به دست\u200cآورد/g, 'به دست آورد'); // Solving a bug! 		text = persianTools.normalizeZwnj(text); 		return text.replace(new RegExp('([\\s\\n\.،«»؛])(' + dictionary.needsNasb + ')([\\s\\n\.،«»؛])(\\u064b|)', 'g'), '$1$2' + NASB +'$3'); 	}, 	wikiDictation: function (text) { 		return persianWikiTools.replaceExcept( 			text, 			persianWikiTools.dictation, 			[persianWikiTools.patterns.fileNames, persianWikiTools.patterns.signatures, persianWikiTools.patterns.url, persianWikiTools.patterns.galleryTag, persianWikiTools.patterns.insideQuote] 		); 	}, 	 	wikiApplyOrthography: function (text) { 		return persianWikiTools.replaceExcept( 			text, 			persianTools.applyOrthography, 			[persianWikiTools.patterns.fileNames, persianWikiTools.patterns.signatures, persianWikiTools.patterns.url, persianWikiTools.patterns.galleryTag] 		).replace(persianWikiTools.patterns.galleryTag, function (gallery) { 			// apply `applyOrthography` on gallery descriptions separatly 			return gallery.replace(/^([^\|]*?\|)(.*)$/mg, function (x, y, z) { 				return y + persianTools.applyOrthography(z); 			}); 		}); 	}, 	 	// probably should be exactly same above but for applyZwnj 	wikiApplyZwnj: function(text) { 		return persianWikiTools.replaceExcept( 			text, 			persianTools.applyZwnj, 			[persianWikiTools.patterns.fileNames, persianWikiTools.patterns.signatures, persianWikiTools.patterns.url, persianWikiTools.patterns.galleryTag] 		).replace(persianWikiTools.patterns.galleryTag, function (gallery) { 			// apply `applyOrthography` on gallery descriptions separatly 			return gallery.replace(/^([^\|]*?\|)(.*)$/mg, function (x, y, z) { 				return y + persianTools.applyZwnj(z); 			}); 		}); 	}, 	 	superTool: function(text) { 		text = persianWikiTools.wikiConvertToPersianCharacters(text); 		text = persianWikiTools.wikiApplyZwnj(text); 		text = persianWikiTools.wikiApplyOrthography(text); 		if (mw.config.get('wgNamespaceNumber') !== 10) { 			text = persianWikiTools.wikiTextDigitsToPersian(text); 		} 		text = persianWikiTools.wikiUrlMinifier(text); 		text = persianWikiTools.wikiDictation(text); 		text = persianWikiTools.wikiPunctuation(text); 		//ابزارهای بیشتر برگرفته از ویکی‌پدیای انگلیسی [[Mediawiki:Gadget-Extra-Editbuttons-autoed.js]] 		text = autoEd.autoEdISBN(text); 		text = autoEd.autoEdWhitespace(text); 		// text = autoEd.autoEdWikilinks(text); 		text = autoEd.autoEdHTMLtoWikitext(text); 		text = autoEd.autoEdHeadlines(text); 		// text = autoEd.autoEdTemplates(text); 		text = autoEd.autoEdTablestoWikitext(text); 		text = autoEd.autoEdExtraBreaks(text); 		// text = autoEd.autoEdLinks(text); 		return text; 	}, 	 	superToolMove: function (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; 	} };