مدیاویکی:Gadget-Extra-Editbuttons-persiantools.js

از ویکی‌خبر، مرجع خبری آزاد

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

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • اینترنت اکسپلورر/ Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
  • اپرا: Ctrl-F5 را بفشارید.
// <nowiki> // DO NOT REMOVE THIS LINE EVER
/**
 * Persian text style improvement tools
 * Tests: [[مدیاویکی:Gadget-Extra-Editbuttons-tests.js]] [[وپ:تست]]
 * See also:
 * * [[مدیاویکی:Gadget-Extra-Editbuttons-persianwikitools.js]]
 * * [[مدیاویکی:Gadget-Extra-Editbuttons-dictionary.js]]
 */
window.persianTools = {
	arabicDigits: '0123456789',
	arabicIndicDigits: '٠١٢٣٤٥٦٧٨٩',
	//نویسه‌های غیرفارسی ي-ك-ە و موارد مشابه پیش از تبدیل به نویسهٔ فارسی در سایر ریجکس‌ها باید به عنوان کاراکتر فارسی شناخته شوند.
	similarpersianCharacters: '\u0643\uFB91\uFB90\uFB8F\uFB8E\uFEDC\uFEDB\uFEDA\uFED9\u0649\uFEEF\u064A\u06C1\u06D5\u06BE\uFEF0-\uFEF4',
	vowels: '\u064B-\u0650\u0652\u0670',
	persianCharacters: '\u0621-\u0655\u067E\u0686\u0698\u06AF\u06A9\u0643\u06AA\uFED9\uFEDA\u06CC\uFEF1\uFEF2' + '\u0643\uFB91\uFB90\uFB8F\uFB8E\uFEDC\uFEDB\uFEDA\uFED9\u0649\uFEEF\u064A\u06C1\u06D5\u06BE\uFEF0-\uFEF4',
	persianCharactersNoVowels: '\u0621-\u064A\u0653-\u0655\u067E\u0686\u0698\u06AF\u06A9\u0643\u06AA\uFED9\uFEDA\u06CC\uFEF1\uFEF2' + '\u0643\uFB91\uFB90\uFB8F\uFB8E\uFEDC\uFEDB\uFEDA\uFED9\u0649\uFEEF\u064A\u06C1\u06D5\u06BE\uFEF0-\uFEF4',
	persianDigits: '۰۱۲۳۴۵۶۷۸۹',
	hamza: '\u0654',

	normalizeZwnj: function(text) {
		return text
			// Replace LRM، RLM characters with ZWNJ and it will remove unneeded ZWNJ at next lines
			// .replace(/(\u202A|\u202B|\u202C|\u202D|\u202E|\u200F|\¬)/g, '\u200c')
			.replace(new RegExp('([' + persianTools.persianCharacters + '] *)\u200F+( *[' + persianTools.persianCharacters + '])', 'g'), '$1\u200c$2')
			// Remove more than a ZWNJs
			.replace(/\u200c{2,}/g, '\u200c')
			// Convert ¬ to zwnj in Persian context
			.replace(new RegExp('([' + persianTools.persianCharacters + '])¬(?=[' + persianTools.persianCharacters + '])', 'g'), '$1\u200c')
			// Clean ZWNJs after characters that don't conncet to the next letter
			.replace(/([۰-۹0-9إأةؤورزژاآدذ،؛,\:«»\\\/@#$٪×\*\(\)ـ\-=\|])\u200c/g, '$1')
			// Clean ZWNJs before English characters
			.replace(/\u200c([\w])/g, '$1')
			.replace(/([\w])\u200c/g, '$1')
			// Clean ZWNJs after and before punctuation
			.replace(/\u200c([\n\s\[\]\.،«»\:\(\)\؛\؟\?\;\$\!\@\-\=\+\\\|])/g, '$1')
			.replace(/([\n\s\[\.،«»\:\(\)\؛\؟\?\;\$\!\@\-\=\+\\\|])\u200c/g, '$1')
			// Clean ZWNJs before brakets which have sapce after\before them
			.replace(/\u200c(\]\][\s\n])/g, '$1')
			.replace(/([\n\s]\[\[)\u200c/g, '$1');
	},

	persianGlyphs: {
		// these two are for visually available ZWNJ #visualZwnj
		'\u200cه': 'ﻫ','ی\u200c': 'ﻰﻲ',
		'ﺃ': 'ﺄﺃ','ﺁ': 'ﺁﺂ','ﺇ': 'ﺇﺈ','ا': 'ﺎا',
		'ب': 'ﺏﺐﺑﺒ','پ': 'ﭖﭗﭘﭙ','ت': 'ﺕﺖﺗﺘ','ث': 'ﺙﺚﺛﺜ',
		'ج': 'ﺝﺞﺟﺠ','چ': 'ﭺﭻﭼﭽ','ح': 'ﺡﺢﺣﺤ','خ': 'ﺥﺦﺧﺨ',
		'د': 'ﺩﺪ','ذ': 'ﺫﺬ','ر': 'ﺭﺮ','ز': 'ﺯﺰ',
		'ژ': 'ﮊﮋ','س': 'ﺱﺲﺳﺴ','ش': 'ﺵﺶﺷﺸ','ص': 'ﺹﺺﺻﺼ',
		'ض': 'ﺽﺾﺿﻀ','ط': 'ﻁﻂﻃﻄ','ظ': 'ﻅﻆﻇﻈ','ع': 'ﻉﻊﻋﻌ',
		'غ': 'ﻍﻎﻏﻐ','ف': 'ﻑﻒﻓﻔ','ق': 'ﻕﻖﻗﻘ','ک': 'ﮎﮏﮐﮑﻙﻚﻛﻜ',
		'گ': 'ﮒﮓﮔﮕ','ل': 'ﻝﻞﻟﻠ','م': 'ﻡﻢﻣﻤ','ن': 'ﻥﻦﻧﻨ',
		'ه': 'ﻩﻪﻫﻬ','هٔ': 'ﮤﮥ','و': 'ﻭﻮ','ﺅ': 'ﺅﺆ',
		'ی': 'ﯼﯽﯾﯿﻯﻰﻱﻲﻳﻴ','ئ': 'ﺉﺊﺋﺌ','لا': 'ﻼ','ﻹ': 'ﻺ',
		'ﻷ': 'ﻸ','ﻵ': 'ﻶ'
	},

	toStandardPersianCharacters: function(text) {
		var i;
		for (i in persianTools.persianGlyphs) {
			if (persianTools.persianGlyphs.hasOwnProperty(i)) {
				text = text.replace(new RegExp('[' + persianTools.persianGlyphs[i] + ']', 'g'), i);
			}
		}
		return persianTools.normalizeZwnj(text) // needed because of #visualZwnj
			.replace(/ك/g, 'ک') // Arabic
			.replace(/ڪ/g, 'ک') // Urdu
			.replace(/ﻙ/g, 'ک') // Pushtu
			.replace(/ﻚ/g, 'ک') // Uyghur
			.replace(/ي/g, 'ی') // Arabic
			.replace(/ى/g, 'ی') // Urdu
			.replace(/ے/g, 'ی') // Urdu
			.replace(/ۍ/g, 'ی') // Pushtu
			.replace(/ې/g, 'ی') // Uyghur
			.replace(/ہ/g, 'ه') // Convert &#x06C1; to &#x0647; ہہہہ to ههه
			.replace(/ە/g, 'ه\u200c') // Kurdish
			.replace(/ھ/g, 'ه'); // Kurdish
	},

	toPersianDigits: function(text) {
		var i = 0;
		for (i = 0; i <= 9; i = i + 1) {
			text = text.replace(new RegExp('[' + persianTools.arabicIndicDigits[i] + persianTools.arabicDigits[i] + ']', 'g'), persianTools.persianDigits[i]);
		}
		return text
			.replace(new RegExp('([' + persianTools.persianDigits + ']) ?%', 'g'), '$1٪')
			.replace(new RegExp('([' + persianTools.persianDigits + '])\\.(?=[' + persianTools.persianDigits + '])', 'g'), '$1٫') // persian decimal separator
			.replace(new RegExp('([' + persianTools.persianDigits + '])\\،(?=[' + persianTools.persianDigits + '])', 'g'), '$1٬'); // جایگزینی جداکننده هزاگان به جای ویرگول در میان اعداد
	},

	applyOrthography: function (text) {
		return text
			// جایگزینی ۀ غیراستاندار+حرف بعدی بدون فاصله به ه+همزه+فاصله
			.replace(/ۀ(?![\s\n])/g, 'هٔ ')
			// Replace ه followed by (space|ZWNJ|lrm) follow by ی with هٔ
			.replace(/ه[\u200c\u200e\s]+ی([\s\n])/g, 'هٔ$1')
			// Replace ه followed by (space|ZWNJ|lrm|nothing) follow by ء or with هٔ
			.replace(/ه[\u200c\u200e\s]*[ءٔ]([\s\n])/g, 'هٔ$1')
			// Replace هٓ or single-character ۀ with the standard هٔ
			.replace(/(ۀ|هٓ)/g, 'هٔ')
			// Replace ه followed by ئ or ی, and then by ی, with ه\u200cای, example: خانهئی becomes خانه\u200cای
			.replace(/ه\u200c[ئی]ی/g, 'ه\u200cای')
			// Function for removing incorrect ZWNJs
			.replace(/([\u200c\u200e])([\s\n])/g, '$2')
			.replace(/([\s\n])([\u200c\u200e])/g, '$1')
			//فاصلهٔ پیش از واکه‌های کوتاه اشتباه است و برای جلوگیر از به هم چسبیدن کلمات فاصله و واکه جابجا باید گردند.
			.replace(new RegExp('([' + persianTools.persianCharacters + persianTools.vowels + persianTools.hamza + '])(\\s)([' + persianTools.vowels + persianTools.hamza + '])', 'g'), '$1$3$2')
			//واکه‌های کوتاه پشت سرهم نمی‌آیند و یک حرف باید بینشان فاصله باشد
			.replace(new RegExp('([' + persianTools.vowels + persianTools.hamza + ']){2,}', 'g'), '$1');
	},

	/**
	 * Replaces Persian characters with Arabic's ones so an Arabic sorter can sort Persian lines
	 */
	dePersian: function (text) {
		return text
			.replace(/ی/g, 'ي')
			.replace(/ک/g, 'ك')
			.replace(/گ/g, 'كی')
			.replace(/ژ/g, 'زی')
			.replace(/چ/g, 'جی')
			.replace(/پ/g, 'بی');
	},
	persianSortText: function (text) {
		return text.split('\n').sort(function (x, y) {
			var keyX = persianTools.dePersian(x),
				keyY = persianTools.dePersian(y);
			if (keyX < keyY) { return -1; }
			if (keyX > keyY) { return 1; }
			return 0;
		}).join('\n');
	},
	persianPastVerbs: '(' +
		'ارزید|افتاد|افراشت|افروخت|افزود|افسرد|افشاند|افکند|انباشت|انجامید|انداخت|اندوخت|اندود|اندیشید|انگاشت|انگیخت|انگیزاند|اوباشت|ایستاد' +
		'|آراست|آراماند|آرامید|آرمید|آزرد|آزمود|آسود|آشامید|آشفت|آشوبید|آغازید|آغشت|آفرید|آکند|آگند|آلود|آمد|آمرزید|آموخت|آموزاند' +
		'|آمیخت|آهیخت|آورد|آویخت|باخت|باراند|بارید|بافت|بالید|باوراند|بایست|بخشود|بخشید|برازید|برد|برید|بست|بسود|بسیجید|بلعید' +
		'|بود|بوسید|بویید|بیخت|پاشاند|پاشید|پالود|پایید|پخت|پذیراند|پذیرفت|پراکند|پراند|پرداخت|پرستید|پرسید|پرهیزید|پروراند|پرورد|پرید' +
		'|پژمرد|پژوهید|پسندید|پلاسید|پلکید|پناهید|پنداشت|پوسید|پوشاند|پوشید|پویید|پیچاند|پیچانید|پیچید|پیراست|پیمود|پیوست|تاباند|تابید|تاخت' +
		'|تاراند|تازاند|تازید|تافت|تپاند|تپید|تراشاند|تراشید|تراوید|ترساند|ترسید|ترشید|ترکاند|ترکید|تکاند|تکانید|تنید|توانست|جَست|جُست' +
		'|جست|جنباند|جنبید|جنگید|جهاند|جهید|جوشاند|جوشید|جوید|چاپید|چایید|چپاند|چپید|چراند|چربید|چرخاند|چرخید|چرید|چسباند|چسبید' +
		'|چشاند|چشید|چکاند|چکید|چلاند|چلانید|چمید|چید|خاراند|خارید|خاست|خایید|خراشاند|خراشید|خرامید|خروشید|خرید|خزید|خست|خشکاند' +
		'|خشکید|خفت|خلید|خمید|خنداند|خندانید|خندید|خواباند|خوابانید|خوابید|خواست|خواند|خوراند|خورد|خوفید|خیساند|خیسید|داد|داشت|دانست' +
		'|درخشانید|درخشید|دروید|درید|دزدید|دمید|دواند|دوخت|دوشید|دوید|دید|دیدم|راند|ربود|رخشید|رساند|رسانید|رست|رَست|رُست' +
		'|رسید|رشت|رفت|رُفت|رقصاند|رقصید|رمید|رنجاند|رنجید|رندید|رهاند|رهانید|رهید|روبید|روفت|رویاند|رویید|ریخت|رید|ریسید' +
		'|زاد|زارید|زایید|زد|زدود|زیست|سابید|ساخت|سپارد|سپرد|سپوخت|ستاند|ستد|سترد|ستود|ستیزید|سرایید|سرشت|سرود|سرید' +
		'|سزید|سفت|سگالید|سنجید|سوخت|سود|سوزاند|شاشید|شایست|شتافت|شد|شست|شکافت|شکست|شکفت|شکیفت|شگفت|شمارد|شمرد|شناخت' +
		'|شناساند|شنید|شوراند|شورید|طپید|طلبید|طوفید|غارتید|غرید|غلتاند|غلتانید|غلتید|غلطاند|غلطانید|غلطید|غنود|فرستاد|فرسود|فرمود|فروخت' +
		'|فریفت|فشاند|فشرد|فهماند|فهمید|قاپید|قبولاند|کاست|کاشت|کاوید|کرد|کشاند|کشانید|کشت|کشید|کفت|کفید|کند|کوبید|کوچید' +
		'|کوشید|کوفت|گَزید|گُزید|گایید|گداخت|گذارد|گذاشت|گذراند|گذشت|گرازید|گرایید|گرداند|گردانید|گردید|گرفت|گروید|گریاند|گریخت|گریست' +
		'|گزارد|گزید|گسارد|گستراند|گسترد|گسست|گسیخت|گشت|گشود|گفت|گمارد|گماشت|گنجاند|گنجانید|گنجید|گندید|گوارید|گوزید|لرزاند|لرزید' +
		'|لغزاند|لغزید|لمباند|لمدنی|لمید|لندید|لنگید|لهید|لولید|لیسید|ماسید|مالاند|مالید|ماند|مانست|مرد|مکشید|مکید|مولید|مویید' +
		'|نازید|نالید|نامید|نشاند|نشست|نکوهید|نگاشت|نگریست|نمایاند|نمود|نهاد|نهفت|نواخت|نوردید|نوشاند|نوشت|نوشید|نیوشید|هراسید|هشت' +
		'|ورزید|وزاند|وزید|یارست|یازید|یافت' +
		')',
	persianPresentVerbs: '(' +
		'ارز|افت|افراز|افروز|افزا|افزای|افسر|افشان|افکن|انبار|انباز|انجام|انداز|اندای|اندوز|اندیش|انگار|انگیز|انگیزان' +
		'|اوبار|ایست|آرا|آرام|آرامان|آرای|آزار|آزما|آزمای|آسا|آسای|آشام|آشوب|آغار|آغاز|آفرین|آکن|آگن|آلا|آلای' +
		'|آمرز|آموز|آموزان|آمیز|آهنج|آور|آویز|آی|بار|باران|باز|باش|باف|بال|باوران|بای|باید|بخش|بخشا|بخشای' +
		'|بر|بَر|بُر|براز|بساو|بسیج|بلع|بند|بو|بوس|بوی|بیز|بین|پا|پاش|پاشان|پالا|پالای|پذیر|پذیران' +
		'|پر|پراکن|پران|پرداز|پرس|پرست|پرهیز|پرور|پروران|پز|پژمر|پژوه|پسند|پلاس|پلک|پناه|پندار|پوس|پوش|پوشان' +
		'|پوی|پیچ|پیچان|پیرا|پیرای|پیما|پیمای|پیوند|تاب|تابان|تاران|تاز|تازان|تپ|تپان|تراش|تراشان|تراو|ترس|ترسان' +
		'|ترش|ترک|ترکان|تکان|تن|توان|توپ|جنب|جنبان|جنگ|جه|جهان|جو|جوش|جوشان|جوی|چاپ|چای|چپ|چپان' +
		'|چر|چران|چرب|چرخ|چرخان|چسب|چسبان|چش|چشان|چک|چکان|چل|چلان|چم|چین|خار|خاران|خای|خر|خراش' +
		'|خراشان|خرام|خروش|خز|خست|خشک|خشکان|خل|خم|خند|خندان|خواب|خوابان|خوان|خواه|خور|خوران|خوف|خیز|خیس' +
		'|خیسان|دار|درخش|درخشان|درو|دزد|دم|ده|دو|دوان|دوز|دوش|ران|ربا|ربای|رخش|رس|رسان' +
		'|رشت|رقص|رقصان|رم|رنج|رنجان|رند|ره|رهان|رو|روب|روی|رویان|ریز|ریس|رین|زا|زار|زای|زدا' +
		'|زدای|زن|زی|ساب|ساز|سای|سپار|سپر|سپوز|ستا|ستان|ستر|ستیز|سر|سرا|سرای|سرشت|سز|سگال|سنب' +
		'|سنج|سوز|سوزان|شاش|شای|شتاب|شکاف|شکف|شکن|شکوف|شکیب|شمار|شمر|شناس|شناسان|شنو|شو|شور|شوران|شوی' +
		'|طپ|طلب|طوف|غارت|غر|غلت|غلتان|غلط|غلطان|غنو|فرسا|فرسای|فرست|فرما|فرمای|فروش|فریب|فشار|فشان|فشر' +
		'|فهم|فهمان|قاپ|قبولان|کار|کاه|کاو|کش|کَش|کُش|کِش|کشان|کف|کن|کوب|کوچ|کوش|گا|گای|گداز' +
		'|گذار|گذر|گذران|گرا|گراز|گرای|گرد|گردان|گرو|گری|گریان|گریز|گز|گزار|گزین|گسار|گستر|گستران|گسل|گشا' +
		'|گشای|گمار|گنج|گنجان|گند|گو|گوار|گوز|گوی|گیر|لرز|لرزان|لغز|لغزان|لم|لمبان|لند|لنگ|له|لول' +
		'|لیس|ماس|مال|مان|مک|مول|موی|میر|ناز|نال|نام|نشان|نشین|نکوه|نگار|نگر|نما|نمای|نمایان|نه' +
		'|نهنب|نواز|نورد|نوش|نوشان|نویس|نیوش|هراس|هست|هل|ورز|وز|وزان|یاب|یار|یاز' +
		')',

	applyZwnj: function (text) {
		return persianTools.normalizeZwnj(text)
			.replace(
				new RegExp('(^|[^' + persianTools.persianCharacters + '])(می|نمی) ?' + persianTools.persianPastVerbs +
					'(م|ی|یم|ید|ند|ه|)($|[^' + persianTools.persianCharacters + '])', 'g'),
				'$1$2\u200c$3$4$5'
			)
			.replace(
				new RegExp('(^|[^' + persianTools.persianCharacters + '])(می|نمی) ?' + persianTools.persianPresentVerbs +
					'(م|ی|د|یم|ید|ند)($|[^' + persianTools.persianCharacters + '])', 'g'),
				'$1$2\u200c$3$4$5'
			)
			// ای «توان» ناقلا!
			.replace(/(\s)(می|نمی) ?توان/g, '$1$2\u200cتوان')
			// چسباندن تمام «ها»ها با فاصلهٔ مجازی
			.replace(/\sها([\]\.،\:»\)\s]|\'{2,3}|\={2,})/g, '\u200cها$1')
			.replace(/\sها(ی|یی|یم|یت|یش|مان|تان|شان)([\]\.،\:»\)\s])/g, '\u200cها$1$2')
			// برای حذف علامت ستاره اضافی قبل از عنوان ها
			.replace(/\n\*\s*(\=+.+?\=+\n)/g, '\n$1')
			// عضو علامت های نقل قول تکی از عنوان ها
			.replace(/(\n=+)(.*?)(?:'+)(.*?)(?:'+)(.*?)(=+\n)/g, '$1$2$3$4$5')
			// اول و آخر هم خط اگر فاصلهٔ مجازی باشد، حذف شود
			.replace(/(^\u200c|\u200c$)/mg, '')
			// شناسه ها
			// توجه: «است» تعدماً از شناسه ها حذف شده چون به عنوان فعل مستقل هم کاربرد دارد و در آن موارد باید جدا نوشته شود
			// مثال: «این یک خانه است» که است در آن باید از خانه جدا نوشته شود
			.replace(new RegExp('ه\\s+(ام|ای|ایم|اید|اند)($|[^' + persianTools.persianCharacters + '\u200c])', 'g'), 'ه\u200c$1$2')
			// موارد جزئی دیگر و بی ربط به فاصلهٔ مجازی، باید منتقل شود
			.replace(/ا\sً/g, 'اً')
			// رفع اشکال که‌ای
			.replace(/ که‌ای /g, ' که ای ');
	},
	
	punctuation: function (text) {
		return text
			.replace(/ː/g, ':') // Replace incorrect : character
			.replace(/\r/g, '')
			// Add or remove space
			// حذف فاصله‌های تکراری میان واژه‌ها، به جز بین نام پارامتر و علامت مساوی
			.replace(/(. ) +(?=[^= ])/g, '$1')
			//فاصله بعد از سجاوندی به جز ! به دلیل (<!-- و !! در بالای جدول‌ها)
			.replace(/([،\.\؛\؟»])([^\s\.\(\)«»\"\[\]<>\d\w\{\}\|۰-۹\'])/g, '$1 $2') 
			// حذف فاصله بعد از گیومه، پرانتز، براکت باز
			.replace(/([\(«\[])\s/g, '$1')
			// حذف فاصله قبل از گیومه، پرانتز، براکت بسته
			.replace(/\s([\)»\]])/g, '$1')
			// افزودن فاصله قبل از گیومه باز
			.replace(/([^ \(\[\|\r\n>'])(«)/g, '$1 $2')
			.replace(/٬\s/g, '، ')
			.replace(/ +\( +/g, ' (')
			.replace(new RegExp('([' + persianTools.persianCharacters + ']) *\\( *(?=[' + persianTools.persianCharacters + '])(?!ها\\)|ان\\))', 'g'), '$1 (')
			.replace(new RegExp('([' + persianTools.persianCharacters + ']) *\\) *(?=[' + persianTools.persianCharacters + '])', 'g'), '$1) ')
			.replace(/([^ \.]) +([؟،\:؛!\.])(\s[^ \.]|<|$)/g, '$1$2$3')// Remove space preceding punctuation, except for ellipses
			// Add Space After Punctuation
			.replace(new RegExp('([' + persianTools.persianCharacters + ']+)([؟،؛!\\.])([' + persianTools.persianCharacters + "]+)", 'g'), '$1$2 $3')
			// New Line
			.replace(/\n\s{1,}\n/g, '\n\n')
			// Removes extra line between two items list
			.replace(/(\n\*.*?)\n+(?=\n\*)/g, '$1')
			// Removes extra line between two items list
			.replace(/(\n#.*?)\n+(?=\n#)/g, '$1')
			// Convert , to ، if there are Persian characters on both sides of it .replace(new RegExp('([' + persianTools.persianCharacters + ']), ?(?=[' + persianTools.persianCharacters + "])", 'g'), '$1$2، ')
			// بعد از نقطه‌ویرگول فارسی علامتی قرار نمی‌گیرد
			.replace(/(؛)(([\s]+)?[\.،؛:!؟\-…])/g, '$1')
			// در انتهای پاراگراف نقطه‌ویرگول فارسی نمی‌آید
			.replace(/(؛)(\s|)\n\n/g, '.\n\n')
			// سجاوندی در ابتدای علامت باز قرار نمی‌گیرد
			.replace(/([\(«])[\s]([؛\.،])/g, '$1')
			// ویرگول فارسی
			// بعد از ویرگول فارسی این علامت‌ها قرار نمی‌گیرد
			.replace(/(،)([\s]+)?([،؛!؟\-][\.،؛!؟\-]*|\.(?!\.))/g, '$1')
			// نقطه
			// باید سه نقطه باشد
			.replace(new RegExp('([' + persianTools.persianCharacters + '])(\\s|)(\\.{3,})', 'g'), '$1$2...')
			// بعد از نقطه این علایم نمی‌آیند
			.replace(new RegExp('([' + persianTools.persianCharacters + '])\\.( *[،؛:!؟\\?]+)', 'g'), '$1.')
			// سجاوندی در ابتدای پرانتز و گیومه باز قرار نمی‌گیرد
			.replace(new RegExp('(\\(|«)[\\.،؛](\\s|)([' + persianTools.persianCharacters + '])', 'g'), '$1$3')
			// سجاوندی در داخل پرانتز
			.replace(new RegExp('([' + persianTools.persianCharacters + '])(\\s|)[\\.،؛](\\s|)(\\))', 'g'), '$1$2$3$4')
			// در صورت وابستگی معنی جملات بهتر است نقطه‌ویرگول فارسی قرار گیرد
			.replace(new RegExp('([' + persianTools.persianCharacters + '])(\\s|)(\\.)(\\s|)(ولی|که|و\\s|بنابراین|لذا)', 'g'), '$1؛ $5')
			/// Question & exclamation mark
			// علامت تعجب تکراری به دلیل وجود !! در عنوان جدول‌های مدیاویکی نباید اصلاح شود.
			// تكرار علامت سوال فارسی
			.replace(/(؟(\s|)){2,}/g, '؟')
			//علامت‌گذاری نادرست
			.replace('؟ !', '؟!').replace('! ؟', '!؟')
			/// سجاوندی غیرفارسی
			// استفاده از ؟ فارسی
			.replace(new RegExp('([' + persianTools.persianCharacters + '])[ ]*[?]', 'g'), '$1؟')
			// استفاده از ; فارسی
			.replace(new RegExp('([' + persianTools.persianCharacters + '])[ ]*[;]', 'g'), '$1؛')
			// استفاده از ، فارسی
			.replace(new RegExp('([' + persianTools.persianCharacters + '])[ ]*[,]', 'g'), '$1،')
			//رفع مشکل استفاده از ـــً به جای گیومه لاتین در متن فارسی
			.replace(new RegExp('ا\\"([ ]*[' + persianTools.persianCharacters + '])', 'g'), 'اً$1');
			// TODO: Should be limited
			// بين حروف و اعداد باید فاصله باشد
			//.replace(new RegExp('(\\d+)([' + persianTools.persianCharacters + ']+)', 'g'), '$1 $2')
			//.replace(new RegExp('([' + persianTools.persianCharacters + ']+)(\\d+)', 'g'), '$1 $2')
			// بين کلمات فارسی و انگلیسی باید فاصله باشد
			//.replace(new RegExp('([a-zA-Z]+)([' + persianTools.persianCharacters + ']+)', 'g'), '$1 $2')
			//.replace(new RegExp('([' + persianTools.persianCharacters + ']+)([a-zA-Z]+)', 'g'), '$1 $2');
	},
};