מדיה ויקי:Gadget-Checkty.js

מתוך ויקיסוגיה
קפיצה לניווט קפיצה לחיפוש
הגרסה להדפסה אינה נתמכת עוד וייתכן שיש בה שגיאות תיצוג. נא לעדכן את הסימניות בדפדפן שלך ולהשתמש בפעולת ההדפסה הרגילה של הדפדפן במקום זה.

הערה: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.

  • פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload), או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
  • גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
  • אינטרנט אקספלורר / אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh), או ללחוץ על צירוף המקשים Ctrl-F5.
  • אופרה: ללחוץ על Ctrl-F5.
// הוספת כפתור "בדיקה" שמבצע החלפות נפוצות של בוט ההחלפות וכן מתריע על בעיות סגנון ועיצוב שונות
// נכתב על ידי [[משתמש:ערן]] ו[[משתמש:קיפודנחש]]
// לעזרה ראו [[mediawiki:Gadget-Checkty.js/הוראות]]
mw.messages.set({
	'checkty-large-element': 'בערך קיים אלמנט גדול, רצוי להקטין כדי שיתאים לרזולוציות נמוכות',
	'checkty-long-list': 'רשימה ארוכה - נראה כי בערך רשימה של מעל 20 פריטים. כדאי לשקול לפצלה לשני טורים באמצעות <a href="' + (new mw.Title('תבנית:טורים')).getUrl() + '">תבנית:טורים</a>',
	'checkty-long-gallery': 'גלריה ארוכה - הערך מכיל גלריה ארוכה. מומלץ לשקול צמצום שלה או העברה לוויקישיתוף.',
	'checkty-waiting-disambig-query': 'ממתין לרשימת פירושונים מהשרת...',
	'checkty-warnings-title': 'הערות לבדיקה:',
	'checkty-no-replacements': 'הדף מכיל תבנית "ללא בוט" ולכן לא יבוצעו החלפות',
	'checkty-replace-summary': '[[וק:רה|החלפות]] ($1)',
	'checkty-disambig-suffix': ' (פירושונים)',
	'checkty-disambig-no-links': 'קישורים לפירושונים - לא נמצאו',
	'checkty-disambig-success': 'קישורים לפירושונים - הבדיקה הסתיימה בהצלחה.',
	'checkty-disambig-links-title': 'הגרסה השמורה האחרונה של הדף מקשרת לדפי פירושונים. אנא תקנו את הקישורים לדפים הבאים: ',
	'checkty-page-doesnt-exist': ' (הדף אינו קיים)',
	'checkty-dismabig-dialog-title': 'תיקון פירושונים',
	'checkty-remove-link': 'הסרת קישור',
	'checkty-disambig-meaning': 'מה הכוונה ב "$1" במשפט: ',
	'checkty-dismabig-fix-summary': 'תיקון קישור לפירושונים',
	'checkty-search': 'חיפוש',
	'checkty-fix-numberRangeDash': 'תיקון קווים מפרידים',
	'checkty-missing-commons-link': 'בערך זה חסר קישור לוויקישיתוף. ניתן להוסיף קישור באמצעות בחירת המקום הנכון להוספתו בערך ולחיצה על הקישור הבא. ',
	'checkty-fairuse-img-replace-template': 'תמונה להחלפה',
	'checkty-set-label': 'הזנת תווית עברית ל-$1',
	'checkty-translate-saved': 'התרגום נשמר!',
//	'checkty-empty-parameters': 'פרמטרים ריקים - דף זה מכיל תבניות עם פרמטרים ריקים. אם הם אינם רלוונטיים ניתן להסירם. ',
//	'checkty-empty-parameters-summary': 'ניקוי קוד',
	'checkty-main-articles-merge-summary': 'מיזוג הפניות לערכים מורחבים',
	'checkty-please-position-caret' : 'אנא מקמו את הסמן במקום בו יש להוסיף ',
	'checkty-ref-dir-fix' : 'תיקון כיווניות להערת שוליים',
	'checkty-naked-link-found' : 'נמצא קישור חיצוני ערום: $1',
	'checkty-naked-link-fix' : 'תיקון',
	'checkty-broken-link': 'חשש לקישור שבור: ',
	'checkty-naked-link-fix-fail': 'שגיאה בתיקון קישור עירום',
	'checkty-naked-link-fixed': 'הקישור $1 הוחלף בתבנית. יש לבדוק את תקינות התוצאה והאם יש לעטוף בתבנית הערה<br> $2',
	'checkty-external-links-many': 'קישורים חיצוניים - פרק הקישורים החיצוניים מכיל $1 קישורים. מומלץ להעביר קישורים העוסקים בנושאים ספציפיים להערות שוליים, ולהסיר קישורים שלא מוסיפים. (ראו עוד ב<a href="' + mw.util.getUrl('ויקיפדיה:קישורים חיצוניים') + '">ויקיפדיה:קישורים חיצוניים</a>)',
	'checkty-external-links-diversity': 'קישורים חיצוניים - פרק הקישורים החיצוניים מכיל מספר קישורים למקורות זהים: $1. כאשר הקישור עוסק באספקט צר של הערך מומלץ להפכו להערת שוליים. (ראו עוד ב<a href="' + mw.util.getUrl('ויקיפדיה:קישורים חיצוניים') + '">ויקיפדיה:קישורים חיצוניים</a>)',
	'checkty-nonsense-edit': 'עריכה זו כוללת שינויים אוטומטיים בלבד. האם ברצונך לשמור למרות זאת?',
	'checkty-category-sort': 'ניתן למיין את הקטגוריות בדף על פי סדר אלפביתי ',
	'checkty-defaultsort-suggest': 'בערך לא מוגדר מיון רגיל. בערכים העוסקים באישים נהוג למיין לפי שם משפחה. ',
	'checkty-language-check': 'בערך זה מופיע הביטוי "$1". '
});

var chectTyTool = {
	origText: null,
	textbox: null,
	skipCheckty: false,
	isSection: mw.util.getParamValue('section'),
	skip_dict: {},
	formatReplacesConfigSafe:  [
		{
		from: /\[\[(File|Image|תמונה):/ig,
		to: '[[קובץ:'
	}, {
		from: /\|thumb(nail)?(?=[\|\]])/ig,
		to: '|ממוזער'
	}, { //remove unseen character
		from: new RegExp('\u200e|\u200f|\u202d|\u202e|\u202c|\u202a|\u202b', 'g'), // lrm/rlm/lro/rlo/popdf invisible characters/lre/rle
		to: "",
		comment: 'הסרת תווים בלתי נראים'
	}, {
		from: / +$/mg,
		to: ''
	}, { // remove accidental nowiki and simplify code
		from: /\[\[([^|\[\]]+)([^|\[\]]+?)\|\1\]\](?:<nowiki\/>)?\2/g,
		to: '[[$1$2]]',
		comment: 'פישוט קישור'
	}, { // trim begining from redundant spaces
		from: /^\s+/g,
		to: '',
		comment: 'הסרת רווחים מיותרים'
	}],
	formatReplacesConfig: [{
		from: /\[\[(.*?)\|\1([a-zא-ת]*)\]\]/g,
		to: '[[$1]]$2'
	}, {
		from: /\[\[(.+?)\|([במל])\1([א-ת]*)\]\]/g,
		to: "$2[[$1]]$3"
	}, { // proper spacing around , and . 
		from: /([א-ת]\]?\]?) ?([,\.]) ?(?=[א-ת]?\[?\[?[א-ת]{3})/g,
		to: "$1$2 ",
		skippable: true
	}, {
		from: /([א-ת])\( ?([א-ת])/g,
		to: "$1 ($2"
	}, {
		from: /(\n\n)\n+/g,
		to: "$1"
	}, {
		from: /== ? ?\n\n==/g,
		to: "==\n=="
	}, {
		from: /^ ? ? \n/gm,
		to: "\n"
	}, {
		from: /(?!.{2}\|)[ \t\xA0]{2,}/g,
		to: ' '
	}, {
		from: /\n\n\*/g,
		to: '\n*'
	},
	{
		from: /([בלמכ])- ((?:\[\[)?[0-9])/g,
		to: '$1־$2'
	},
	{ // move , suffix outside links
		from: /,\]\]/g,
		to: ']],'
	}],
	regexes: [],
	ignoreRegexes: [],
	run: function () {
		if (this != chectTyTool) {
			chectTyTool.run();
			return;
		}
		var t = $('#wpTextbox1');
		this.textbox = t.length ? t[0] : null;
		if (!this.textbox || this.textbox.value.length === 0) return;
		// indication that skippable replacements should be ignored in the page
		this.skipCheckty = this.textbox.value.match(/{{ללא[_ ]בוט\|\s*צ'קטי\s*}}/g);
		if (!($('#checktyResults').length)) $('.editButtons').after('<div id="checktyResults"><div class="checktyResultsTitle">'+mw.msg( 'checkty-warnings-title' )+'</div></div>');
		//first call to remote functions than to local
		if ( ( chectTyTool.textbox.value === chectTyTool.origText ) && ( mw.config.get('wgAction') === 'edit') ) 
			this.onSaveProtection();
		
		this.formatChecks();
		this.linkChecks();
		if(!this.isSection) {
			this.articleOrgChecks();
			this.checkImages();
		}
		this.languageCheck();
		this.expandWikidata();
	},
	formatChecks: function() { 
		if (!this.isSection)
			this.build_regexes();
		this.formatReplace();
		this.decodeExternalLinks();

		// format - semi manual
		this.mainArticlesMerge();
		this.numberRangeDash(false);
	},
	decodeExternalLinks: function() {
		var t = this.textbox.value, newTxt = t, 
		externalLinkRgx = /http[^ \]|]+/g,
		decodeRgx = /(?:%[0-9a-z]{2}){2,}/ig,
		m, mm, newLink;
		while ( m = externalLinkRgx.exec(t) ) {
			newLink = m[0];
			while (mm = decodeRgx.exec(m[0])) {
				try {
					// decode URL except special chars
					var niceLink = decodeURI(mm[0]).replace(/[ |"\n\[\]{}<>]/g, encodeURI);
					if (niceLink == niceLink.normalize()) newLink = newLink.replace(mm[0], niceLink);
				} catch(ex) {
				}
			}
			newTxt = newTxt.replace(m[0], newLink);
		}
		if (newTxt === t) return;
		this.updateText(newTxt);
		chectTyTool.addSummary('קידוד קישורים');
	},
	articleOrgChecks: function() {
		this.titleOrderCheck();
		this.checkRefs();
		this.checkGallery();
		this.defaultSortSuggest();
		this.categoryOrder();
	},
	defaultSortSuggest: function(execute) {
		var txt = this.textbox.value,
		isPerson = false,
		firstFamilyRgx = /^([^ ]+) ([^ ]+)$/,
		name, defaultSortMsg;
		if (/\{\{מיון רגיל:/.exec(txt)) return; // skip if already exists
		if (!firstFamilyRgx.exec(mw.config.get('wgTitle'))) return; // skip if can't suggest

		isPerson = /== ?(ביוגרפיה|קורות חיים|חיי[וה]) ?==/.exec(txt); // heuristic to identify biographic articles
		if (!isPerson) return; // skip for non biographic pages

		if (!execute) {
			defaultSortMsg = $('<div>', { text: mw.msg('checkty-defaultsort-suggest') }).append($('<a>', {
				href: '#',
				text: 'הוספת מיון רגיל',
			}).click(function(){ chectTyTool.defaultSortSuggest(true); return false;}));
			this.writeMsg(defaultSortMsg, 'info');
		} else {
			name = firstFamilyRgx.exec(mw.config.get('wgTitle'));
			txt = txt.replace('[[קטגוריה', '{{מיון רגיל:' + name[2] + ', ' + name[1] + '}}\n[[קטגוריה');
			this.addSummary('מיון רגיל');
			this.updateText(txt);
		}
	},
	categoryOrder: function(execute) {
		var txt = this.textbox.value,
		newTxt = txt,
		self = this;
		categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g,
		cats = [], m = null, oldCats = null, categorySortMsg = null;
		while(m=categoryRE.exec(txt)) {
			cats.push(m[1]);
			newTxt = newTxt.replace(m[0], '');
		}
		oldCats = JSON.stringify(cats);
		cats.sort(function(a,b){ 
			if (/\|\*\]\]/.exec(a)) return -1; if (/\|\*\]\]/.exec(b)) return 1;
			if (/נפטרים ב-|נפטרות|שנפטרו/.exec(a)) return 1; if(/נפטרים ב-|נפטרות|שנפטרו/.exec(b)) return -1;
			if (/(ילידי|ילידות|שנולדו).*[0-9]/.exec(a)) return 1; if(/(ילידי|ילידות|שנולדו).*[0-9]/.exec(b)) return -1;
			if (/אישים במאה ה-|אישים שחיו במאה ה-|אפיפיורים במאה ה-/.exec(a)) return 1; if(/אישים במאה ה-|אישים שחיו במאה ה-|אפיפיורים במאה ה-/.exec(b)) return -1;
			return a>=b;
		});
		if (oldCats == JSON.stringify(cats)) return; // same order - nothing to do
		if (!execute) {
			categorySortMsg = $('<div>', { text: mw.msg('checkty-category-sort') }).append($('<a>', {
				href: '#',
				text: 'סידור',
			}).click(function(){ chectTyTool.categoryOrder(true); return false;}));
			this.writeMsg(categorySortMsg, 'info');
		} else {
			newTxt = newTxt.trimEnd();
			newTxt += '\n' + cats.join('\n');
			if (newTxt != txt)
			OO.ui.confirm( 'יש לאשר סדר הקטגוריות המוצע:' + cats.join(', ').replace(/\[\[קטגוריה:([^\[\]]+)\]\]/g, '$1') ).done( function ( confirmed ) {
				if ( !confirmed ) return;
				self.addSummary('סידור קטגוריות');
				self.updateText(newTxt);
			} );
		}
	},
	linkChecks: function() {
		this.overlinkify();
		this.nakedLinks();
		this.checkExternalLinks();
		this.disambigCheck();
	},
	expandWikidata: function() {
		this.wikidataLabelsMissing();
		this.extractWikidataLabelsSuggestions();
		if (!this.isSection) {
			this.addAuthorityControl();
		}
	},
	createSearchLink: function(v) {
		var highlightStr = this.highlightString,
		 searchLink = $('<a href="#">'+mw.msg( 'checkty-search' )+'</a>').data({'search': v}).click(function(e){ 
			highlightStr($(this).data('search')); e.preventDefault();
		});
		return searchLink;
	},
	onSaveProtection: function() {
		$('#wpSave').click(function(e){
			if (chectTyTool.textbox.value === chectTyTool.origText) {
				OO.ui.confirm( mw.msg('checkty-nonsense-edit') ).done( function ( confirmed ) {
				    if ( confirmed ) {
					chectTyTool.origText = '';
					$('#editform').submit();
				    } else {
					e.preventDefault();
				    }
				} );
				e.preventDefault();
			}
		});
	},
	updateText: function( val ) {
		if (this.textbox.value === chectTyTool.origText) {
			chectTyTool.origText = val;
		}
		this.textbox.value = val;
	},
	nakedLinks: function() {
		var t = this.textbox.value,
		nakeRegex=/\[(http[^ ]+?)\]|\{\{הערה *\| *(?:1 *= *)?(https?:\/\/[^ }|]+)\}\}/g,
		nakeErrors=[], m, self= this;
		while (m = nakeRegex.exec(t)) {
			var nakedUrl = m[1] || m[2],
			fixNakedLink = $( '<a href="#">' + mw.msg( 'checkty-naked-link-fix' )+'</a>' ).data( { 'search': nakedUrl, 'inRef': m[2] }).click( function ( e ) { 
				var searchUrl = $(this).data( 'search' ),
				inRef = $(this).data('inRef'),
				citoidTemplatesPromise = new mw.Api().loadMessagesIfMissing( [ 'citoid-template-type-map.json' ] );
		        // Common case: pasting a URI into this field. Citoid expects
		        // minimally encoded input, so do some speculative decoding here to
		        // avoid 404 fetches. T146539
				searchUrl = decodeURIComponent(searchUrl);
				citoidPromise = $.ajax('/api/rest_v1/data/citation/mediawiki/'+encodeURIComponent(searchUrl), {
					headers: { 'accept-language': mw.config.get( 'wgContentLanguage' ) },
					timeout: 20 * 1000, // 20 seconds
					type: 'GET'
				});
				citoidPromise.done(function(d){
				citoidTemplatesPromise.done(function(){
					var CiteTemplates = JSON.parse( mw.message( 'citoid-template-type-map.json' ).plain() );
					if ( d.length === 0 || !CiteTemplates[ d[0].itemType ] ) {
						self.writeMsg( mw.msg( 'checkty-naked-link-fix-fail' ) );
						return;
					}

					var api = new mw.Api().get( {
						action: 'templatedata',
						titles: 'Template:' + CiteTemplates[ d[0].itemType ]
					}).done(function(tdq){
						for(var pid in tdq.pages){
							var td = tdq.pages[pid],
							params = [];
							for(var k in d[0]) {
								if (td.maps['citoid'][k]) {
									if ($.isArray(td.maps['citoid'][k]) && $.isArray(d[0][k])) {
										for(var i = 0;i < d[0][k].length; i++) {
											if ($.isArray(d[0][k][i]) && $.isArray(td.maps['citoid'][k][i])) {
												for(var j = 0;j < d[0][k][i].length; j++) {
													params.push(td.maps['citoid'][k][i][j] + '=' + d[0][k][i][j].replace(/\|/g, '{{!}}'));
												}
											}
										}
									}
									else {
										if ($.isArray(d[0][k])) {
											for(var i = 0;i < d[0][k].length; i++) if ($.isArray(d[0][k][i])) d[0][k][i] = d[0][k][i].join(' ');
											d[0][k] = d[0][k].join(', ');
										}
										params.push(td.maps['citoid'][k] + '=' + d[0][k].replace(/\|/g, '{{!}}'));
									}
								}
							}
							var template = '{{'+CiteTemplates[d[0].itemType]+'|' + params.join('|')+'}}',
							wikitext = self.textbox.value;
							if ( inRef ) {
								wikitext = wikitext.replace(new RegExp('\\{\\{הערה *\\| *(?:1 *= *)?'+mw.util.escapeRegExp(searchUrl)+'\\}\\}', 'g'), '{{הערה|' + template + '}}');
							} else {
								// this is more context sensitive - sometimes we may or may not want to wrap with ref
								wikitext = wikitext.replace(new RegExp('\\['+mw.util.escapeRegExp(searchUrl)+'\\]', 'g'), template);
							}
							self.textbox.value = wikitext;
							self.writeMsg($('<div>').append(mw.msg('checkty-naked-link-fixed', searchUrl, template)).append(self.createSearchLink(template)));
							chectTyTool.addSummary('הלבשת קישורים עירומים');
						}
					})
				});
				}).fail(function(){
					self.writeMsg($('<div>').append(mw.msg('checkty-broken-link') + searchUrl));
				});
				e.preventDefault();
			});
			this.writeMsg($('<div>').append([mw.msg('checkty-naked-link-found', nakedUrl)+'" [',fixNakedLink, '&nbsp;-&nbsp;', this.createSearchLink(m[0]), ']']), 'alert');
		}
	},
	checkExternalLinks: function() {
		var t = this.textbox.value,
		externalLinksRgx = /== *קישורים חיצוניים *==(?:\n\{\{.+)*((?:\n\*.+|\n\{\{.+\}\})+)/mg,
		tplCounterRgx = /\n\* *\{\{([^|]+)/g,
		externalLinks = externalLinksRgx.exec(t), tplCounter={}, sameSources=[], m;
		if (!externalLinks) return;
		externalLinks = externalLinks[1];
		if (externalLinks.split('\n').length > 8) {
			this.writeMsg('<div>' + mw.msg('checkty-external-links-many', externalLinks.split('\n').length) + '</div>', 'alert');
		}
		else {
			while(m = tplCounterRgx.exec(externalLinks)) tplCounter[m[1]] = (tplCounter[m[1]]? tplCounter[m[1]]+1 : 1);
			delete tplCounter['קישור כללי'];
			for(m in tplCounter) {
				if (tplCounter[m] > 1) sameSources.push(m + ' &rlm;(' + tplCounter[m] + ')');
			}
			if (sameSources.length) {
				this.writeMsg('<div>' + mw.msg('checkty-external-links-diversity', sameSources.join(', ')) + '</div>', 'alert');
			}
		}
	},
	checkRefs: function() {
		this.refsConsistencyCheck();
		this.ibidWarning();
		this.mergeRefs();
		this.refDirSuggest();
	},
	writeMsg: function (msg, icon) {
		var x;
		if (msg instanceof Array) {
			if (msg.length === 0) return;
			msg = '<div>' + msg.join('<br/>') + '</div>';
		}
		x = $(msg).css('display', 'none').addClass('checktyMsg');
		if ( icon ) {
			var iconWidget = new OO.ui.IconWidget( {
				icon: icon,
			 } );
			x.prepend(iconWidget.$element);
		}
		$('#checktyResults').append(x);
		x.show('slow');
		return x;
	},
	build_regexes: function (data, protect) {
		if (/\{\{\s*ללא[_ ]בוט\s*\}\}/.test(this.textbox.value)) {
			this.writeMsg('<div>'+mw.msg( 'checkty-no-replacements' )+'</div>', 'info');
			return;
		}
		if (data) {
			var lines = data.split(/\n/),
			clear_nowiki = /\|<nowiki>(.*)<\/nowiki>/,
			protect_title_regex = /\[\[(.+?)\]\]/g,
			matches, regex, pTitle;
			while (lines.length) {
				if (!(matches = lines.shift().match(/^\|(\d+)/))) continue;
				var num = parseInt(matches[1], 10);
				if (!(matches = lines.shift().match(clear_nowiki))) continue;
				try {
					regex = new RegExp(matches[1], 'g');
				} catch (e) {
					//ignore
					continue;
				}
				if (!(matches = lines.shift().match(clear_nowiki))) continue;
				this.regexes[num] = [regex, matches[1]];
				var ignore = lines.shift(),
					ignoreRegex = /^\|(?:<nowiki>)?(.+?)(?:<\/nowiki>)?$/.exec(ignore);
				if (ignoreRegex) {
					this.ignoreRegexes.push('(?:' + ignoreRegex[1] + ')');
				}
			}
			if (protect) {
				// add titles of pages explicitly marked as special
				while (pTitle = protect_title_regex.exec(protect)) {
					this.ignoreRegexes.push(mw.util.escapeRegExp(pTitle[1]));
					this.ignoreRegexes.push('(?:\\[\\[' + mw.util.escapeRegExp(pTitle[1]) + '\\|.+?\\]\\])'); //protect links [[A (x)|A]] or other variations
				}
			}
			this.process_page();
		} else {
			var replceQuery = $.ajax({
				url: mw.util.getUrl( (window.replaceListPage || 'ויקיפדיה:בוט/בוט החלפות/רשימת החלפות נוכחית'), { action: 'raw', ctype: 'text/x-wiki' } ),
				dataType: 'html'
			}), protectQuery = $.ajax({
				url: mw.util.getUrl( 'ויקיפדיה:בוט/בוט החלפות/דפים חריגים', { action: 'raw', ctype: 'text/x-wiki' } ),
				dataType: 'html'
			});
			$.when(replceQuery, protectQuery).done(function(dataRepalce, dataProtect){
				chectTyTool.build_regexes(dataRepalce[0], dataProtect[0]);
			});
		}
	},
	process_page: function () {
		var t = this.textbox.value,
			skip_ar = [],
			actual_replaced = [], // list of actual replcements for summary
			actual_replaced_details = [], // list of actual replcements with details for editor
			skipmatch = t.match(/{{ללא[_ ]בוט\|\s*(\d+)\s*}}/g), i, match;
		if (skipmatch)
			for (i = 0; i < skipmatch.length; i++) {
				var matches = skipmatch[i].match(/{{ללא[_ ]בוט\|\s*(\d+)\s*}}/), detailedSkip = '';
				chectTyTool.skip_dict[parseInt(matches[1], 10)] = true;
				if (this.regexes[matches[1]]) {
					detailedSkip = ': ' + $.trim(this.regexes[matches[1]][0].toString());
					skip_ar.push($('<li></li>').append(matches[1] + detailedSkip + '&nbsp;').append(this.createSearchLink(this.regexes[matches[1]][0])));
				}
			}
		var specials = [],
		    ignoreRegex = new RegExp('(' + this.ignoreRegexes.join('|') + ')');
		for (i in this.regexes) // assume regexs on templates are safe if contain template wikicode
			if (/\\{\\{/.test(this.regexes[i][0]) && this.regexes[i][0].test(t)) {
				t = t.replace(this.regexes[i][0], this.regexes[i][1]);
				actual_replaced.push($.trim(this.regexes[i][1].replace(/\$\d*/g, '')));
				actual_replaced_details.push(i + ': ' + $.trim(this.regexes[i][1].replace(/\$\d*/g, '')));
			}
		while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those.
			match = t.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])/);
			if ((!match || !match.length) && this.ignoreRegexes.length ) match = t.match(ignoreRegex);
			if (!match || !match.length) break;
			specials.push(match[0]);
			t = t.replace(match[0], "\0" + specials.length + "\0");
		}
		for (i in this.regexes)
			if (!chectTyTool.skip_dict[i] && !isNaN(i))
				if (this.regexes[i][0].test(t)) {
					var before = t, tries=0, befText, afterText;
					/* repeat replacement for 3 times as sometimes need to converge for more than a single run
					   Such as boundary [^a-z][a-z][^a-z] replacing [a|a]. Use of negative char match is useful 
					   for different regex engines with different support of look ahead and lookbehind */
					do {
						before = t;
						t = t.replace(this.regexes[i][0], this.regexes[i][1]);
						if ((tries==0) && (t != before)) {
							// 1st match as representative example for summary
							befText = this.regexes[i][0].exec(before)[0];
							afterText = befText.replace(this.regexes[i][0], this.regexes[i][1]);
							actual_replaced.push(afterText);
							actual_replaced_details.push(i + ': ' + befText + ' ← ' + afterText);
						}
						tries++;
					} while ((tries < 3) && (t != before))
				}
		while (true) {
			match = t.match(/\0(\d+)\0/);
			if (!match || !match.length) break;
			t = t.replace(match[0], specials[parseInt(match[1], 10) - 1]);
		}
		this.updateText(t);
		var msg = ['החלפות - בוצעו ' + actual_replaced.length + ' החלפות' + (actual_replaced_details.length==0? '.' : ': ' + actual_replaced_details.join(', '))];
		if (skip_ar.length) {
			msg.push('<br />החלפות שלא התבצעו בגלל תבנית "ללא בוט": ');
			msg.push($('<ul></ul>').append(skip_ar));
		}
		if(actual_replaced.length) {
			msg.push(' אנא בצעו "הצגת שינויים" לפני שמירה, כדי לוודא שהסקריפט לא גרם נזק.');
		}
		this.writeMsg($('<div></div>').append(msg), 'info');

		if (actual_replaced.length) chectTyTool.addSummary(mw.msg('checkty-replace-summary', actual_replaced.join(', ')));
	},
	fetchDisambigLinks: function (next) {
		var dfd = new jQuery.Deferred();
		var api = new mw.Api();
		var params = {
			action: 'query',
			generator: 'links',
			titles: mw.config.get('wgPageName'),
			prop: 'pageprops',
			ppprop: 'disambiguation',
			gpllimit: '500',
			redirects: 1
		};
		if (next !== undefined) {
			params.gplcontinue = next;
		}
		api.get(params).done(function (data) {
			//extract disambig pages
			if (!data.hasOwnProperty('query')) {
				dfd.reject();
				return;
			}
			var redirects = {};
			if (data.query.redirects) {
				$.each(data.query.redirects, function(i,r) { redirects[r.to] = r.from; });
			}
			var disambigs = [];
			for (var pid in data.query.pages) {
				var p = data.query.pages[pid],
				isDisambigPage = p.pageprops && p.title != mw.config.get('wgTitle') + mw.msg( 'checkty-disambig-suffix' );
				//list only real disambig links
				if (isDisambigPage && chectTyTool.getLinkRegex(p.title).exec(chectTyTool.textbox.value)) {
					disambigs.push(redirects[p.title] || p.title);
				}
			}
			if (data['query-continue'] !== undefined) {
				var nextReq = chectTyTool.fetchDisambigLinks(data['query-continue'].links.gplcontinue);
				nextReq.done(function (more) {
					dfd.resolve($.merge(disambigs, more));
				});
			} else {
				dfd.resolve(disambigs);
			}
		});
		return dfd.promise();
	},
	mainArticlesMerge: function() {
		var origTxt = this.textbox.value, txt = this.textbox.value, m;
		
		while (m = /(\{\{(?:הפניה לערך מורחב|ערך מורחב)\|[^=]+?\}\}\n){2,}/g.exec(txt)) {
			var articles = [], expArticleRE = /\{\{(?:הפניה לערך מורחב|ערך מורחב)\|([^=]+?)\}\}/g;
			while (ma = expArticleRE.exec(m[0])) articles.push(ma[1]);
			txt = txt.replace(m[0], '{{הפניה לערך מורחב|ערכים=[['+articles.join(']], [[')+']]}}\n');
		}
		this.textbox.value = txt;
		if (origTxt != txt) chectTyTool.addSummary( mw.msg( 'checkty-main-articles-merge-summary' ) );
	},
	formatReplace: function () {
		var txt = this.textbox.value, newTxt;
		// Format autofix
		var specials=[], match;
//		var emptyParametersRgx = /\n *\| *[^|=]+?= *(?=\n(?: *\||\}\}))/mg, emptyParametersMsg, emptyParametersBtn;
		$(this.formatReplacesConfigSafe).each(function (i, o) {

			newTxt = txt.replace(o.from, o.to);
			if ( newTxt!=txt && o.comment) {
				chectTyTool.addSummary( o.comment );
			}
			txt = newTxt;
		});
		
		//extract inner links, inner templates and inner params - we don't want to sptit those.
		while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those.
			match = txt.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])/);
			if (!match || !match.length) break;
			specials.push(match[0]);
			txt = txt.replace(match[0], "\0" + specials.length + "\0");
		}
		
		$(this.formatReplacesConfig).each(function (i, o) {
			newTxt = txt.replace(o.from, o.to);
			if (o.skippable && (chectTyTool.skipCheckty || this.isSection)) return; // skip this one respecting {ללא בוט}
			if ( newTxt!=txt && o.comment) {
				chectTyTool.addSummary( o.comment );
			}
			txt = newTxt;
		});

		while (true) {
			match = txt.match(/\0(\d+)\0/);
			if (!match || !match.length) break;
			txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]);
		}
		this.updateText(txt);
//		if (!emptyParametersRgx.test(txt)) return;
//		emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', {
//			href: '#',
//			text: 'ניקוי'
//		}).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; }));
//		this.writeMsg(emptyParametersMsg, 'info');
	},
	disambigCheck: function () {
		var disambigMsg = this.writeMsg($('<div>', {
			id: 'waitForDisambigs'
		}).text( mw.msg( 'checkty-waiting-disambig-query' ) ), 'info'), self = this;
		
		this.fetchDisambigLinks().fail(function () {
			disambigMsg.remove();
			self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-no-links') }), 'check');
		}).done(function (res) {
			var disambigs;
			disambigMsg.remove();
			if (res.length === 0) {
				self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-success') }), 'check');
				return;
			}
			disambigs = $('<div id="disambigWarnning">'+mw.msg( 'checkty-disambig-links-title' )+'</div>').prepend('<img src="//upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Disambig_RTL.svg/15px-Disambig_RTL.svg.png">').css('padding', '0 5px');
			$.each(res, function (i, disTitle) {
				if (i > 0) {
					disambigs.append(', ');
				}
				disambigs.append($('<a href="' + mw.util.getUrl(disTitle) + '">' + disTitle + '</a>').click(function () {
					var disambigName = $(this).text();
					new mw.Api().get({
						action: 'parse',
						page: disambigName,
						prop: 'text',
						redirects: 1
					}).done(function (data) {
						if (data && data.parse && data.parse.text) {
							var disambig = data.parse.text['*'];
							mw.loader.using( ['jquery.ui'] ).done ( function() { chectTyTool.resolveDisambig( disambigName, disambig ); } );
						} else {
							console.error(data);
						}
					});
					return false;
				}));
			});
			chectTyTool.writeMsg(disambigs);
		});
	},
	getLinkRegex: function(name) {
		return	new RegExp('(?:\\.|^)([^\\.\n]*(\\[\\[' + mw.util.escapeRegExp(name) + '[\\|\\]]).*?)[\\.\\n]', 'm');
	},
	resolveDisambig: function (name, data) {
		var offset = 0,
			textbox = this.textbox,
			linkRgx = this.getLinkRegex(name),
			orgPos = $(textbox).textSelection('getCaretPosition'),
			cSentence = $('<div>');
		var options = $('<div>').append($('li', data).filter(function() { return $(this).closest( '.checkty-ignore' ).length === 0; } ).map(function () {
			var a = $(this).children('a').get(0);
			if (a) {
				var storeTitle = $(this).text();
				var anchor = '',
					h = a.href;
				if (h.indexOf('#') + 1) anchor = decodeURI(h.substr(h.indexOf('#')).replace(/\./g, '%').replace(/_/g, ' '));
				$(a).text( a.title.replace(mw.msg( 'checkty-page-doesnt-exist' ), "") + anchor);
				a.title = storeTitle;
			}
			return a || null;
		}).click(resolve))
			.append($('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').click(removeLink));
		var disambigDialog = $('<div>').append( mw.msg('checkty-disambig-meaning', name) + '<hr/>').append(cSentence).append(options.buttonset()).dialog({
			title: mw.msg( 'checkty-dismabig-dialog-title' ),
			close: function () {
				$(textbox).textSelection('setSelection', {
					start: orgPos
				});
			}
		});
		findSentence();
		function findSentence() {
			var text = textbox.value.substr(offset),
				m = text.match(linkRgx);
			if (!m) {
				disambigDialog.dialog('close');
				return;
			}
			offset += text.indexOf(m[1]) + m[1].indexOf(m[2]);
			var linkIndex = m[1].indexOf(m[2]) + 2,
				html = m[1].substr(0, linkIndex) + '<big>' + name + '</big>' + m[1].substr(linkIndex + name.length);
			cSentence.html(html);
		}
		function resolve() {
			var answer = $(this).text(),
				text = textbox.value,
				startLink = text.indexOf('[[' + name, offset);
			if (text.charAt(startLink + 2 + name.length) != '|') answer += '|' + name;
			offset += answer.length + 2;
			text = text.substr(0, startLink + 2) + answer + text.substr(startLink + 2 + name.length);
			textbox.value = text;
			findSentence();
			chectTyTool.addSummary( mw.msg( 'checkty-dismabig-fix-summary' ) );
			return false;
		}
		function removeLink() {
			var text = textbox.value,
				startLink = text.indexOf('[[' + name, offset),
				endLink = text.indexOf(']]', startLink),
				pipeChar = startLink + 2 + name.length,
				linkText = (text.charAt(pipeChar) != '|') ? name : text.substr(pipeChar + 1, endLink - pipeChar - 1);
			offset += (endLink - startLink) + linkText.length;
			text = text.substr(0, startLink) + linkText + text.substr(endLink + 2);
			textbox.value = text;
			findSentence();
			return false;
		}
	},
	addSummary: function (msg) {
		var editSummary = $('#wpSummary').val();
		if (editSummary.indexOf(msg) === -1) $('#wpSummary').val(editSummary + (editSummary.length === 0 ? '' : ', ') + msg);
		// tag the edit
		if ( $('#checktyTag').length === 0 ) {
			$('#editform').append('<input type="hidden" name="wpChangeTags" id="checktyTag" value="צ\'קטי">');
		}		
	},
	checkGallery: function() {
		var text = this.textbox.value,
			longGalleryThreshold = 16,
			galleryRgx = /<gallery.+?\n(\n|.)+?<\/gallery>/mg,
			m, longGallery=false;
		while ( m=galleryRgx.exec( text ) ) { var galLength = m[0].split('\n').length-2; longGallery |= (galLength > longGalleryThreshold); }
		if (longGallery) {
			this.writeMsg('<div>' + mw.msg('checkty-long-gallery') + '</div>', 'alert');
		}
	},
	checkImages: function (data) {
		var fairUsageTemplates = ['תבנית:שימוש הוגן', 'תבנית:תמונת חבר כנסת'];
		if (!data) {
			if (!(/\{\{(ויקישיתוף בשורה|מיזמים)/.test(this.textbox.value))) {
				$.getJSON('//www.wikidata.org/w/api.php?callback=?', {
					languages: 'he',
					action: 'wbgetentities',
					sites: mw.config.get('wgDBname'),
					titles: mw.config.get('wgTitle'),
					format: 'json',
					props: 'claims'
				}).done(function (data) {
					if (data.success === undefined || !data.success) return;
					for (var entityId in data.entities) {
						var claims = data.entities[entityId].claims;
						if (claims && claims.hasOwnProperty('P373')) {
							chectTyTool.writeMsg($('<div>', {
								text: mw.msg('checkty-missing-commons-link')
							}).prepend('<img src="//upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Commons-logo.svg/15px-Commons-logo.svg.png">').css('padding', '0 5px').append($('<a>', {
								href: '#',
								text: 'להוספה'
							}).click(function (e) {
								e.preventDefault();
								var ta = $('#wpTextbox1');
								if (ta.textSelection('getCaretPosition') >= ta.val().length) {
									chectTyTool.writeMsg($('<div>').text(mw.msg('checkty-please-position-caret')));
								} else {
									ta.textSelection('encapsulateSelection',{pre:'{{ויקישיתוף בשורה}}'});
									chectTyTool.addSummary('ויקישיתוף בשורה');
								}
							})));
						}
					}
				});
			}
			//in case there are no images in page
			if (!(/\[\[(תמונה|קובץ|File|Image):/i.test(this.textbox.value))) {
				var articleName = mw.config.get('wgPageName');
				var that = this; // we want to use "this" in the done method of the api call.
				new mw.Api().post( {
					action: 'parse',
					title: articleName,
					text: this.textbox.value
				} ).done( function( data ) {
					if ( data && data.parse && data.parse.text && $(  data.parse.text['*'] ).find( 'a.image  img' ).filter(function() { 
						var width = $(this).attr('width');
						if (isNaN(width)) width = $(this).width();
						else width = parseInt(width);
						return (width >= 100) && $(this).parents('.navbox').length==0; 
					} ).length === 0 ) {
						var fistURL = that.fistURL({
							datatype: 'articles',
							data: articleName
						});
						var msg = $('<div>', {
							text: 'בדף זה אין תמונות. ניתן לחפש תמונות חופשיות ממקורות שונים. '
						}).append($('<a>', {
							href: decodeURI(fistURL),
							text: 'חיפוש תמונות',
							target: '_blank'
						}));
						that.writeMsg(msg, 'info');
					}
				});
				return;
			}
			new mw.Api().get({
				action: 'query',
				generator: 'images',
				titles: mw.config.get('wgPageName'),
				prop: 'templates',
				tltemplates: fairUsageTemplates.join('|')
			}).done(function (data) {
				if (data && data.query && data.query.pages) chectTyTool.checkImages(data.query.pages);
			});
		} else {
			var fairUseImgs = $.map(data, function (o) {
				if (!o.templates) return;
				var isFairUsage;
				$.each(o.templates, function (k, license) {
					if ($.inArray(license.title, fairUsageTemplates) != -1) {
						isFairUsage = true;
						return false;
					}
				});
				if (isFairUsage) return o.title;
			});
			if (fairUseImgs.length === 0) return;
			//add message with fair usage images
			var fistURL = this.fistURL({
				data: fairUseImgs.join('\r\n'),
				datatype: 'replaceimages'
			});
			var msg = $('<div>', {
				text: 'הדף מכיל תמונות בשימוש הוגן, שמומלץ להחליפן בחלופות חופשיות במידת האפשר. '
			}).append($('<a>', {
				href: fistURL,
				text: 'חיפוש חלופות חופשיות',
				target: '_blank'
			}));
			if (!(new RegExp('\{\{'+mw.msg('checkty-fairuse-img-replace-template')+'\}\}').test($('#wpTextbox1').val())))
				msg.append(' - ').append($('<a>', {
					text: 'סימון להחלפה',
					href: '#'
				}).click(function () {
					var t = $('#wpTextbox1');
					$.each(fairUseImgs, function (i, fiImg) {
						var imgName = mw.util.escapeRegExp(/.:(.+)$/.exec(fiImg)[1]),
						imgDescRE =  new RegExp(imgName.replace(' ', '[ _]') + '((?:[^\\[\\]]|\\[\\[[^\\[\\]]*?\\]\\])*?)\]\]', 'i'),
						matches;
						if (!(matches = imgDescRE.exec(t.val()))) {
							return;
						}
						//this is thumb img
						var imgDesc = matches[1].split('|'), isThumb = false, imgCaption = '';
						for (var i in imgDesc) {
							if (/thumb|ממוזער/i.test(imgDesc[i])) {
								isThumb = true;
							} else if (!(/^(ימין|שמאל|מרכז|right|left|center|[0-9]+px)?$/i.test(imgDesc[i]))) {
								imgCaption = imgDesc[i]; //unknown parameter assumed to be description
							}
						}
						if (isThumb) {
							if (imgCaption) {
								imgDesc = matches[1].replace(imgCaption, imgCaption + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
							} else {
								imgDesc = matches[1] + '|{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}';
							}
							t.val(t.val().replace(matches[1], imgDesc));
							chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
						} else {
							//is in infobox heuristic: = before image tag
							var isInInfobox = new RegExp('=\s*\\[\\[(?:file|image|קובץ|תמונה):' + imgName.replace(' ', '[ _]') + '[^\\]]*?\]\]', 'i');
							if (isInInfobox.test(t.val())) {
								t.val(t.val().replace(matches[0], matches[0] + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'));
								chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
							}
						}
					});
				}));
			this.writeMsg(msg, 'alert');
		}
	},
	fistURL: function (p) {
		return 'https://tools.wmflabs.org/fist/fist.php?doit=1&language=he&project=wikipedia&params[catdepth]=&params[random]=&params[startat]=&params[ll_max]=5&params[free_only]=1&params[commons_max]=5&params[flickr_max]=5&params[include_flickr_id]=1&params[flickr_new_name_from_article]=1&params[picasa_max]=5&params[wts_max]=5&params[gimp_max]=&params[esp_max]=5&params[geograph_max]=5&params[geograph_max_de]=5&params[geograph_max_channel-islands]=5&params[freemages_max]=5&params[forarticles]=all&params[lessthan_images]=&params[default_thumbnail_size]=250&params[jpeg]=1&params[png]=1&params[gif]=1&params[svg]=1&params[output_format]=out_html&params[min_width]=80&params[min_height]=80&params[ab_max]=5&sources[languagelinks]=1&sources[commons]=1&sources[flickr]=1&' + $.param(p);
	},
	languageCheck: function (checks) { //style and language check
		var txt = this.textbox.value;
		if (checks) {
			var checkWarnings = $('<div></div>');
			for (var x in checks) {
				if (checks[x]['test'].test(txt)) {
					var m = checks[x]['test'].exec(txt), langCheckPrefix = '';
					if (m[0].split(' ').length < 4 && checks[x]['test'].source.indexOf('\\]')==-1) langCheckPrefix = mw.msg('checkty-language-check', m[0]);
					checkWarnings.append(this.createSearchLink(checks[x]['test']));
					checkWarnings.append('&nbsp;-&nbsp;' + langCheckPrefix + checks[x]['remark'] + '<br/>');
				}
			}
 
			// Design checks: Elements width
			var largeElement = /[6789][0-9][0-9]px/;
			if (largeElement.test(txt)) checkWarnings.append(mw.msg( 'checkty-large-element' ) + '<br/>');
			var manyLi = new RegExp('(?:\n\\*.*){20}');
			if (manyLi.test(txt)) {
				checkWarnings.append(this.createSearchLink(manyLi));
				checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-long-list' ));
			}
			if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
		} else {
			var api = new mw.Api();
			api.get({
				action:'parse',
				page: 'ויקיפדיה:בדיקה אוטומטית',
				prop: 'wikitext'
				}).done(function (data) {
					if (!(data && data.parse && data.parse.wikitext)) return;
					var DictionaryText = data.parse.wikitext['*'].split('-----')[1]
					var genrealWarningWords = DictionaryText.split('\n*');
					var checks = [];
					for (var i=0;i<genrealWarningWords.length;i++)
					{
						var splittedWarn = genrealWarningWords[i].split("//");
						if ( splittedWarn.length !== 2 ) continue;
						checks.push({
							'test': new RegExp( splittedWarn[0], 'i' ),
							'remark': splittedWarn[1]
						});
					}
					chectTyTool.languageCheck(checks);
			});
			var countRgx = /(?:[^ ]+ ){2}.?(?:ש[נת]י|שלוש[תה]?|ארבע[הת]?|חמשת?|חמישה|ששת?|שבע[הת]?|תשע[הת]?|עשר[הת]?) [א-ת]+/g,
			gramCheck = [], m, self = this;
			while (m = countRgx.exec(txt)) { gramCheck.push(m) }
			if (gramCheck.length) $.post('//tools.wmflabs.org/eranbot/shtei_shekel/heb_check.py', { wikitext: gramCheck.join('\n') } ).done(function(d){
				if (!d.errs || d.errs.length === 0) return;
				var zaharNekevaWarns = $('<div></div>');
				for ( var i = 0; i < d.errs.length; i++ ) {
					var origRgx = new RegExp(d.errs[i].orig);
					zaharNekevaWarns.append(self.createSearchLink(origRgx));
					zaharNekevaWarns.append('&nbsp;-&nbsp;ייתכן שיש אי התאמה במין ב"' + d.errs[i].orig + '" (תיקון: '+d.errs[i].suggested+') <br/>');
				}
				chectTyTool.writeMsg(zaharNekevaWarns, 'alert');
			});

		}
	},
	refsConsistencyCheck: function () {
		function safeRegexFix(fixRegex, fixReplace, check){
			var txt = $('#wpTextbox1').val(), 
				m;
			//remove templates within templates
			var specials = [];
			while (m = /\{\{(?!הערה\|)[^\{]*?\}\}/g.exec(txt)) {
				txt = txt.replace(m[0], '\0' + specials.length + '\0')
				specials.push(m[0])
			}
			if (check) {
				var counterA = 0, counterB = 0;
				while (fixRegex.exec(txt)) counterA++;
				while (fixReplace.exec(txt)) counterB++;
				return [counterA, counterB];
			} else {
				txt = txt.replace(/(\{\{הערה\|.*?\}\}|<ref>.*?<\/ref>)\s+(?=(\{\{הערה\||<ref>))/g, '$1'); // remove spaces between refs
				txt = txt.replace(fixRegex, fixReplace);
				while (m = specials.pop()) txt = txt.replace('\0' + specials.length + '\0', m);
				$('#wpTextbox1').val(txt);
			} 
		}
		var refAfter = /([\.\,])\s*((\{\{הערה.*?\}\}|<ref>.*?<\/ref>)+)\.?/g,
		refBefore = /\.?((\{\{הערה\|([^\{]|\{(?!\{הערה\|))*\}\}|<ref>([^<]|<(?!\/ref>))*<\/ref>)+)\s*([\.\,])/g,
		refCounter = safeRegexFix(refAfter, refBefore, true);
		if (refCounter[0] > 0 && refCounter[1] > 0) {
			this.writeMsg($('<div>', {
				text: 'חוסר תאימות בהערות שוליים: ' + refCounter[0] + ' הערות אחרי סימן פיסוק, ' + refCounter[1] + ' הערות לפני סימן פיסוק [תיקון: '
			}).append($('<a>', {
				text: 'אחרי',
				href: '#'
			}).click(function () {
				safeRegexFix(refBefore, '$5$1', false);
				chectTyTool.addSummary('אחידות במיקום הערות שוליים');
			})).append(' | ').append($('<a>', {
				text: 'לפני',
				href: '#'
			}).click(function () {
				safeRegexFix(refAfter, '$2$1', false);
				chectTyTool.addSummary('אחידות במיקום הערות שוליים');
			})).append(']'), 'alert');
		}
	},
	ibidWarning: function() {
		var refRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g,
			wikitext = this.textbox.value, self=this, m;
		var checkWarnings = $('<div></div>');
		while ( m = refRE.exec( wikitext ) ){
			if(/^שם[ .,]|^שם$/.test(m[1]) || /\bibid(?![^a-z])/i.test(m[1])){
				checkWarnings.append(this.createSearchLink(m[0]));
				checkWarnings.append('&nbsp;-&nbsp;נמצאה הערת שוליים המפנה להערה הקודמת בצורה של שם. יש להחליף לציון מקור מדויק. ראו עוד: <a href="'+mw.util.getUrl('ויקיפדיה:הערות שוליים')+'">ויקיפדיה:הערות שוליים</a><br/>');
			}
		}
		if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
	},
	mergeRefs: function() { // merge refs with same content
		this.autoMergeRefs(); // merge refs with name and content that are equal
		this.mergeRefsWithoutName(); // merge refs with same content and assign name. requires some manual work
	},
	autoMergeRefs: function() { // merge refs with same content and same name
		var references = {},// a dictionary where key is the ref name and value is count
		refReEn = /<ref name="([^"]+?)">(.+?)<\/ref>/g,
		wikitext = this.textbox.value, mergedRefs = [], m, k, i;
		while ( m = refReEn.exec( wikitext ) ){
			references[m[1]] = (references[m[1]] || 0) + 1;
		}

		for (k in references) {
			if (references[k] > 1) {
				var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext),
				shortRef = '{{הערה|שם=' + k + '}}';
				i = 0;
				if (content)
					wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(content[0]), 'g'), function(m) { return (i++? shortRef : m); });
				mergedRefs.push(k);
			}
		
		}
		if (mergedRefs.length) {
			this.writeMsg( $('<div>').text('מיזוג הערות: ' + mergedRefs.join(', ')) );
			this.addSummary( 'מיזוג הערות אוטומטי' );
			this.textbox.value = wikitext;
		}
	},
	mergeRefsWithoutName: function() { // merge refs with same content
		var references = {},// a dictionary where key is the ref content and the value is list of uses
		refRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g,
		wikitext = this.textbox.value, m;
		while ( m = refRE.exec( wikitext ) ){
			references[m[1]] = references[m[1]] || [];
			references[m[1]].push(m[0]);
		}
		for (var refContet in references) {
			var refUses = references[refContet];
			if ( refUses.length === 1 ) continue;
			if(/^שם[ .,]|^שם$/.test(refContet) || /\bibid(?![^a-z])/i.test(refContet)) continue; // skip ibid refs

			var commonRefStructure = /(.+?) .+ (?:עמ|p).? ?([0-9]+)/.exec(refContet);
			var defaultRefName = '';
			if (commonRefStructure) {
				defaultRefName = commonRefStructure[1]+commonRefStructure[2];
			}
			var refName = prompt('ישנה הערת שוליים החוזרת מספר פעמים. ניתן להפנות את כל המופעים אל הערה אחת באמצעות מתן שם קצר ובעל משמעות להערה.\nאנא הזינו שם להערה הבאה:\n'+refContet, defaultRefName);
			if ( !refName ) continue;
			wikitext = wikitext.replace( refUses[0], '{{הערה|שם='+refName+'|'+refContet+'}}');
			for (var refI = 1; refI<refUses.length; refI++){
				wikitext = wikitext.replace( refUses[refI], '{{הערה|שם='+refName+'}}');
			}
			this.textbox.value = wikitext;
		}
	},
	titleOrderCheck: function(){
		// validates the titles order is consistent
		var orderedTitles = ['ראו גם', 'לקריאה נוספת', 'קישורים חיצוניים', 'הערות שוליים'], 
			isSorted = 1,
			titles = $('#wpTextbox1').val().match('==\\s*'+orderedTitles.join('|')+'\\s*==','g'), i, indexes;
		if (!titles) return; // no such titles
		indexes = $.map( titles, function(e){return orderedTitles.indexOf(e.replace(/\s*==\s*/g,''))});
		for ( i=0; ( i < indexes.length-1 ) && isSorted; i++) {	isSorted &= (indexes[i] < indexes[i+1]) };
		if ( !isSorted ) {
			this.writeMsg($('<div>מומלץ לתקן את סדר הכותרות ל: ' + orderedTitles.join(', ') + '</div>'), 'alert' );
		}
	},
	refDirSuggest: function() { // suggest adding direction for refs
		var wikitext = this.textbox.value,
			defaultDir = (/{{הערות שוליים *\| *יישור *= *שמאל}}/.exec( wikitext ))? 'ltr' : 'rtl',
			ltrRefRegex = /\{\{הערה\|(?:שם ?=[^|]*\|)?(?:1= *)?(?! *\[?https?:\/\/[^ ]+\]? *\}\})( *\[?[a-z][^א-ת{|]+?)\}\}/ig,
			rtlRefRegex = /\{\{הערה\|(?!שם ?=)(?:1= *)?([א-ת][^a-z{|]+?|\[http:[^ ]+ [א-ת][^a-z{|]+?)\}\}/ig,
			nonDefaultRefRegex = (defaultDir == 'rtl') ? ltrRefRegex : rtlRefRegex,
			uncommonDir = (defaultDir == 'rtl') ? 'שמאל' : 'ימין',
			m;

		while( m = nonDefaultRefRegex.exec(wikitext))
		{
			var fixRefDirLink = $('<a href="#">'+mw.msg( 'checkty-ref-dir-fix' )+'</a>').data({'search': m[0]}).click(function(e){ 
				var specificRefRgx = new RegExp('\\[\\[('+mw.util.escapeRegExp($(this).data('search'))+')(\\]\\]|\\|).+\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g'),
				wikitext = $('#wpTextbox1').val();
				wikitext = wikitext.replace($(this).data('search'), $(this).data('search').replace('}}', '|כיוון='+uncommonDir+'}}'));
				$('#wpTextbox1').val(wikitext);
				chectTyTool.addSummary(mw.msg('checkty-ref-dir-fix'));
				e.preventDefault();
			});

			var searchRef = this.createSearchLink(m[1]);
			this.writeMsg($('<div>').append(['נמצאה הערת שוליים ללא הגדרת כיווניות "'+m[1]+'" [',searchRef, '&nbsp;-&nbsp;', fixRefDirLink, ']']), 'alert');
		}
	},
	overlinkify: function() {
		function removeOverlink(context, link){
			var newcontext = context;
			do {
				context = newcontext;
				newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[\\1\\|(.+?)\\]\\]', 'g'), '[[$1$2$3');
				newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[(\\1)\\]\\]', 'g'), '[[$1$2$3');
			} while( newcontext != context )
			return newcontext;
		}
		// using [^{}\n] as a quick hack to counting links within templates
		var wikitext = this.textbox.value,
			overlinkingRgx = /\[\[([^\[\]\|]+?)(?:\]\]|\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\[\[\1(?:\]\]|\|.+?\]\])/g,
			m;
		
		while ( m = overlinkingRgx.exec(wikitext) )
		{
			var removeLink = $('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').data({'search': m[1]}).click(function(e){ 
				var specificOverlinkingRgx = new RegExp('\\[\\[('+$(this).data('search')+')(\\]\\]|\\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g');
				var wikitext = $('#wpTextbox1').val(), m;
				while( m = specificOverlinkingRgx.exec( wikitext ) )
				{
					wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
				}
				$('#wpTextbox1').val(wikitext);
				chectTyTool.addSummary('הסרת קישורים עודפים');
				e.preventDefault();
			});
			var searchLink = this.createSearchLink( new RegExp( '\\[\\[' + mw.util.escapeRegExp(m[1]) + '(?:\\||\\]\\])' ) );
			this.writeMsg($('<div>').append(['נמצאו קישורים עודפים ל"'+m[1]+'" [',searchLink, '&nbsp;-&nbsp;', removeLink, ']']), 'alert');
			wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
		}
	},
	getWikidataApi: function(callback) {
		return new mw.ForeignApi( 'https://www.wikidata.org/w/api.php' );
	},
	extractWikidataLabelsSuggestions: function() {
		var suggestLabelsREen =  /(?:\[\[|\|)([א-ת' \-]+?)\]\](?: \('*([a-z][^א-ת]+?)'*\)| *\{\{אנג?\|(.+?)\}\})/gi,
			langLink =  /\{\{קישור שפה\|([א-ת]+)\| *([^|]+?)\| *([א-ת '\-]+?)\}\}/gi,
			langTable = { 'ספרדית': 'es', 'אנגלית': 'en' },
			self = this,
			text = this.textbox.value,
			suggestionsByLang={}, // lang -> { foreign title -> hebrew label }
			foreignTitles= [],
			m, lang, suggestions;
		
		suggestionsByLang['en'] = {};
		// populate suggestions
		while(m = suggestLabelsREen.exec(text)) suggestionsByLang['en'][m[2] || m[3]] = m[1];
		while(m = langLink.exec(text)) {
			if (!langTable.hasOwnProperty(m[1])) 
			{
				console.log('wikidataLabelsSuggested: Missing lang: ' + m[1]);
				continue;
			}
			lang = langTable[m[1]]; // lang code
			if (!suggestionsByLang[lang]) suggestionsByLang[lang] = {};
			suggestionsByLang[lang][m[2]] = m[3];
		}

		// query wikidata by lang
		for (lang in suggestionsByLang) {
			self.suggestWikidataLabelTranslate(suggestionsByLang[lang], lang);
		}

	},
	suggestWikidataLabelTranslate: function(suggestions, lang) {
		var foreignTitles = [], batchsize = 50, self = this;
		for(var v in suggestions) foreignTitles.push(v);
		if (foreignTitles.length === 0) return;

		var extWikiApi = new mw.ForeignApi('//'+lang+'.wikipedia.org/w/api.php'),
			queries = Math.ceil(foreignTitles.length/batchsize),
			def = $.Deferred(), dataEntities = {}, redirects = {};

		for(var i=0; i<queries; i++)
		{
			// go through enwiki API, to resolve redirects instead of direct approach with wikidataApi.getEntitiesByPage
			extWikiApi.get({
				action: 'query',
				titles: foreignTitles.slice(i*batchsize,(i+1)*batchsize).join('|'),
				redirects: 1,
				prop: 'pageprops',
				ppprop: 'wikibase_item'
			}).done(function(d) {
				for(var i in d.query.redirects) redirects[d.query.redirects[i].to]=d.query.redirects[i].from;
				var wikidataIds = [];
				for(var i in d.query.pages) if(d.query.pages[i].pageprops && d.query.pages[i].pageprops.wikibase_item) wikidataIds.push(d.query.pages[i].pageprops.wikibase_item);

				if (wikidataIds.length === 0) return;
				self.getWikidataApi().get({
					action: 'wbgetentities',
					ids: '\x1f' + wikidataIds.join( '\x1f' ),
					props: '\x1f' + ['labels', 'sitelinks'].join( '\x1f' ),
					languages: '\x1f' + ['he', lang].join( '\x1f' )
				}).done(function(d){
					queries--;
					$.extend(dataEntities, d.entities);
					if (queries === 0) def.resolve(dataEntities);
				});
			});
		}

		def.done(function(data) {
			var found = false,
			    translations = $('<div>ייתכן שהערך מכיל תוויות חסרות לישויות בוויקינתונים:</div>'),
			    langSite = lang + 'wiki'; // example: enwiki
			for(var en in data)
			{
				if (/^-/.exec(en)) continue;
				if (data[en].labels && data[en].labels.hasOwnProperty('he')) continue; // already have hebrew label
				found = true;
				var suggestion = suggestions[data[en].sitelinks[langSite].title] || suggestions[redirects[data[en].sitelinks[langSite].title]];
					
				translations.append($('<li>').append($('<a>', {
								href: 'https://www.wikidata.org/wiki/'+en,
								text: en + ' ('+data[en].labels[lang].value+')',
								target:'_blank'
							}).data({
								'he': suggestion,
								'foreignLabel': data[en].sitelinks[langSite].title,
								'q': en
							}).click(function(){
								self.wikidataLabelTranslate($(this).data('q'), $(this).data('foreignLabel'), $(this).data('he'));
								return false;
							})));
			}
			if (found) self.writeMsg(translations, 'articleSearch');
		});
	},
	wikidataLabelTranslate: function(entityId, foreignLabel, suggestion) {
		var localLabel = prompt(mw.msg('checkty-set-label', foreignLabel), suggestion);
		if (localLabel) {
			this.getWikidataApi().postWithToken( 'csrf', {
				action: 'wbsetlabel',
				id: entityId,
				value: localLabel,
				language: mw.config.get('wgContentLanguage')
			} ).done(function(d) { if (d.success) mw.notify(mw.msg('checkty-translate-saved')); })
		}
	},
	wikidataLabelsMissing: function() {
		var self = this, 
			needTranslateQ = $( 'a.wb-entity-link[href*="Q"]' )
				.filter( function( i, e ) { return /[a-z]/i.test( e.text ) } )
				.map( function() { 
					var m=/(Q[0-9]+)/.exec(this.href); 
					if (m) return m[0];
				})
				.toArray();
		if (needTranslateQ.length === 0 ) return;

		this.getWikidataApi().get({
			action: 'wbgetentities',
			ids: '\x1f' + needTranslateQ.join( '\x1f' ),
			props: '\x1f' + ['labels'].join( '\x1f' ),
			languages: mw.config.get('wgContentLanguage')
		}).done( function(d) {
			var needTranslateIndeedQ = [];
			if (!d.entities) return;
			for(var q in d.entities) {
				if (d.entities[q].labels && !d.entities[q].labels.hasOwnProperty(mw.config.get('wgContentLanguage'))) needTranslateIndeedQ.push(q);
			}
		
			if(needTranslateIndeedQ.length === 0) return;
			var msg = $('<div>הישויות הבאות חסרות תווית בעברית בוויקינתונים: </div>').append($( 'a.wb-entity-link[href*="Q"]' ).filter( function( i, e ) { return $.inArray(/Q[0-9]+/.exec(e.href)[0], needTranslateIndeedQ)+1 } ).clone().css('margin', '0 3px'));
			self.writeMsg(msg, 'alert');
			$('a', msg).click(function(){
				self.wikidataLabelTranslate(/Q[0-9]+/.exec($(this).prop('href'))[0], $(this).text());
				return false;
			});
		});

	},
	numberRangeDash: function(fix) {
		// replace minus => dash foreach x-y s.t x<y and swap y and x otherwise. prefix/suffix requirement in regex to make sure it is within sentence
		var numberRangeReNoMinus = /([א-ת]'?[-\ ]*)((?:\[\[|\()?[0-9]+(?:\]\])?)-((?:\[\[)?[0-9]+)((?:\]\]|\))?[.:,]?(?:[ \|]|\n)(?!לפנה"ס))/g,
			wikitext = this.textbox.value, replacements = [],  m, i;
		while(m = numberRangeReNoMinus.exec(wikitext))
		{
			// note - in replacement we dont include the prefix/suffix to make consistent replacement
			if ( parseInt(m[2].replace(/[^0-9]/g, '')) <  parseInt(m[3].replace(/[^0-9]/g, '')) ) {
				replacements.push([m[1]+m[2] + '-' + m[3], m[1]+m[2] + '–' + m[3]]);
			}
			else if ( (parseInt(m[2].replace(/[^0-9]/g, '')) >  parseInt(m[3].replace(/[^0-9]/g, ''))) && (/^[0-9]+$/.test(m[2])) && (/^[0-9]+$/.test(m[3])) ) {
				replacements.push([m[1]+m[2] + '-' + m[3], m[1]+m[3] + '–' + m[2]]);
			}
		}

		if (replacements.length === 0) return;
		if (fix) {
			for(i = 0; i < replacements.length; i++) {
				wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(replacements[i][0]), 'g'), replacements[i][1]);
			}
			this.textbox.value = wikitext;
			this.addSummary( 'קו מפריד בטווח מספרים' );
		} else {
			this.writeMsg($('<div><a href="#">'+mw.msg( 'checkty-fix-numberRangeDash' )+'</a></div>').click(function(e){  chectTyTool.numberRangeDash(true); e.preventDefault(); }));
		}
	},
	//original version from http://code.google.com/p/proveit-js/source/browse/ProveIt_Wikipedia.js#384
	//thanks to Georgia Tech Research Corporation. Atlanta, GA 30332-0415
	highlightString: function (toFind) {
		var txtArea = $('#wpTextbox1');
		// cast to string if this is regex
		if ( RegExp.prototype.isPrototypeOf(toFind) ) {
			toFind = toFind.exec(txtArea.val());
			if (!toFind) return;
			toFind = toFind[0];
		}
		var nextPlace = txtArea.val().indexOf(toFind, txtArea.textSelection('getCaretPosition') + 1);
		if (nextPlace === -1) nextPlace = txtArea.val().indexOf(toFind); //start from begining
		if (nextPlace === -1) return; //not found... nothing to do
		var origText = txtArea.val();
		txtArea.val(origText.substring(0, nextPlace));
		txtArea.focus();
		txtArea.scrollTop(1000000); //Larger than any real textarea (hopefully)
		var curScrollTop = txtArea.scrollTop();
		txtArea.val(origText);
		if (curScrollTop > 0) {
			var HALF_EDIT_BOX_HEIGHT = 200;
			txtArea.scrollTop(curScrollTop + HALF_EDIT_BOX_HEIGHT);
		}
		txtArea.focus().textSelection('setSelection', {
			start: nextPlace,
			end: nextPlace + toFind.length
		});
	},
	addAuthorityControl: function(v) {
		var t = this.textbox.value,
		acTemplate = /\{\{בקרת זהויות[\}|]/g,
		artsTitle = /== *(?:מ?ספרי[הו]|מ?יצירותי[הו]|מ?חיבורי[הו]|פילמוגרפיה.*|(?:מבחר)? (?:כתבי)|דיסקוגרפיה|יצירות) *==/, //cheap hint for art occuption in text
		artsCategory = /\[\[קטגוריה:(מוזיקאיות|מוזיקאים|זמרות|זמרים|סופרים|סופרות|ציירות|ציירים|במאי|רבנים|רבניות)(?!.+\*)/; //cheap hint for art occuption in category
		if ( acTemplate.exec( t ) ) return; // AC already exist
		if ( !artsTitle.exec( t ) && !artsCategory.exec( t ) ) return; // no hint will have authority control
		this.getWikidataApi().get({
			action: 'wbgetentities',
			languages: 'he',
			sites: mw.config.get('wgDBname'),
			titles: mw.config.get('wgPageName'),
			props: '\x1f' + ['claims', 'info'].join( '\x1f' )
		}).done(function(d){
			var hasAC = false, 
			authControlProps = [ 'P3372', 'P864', 'P1907', 'P6804', 'P2558', 'P4186', 'P3293', 'P1015', 'P2092', 'P1890', 'P950', 'P268', 'P428', 'P651', 'P1273', 'P271', 'P1908', 'P1707', 'P2456', 'P2349', 'P6792', 'P227', 'P902', 'P1146', 'P396', 'P1736', 'P213', 'P347', 'P1248', 'P244', 'P886', 'P1368', 'P640', 'P434', 'P982', 'P1330', 'P966', 'P1004', 'P436', 'P1407', 'P435', 'P549', 'P1225', 'P1048', 'P349', 'P2041', 'P691', 'P409', 'P3348', 'P949', 'P5034', 'P1695', 'P1003', 'P1375', 'P1006', 'P496', 'P2750', 'P1053', 'P3065', 'P650', 'P350', 'P947', 'P906', 'P781', 'P3430', 'P269', 'P4012', 'P1323', 'P7314', 'P1693', 'P3544', 'P1694', 'P1362', 'P1315', 'P6213', 'P245', 'P1157', 'P8034', 'P214', 'P7859' ],
			entityId, entity;
			for (entityId in d.entities) { entity = d.entities[entityId]; };
			if (!entityId) return; // no entity

			if (entity.hasOwnProperty('claims')) authControlProps.forEach(function(p) { hasAC |= entity.claims.hasOwnProperty(p); })
			if (hasAC) {
				chectTyTool.addAuthorityControlTemplate();
			}
			chectTyTool.viafSearch(entity, entityId, hasAC);
		});
	},
	viafSearch: function(entity, entityId, hasAC){
		if (entity.hasOwnProperty('claims') && entity.claims.hasOwnProperty('P214')) {
			return;
		}
		$.getJSON('https://www.viaf.org/viaf/AutoSuggest?callback=?&' + $.param({query: mw.config.get('wgTitle').replace(/ \([^()]+\)$/, '')})).done( function(d) { 
			if (!d.result || d.result.length === 0) return;
			var viafOptions = $('<div>לערך זה אין בקרת זהויות ומזהה VIAF. ייתכן שיש דף מקביל ב-VIAF</div>');
			for (var i = 0; i < d.result.length; i++) {
				var viafLink = $('<a>', {
					href: 'https://viaf.org/viaf/' + d.result[i].viafid,
					target: '_blank'
				}).text(d.result[i].term),
				viafAddLink = $('<a>', {
					href: '#'
				}).text('הוספה').data({ 'viaf': d.result[i].viafid }).click(function(e){ 
					var viafId = $(this).data('viaf');
					
					chectTyTool.createClaim(entityId, entity.lastrevid, 'value', 'P214', viafId);
					if (!hasAC) chectTyTool.addAuthorityControlTemplate();
					e.preventDefault();

				});
				viafOptions.append($('<li>').append(viafLink, ' - ', viafAddLink));

			}
			chectTyTool.writeMsg(viafOptions);
		} );
	},
	createClaim: function ( entityId, baseRevId, snakType, propertyId, value ) {
		if (
			typeof entityId !== 'string'
			|| typeof baseRevId !== 'number'
			|| typeof snakType !== 'string'
			|| typeof propertyId !== 'string'
			|| value && typeof value !== 'string' && typeof value !== 'object'
		) {
			throw new Error( 'Parameter not specified properly' );
		}
		var params = {
			action: 'wbcreateclaim',
			entity: entityId,
			baserevid: baseRevId,
			snaktype: snakType,
			property: propertyId
		};
		if ( value ) {
			params.value = JSON.stringify( value );
		}
		
		return this.getWikidataApi().postWithToken( 'csrf', params );
	},
	addAuthorityControlTemplate: function(){
		var t = this.textbox.value,
		viafTemplate = /\{\{בקרת זהויות[\}|]/g,
		newText;
		if ( viafTemplate.exec( t ) ) return; // viaf already exist
		newText = t.replace(/{{קצרמר/, '{{בקרת זהויות}}\n{{קצרמר'); // before stub
		if (newText == t) newText = t.replace(/{{מיון רגיל:/, '{{בקרת זהויות}}\n{{מיון רגיל:'); //before default sort
		if (newText == t) newText = t.replace(/\[\[קטגוריה:/, '{{בקרת זהויות}}\n[[קטגוריה:'); // before categories
		if (newText == t) newText = t += '\n{{בקרת זהויות}}';
		this.textbox.value = newText;
		this.addSummary('בקרת זהויות');
	}
};

if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) + 1) $(document).ready(function () {
	chectTyTool.origText = $('#wpTextbox1').val();
	var checktyBtn = new OO.ui.ButtonInputWidget({ label: 'בדיקה', title: 'צ\'קטי - כלי לבדיקת בעיות נפוצות ועוד', accessKey: (window.checkToolKey || 'e'), id:'btnCheckTool' });
	checktyBtn.$button.updateTooltipAccessKeys();
	$('#wpPreviewWidget').after(checktyBtn.$element.click(chectTyTool.run));
});