אונטערשייד צווישן ווערסיעס פון "מעדיעוויקי:Gadget-Checkty.js"

פון המכלול
קפיצה לניווט קפיצה לחיפוש
(צופאסונג)
(החלפות ([[קאטעגאריע, {{כ}}, , ))
שורה 10: שורה 10:
'checkty-warnings-title': 'הערות לבדיקה:',
'checkty-warnings-title': 'הערות לבדיקה:',
'checkty-no-replacements': 'הדף מכיל תבנית "ללא בוט" ולכן לא יבוצעו החלפות',
'checkty-no-replacements': 'הדף מכיל תבנית "ללא בוט" ולכן לא יבוצעו החלפות',
'checkty-replace-summary': '[[וק:רה|החלפות]] ($1)',
'checkty-replace-summary': '[[מכ:רה|החלפות]] ($1)',
'checkty-disambig-suffix': ' (פירושונים)',
'checkty-disambig-suffix': ' (פירושונים)',
'checkty-disambig-no-links': 'קישורים לפירושונים - לא נמצאו',
'checkty-disambig-no-links': 'קישורים לפירושונים - לא נמצאו',
שורה 53: שורה 53:
function dotSpaceRegex() {
function dotSpaceRegex() {
try {
try {
// proper spacing around , and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
// proper spacing around, and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
return new RegExp('(?<!\\.[א-ת]*)([א-ת]\\]?\\]?"?) ?([,\\.]) ?(?=[א-ת]?\\[?\\[?[א-ת]{3})(?![א-ת]*\\.[א-ת])','g');
return new RegExp('(?<!\\.[א-ת]*)([א-ת]\\]?\\]?"?) ?([,\\.]) ?(?=[א-ת]?\\[?\\[?[א-ת]{3})(?![א-ת]*\\.[א-ת])','g');
} catch(e) {
} catch(e) {
console.log('Checkty - browser doesnt support negative lookhead or lookbehind (ES2018)');
console.log('Checkty - browser doesnt support negative lookhead or lookbehind (ES2018)');
//fallback to different regex with slightly less protections
//fallback to different regex with slightly less protections
return /([א-ת]\]?\]?) ?([,\.]) ?(?=[א-ת]?\[?\[?[א-ת]{3})/g;
return /([א-ת]\]?\]?) ?([,\.]) ?(?=[א-ת]?\[?\[?[א-ת]{3})/g;
}
}
}
}
שורה 69: שורה 69:
skip_dict: {},
skip_dict: {},
named_comment: '{{' + 'הער' + 'ה|שם=',
named_comment: '{{' + 'הער' + 'ה|שם=',
formatReplacesConfigSafe: [
formatReplacesConfigSafe: [
{
{
from: /\[\[(File|Image|תמונה):/ig,
from: /\[\[(File|Image|תמונה):/ig,
to: '[[קובץ:'
to: '[[קובץ:'
}, {
}, {
from: /\|thumb(nail)?(?=[\|\]])/ig,
from: /\|thumb(nail)?(?=[\|\]])/ig,
to: '|ממוזער'
to: '|ממוזער'
}, { //remove unseen character
}, { //remove unseen character
from: new RegExp('\u200e|\u200f|\u202d|\u202e|\u202c|\u202a|\u202b', 'g'), // lrm/rlm/lro/rlo/popdf invisible characters/lre/rle
from: new RegExp('\u200e|\u200f|\u202d|\u202e|\u202c|\u202a|\u202b', 'g'), // lrm/rlm/lro/rlo/popdf invisible characters/lre/rle
to: "",
to: "",
comment: 'הסרת תווים בלתי נראים'
comment: 'הסרת תווים בלתי נראים'
}, { // trim spaces in end of line
}, { // trim spaces in end of line
from: / +$/mg,
from: / +$/mg,
to: ''
to: ''
}, { // remove accidental nowiki and simplify code
}, { // remove accidental nowiki and simplify code
from: /\[\[([^|\[\]]+)([^|\[\]]+?)\|\1\]\](?:<nowiki\/>)?\2/g,
from: /\[\[([^|\[\]]+)([^|\[\]]+?)\|\1\]\](?:<nowiki\/>)?\2/g,
to: '[[$1$2]]',
to: '[[$1$2]]',
comment: 'פישוט קישור'
comment: 'פישוט קישור'
}, { // trim beginning from redundant spaces
}, { // trim beginning from redundant spaces
from: /^\s+/g,
from: /^\s+/g,
to: '',
to: '',
comment: 'הסרת רווחים מיותרים'
comment: 'הסרת רווחים מיותרים'
}, { // trim redundant spaces from category links
}, { // trim redundant spaces from category links
from: /\[\[קטגוריה: */g,
from: /\[\[קטגוריה: */g,
to: '[[קטגוריה:'
to: '[[קאטעגאריע:'
}],
}],
formatReplacesConfig: [{ // piped link has identical text before and after the pipe
formatReplacesConfig: [{ // piped link has identical text before and after the pipe
from: /\[\[(.*?)\|\1([.,a-zא-ת]*)\]\]/g,
from: /\[\[(.*?)\|\1([.,a-zא-ת]*)\]\]/g,
to: '[[$1]]$2'
to: '[[$1]]$2'
}, { // piped link contains bold, underline or quotation mark in it
}, { // piped link contains bold, underline or quotation mark in it
from: /\[\[(.*?)\|('''?'?'?|")\1\2\]\]/g,
from: /\[\[(.*?)\|('''?'?'?|")\1\2\]\]/g,
to: '$2[[$1]]$2'
to: '$2[[$1]]$2'
}, { // piped link contains bold, underline or quotation mark at the beginning of it
}, { // piped link contains bold, underline or quotation mark at the beginning of it
from: /('''?'?'?|")\[\[(.*?)\|\2\1\]\]/g,
from: /('''?'?'?|")\[\[(.*?)\|\2\1\]\]/g,
to: '$1[[$2]]$1'
to: '$1[[$2]]$1'
}, { // piped link contains bold, underline or quotation mark at the end of it
}, { // piped link contains bold, underline or quotation mark at the end of it
from: /\[\[(.*?)\|('''?'?'?|")\1\]\]\2/g,
from: /\[\[(.*?)\|('''?'?'?|")\1\]\]\2/g,
to: '$2[[$1]]$2'
to: '$2[[$1]]$2'
}, { // piped link contains brackets in it
}, { // piped link contains brackets in it
from: /\[\[(.*?)\|(\(?)\1(\)?)\]\]/g,
from: /\[\[(.*?)\|(\(?)\1(\)?)\]\]/g,
to: '$2[[$1]]$3'
to: '$2[[$1]]$3'
}, {
}, {
from: /\[\[(.+?)\|([במל])\1([א-ת]*)\]\]/g,
from: /\[\[(.+?)\|([במל])\1([א-ת]*)\]\]/g,
to: "$2[[$1]]$3"
to: "$2[[$1]]$3"
}, { // proper spacing around , and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
}, { // proper spacing around, and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
from: dotSpaceRegex(),
from: dotSpaceRegex(),
to: "$1$2 ",
to: "$1$2 ",
skippable: true
skippable: true
}, {
}, {
from: /([א-ת])\( ?([א-ת])/g,
from: /([א-ת])\( ?([א-ת])/g,
to: "$1 ($2"
to: "$1 ($2"
}, {
}, {
from: /(\n\n)\n+/g,
from: /(\n\n)\n+/g,
to: "$1"
to: "$1"
}, {
}, {
from: /== ? ?\n\n==/g,
from: /== ? ?\n\n==/g,
to: "==\n=="
to: "==\n=="
}, {
}, {
from: /^ ? ? \n/gm,
from: /^ ? ? \n/gm,
to: "\n"
to: "\n"
}, {
}, {
from: /(?!.{2}\|)[ \t\xA0]{2,}/g,
from: /(?!.{2}\|)[ \t\xA0]{2,}/g,
to: ' '
to: ' '
}, {
}, {
from: /\n\n\*/g,
from: /\n\n\*/g,
to: '\n*'
to: '\n*'
},
},
{
{
from: /([בלמכ])- ((?:\[\[)?[0-9])/g,
from: /([בלמכ])- ((?:\[\[)?[0-9])/g,
to: '$1־$2'
to: '$1־$2'
},
},
{ // move , suffix outside links
{ // move, suffix outside links
from: /,\]\]/g,
from: /,\]\]/g,
to: ']],'
to: ']],'
},
},
    { // code simlification: merge bold text coming near each other
{ // code simlification: merge bold text coming near each other
from: /'''([^']*)''' '''([^']*)'''/g,
from: /'''([^']*) ([^']*)'''/g,
to: '\'\'\'$1 $2\'\'\''
to: '\'\'\'$1 $2\'\'\''
},
},
{ // section between two headings without content
{ // section between two headings without content
from: /\n==[^=\n]+?==\n*(\n==[^=\n]+?==\n)/g,
from: /\n==[^=\n]+?==\n*(\n==[^=\n]+?==\n)/g,
to: '$1',
to: '$1',
comment: 'הסרת כותרות ריקות'
comment: 'הסרת כותרות ריקות'
}],
}],
regexes: [],
regexes: [],
ignoreRegexes: [],
ignoreRegexes: [],
verifyRun: function () {
verifyRun: function () {
var self = this, runExcute = true,
var self = this, runExcute = true,
inUseTemplatesRgx = /\{\{בעבודה[ \}\|]/;
inUseTemplatesRgx = /\{\{בעבודה[ \}\|]/;
if (!this.textbox || this.textbox.value.length === 0) return;
if (!this.textbox || this.textbox.value.length === 0) return;


// this tool is not indented to be used in discussion pages
// this tool is not indented to be used in discussion pages
if ( mw.config.get('wgNamespaceNumber') % 2 == 1 || ( mw.config.get('wgNamespaceNumber') != 0 && /\(IST\)/.exec(this.textbox.value ) )) {
if ( mw.config.get('wgNamespaceNumber') % 2 == 1 || ( mw.config.get('wgNamespaceNumber') != 0 && /\(IST\)/.exec(this.textbox.value ) )) {
runExcute = false;
runExcute = false;
OO.ui.confirm(mw.msg('checkty-wrong-use-discussion')).done( function( confirmed ) { if ( confirmed ) self.execute(); });
OO.ui.confirm(mw.msg('checkty-wrong-use-discussion')).done( function( confirmed ) { if ( confirmed ) self.execute(); });
}
}


// this tool is not intended to be used while other people are working on the same page
// this tool is not intended to be used while other people are working on the same page
if( inUseTemplatesRgx.exec(this.textbox.value) ) {
if( inUseTemplatesRgx.exec(this.textbox.value) ) {
runExcute = false;
runExcute = false;
OO.ui.confirm( mw.msg( 'checkty-inuse-warning' ) ).done( function( confirmed ) { if ( confirmed ) self.execute(); });
OO.ui.confirm( mw.msg( 'checkty-inuse-warning' ) ).done( function( confirmed ) { if ( confirmed ) self.execute(); });
}
}
if (runExcute) this.execute();
if (runExcute) this.execute();
},
},
run: function () {
run: function () {
if (this != chectTyTool) {
if (this != chectTyTool) {
chectTyTool.run();
chectTyTool.run();
return;
return;
}
}
var t = $('#wpTextbox1');
var t = $('#wpTextbox1');
this.textbox = t.length ? t[0] : null;
this.textbox = t.length ? t[0] : null;


this.verifyRun();
this.verifyRun();
},
},
execute: function() {
execute: function() {
// indication that skippable replacements should be ignored in the page
// indication that skippable replacements should be ignored in the page
this.skipCheckty = this.textbox.value.match(/{{ללא[_ ]בוט\|\s*צ'קטי\s*}}/g);
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>');
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
//first call to remote functions than to local
if ( ( chectTyTool.textbox.value === chectTyTool.origText ) && ( mw.config.get('wgAction') === 'edit') )  
if ( ( chectTyTool.textbox.value === chectTyTool.origText ) && ( mw.config.get('wgAction') === 'edit') )
this.onSaveProtection();
this.onSaveProtection();
this.formatChecks();
this.formatChecks();
this.linkChecks();
this.linkChecks();
if(!this.isSection) {
if(!this.isSection) {
this.articleOrgChecks();
this.articleOrgChecks();
this.checkImages();
this.checkImages();
}
}
this.languageCheck();
this.languageCheck();
this.vavCheck();
this.vavCheck();
this.expandWikidata();
this.expandWikidata();
this.duplicatedCategory();
this.duplicatedCategory();
},
},
formatChecks: function() {  
formatChecks: function() {
if (!this.isSection)
if (!this.isSection)
this.build_regexes();
this.build_regexes();
this.formatReplace();
this.formatReplace();
this.decodeExternalLinks();
this.decodeExternalLinks();


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


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


if (!execute) {
if (!execute) {
defaultSortMsg = $('<div>', { text: mw.msg('checkty-defaultsort-suggest') }).append($('<a>', {
defaultSortMsg = $('<div>', { text: mw.msg('checkty-defaultsort-suggest') }).append($('<a>', {
href: '#',
href: '#',
text: 'הוספת מיון רגיל',
text: 'הוספת מיון רגיל',
}).click(function(){ chectTyTool.defaultSortSuggest(true); return false;}));
}).click(function(){ chectTyTool.defaultSortSuggest(true); return false;}));
this.writeMsg(defaultSortMsg, 'info');
this.writeMsg(defaultSortMsg, 'info');
} else {
} else {
name = firstFamilyRgx.exec(mw.config.get('wgTitle'));
name = firstFamilyRgx.exec(mw.config.get('wgTitle'));
txt = txt.replace('[[קטגוריה', '{{מיון רגיל:' + name[2] + ', ' + name[1] + '}}\n[[קטגוריה');
txt = txt.replace('[[קאטעגאריע', '{{מיון רגיל:' + name[2] + ', ' + name[1] + '}}\n[[קאטעגאריע');
this.addSummary('מיון רגיל');
this.addSummary('מיון רגיל');
this.updateText(txt);
this.updateText(txt);
}
}
},
},
categoryOrder: function(execute) {
categoryOrder: function(execute) {
var txt = this.textbox.value,
var txt = this.textbox.value,
newTxt = txt,
newTxt = txt,
self = this,
self = this,
categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g,
categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g,
cats = [], m = null, oldCats = null, categorySortMsg = null;
cats = [], m = null, oldCats = null, categorySortMsg = null;
while(m=categoryRE.exec(txt)) {
while(m=categoryRE.exec(txt)) {
cats.push(m[1]);
cats.push(m[1]);
newTxt = newTxt.replace(m[0], '');
newTxt = newTxt.replace(m[0], '');
}
}
oldCats = JSON.stringify(cats);
oldCats = JSON.stringify(cats);
cats.sort(function(a,b){  
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 (/נפטרים ב-|נפטרות|שנפטרו/.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 (/(ילידי|ילידות|שנולדו).*[0-9]/.exec(a)) return 1; if(/(ילידי|ילידות|שנולדו).*[0-9]/.exec(b)) return -1;
if (/אישים במאה ה-|אישים שחיו במאה ה-|אפיפיורים במאה ה-/.exec(a)) return 1; if(/אישים במאה ה-|אישים שחיו במאה ה-|אפיפיורים במאה ה-/.exec(b)) return -1;
if (/אישים במאה ה-|אישים שחיו במאה ה-|אפיפיורים במאה ה-/.exec(a)) return 1; if(/אישים במאה ה-|אישים שחיו במאה ה-|אפיפיורים במאה ה-/.exec(b)) return -1;
return a>=b;
return a>=b;
});
});
if (oldCats == JSON.stringify(cats)) return; // same order - nothing to do
if (oldCats == JSON.stringify(cats)) return; // same order - nothing to do
if (!execute) {
if (!execute) {
categorySortMsg = $('<div>', { text: mw.msg('checkty-category-sort') }).append($('<a>', {
categorySortMsg = $('<div>', { text: mw.msg('checkty-category-sort') }).append($('<a>', {
href: '#',
href: '#',
text: 'סידור',
text: 'סידור',
}).click(function(){ chectTyTool.categoryOrder(true); return false;}));
}).click(function(){ chectTyTool.categoryOrder(true); return false;}));
this.writeMsg(categorySortMsg, 'info');
this.writeMsg(categorySortMsg, 'info');
} else {
} else {
newTxt = newTxt.trimEnd();
newTxt = newTxt.trimEnd();
newTxt += '\n' + cats.join('\n');
newTxt += '\n' + cats.join('\n');
if (newTxt != txt)
if (newTxt != txt)
OO.ui.confirm( 'יש לאשר סדר הקטגוריות המוצע:' + cats.join(', ').replace(/\[\[קטגוריה:([^\[\]]+)\]\]/g, '$1') ).done( function ( confirmed ) {
OO.ui.confirm( 'יש לאשר סדר הקטגוריות המוצע:' + cats.join(', ').replace(/\[\[קטגוריה:([^\[\]]+)\]\]/g, '$1') ).done( function ( confirmed ) {
if ( !confirmed ) return;
if ( !confirmed ) return;
self.addSummary('סידור קטגוריות');
self.addSummary('סידור קטגוריות');
self.updateText(newTxt);
self.updateText(newTxt);
} );
} );
}
}
},
},
duplicatedCategory: function(execute) {
duplicatedCategory: function(execute) {
var txt = this.textbox.value,
var txt = this.textbox.value,
newTxt = txt,
newTxt = txt,
categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g,
categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g,
cats = [], m = null, permutedCats = null;
cats = [], m = null, permutedCats = null;
while(m=categoryRE.exec(txt)) {
while(m=categoryRE.exec(txt)) {
cats.push(m[1]);
cats.push(m[1]);
newTxt = newTxt.replace(m[0], '');
newTxt = newTxt.replace(m[0], '');
}
}
permutedCats = cats.filter(function(cat, i) {
permutedCats = cats.filter(function(cat, i) {
return cats.indexOf(cat) == i;
return cats.indexOf(cat) == i;
});
});


if (cats.length == permutedCats.length) return; // no duplicates
if (cats.length == permutedCats.length) return; // no duplicates


newTxt = newTxt.trimEnd();
newTxt = newTxt.trimEnd();
newTxt += '\n' + permutedCats.join('\n');
newTxt += '\n' + permutedCats.join('\n');
if (newTxt != txt)
if (newTxt != txt)
this.addSummary('הסרת קטגוריה כפולה');
this.addSummary('הסרת קטגוריה כפולה');
this.updateText(newTxt);
this.updateText(newTxt);
},
},
linkChecks: function() {
linkChecks: function() {
this.overlinkify();
this.overlinkify();
this.nakedLinks();
this.nakedLinks();
this.checkExternalLinks();
this.checkExternalLinks();
this.disambigCheck();
this.disambigCheck();
},
},
expandWikidata: function() {
expandWikidata: function() {
this.wikidataLabelsMissing();
this.wikidataLabelsMissing();
this.extractWikidataLabelsSuggestions();
this.extractWikidataLabelsSuggestions();
if (!this.isSection) {
if (!this.isSection) {
this.addAuthorityControl();
this.addAuthorityControl();
}
}
},
},
createSearchLink: function(v) {
createSearchLink: function(v) {
var highlightStr = this.highlightString,
var highlightStr = this.highlightString,
searchLink = $('<a href="#">'+mw.msg( 'checkty-search' )+'</a>').data({'search': v}).click(function(e){  
searchLink = $('<a href="#">'+mw.msg( 'checkty-search' )+'</a>').data({'search': v}).click(function(e){
highlightStr($(this).data('search')); e.preventDefault();
highlightStr($(this).data('search')); e.preventDefault();
});
});
return searchLink;
return searchLink;
},
},
onSaveProtection: function() {
onSaveProtection: function() {
$('#wpSave').click(function(e){
$('#wpSave').click(function(e){
if (chectTyTool.textbox.value === chectTyTool.origText) {
if (chectTyTool.textbox.value === chectTyTool.origText) {
OO.ui.confirm( mw.msg('checkty-nonsense-edit') ).done( function ( confirmed ) {
OO.ui.confirm( mw.msg('checkty-nonsense-edit') ).done( function ( confirmed ) {
    if ( confirmed ) {
if ( confirmed ) {
chectTyTool.origText = '';
chectTyTool.origText = '';
$('#editform').submit();
$('#editform').submit();
    } else {
} else {
e.preventDefault();
e.preventDefault();
    }
}
} );
} );
e.preventDefault();
e.preventDefault();
}
}
});
});
},
},
updateText: function( val ) {
updateText: function( val ) {
if (this.textbox.value === chectTyTool.origText) {
if (this.textbox.value === chectTyTool.origText) {
chectTyTool.origText = val;
chectTyTool.origText = val;
}
}
this.textbox.value = val;
this.textbox.value = val;
},
},
nakedLinks: function() {
nakedLinks: function() {
var t = this.textbox.value,
var t = this.textbox.value,
nakeRegex=/\[(http[^ ]+?)\]|\{\{הערה *\| *(?:1 *= *)?(https?:\/\/[^ }|]+)\}\}|<ref(?: [^/>]*)?>(https?:\/\/[^ }|]+?)<\/ref>/g,
nakeRegex=/\[(http[^ ]+?)\]|\{\{הערה *\| *(?:1 *= *)?(https?:\/\/[^ }|]+)\}\}|<ref(?: [^/>]*)?>(https?:\/\/[^ }|]+?)<\/ref>/g,
nakeErrors=[], m, self= this;
nakeErrors=[], m, self= this;
while (m = nakeRegex.exec(t)) {
while (m = nakeRegex.exec(t)) {
var nakedUrl = m[1] || m[2] || m[3],
var nakedUrl = m[1] || m[2] || m[3],
fixNakedLink = $( '<a href="#">' + mw.msg( 'checkty-naked-link-fix' )+'</a>' ).data( { 'search': nakedUrl, 'inRefTemplate': m[2], 'inRef': m[3] }).click( function ( e ) {  
fixNakedLink = $( '<a href="#">' + mw.msg( 'checkty-naked-link-fix' )+'</a>' ).data( { 'search': nakedUrl, 'inRefTemplate': m[2], 'inRef': m[3] }).click( function ( e ) {
var searchUrl = $(this).data( 'search' ),
var searchUrl = $(this).data( 'search' ),
inRef = $(this).data('inRef'),
inRef = $(this).data('inRef'),
inRefTemplate = $(this).data('inRefTemplate'),
inRefTemplate = $(this).data('inRefTemplate'),
citoidTemplatesPromise = new mw.Api().loadMessagesIfMissing( [ 'citoid-template-type-map.json' ] );
citoidTemplatesPromise = new mw.Api().loadMessagesIfMissing( [ 'citoid-template-type-map.json' ] );
        // Common case: pasting a URI into this field. Citoid expects
// Common case: pasting a URI into this field. Citoid expects
        // minimally encoded input, so do some speculative decoding here to
// minimally encoded input, so do some speculative decoding here to
        // avoid 404 fetches. T146539
// avoid 404 fetches. T146539
searchUrl = decodeURIComponent(searchUrl);
searchUrl = decodeURIComponent(searchUrl);
citoidPromise = $.ajax('/api/rest_v1/data/citation/mediawiki/'+encodeURIComponent(searchUrl), {
citoidPromise = $.ajax('/api/rest_v1/data/citation/mediawiki/'+encodeURIComponent(searchUrl), {
headers: { 'accept-language': mw.config.get( 'wgContentLanguage' ) },
headers: { 'accept-language': mw.config.get( 'wgContentLanguage' ) },
timeout: 20 * 1000, // 20 seconds
timeout: 20 * 1000, // 20 seconds
type: 'GET'
type: 'GET'
});
});
citoidPromise.done(function(d){
citoidPromise.done(function(d){
citoidTemplatesPromise.done(function(){
citoidTemplatesPromise.done(function(){
var CiteTemplates = JSON.parse( mw.message( 'citoid-template-type-map.json' ).plain() );
var CiteTemplates = JSON.parse( mw.message( 'citoid-template-type-map.json' ).plain() );
if ( d.length === 0 || !CiteTemplates[ d[0].itemType ] ) {
if ( d.length === 0 || !CiteTemplates[ d[0].itemType ] ) {
self.writeMsg( mw.msg( 'checkty-naked-link-fix-fail' ) );
self.writeMsg( mw.msg( 'checkty-naked-link-fix-fail' ) );
return;
return;
}
}


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


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


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


while (true) {
while (true) {
match = txt.match(/\0(\d+)\0/);
match = txt.match(/\0(\d+)\0/);
if (!match || !match.length) break;
if (!match || !match.length) break;
txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]);
txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]);
}
}
this.updateText(txt);
this.updateText(txt);
// if (!emptyParametersRgx.test(txt)) return;
// if (!emptyParametersRgx.test(txt)) return;
// emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', {
// emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', {
// href: '#',
// href: '#',
// text: 'ניקוי'
// text: 'ניקוי'
// }).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; }));
// }).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; }));
// this.writeMsg(emptyParametersMsg, 'info');
// this.writeMsg(emptyParametersMsg, 'info');
},
},
vavCheck: function () {
vavCheck: function () {
var text = this.textbox.value,
var text = this.textbox.value,
vavRegex = /[כלבמשה]\[\[ו[^ו][א-ת ]+\]\]/g, self = this;
vavRegex = /[כלבמשה]\[\[ו[^ו][א-ת ]+\]\]/g, self = this;
if (!vavRegex.exec( text )) return;
if (!vavRegex.exec( text )) return;
var vavWarning = $('<div>').text( mw.msg( 'checkty-vav-warning' ) ).append(this.createSearchLink(vavRegex));
var vavWarning = $('<div>').text( mw.msg( 'checkty-vav-warning' ) ).append(this.createSearchLink(vavRegex));
// TODO: add semi-automatic fix option?
// TODO: add semi-automatic fix option?
chectTyTool.writeMsg(vavWarning);
chectTyTool.writeMsg(vavWarning);
},
},
disambigCheck: function () {
disambigCheck: function () {
var disambigMsg = this.writeMsg($('<div>', {
var disambigMsg = this.writeMsg($('<div>', {
id: 'waitForDisambigs'
id: 'waitForDisambigs'
}).text( mw.msg( 'checkty-waiting-disambig-query' ) ), 'info'), self = this;
}).text( mw.msg( 'checkty-waiting-disambig-query' ) ), 'info'), self = this;
this.fetchDisambigLinks().fail(function () {
this.fetchDisambigLinks().fail(function () {
disambigMsg.remove();
disambigMsg.remove();
self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-no-links') }), 'check');
self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-no-links') }), 'check');
}).done(function (res) {
}).done(function (res) {
var disambigs;
var disambigs;
disambigMsg.remove();
disambigMsg.remove();
if (res.length === 0) {
if (res.length === 0) {
self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-success') }), 'check');
self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-success') }), 'check');
return;
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');
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) {
$.each(res, function (i, disTitle) {
if (i > 0) {
if (i > 0) {
disambigs.append(', ');
disambigs.append(', ');
}
}
disambigs.append($('<a href="' + mw.util.getUrl(disTitle) + '">' + disTitle + '</a>').click(function () {
disambigs.append($('<a href="' + mw.util.getUrl(disTitle) + '">' + disTitle + '</a>').click(function () {
var disambigName = $(this).text();
var disambigName = $(this).text();
new mw.Api().get({
new mw.Api().get({
action: 'parse',
action: 'parse',
page: disambigName,
page: disambigName,
prop: 'text',
prop: 'text',
redirects: 1
redirects: 1
}).done(function (data) {
}).done(function (data) {
if (data && data.parse && data.parse.text) {
if (data && data.parse && data.parse.text) {
var disambig = data.parse.text['*'];
var disambig = data.parse.text['*'];
mw.loader.using( ['jquery.ui'] ).done ( function() { chectTyTool.resolveDisambig( disambigName, disambig ); } );
mw.loader.using( ['jquery.ui'] ).done ( function() { chectTyTool.resolveDisambig( disambigName, disambig ); } );
} else {
} else {
console.error(data);
console.error(data);
}
}
});
});
return false;
return false;
}));
}));
});
});
chectTyTool.writeMsg(disambigs);
chectTyTool.writeMsg(disambigs);
});
});
},
},
getLinkRegex: function(name) {
getLinkRegex: function(name) {
return new RegExp('(?:\\.|^)([^\\.\n]*(\\[\\[' + mw.util.escapeRegExp(name) + '[\\|\\]]).*?)[\\.\\n]', 'm');
return new RegExp('(?:\\.|^)([^\\.\n]*(\\[\\[' + mw.util.escapeRegExp(name) + '[\\|\\]]).*?)[\\.\\n]', 'm');
},
},
resolveDisambig: function (name, data) {
resolveDisambig: function (name, data) {
var offset = 0,
var offset = 0,
textbox = this.textbox,
textbox = this.textbox,
linkRgx = this.getLinkRegex(name),
linkRgx = this.getLinkRegex(name),
orgPos = $(textbox).textSelection('getCaretPosition'),
orgPos = $(textbox).textSelection('getCaretPosition'),
cSentence = $('<div>');
cSentence = $('<div>');
var options = $('<div>').append($('li', data).filter(function() { return $(this).closest( '.checkty-ignore' ).length === 0; } ).map(function () {
var options = $('<div>').append($('li', data).filter(function() { return $(this).closest( '.checkty-ignore' ).length === 0; } ).map(function () {
var a = $(this).children('a').get(0);
var a = $(this).children('a').get(0);
if (a) {
if (a) {
var storeTitle = $(this).text();
var storeTitle = $(this).text();
var anchor = '',
var anchor = '',
h = a.href;
h = a.href;
if (h.indexOf('#') + 1) anchor = decodeURI(h.substr(h.indexOf('#')).replace(/\./g, '%').replace(/_/g, ' '));
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).text( a.title.replace(mw.msg( 'checkty-page-doesnt-exist' ), "") + anchor);
a.title = storeTitle;
a.title = storeTitle;
}
}
return a || null;
return a || null;
}).click(resolve))
}).click(resolve))
.append($('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').click(removeLink));
.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({
var disambigDialog = $('<div>').append( mw.msg('checkty-disambig-meaning', name) + '<hr/>').append(cSentence).append(options.buttonset()).dialog({
title: mw.msg( 'checkty-dismabig-dialog-title' ),
title: mw.msg( 'checkty-dismabig-dialog-title' ),
close: function () {
close: function () {
$(textbox).textSelection('setSelection', {
$(textbox).textSelection('setSelection', {
start: orgPos
start: orgPos
});
});
}
}
});
});
findSentence();
findSentence();
function findSentence() {
function findSentence() {
var text = textbox.value.substr(offset),
var text = textbox.value.substr(offset),
m = text.match(linkRgx);
m = text.match(linkRgx);
if (!m) {
if (!m) {
disambigDialog.dialog('close');
disambigDialog.dialog('close');
return;
return;
}
}
offset += text.indexOf(m[1]) + m[1].indexOf(m[2]);
offset += text.indexOf(m[1]) + m[1].indexOf(m[2]);
var linkIndex = m[1].indexOf(m[2]) + 2,
var linkIndex = m[1].indexOf(m[2]) + 2,
html = m[1].substr(0, linkIndex) + '<big>' + name + '</big>' + m[1].substr(linkIndex + name.length);
html = m[1].substr(0, linkIndex) + '<big>' + name + '</big>' + m[1].substr(linkIndex + name.length);
cSentence.html(html);
cSentence.html(html);
}
}
function resolve() {
function resolve() {
var answer = $(this).text(),
var answer = $(this).text(),
text = textbox.value,
text = textbox.value,
startLink = text.indexOf('[[' + name, offset);
startLink = text.indexOf('[[' + name, offset);
if (text.charAt(startLink + 2 + name.length) != '|') answer += '|' + name;
if (text.charAt(startLink + 2 + name.length) != '|') answer += '|' + name;
offset += answer.length + 2;
offset += answer.length + 2;
text = text.substr(0, startLink + 2) + answer + text.substr(startLink + 2 + name.length);
text = text.substr(0, startLink + 2) + answer + text.substr(startLink + 2 + name.length);
textbox.value = text;
textbox.value = text;
findSentence();
findSentence();
chectTyTool.addSummary( mw.msg( 'checkty-dismabig-fix-summary' ) );
chectTyTool.addSummary( mw.msg( 'checkty-dismabig-fix-summary' ) );
return false;
return false;
}
}
function removeLink() {
function removeLink() {
var text = textbox.value,
var text = textbox.value,
startLink = text.indexOf('[[' + name, offset),
startLink = text.indexOf('[[' + name, offset),
endLink = text.indexOf(']]', startLink),
endLink = text.indexOf(']]', startLink),
pipeChar = startLink + 2 + name.length,
pipeChar = startLink + 2 + name.length,
linkText = (text.charAt(pipeChar) != '|') ? name : text.substr(pipeChar + 1, endLink - pipeChar - 1);
linkText = (text.charAt(pipeChar) != '|') ? name : text.substr(pipeChar + 1, endLink - pipeChar - 1);
offset += (endLink - startLink) + linkText.length;
offset += (endLink - startLink) + linkText.length;
text = text.substr(0, startLink) + linkText + text.substr(endLink + 2);
text = text.substr(0, startLink) + linkText + text.substr(endLink + 2);
textbox.value = text;
textbox.value = text;
findSentence();
findSentence();
return false;
return false;
}
}
},
},
addSummary: function (msg) {
addSummary: function (msg) {
var editSummary = $('#wpSummary').val();
var editSummary = $('#wpSummary').val();
if (editSummary.indexOf(msg) === -1) $('#wpSummary').val(editSummary + (editSummary.length === 0 ? '' : ', ') + msg);
if (editSummary.indexOf(msg) === -1) $('#wpSummary').val(editSummary + (editSummary.length === 0 ? '' : ', ') + msg);
// tag the edit
// tag the edit
if ( $('#checktyTag').length === 0 ) {
if ( $('#checktyTag').length === 0 ) {
$('#editform').append('<input type="hidden" name="wpChangeTags" id="checktyTag" value="צ\'קטי">');
$('#editform').append('<input type="hidden" name="wpChangeTags" id="checktyTag" value="צ\'קטי">');
}
}  
},
},
checkGallery: function() {
checkGallery: function() {
var text = this.textbox.value,
var text = this.textbox.value,
longGalleryThreshold = 16,
longGalleryThreshold = 16,
galleryRgx = /<gallery.+?\n(\n|.)+?<\/gallery>/mg,
galleryRgx = /<gallery.+?\n(\n|.)+?<\/gallery>/mg,
m, longGallery=false;
m, longGallery=false;
while ( m=galleryRgx.exec( text ) ) { var galLength = m[0].split('\n').length-2; longGallery |= (galLength > longGalleryThreshold); }
while ( m=galleryRgx.exec( text ) ) { var galLength = m[0].split('\n').length-2; longGallery |= (galLength > longGalleryThreshold); }
if (longGallery) {
if (longGallery) {
this.writeMsg('<div>' + mw.msg('checkty-long-gallery') + '</div>', 'alert');
this.writeMsg('<div>' + mw.msg('checkty-long-gallery') + '</div>', 'alert');
}
}
},
},
checkImages: function (data) {
checkImages: function (data) {
var fairUsageTemplates = ['תבנית:שימוש הוגן', 'תבנית:תמונת חבר כנסת'];
var fairUsageTemplates = ['תבנית:שימוש הוגן', 'תבנית:תמונת חבר כנסת'];
if (!data) {
if (!data) {
if (!(/\{\{(ויקישיתוף בשורה|מיזמים)/.test(this.textbox.value))) {
if (!(/\{\{(ויקישיתוף בשורה|מיזמים)/.test(this.textbox.value))) {
$.getJSON('//www.wikidata.org/w/api.php?callback=?', {
$.getJSON('//www.wikidata.org/w/api.php?callback=?', {
languages: 'he',
languages: 'he',
action: 'wbgetentities',
action: 'wbgetentities',
sites: mw.config.get('wgDBname'),
sites: mw.config.get('wgDBname'),
titles: mw.config.get('wgTitle'),
titles: mw.config.get('wgTitle'),
format: 'json',
format: 'json',
props: 'claims'
props: 'claims'
}).done(function (data) {
}).done(function (data) {
if (data.success === undefined || !data.success) return;
if (data.success === undefined || !data.success) return;
for (var entityId in data.entities) {
for (var entityId in data.entities) {
var claims = data.entities[entityId].claims;
var claims = data.entities[entityId].claims;
if (claims && claims.hasOwnProperty('P373')) {
if (claims && claims.hasOwnProperty('P373')) {
chectTyTool.writeMsg($('<div>', {
chectTyTool.writeMsg($('<div>', {
text: mw.msg('checkty-missing-commons-link')
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>', {
}).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: '#',
href: '#',
text: 'להוספה'
text: 'להוספה'
}).click(function (e) {
}).click(function (e) {
e.preventDefault();
e.preventDefault();
var ta = $('#wpTextbox1');
var ta = $('#wpTextbox1');
if (ta.textSelection('getCaretPosition') >= ta.val().length) {
if (ta.textSelection('getCaretPosition') >= ta.val().length) {
chectTyTool.writeMsg($('<div>').text(mw.msg('checkty-please-position-caret')));
chectTyTool.writeMsg($('<div>').text(mw.msg('checkty-please-position-caret')));
} else {
} else {
ta.textSelection('encapsulateSelection',{pre:'{{ויקישיתוף בשורה}}'});
ta.textSelection('encapsulateSelection',{pre:'{{ויקישיתוף בשורה}}'});
chectTyTool.addSummary('ויקישיתוף בשורה');
chectTyTool.addSummary('ויקישיתוף בשורה');
}
}
})));
})));
}
}
}
}
});
});
}
}
//in case there are no images in page
//in case there are no images in page
if (!(/\[\[(תמונה|קובץ|File|Image):/i.test(this.textbox.value))) {
if (!(/\[\[(תמונה|קובץ|File|Image):/i.test(this.textbox.value))) {
var articleName = mw.config.get('wgPageName');
var articleName = mw.config.get('wgPageName');
var that = this; // we want to use "this" in the done method of the api call.
var that = this; // we want to use "this" in the done method of the api call.
new mw.Api().post( {
new mw.Api().post( {
action: 'parse',
action: 'parse',
title: articleName,
title: articleName,
text: this.textbox.value
text: this.textbox.value
} ).done( function( data ) {
} ).done( function( data ) {
if ( data && data.parse && data.parse.text && $( data.parse.text['*'] ).find( 'a.image img' ).filter(function() {  
if ( data && data.parse && data.parse.text && $( data.parse.text['*'] ).find( 'a.image img' ).filter(function() {
var width = $(this).attr('width');
var width = $(this).attr('width');
if (isNaN(width)) width = $(this).width();
if (isNaN(width)) width = $(this).width();
else width = parseInt(width);
else width = parseInt(width);
return (width >= 100) && $(this).parents('.navbox').length==0;  
return (width >= 100) && $(this).parents('.navbox').length==0;
} ).length === 0 ) {
} ).length === 0 ) {
var fistURL = that.fistURL({
var fistURL = that.fistURL({
datatype: 'articles',
datatype: 'articles',
data: articleName
data: articleName
});
});
var msg = $('<div>', {
var msg = $('<div>', {
text: 'בדף זה אין תמונות. ניתן לחפש תמונות חופשיות ממקורות שונים. '
text: 'בדף זה אין תמונות. ניתן לחפש תמונות חופשיות ממקורות שונים. '
}).append($('<a>', {
}).append($('<a>', {
href: decodeURI(fistURL),
href: decodeURI(fistURL),
text: 'חיפוש תמונות',
text: 'חיפוש תמונות',
target: '_blank'
target: '_blank'
}));
}));
that.writeMsg(msg, 'info');
that.writeMsg(msg, 'info');
}
}
});
});
return;
return;
}
}
new mw.Api().get({
new mw.Api().get({
action: 'query',
action: 'query',
generator: 'images',
generator: 'images',
titles: mw.config.get('wgPageName'),
titles: mw.config.get('wgPageName'),
prop: 'templates',
prop: 'templates',
tltemplates: fairUsageTemplates.join('|')
tltemplates: fairUsageTemplates.join('|')
}).done(function (data) {
}).done(function (data) {
if (data && data.query && data.query.pages) chectTyTool.checkImages(data.query.pages);
if (data && data.query && data.query.pages) chectTyTool.checkImages(data.query.pages);
});
});
} else {
} else {
var fairUseImgs = $.map(data, function (o) {
var fairUseImgs = $.map(data, function (o) {
if (!o.templates) return;
if (!o.templates) return;
var isFairUsage;
var isFairUsage;
$.each(o.templates, function (k, license) {
$.each(o.templates, function (k, license) {
if ($.inArray(license.title, fairUsageTemplates) != -1) {
if ($.inArray(license.title, fairUsageTemplates) != -1) {
isFairUsage = true;
isFairUsage = true;
return false;
return false;
}
}
});
});
if (isFairUsage) return o.title;
if (isFairUsage) return o.title;
});
});
if (fairUseImgs.length === 0) return;
if (fairUseImgs.length === 0) return;
//add message with fair usage images
//add message with fair usage images
var fistURL = this.fistURL({
var fistURL = this.fistURL({
data: fairUseImgs.join('\r\n'),
data: fairUseImgs.join('\r\n'),
datatype: 'replaceimages'
datatype: 'replaceimages'
});
});
var msg = $('<div>', {
var msg = $('<div>', {
text: 'הדף מכיל תמונות בשימוש הוגן, שמומלץ להחליפן בחלופות חופשיות במידת האפשר. '
text: 'הדף מכיל תמונות בשימוש הוגן, שמומלץ להחליפן בחלופות חופשיות במידת האפשר. '
}).append($('<a>', {
}).append($('<a>', {
href: fistURL,
href: fistURL,
text: 'חיפוש חלופות חופשיות',
text: 'חיפוש חלופות חופשיות',
target: '_blank'
target: '_blank'
}));
}));
if (!(new RegExp('\{\{'+mw.msg('checkty-fairuse-img-replace-template')+'\}\}').test($('#wpTextbox1').val())))
if (!(new RegExp('\{\{'+mw.msg('checkty-fairuse-img-replace-template')+'\}\}').test($('#wpTextbox1').val())))
msg.append(' - ').append($('<a>', {
msg.append(' - ').append($('<a>', {
text: 'סימון להחלפה',
text: 'סימון להחלפה',
href: '#'
href: '#'
}).click(function () {
}).click(function () {
var t = $('#wpTextbox1');
var t = $('#wpTextbox1');
$.each(fairUseImgs, function (i, fiImg) {
$.each(fairUseImgs, function (i, fiImg) {
var imgName = mw.util.escapeRegExp(/.:(.+)$/.exec(fiImg)[1]),
var imgName = mw.util.escapeRegExp(/.:(.+)$/.exec(fiImg)[1]),
imgDescRE = new RegExp(imgName.replace(' ', '[ _]') + '((?:[^\\[\\]]|\\[\\[[^\\[\\]]*?\\]\\])*?)\]\]', 'i'),
imgDescRE = new RegExp(imgName.replace(' ', '[ _]') + '((?:[^\\[\\]]|\\[\\[[^\\[\\]]*?\\]\\])*?)\]\]', 'i'),
matches;
matches;
if (!(matches = imgDescRE.exec(t.val()))) {
if (!(matches = imgDescRE.exec(t.val()))) {
return;
return;
}
}
//this is thumb img
//this is thumb img
var imgDesc = matches[1].split('|'), isThumb = false, imgCaption = '';
var imgDesc = matches[1].split('|'), isThumb = false, imgCaption = '';
for (var i in imgDesc) {
for (var i in imgDesc) {
if (/thumb|ממוזער/i.test(imgDesc[i])) {
if (/thumb|ממוזער/i.test(imgDesc[i])) {
isThumb = true;
isThumb = true;
} else if (!(/^(ימין|שמאל|מרכז|right|left|center|[0-9]+px)?$/i.test(imgDesc[i]))) {
} else if (!(/^(ימין|שמאל|מרכז|right|left|center|[0-9]+px)?$/i.test(imgDesc[i]))) {
imgCaption = imgDesc[i]; //unknown parameter assumed to be description
imgCaption = imgDesc[i]; //unknown parameter assumed to be description
}
}
}
}
if (isThumb) {
if (isThumb) {
if (imgCaption) {
if (imgCaption) {
imgDesc = matches[1].replace(imgCaption, imgCaption + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
imgDesc = matches[1].replace(imgCaption, imgCaption + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
} else {
} else {
imgDesc = matches[1] + '|{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}';
imgDesc = matches[1] + '|{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}';
}
}
t.val(t.val().replace(matches[1], imgDesc));
t.val(t.val().replace(matches[1], imgDesc));
chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
} else {
} else {
//is in infobox heuristic: = before image tag
//is in infobox heuristic: = before image tag
var isInInfobox = new RegExp('=\s*\\[\\[(?:file|image|קובץ|תמונה):' + imgName.replace(' ', '[ _]') + '[^\\]]*?\]\]', 'i');
var isInInfobox = new RegExp('=\s*\\[\\[(?:file|image|קובץ|תמונה):' + imgName.replace(' ', '[ _]') + '[^\\]]*?\]\]', 'i');
if (isInInfobox.test(t.val())) {
if (isInInfobox.test(t.val())) {
t.val(t.val().replace(matches[0], matches[0] + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'));
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')+'}}');
chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
}
}
}
}
});
});
}));
}));
this.writeMsg(msg, 'alert');
this.writeMsg(msg, 'alert');
}
}
},
},
fistURL: function (p) {
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);
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);
},
},
removeRefs: function (text) { // remove refs from text. use for internal checks only
removeRefs: function (text) { // remove refs from text. use for internal checks only
var cleanText = text;
var cleanText = text;
cleanText = cleanText.replace(/<ref(?: [^>]+?)?>.+?<\/ref>|\{\{הערה\|.*?\}\}/g, '');
cleanText = cleanText.replace(/<ref(?: [^>]+?)?>.+?<\/ref>|\{\{הערה\|.*?\}\}/g, '');
return cleanText;
return cleanText;
},
},
languageCheck: function (checks) { //style and language check
languageCheck: function (checks) { //style and language check
var txt = this.textbox.value;
var txt = this.textbox.value;
if (txt.length === 0) return; // nothing to do
if (txt.length === 0) return; // nothing to do
if (checks) {
if (checks) {
var textNoRefs = this.removeRefs(txt); // avoid language checks in refs. TODO: skip only quotes/book names/external links but not comments in footnotes
var textNoRefs = this.removeRefs(txt); // avoid language checks in refs. TODO: skip only quotes/book names/external links but not comments in footnotes
var checkWarnings = $('<div></div>');
var checkWarnings = $('<div></div>');
for (var x in checks) {
for (var x in checks) {
if (checks[x]['test'].test(textNoRefs)) {
if (checks[x]['test'].test(textNoRefs)) {
var m = checks[x]['test'].exec(txt), langCheckPrefix = '';
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]);
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(this.createSearchLink(checks[x]['test']));
checkWarnings.append('&nbsp;-&nbsp;' + langCheckPrefix + checks[x]['remark'] + '<br/>');
checkWarnings.append('&nbsp;-&nbsp;' + langCheckPrefix + checks[x]['remark'] + '<br/>');
}
}
}
}


// Lint checker: wikilink-in-extlink. see [[mw:Help:Lint_errors/wikilink-in-extlink]]
// Lint checker: wikilink-in-extlink. see [[mw:Help:Lint_errors/wikilink-in-extlink]]
var wikilinkInExtLink = /[^\[]\[[^\[\]]+\[\[.+?\]\]/;
var wikilinkInExtLink = /[^\[]\[[^\[\]]+\[\[.+?\]\]/;
if (wikilinkInExtLink.test(txt)) {
if (wikilinkInExtLink.test(txt)) {
checkWarnings.append(this.createSearchLink(wikilinkInExtLink));
checkWarnings.append(this.createSearchLink(wikilinkInExtLink));
checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-wikilink-in-extlink' ));
checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-wikilink-in-extlink' ));
}
}


// Design checks: Elements width
// Design checks: Elements width
var largeElement = /[6789][0-9][0-9]px/;
var largeElement = /[6789][0-9][0-9]px/;
if (largeElement.test(txt)) checkWarnings.append(mw.msg( 'checkty-large-element' ) + '<br/>');
if (largeElement.test(txt)) checkWarnings.append(mw.msg( 'checkty-large-element' ) + '<br/>');


// Design checks: Long lists can have hint to use columns
// Design checks: Long lists can have hint to use columns
var manyLi = new RegExp('(?:\n\\*.*){20}');
var manyLi = new RegExp('(?:\n\\*.*){20}');
if (manyLi.test(txt)) {
if (manyLi.test(txt)) {
checkWarnings.append(this.createSearchLink(manyLi));
checkWarnings.append(this.createSearchLink(manyLi));
checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-long-list' ));
checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-long-list' ));
}
}
if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
} else {
} else {
var api = new mw.Api();
var api = new mw.Api();
api.get({
api.get({
action:'parse',
action:'parse',
page: 'המכלול:בדיקה אוטומטית',
page: 'המכלול:בדיקה אוטומטית',
prop: 'wikitext'
prop: 'wikitext'
}).done(function (data) {
}).done(function (data) {
if (!(data && data.parse && data.parse.wikitext)) return;
if (!(data && data.parse && data.parse.wikitext)) return;
var DictionaryText = data.parse.wikitext['*'].split('-----')[1]
var DictionaryText = data.parse.wikitext['*'].split('-----')[1]
var genrealWarningWords = DictionaryText.split('\n*');
var genrealWarningWords = DictionaryText.split('\n*');
var checks = [];
var checks = [];
for (var i=0;i<genrealWarningWords.length;i++)
for (var i=0;i<genrealWarningWords.length;i++)
{
{
var splittedWarn = genrealWarningWords[i].split("//");
var splittedWarn = genrealWarningWords[i].split("//");
if ( splittedWarn.length !== 2 ) continue;
if ( splittedWarn.length !== 2 ) continue;
try {
try {
checks.push({
checks.push({
'test': new RegExp( splittedWarn[0], 'i' ),
'test': new RegExp( splittedWarn[0], 'i' ),
'remark': splittedWarn[1]
'remark': splittedWarn[1]
});
});
}
}
catch(e)
catch(e)
{
{
/* negative lookbehind and similar advanced regex
/* negative lookbehind and similar advanced regex
will be skipped in browser which don't support it */
will be skipped in browser which don't support it */
console.log('Skippted automatic check ' + i );
console.log('Skippted automatic check ' + i );
console.log(splittedWarn);
console.log(splittedWarn);
}
}
}
}
chectTyTool.languageCheck(checks);
chectTyTool.languageCheck(checks);
});
});
var countRgx = /(?:[^ ]+ ){2}.?(?:ש[נת]י|שלוש[תה]?|ארבע[הת]?|חמשת?|חמישה|ששת?|שבע[הת]?|תשע[הת]?|עשר[הת]?) [א-ת]+/g,
var countRgx = /(?:[^ ]+ ){2}.?(?:ש[נת]י|שלוש[תה]?|ארבע[הת]?|חמשת?|חמישה|ששת?|שבע[הת]?|תשע[הת]?|עשר[הת]?) [א-ת]+/g,
gramCheck = [], m, self = this;
gramCheck = [], m, self = this;
while (m = countRgx.exec(txt)) { gramCheck.push(m) }
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 (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;
if (!d.errs || d.errs.length === 0) return;
var zaharNekevaWarns = $('<div></div>');
var zaharNekevaWarns = $('<div></div>');
for ( var i = 0; i < d.errs.length; i++ ) {
for ( var i = 0; i < d.errs.length; i++ ) {
var origRgx = new RegExp(d.errs[i].orig);
var origRgx = new RegExp(d.errs[i].orig);
zaharNekevaWarns.append(self.createSearchLink(origRgx));
zaharNekevaWarns.append(self.createSearchLink(origRgx));
zaharNekevaWarns.append('&nbsp;-&nbsp;ייתכן שיש אי התאמה במין ב"' + d.errs[i].orig + '" (תיקון: '+d.errs[i].suggested+') <br/>');
zaharNekevaWarns.append('&nbsp;-&nbsp;ייתכן שיש אי התאמה במין ב"' + d.errs[i].orig + '" (תיקון: '+d.errs[i].suggested+') <br/>');
}
}
chectTyTool.writeMsg(zaharNekevaWarns, 'alert');
chectTyTool.writeMsg(zaharNekevaWarns, 'alert');
});
});


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


for (k in references) {
for (k in references) {
if (references[k] > 1) {
if (references[k] > 1) {
var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext),
var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext),
shortRef = chectTyTool.named_comment + k + '}}';
shortRef = chectTyTool.named_comment + k + '}}';
i = 0;
i = 0;
if (content)
if (content)
wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(content[0]), 'g'), function(m) { return (i++? shortRef : m); });
wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(content[0]), 'g'), function(m) { return (i++? shortRef : m); });
mergedRefs.push(k);
mergedRefs.push(k);
}
}
}
}
// merge referecnes with same content but different name
// merge referecnes with same content but different name
for (k in refsContent) {
for (k in refsContent) {
if ($.inArray(k,mergedRefsNames) != -1) continue; // skip name already merged
if ($.inArray(k,mergedRefsNames) != -1) continue; // skip name already merged
for (i in refsContent) {
for (i in refsContent) {
if (k === i) continue; // skip same name
if (k === i) continue; // skip same name
if (refsContent[k].content == refsContent[i].content) { // two refs with same content but different name
if (refsContent[k].content == refsContent[i].content) { // two refs with same content but different name
var oldRefName = new RegExp('<ref name="'+mw.util.escapeRegExp(i)+'" */>', 'g');
var oldRefName = new RegExp('<ref name="'+mw.util.escapeRegExp(i)+'" */>', 'g');
mergedRefsNames.push(i);
mergedRefsNames.push(i);
shortRef = chectTyTool.named_comment + k + '}}';
shortRef = chectTyTool.named_comment + k + '}}';
wikitext = wikitext.replace(refsContent[i].text, shortRef);
wikitext = wikitext.replace(refsContent[i].text, shortRef);
wikitext = wikitext.replace(oldRefName, shortRef);
wikitext = wikitext.replace(oldRefName, shortRef);
}
}
}
}
}
}


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


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


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


var searchRef = this.createSearchLink(m[1]);
var searchRef = this.createSearchLink(m[1]);
this.writeMsg($('<div>').append(['נמצאה הערת שוליים ללא הגדרת כיווניות "'+m[1]+'" [',searchRef, '&nbsp;-&nbsp;', fixRefDirLink, ']']), 'alert');
this.writeMsg($('<div>').append(['נמצאה הערת שוליים ללא הגדרת כיווניות "'+m[1]+'" [',searchRef, '&nbsp;-&nbsp;', fixRefDirLink, ']']), 'alert');
}
}
},
},
refSection: function(fix) {
refSection: function(fix) {
var wikitext = this.textbox.value, newText = wikitext, self = this,
var wikitext = this.textbox.value, newText = wikitext, self = this,
refRE = /<ref>|\{\{הערה\|/g,
refRE = /<ref>|\{\{הערה\|/g,
refSectionRE = /\{\{הערות[ _]שוליים|<references[ >]/g,
refSectionRE = /\{\{הערות[ _]שוליים|<references[ >]/g,
hasRef = refRE.exec(wikitext) != null,
hasRef = refRE.exec(wikitext) != null,
hasRefSection = refSectionRE.exec(wikitext) != null;
hasRefSection = refSectionRE.exec(wikitext) != null;
if (hasRefSection) return; //not missing
if (hasRefSection) return; //not missing
if (!hasRef) return; // not needed
if (!hasRef) return; // not needed
if (fix) { // fix only when when explictly asked
if (fix) { // fix only when when explictly asked
var autoRefSection = '\n== הערות שוליים ==\n{{הערות שוליים}}\n'
var autoRefSection = '\n== הערות שוליים ==\n{{הערות שוליים}}\n'
var lastItems = [/(\n{{בקרת זהויות)/, /(\n{{קצרמר)/,/\n({{הבהרה (?:רפואית|הלכתית|משפטית))/,/(\n{{מיון רגיל:)/, /(\n\[\[קטגוריה:)/];
var lastItems = [/(\n{{בקרת זהויות)/, /(\n{{קצרמר)/,/\n({{הבהרה (?:רפואית|הלכתית|משפטית))/,/(\n{{מיון רגיל:)/, /(\n\[\[קטגוריה:)/];
for (var i=0; (i < lastItems.length) && (wikitext == newText); i++ ) newText = wikitext.replace(lastItems[i], autoRefSection + '$1');
for (var i=0; (i < lastItems.length) && (wikitext == newText); i++ ) newText = wikitext.replace(lastItems[i], autoRefSection + '$1');
if ( wikitext === newText ) newText = wikitext + autoRefSection;
if ( wikitext === newText ) newText = wikitext + autoRefSection;
this.textbox.value = newText;
this.textbox.value = newText;
this.addSummary('פרק הערות שוליים');
this.addSummary('פרק הערות שוליים');
this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-added' )+'</div>'), 'info');
this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-added' )+'</div>'), 'info');


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


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


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


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


for(var i=0; i<queries; i++)
for(var i=0; i<queries; i++)
{
{
// go through enwiki API, to resolve redirects instead of direct approach with wikidataApi.getEntitiesByPage
// go through enwiki API, to resolve redirects instead of direct approach with wikidataApi.getEntitiesByPage
extWikiApi.get({
extWikiApi.get({
action: 'query',
action: 'query',
titles: foreignTitles.slice(i*batchsize,(i+1)*batchsize).join('|'),
titles: foreignTitles.slice(i*batchsize,(i+1)*batchsize).join('|'),
redirects: 1,
redirects: 1,
prop: 'pageprops',
prop: 'pageprops',
ppprop: 'wikibase_item'
ppprop: 'wikibase_item'
}).done(function(d) {
}).done(function(d) {
for(var i in d.query.redirects) redirects[d.query.redirects[i].to]=d.query.redirects[i].from;
for(var i in d.query.redirects) redirects[d.query.redirects[i].to]=d.query.redirects[i].from;
var wikidataIds = [];
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);
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;
if (wikidataIds.length === 0) return;
self.getWikidataApi().get({
self.getWikidataApi().get({
action: 'wbgetentities',
action: 'wbgetentities',
ids: '\x1f' + wikidataIds.join( '\x1f' ),
ids: '\x1f' + wikidataIds.join( '\x1f' ),
props: '\x1f' + ['labels', 'sitelinks'].join( '\x1f' ),
props: '\x1f' + ['labels', 'sitelinks'].join( '\x1f' ),
languages: '\x1f' + ['he', lang].join( '\x1f' )
languages: '\x1f' + ['he', lang].join( '\x1f' )
}).done(function(d){
}).done(function(d){
queries--;
queries--;
$.extend(dataEntities, d.entities);
$.extend(dataEntities, d.entities);
if (queries === 0) def.resolve(dataEntities);
if (queries === 0) def.resolve(dataEntities);
});
});
});
});
}
}


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


this.getWikidataApi().get({
this.getWikidataApi().get({
action: 'wbgetentities',
action: 'wbgetentities',
ids: '\x1f' + needTranslateQ.join( '\x1f' ),
ids: '\x1f' + needTranslateQ.join( '\x1f' ),
props: '\x1f' + ['labels'].join( '\x1f' ),
props: '\x1f' + ['labels'].join( '\x1f' ),
languages: mw.config.get('wgContentLanguage')
languages: mw.config.get('wgContentLanguage')
}).done( function(d) {
}).done( function(d) {
var needTranslateIndeedQ = [];
var needTranslateIndeedQ = [];
if (!d.entities) return;
if (!d.entities) return;
for(var q in d.entities) {
for(var q in d.entities) {
if (d.entities[q].labels && !d.entities[q].labels.hasOwnProperty(mw.config.get('wgContentLanguage'))) needTranslateIndeedQ.push(q);
if (d.entities[q].labels && !d.entities[q].labels.hasOwnProperty(mw.config.get('wgContentLanguage'))) needTranslateIndeedQ.push(q);
}
}
if(needTranslateIndeedQ.length === 0) return;
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'));
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');
self.writeMsg(msg, 'alert');
$('a', msg).click(function(){
$('a', msg).click(function(){
self.wikidataLabelTranslate(/Q[0-9]+/.exec($(this).prop('href'))[0], $(this).text());
self.wikidataLabelTranslate(/Q[0-9]+/.exec($(this).prop('href'))[0], $(this).text());
return false;
return false;
});
});
});
});


},
},
numberRangeDash: function(fix) {
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
// 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 = /([^|\n]*[א-ת]+'?[-\ ]*)((?:\[\[|\()?[0-9]+(?:\]\])?)-((?:\[\[)?[0-9]+)((?:\]\]|\))?[.:,]?(?:[ \|]|\n)(?!לפנה"ס))/g,
var numberRangeReNoMinus = /([^|\n]*[א-ת]+'?[-\ ]*)((?:\[\[|\()?[0-9]+(?:\]\])?)-((?:\[\[)?[0-9]+)((?:\]\]|\))?[.:,]?(?:[ \|]|\n)(?!לפנה"ס))/g,
wikitext = this.textbox.value, replacements = [], m, i;
wikitext = this.textbox.value, replacements = [], m, i;
while(m = numberRangeReNoMinus.exec(wikitext))
while(m = numberRangeReNoMinus.exec(wikitext))
{
{
if (/^קובץ:|בואינג [0-9]/.exec(m[1])) continue; // skip wrong suggestion
if (/^קובץ:|בואינג [0-9]/.exec(m[1])) continue; // skip wrong suggestion
// note - in replacement we dont include the prefix/suffix to make consistent replacement
// 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, '')) ) {
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]]);
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])) ) {
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]]);
replacements.push([m[1]+m[2] + '-' + m[3], m[1]+m[3] + '–' + m[2]]);
}
}
}
}


if (replacements.length === 0) return;
if (replacements.length === 0) return;
if (fix) {
if (fix) {
for(i = 0; i < replacements.length; i++) {
for(i = 0; i < replacements.length; i++) {
wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(replacements[i][0]), 'g'), replacements[i][1]);
wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(replacements[i][0]), 'g'), replacements[i][1]);
}
}
this.textbox.value = wikitext;
this.textbox.value = wikitext;
this.addSummary( 'קו מפריד בטווח מספרים' );
this.addSummary( 'קו מפריד בטווח מספרים' );
} else {
} else {
this.writeMsg($('<div><a href="#">'+mw.msg( 'checkty-fix-numberRangeDash' )+'</a></div>').click(function(e){ chectTyTool.numberRangeDash(true); e.preventDefault(); }));
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
//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
//thanks to Georgia Tech Research Corporation. Atlanta, GA 30332-0415
highlightString: function (toFind) {
highlightString: function (toFind) {
var txtArea = $('#wpTextbox1');
var txtArea = $('#wpTextbox1');
// cast to string if this is regex
// cast to string if this is regex
if ( RegExp.prototype.isPrototypeOf(toFind) ) {
if ( RegExp.prototype.isPrototypeOf(toFind) ) {
toFind = toFind.exec(txtArea.val());
toFind = toFind.exec(txtArea.val());
if (!toFind) return;
if (!toFind) return;
toFind = toFind[0];
toFind = toFind[0];
}
}
var nextPlace = txtArea.val().indexOf(toFind, txtArea.textSelection('getCaretPosition') + 1);
var nextPlace = txtArea.val().indexOf(toFind, txtArea.textSelection('getCaretPosition') + 1);
if (nextPlace === -1) nextPlace = txtArea.val().indexOf(toFind); //start from begining
if (nextPlace === -1) nextPlace = txtArea.val().indexOf(toFind); //start from begining
if (nextPlace === -1) return; //not found... nothing to do
if (nextPlace === -1) return; //not found... nothing to do
var origText = txtArea.val();
var origText = txtArea.val();
txtArea.val(origText.substring(0, nextPlace));
txtArea.val(origText.substring(0, nextPlace));
txtArea.focus();
txtArea.focus();
txtArea.scrollTop(1000000); //Larger than any real textarea (hopefully)
txtArea.scrollTop(1000000); //Larger than any real textarea (hopefully)
var curScrollTop = txtArea.scrollTop();
var curScrollTop = txtArea.scrollTop();
txtArea.val(origText);
txtArea.val(origText);
if (curScrollTop > 0) {
if (curScrollTop > 0) {
var HALF_EDIT_BOX_HEIGHT = 200;
var HALF_EDIT_BOX_HEIGHT = 200;
txtArea.scrollTop(curScrollTop + HALF_EDIT_BOX_HEIGHT);
txtArea.scrollTop(curScrollTop + HALF_EDIT_BOX_HEIGHT);
}
}
txtArea.focus().textSelection('setSelection', {
txtArea.focus().textSelection('setSelection', {
start: nextPlace,
start: nextPlace,
end: nextPlace + toFind.length
end: nextPlace + toFind.length
});
});
},
},
addAuthorityControl: function(v) {
addAuthorityControl: function(v) {
var t = this.textbox.value,
var t = this.textbox.value,
acTemplate = /\{\{בקרת זהויות[\}|]/g,
acTemplate = /\{\{בקרת זהויות[\}|]/g,
artsTitle = /== *(?:מ?ספרי[הו]|מ?יצירותי[הו]|מ?חיבורי[הו]|מאמרים נבחרים|פילמוגרפיה.*|(?:מבחר)? (?:כתבי)|דיסקוגרפיה|יצירות) *==/, //cheap hint for art occuption in text
artsTitle = /== *(?:מ?ספרי[הו]|מ?יצירותי[הו]|מ?חיבורי[הו]|מאמרים נבחרים|פילמוגרפיה.*|(?:מבחר)? (?:כתבי)|דיסקוגרפיה|יצירות) *==/, //cheap hint for art occuption in text
artsCategory = /\[\[קטגוריה:(מוזיקאיות|מוזיקאים|זמרות|זמרים|סופרים|סופרות|משוררים|משוררות|מתרגמים|ציירות|ציירים|במאי|רבנים|רבניות)(?!.+\*)/; //cheap hint for art occuption in category
artsCategory = /\[\[קטגוריה:(מוזיקאיות|מוזיקאים|זמרות|זמרים|סופרים|סופרות|משוררים|משוררות|מתרגמים|ציירות|ציירים|במאי|רבנים|רבניות)(?!.+\*)/; //cheap hint for art occuption in category
if ( acTemplate.exec( t ) ) return; // AC already exist
if ( acTemplate.exec( t ) ) return; // AC already exist
if ( !artsTitle.exec( t ) && !artsCategory.exec( t ) ) return; // no hint will have authority control
if ( !artsTitle.exec( t ) && !artsCategory.exec( t ) ) return; // no hint will have authority control
this.getWikidataApi().get({
this.getWikidataApi().get({
action: 'wbgetentities',
action: 'wbgetentities',
languages: 'he',
languages: 'he',
sites: mw.config.get('wgDBname'),
sites: mw.config.get('wgDBname'),
titles: mw.config.get('wgPageName'),
titles: mw.config.get('wgPageName'),
props: '\x1f' + ['claims', 'info'].join( '\x1f' )
props: '\x1f' + ['claims', 'info'].join( '\x1f' )
}).done(function(d){
}).done(function(d){
var hasAC = false,  
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' ],
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;
entityId, entity;
for (entityId in d.entities) { entity = d.entities[entityId]; };
for (entityId in d.entities) { entity = d.entities[entityId]; };
if (!entityId) return; // no entity
if (!entityId) return; // no entity


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


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


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

רעוויזיע פון 10:54, 30 נאוועמבער 2022

// הוספת כפתור "בדיקה" שמבצע החלפות נפוצות של בוט ההחלפות וכן מתריע על בעיות סגנון ועיצוב שונות
// נכתב על ידי [[משתמש:ערן]] ו[[משתמש:קיפודנחש]]
// לעזרה ראו [[mediawiki:Gadget-Checkty.js/הוראות]]
mw.messages.set({
	'checkty-large-element': 'בערך קיים אלמנט גדול, רצוי להקטין כדי שיתאים לרזולוציות נמוכות',
	'checkty-wikilink-in-extlink': 'בערך קיים קישור פנימי בתוך קישור חיצוני. רצוי לבטל את הקישור הפנימי או לצמצם את המסגרת של הקישור החיצוני',
	'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-missing-ref-section-add': 'נמצאו הערות שוליים בערך אך לא פרק מתאים. מומלץ להוסיף את הפרק לערך, וניתן להוסיף אותו אוטומטית במקום המשוער לכך.',
	'checkty-missing-ref-section-added': 'פרק הערות שוליים הוסף.',
	'checkty-missing-ref-section-autofix': 'הוספה אוטומטית',
	'checkty-please-position-caret' : 'אנא מקמו את הסמן במקום בו יש להוסיף ',
	'checkty-ref-dir-fix' : 'תיקון כיווניות להערת שוליים',
	'checkty-ref-merge' : 'מיזוג הערות שוליים',
	'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". ',
	'checkty-wrong-use-discussion': 'דף זה עשוי להיות דף דיונים. אין לערוך תגובות של עורכים אחרים והשימוש בבדיקה של דף כזה אינו מומלץ. האם ברצונך להפעיל את הכלי למרות זאת?',
	'checkty-vav-warning': 'כאשר ו עיצורית מופיעה באמצע מילה נהוג להכפילה. ייתכן שיש מופעים שדורשים תיקון.',
	'checkty-inuse-warning': 'הדף כולל תבנית בעבודה. אנא הימנעו מעריכה של ערך בעבודה כאשר משתמשים אחרים עובדים עליו במקביל. האם ברצונכם להפעיל בדיקה אוטומטית בכל זאת?'
});

function dotSpaceRegex() {
	try {
 // proper spacing around, and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
 return new RegExp('(?<!\\.[א-ת]*)([א-ת]\\]?\\]?"?) ?([,\\.]) ?(?=[א-ת]?\\[?\\[?[א-ת]{3})(?![א-ת]*\\.[א-ת])','g');
	} catch(e) {
 console.log('Checkty - browser doesnt support negative lookhead or lookbehind (ES2018)');
 //fallback to different regex with slightly less protections
 return /([א-ת]\]?\]?) ?([,\.]) ?(?=[א-ת]?\[?\[?[א-ת]{3})/g;
	}
}	

var chectTyTool = {
	origText: null,
	textbox: null,
	skipCheckty: false,
	isSection: mw.util.getParamValue('section'),
	skip_dict: {},
	named_comment: '{{' + 'הער' + 'ה|שם=',
	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: 'הסרת תווים בלתי נראים'
	}, { // trim spaces in end of line
 from: / +$/mg,
 to: ''
	}, { // remove accidental nowiki and simplify code
 from: /\[\[([^|\[\]]+)([^|\[\]]+?)\|\1\]\](?:<nowiki\/>)?\2/g,
 to: '[[$1$2]]',
 comment: 'פישוט קישור'
	}, { // trim beginning from redundant spaces
 from: /^\s+/g,
 to: '',
 comment: 'הסרת רווחים מיותרים'
	}, { // trim redundant spaces from category links
 from: /\[\[קטגוריה: */g,
 to: '[[קאטעגאריע:'
	}],
	formatReplacesConfig: [{ // piped link has identical text before and after the pipe
 from: /\[\[(.*?)\|\1([.,a-zא-ת]*)\]\]/g,
 to: '[[$1]]$2'
	}, { // piped link contains bold, underline or quotation mark in it
 from: /\[\[(.*?)\|('''?'?'?|")\1\2\]\]/g,
 to: '$2[[$1]]$2'
	}, { // piped link contains bold, underline or quotation mark at the beginning of it
 from: /('''?'?'?|")\[\[(.*?)\|\2\1\]\]/g,
 to: '$1[[$2]]$1'
	}, { // piped link contains bold, underline or quotation mark at the end of it
 from: /\[\[(.*?)\|('''?'?'?|")\1\]\]\2/g,
 to: '$2[[$1]]$2'
	}, { // piped link contains brackets in it
 from: /\[\[(.*?)\|(\(?)\1(\)?)\]\]/g,
 to: '$2[[$1]]$3'
	}, {
 from: /\[\[(.+?)\|([במל])\1([א-ת]*)\]\]/g,
 to: "$2[[$1]]$3"
	}, { // proper spacing around, and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
 from: dotSpaceRegex(),
 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: ']],'
	},
 { // code simlification: merge bold text coming near each other
 from: /'''([^']*) ([^']*)'''/g,
 to: '\'\'\'$1 $2\'\'\''
	},
	{ // section between two headings without content
 from: /\n==[^=\n]+?==\n*(\n==[^=\n]+?==\n)/g,
 to: '$1',
 comment: 'הסרת כותרות ריקות'
	}],
	regexes: [],
	ignoreRegexes: [],
	verifyRun: function () {
 var self = this, runExcute = true,
 inUseTemplatesRgx = /\{\{בעבודה[ \}\|]/;
 if (!this.textbox || this.textbox.value.length === 0) return;

 // this tool is not indented to be used in discussion pages
 if ( mw.config.get('wgNamespaceNumber') % 2 == 1 || ( mw.config.get('wgNamespaceNumber') != 0 && /\(IST\)/.exec(this.textbox.value ) )) {
 runExcute = false;
 OO.ui.confirm(mw.msg('checkty-wrong-use-discussion')).done( function( confirmed ) { if ( confirmed ) self.execute(); });
 }

 // this tool is not intended to be used while other people are working on the same page
 if( inUseTemplatesRgx.exec(this.textbox.value) ) {
 runExcute = false;
 OO.ui.confirm( mw.msg( 'checkty-inuse-warning' ) ).done( function( confirmed ) { if ( confirmed ) self.execute(); });
 }
 if (runExcute) this.execute();
	},
	run: function () {
 if (this != chectTyTool) {
 chectTyTool.run();
 return;
 }
 var t = $('#wpTextbox1');
 this.textbox = t.length ? t[0] : null;

 this.verifyRun();
	},
	execute: function() {
 // 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.vavCheck();
 this.expandWikidata();
 this.duplicatedCategory();
	},
	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);
 } );
 }
	},
	duplicatedCategory: function(execute) {
 var txt = this.textbox.value,
 newTxt = txt,
 categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g,
 cats = [], m = null, permutedCats = null;
 while(m=categoryRE.exec(txt)) {
 cats.push(m[1]);
 newTxt = newTxt.replace(m[0], '');
 }
 permutedCats = cats.filter(function(cat, i) {
 return cats.indexOf(cat) == i;
 });

 if (cats.length == permutedCats.length) return; // no duplicates

 newTxt = newTxt.trimEnd();
 newTxt += '\n' + permutedCats.join('\n');
 if (newTxt != txt)
 this.addSummary('הסרת קטגוריה כפולה');
 this.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?:\/\/[^ }|]+)\}\}|<ref(?: [^/>]*)?>(https?:\/\/[^ }|]+?)<\/ref>/g,
 nakeErrors=[], m, self= this;
 while (m = nakeRegex.exec(t)) {
 var nakedUrl = m[1] || m[2] || m[3],
 fixNakedLink = $( '<a href="#">' + mw.msg( 'checkty-naked-link-fix' )+'</a>' ).data( { 'search': nakedUrl, 'inRefTemplate': m[2], 'inRef': m[3] }).click( function ( e ) {
 var searchUrl = $(this).data( 'search' ),
 inRef = $(this).data('inRef'),
 inRefTemplate = $(this).data('inRefTemplate'),
 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 ( inRefTemplate ) {
 wikitext = wikitext.replace(new RegExp('\\{\\{הערה *\\| *(?:1 *= *)?'+mw.util.escapeRegExp(searchUrl)+'\\}\\}', 'g'), '{{הערה|' + template + '}}');
 } else if ( inRef ) {
 wikitext = wikitext.replace(new RegExp('(<ref[^>]*>)'+mw.util.escapeRegExp(searchUrl)+'(</ref>)', 'g'), '$1' + template + '$2');
 } 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 + ' {{כ}}(' + 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();
 if (!this.isSection) {
 this.refSection();
 }
	},
	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) || (redirects[p.title] && chectTyTool.getLinkRegex(redirects[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]+?\}\}\n){2,}/g.exec(txt)) {
 var articles = [], expArticleRE = /\{\{(?:הפניה לערך מורחב|ערך מורחב)\|([^=\n]+?)\}\}/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. Also syntaxhighlight
 match = txt.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])|<syntaxhighlight.*>[\s\S]*?<\/syntaxhighlight>/);
 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');
	},
	vavCheck: function () {
 var text = this.textbox.value,
 vavRegex = /[כלבמשה]\[\[ו[^ו][א-ת ]+\]\]/g, self = this;
 if (!vavRegex.exec( text )) return;
 var vavWarning = $('<div>').text( mw.msg( 'checkty-vav-warning' ) ).append(this.createSearchLink(vavRegex));
 // TODO: add semi-automatic fix option?
 chectTyTool.writeMsg(vavWarning);
 
	},
	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);
	},
	removeRefs: function (text) { // remove refs from text. use for internal checks only
 var cleanText = text;
 cleanText = cleanText.replace(/<ref(?: [^>]+?)?>.+?<\/ref>|\{\{הערה\|.*?\}\}/g, '');
 return cleanText;
	},
	languageCheck: function (checks) { //style and language check
 var txt = this.textbox.value;
 if (txt.length === 0) return; // nothing to do
 if (checks) {
 var textNoRefs = this.removeRefs(txt); // avoid language checks in refs. TODO: skip only quotes/book names/external links but not comments in footnotes
 var checkWarnings = $('<div></div>');
 for (var x in checks) {
 if (checks[x]['test'].test(textNoRefs)) {
 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/>');
 }
 }

 // Lint checker: wikilink-in-extlink. see [[mw:Help:Lint_errors/wikilink-in-extlink]]
 var wikilinkInExtLink = /[^\[]\[[^\[\]]+\[\[.+?\]\]/;
 if (wikilinkInExtLink.test(txt)) {
 checkWarnings.append(this.createSearchLink(wikilinkInExtLink));
 checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-wikilink-in-extlink' ));
 }

 // Design checks: Elements width
 var largeElement = /[6789][0-9][0-9]px/;
 if (largeElement.test(txt)) checkWarnings.append(mw.msg( 'checkty-large-element' ) + '<br/>');

 // Design checks: Long lists can have hint to use columns
 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;
 try {
 checks.push({
 'test': new RegExp( splittedWarn[0], 'i' ),
 'remark': splittedWarn[1]
 });
 }
 catch(e)
 {
 /* negative lookbehind and similar advanced regex
 will be skipped in browser which don't support it */
 console.log('Skippted automatic check ' + i );
 console.log(splittedWarn);
 }
 }
 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
 refsContent = {},// a dictionary where key is the ref name and value is the content
 refReEn = /<ref name="([^"]+?)">(.+?)<\/ref>/g,
 wikitext = this.textbox.value, mergedRefs = [], mergedRefsNames = [], m, k, i;
 while ( m = refReEn.exec( wikitext ) ){
 references[m[1]] = (references[m[1]] || 0) + 1;
 refsContent[m[1]] = { content: m[2], text: m[0] };
 }

 for (k in references) {
 if (references[k] > 1) {
 var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext),
 shortRef = chectTyTool.named_comment + 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);
 }
 }
 // merge referecnes with same content but different name
 for (k in refsContent) {
 if ($.inArray(k,mergedRefsNames) != -1) continue; // skip name already merged
 for (i in refsContent) {
 if (k === i) continue; // skip same name
 if (refsContent[k].content == refsContent[i].content) { // two refs with same content but different name
 var oldRefName = new RegExp('<ref name="'+mw.util.escapeRegExp(i)+'" */>', 'g');
 mergedRefsNames.push(i);
 shortRef = chectTyTool.named_comment + k + '}}';
 wikitext = wikitext.replace(refsContent[i].text, shortRef);
 wikitext = wikitext.replace(oldRefName, shortRef);
 }
 }
 }

 if (mergedRefs.length + mergedRefsNames.length) {
 if (mergedRefs.length) this.writeMsg( $('<div>').text('מיזוג הערות: ' + mergedRefs.join(', ')) );
 if (mergedRefsNames.length) this.writeMsg( $('<div>').text('מיזוג הערות עם שמות שונים: ' + mergedRefsNames.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
 refTemplateRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g,
 refTagRE = /<ref>(.+?)<\/ref>/g,
 wikitext = this.textbox.value, m;
 while ( m = refTemplateRE.exec( wikitext ) ){
 references[m[1]] = references[m[1]] || [];
 references[m[1]].push(m[0]);
 }
 while ( m = refTagRE.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], chectTyTool.named_comment+refName+'|'+refContet+'}}');
 for (var refI = 1; refI<refUses.length; refI++) {
 wikitext = wikitext.replace( refUses[refI], chectTyTool.named_comment+refName+'}}');
 this.addSummary( mw.msg( 'checkty-ref-merge' ) ); // addSummary will only add it once
 }
 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][^א-ת\u0600-\u06FF{|]+?)\}\}/ig,
 rtlRefRegex = /\{\{הערה\|(?!שם ?=)(?:1= *)?([א-ת\u0600-\u06FF][^a-z{|]+?|\[http:[^ ]+ [א-ת\u0600-\u06FF][^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');
 }
	},
	refSection: function(fix) {
 var wikitext = this.textbox.value, newText = wikitext, self = this,
 refRE = /<ref>|\{\{הערה\|/g,
 refSectionRE = /\{\{הערות[ _]שוליים|<references[ >]/g,
 hasRef = refRE.exec(wikitext) != null,
 hasRefSection = refSectionRE.exec(wikitext) != null;
 if (hasRefSection) return; //not missing
 if (!hasRef) return; // not needed
 if (fix) { // fix only when when explictly asked
 var autoRefSection = '\n== הערות שוליים ==\n{{הערות שוליים}}\n'
 var lastItems = [/(\n{{בקרת זהויות)/, /(\n{{קצרמר)/,/\n({{הבהרה (?:רפואית|הלכתית|משפטית))/,/(\n{{מיון רגיל:)/, /(\n\[\[קטגוריה:)/];
 for (var i=0; (i < lastItems.length) && (wikitext == newText); i++ ) newText = wikitext.replace(lastItems[i], autoRefSection + '$1');
 if ( wikitext === newText ) newText = wikitext + autoRefSection;
 this.textbox.value = newText;
 this.addSummary('פרק הערות שוליים');
 this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-added' )+'</div>'), 'info');

 } else {
 this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-add' )+'</div>').append($('<a href="#">'+mw.msg( 'checkty-missing-ref-section-autofix' )+'</a>').click(function(){ self.refSection(true); return false; })), 'info');
 }
	},
	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) ) {
 if (/(?:File|קובץ|תמונה|מדיה):.+/.test(m[1])) {
 continue; // skip files
 }
 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,
 batchSize = 50,
 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;
 if (needTranslateQ.length>batchSize) needTranslateQ = needTranslateQ.slice(0, batchSize); // limit to batch size

 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 = /([^|\n]*[א-ת]+'?[-\ ]*)((?:\[\[|\()?[0-9]+(?:\]\])?)-((?:\[\[)?[0-9]+)((?:\]\]|\))?[.:,]?(?:[ \|]|\n)(?!לפנה"ס))/g,
 wikitext = this.textbox.value, replacements = [], m, i;
 while(m = numberRangeReNoMinus.exec(wikitext))
 {
 if (/^קובץ:|בואינג [0-9]/.exec(m[1])) continue; // skip wrong suggestion
 // 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,
 acTemplate = '{{' + 'בקרת זהויות}}',
 newText;
 if ( viafTemplate.exec( t ) ) return; // viaf already exist
 newText = t.replace(/{{קצרמר/, acTemplate + '\n{{קצרמר'); // before stub
 if (newText == t) newText = t.replace(/{{מיון רגיל:/, acTemplate + '\n{{מיון רגיל:'); //before default sort
 if (newText == t) newText = t.replace(/\[\[קטגוריה:/, acTemplate + '\n[[קאטעגאריע:'); // before categories
 if (newText == t) newText = t + '\n' + acTemplate;
 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));
});