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

פון המכלול
קפיצה לניווט קפיצה לחיפוש
(בעסער דא?)
(rawLinks, שנעלע ארבעט דערווייל)
שורה 3: שורה 3:
// לעזרה ראו [[mediawiki:Gadget-Checkty.js/הוראות]]
// לעזרה ראו [[mediawiki:Gadget-Checkty.js/הוראות]]
mw.messages.set({
mw.messages.set({
'checkty-large-element': 'בערך קיים אלמנט גדול, רצוי להקטין כדי שיתאים לרזולוציות נמוכות',
    'checkty-large-element': 'בערך קיים אלמנט גדול, רצוי להקטין כדי שיתאים לרזולוציות נמוכות',
'checkty-wikilink-in-extlink': 'בערך קיים קישור פנימי בתוך קישור חיצוני. רצוי לבטל את הקישור הפנימי או לצמצם את המסגרת של הקישור החיצוני',
    'checkty-wikilink-in-extlink': 'בערך קיים קישור פנימי בתוך קישור חיצוני. רצוי לבטל את הקישור הפנימי או לצמצם את המסגרת של הקישור החיצוני',
'checkty-long-list': 'רשימה ארוכה - נראה כי בערך רשימה של מעל 20 פריטים. כדאי לשקול לפצלה לשני טורים באמצעות <a href="' + (new mw.Title('מוסטער:טורים')).getUrl() + '">מוסטער:טורים</a>',
    'checkty-long-list': 'רשימה ארוכה - נראה כי בערך רשימה של מעל 20 פריטים. כדאי לשקול לפצלה לשני טורים באמצעות <a href="' + (new mw.Title('מוסטער:טורים')).getUrl() + '">מוסטער:טורים</a>',
'checkty-long-gallery': 'גלריה ארוכה - הערך מכיל גלריה ארוכה. מומלץ לשקול צמצום שלה או העברה לוויקישיתוף.',
    'checkty-long-gallery': 'גלריה ארוכה - הערך מכיל גלריה ארוכה. מומלץ לשקול צמצום שלה או העברה לוויקישיתוף.',
'checkty-waiting-disambig-query': 'ממתין לרשימת פירושונים מהשרת...',
    'checkty-waiting-disambig-query': 'ממתין לרשימת פירושונים מהשרת...',
'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': 'לינקס צו באדייטן - נישט געטראפן',
'checkty-disambig-success': 'לינקס צו באדייטן - די בדיקה איז סוקסעספול פארענדיגט.',
    'checkty-disambig-success': 'לינקס צו באדייטן - די בדיקה איז סוקסעספול פארענדיגט.',
'checkty-disambig-links-title': 'די לעצטע אפגעהיטענע ווערסיע פארבינדט צו באדייטן בלעטער. ביטע פאררעכט די לינקס צו די בלעטער: ',
    'checkty-disambig-links-title': 'די לעצטע אפגעהיטענע ווערסיע פארבינדט צו באדייטן בלעטער. ביטע פאררעכט די לינקס צו די בלעטער: ',
'checkty-page-doesnt-exist': ' (דער בלאט עקזיסטירט נישט)',
    'checkty-page-doesnt-exist': ' (דער בלאט עקזיסטירט נישט)',
'checkty-dismabig-dialog-title': 'באדייטן פאררעכטונג',
    'checkty-dismabig-dialog-title': 'באדייטן פאררעכטונג',
'checkty-remove-link': 'הסרת קישור',
    'checkty-remove-link': 'הסרת קישור',
'checkty-disambig-meaning': 'מה הכוונה ב "$1" במשפט: ',
    'checkty-disambig-meaning': 'מה הכוונה ב "$1" במשפט: ',
'checkty-dismabig-fix-summary': 'תיקון קישור לפירושונים',
    'checkty-dismabig-fix-summary': 'תיקון קישור לפירושונים',
'checkty-search': 'חיפוש',
    'checkty-search': 'חיפוש',
'checkty-fix-numberRangeDash': 'תיקון קווים מפרידים',
    'checkty-fix-numberRangeDash': 'תיקון קווים מפרידים',
'checkty-missing-commons-link': 'בערך זה חסר קישור לוויקישיתוף. ניתן להוסיף קישור באמצעות בחירת המקום הנכון להוספתו בערך ולחיצה על הקישור הבא. ',
    'checkty-missing-commons-link': 'בערך זה חסר קישור לוויקישיתוף. ניתן להוסיף קישור באמצעות בחירת המקום הנכון להוספתו בערך ולחיצה על הקישור הבא. ',
'checkty-fairuse-img-replace-template': 'תמונה להחלפה',
    'checkty-fairuse-img-replace-template': 'תמונה להחלפה',
'checkty-set-label': 'הזנת תווית עברית ל-$1',
    'checkty-set-label': 'הזנת תווית עברית ל-$1',
'checkty-translate-saved': 'התרגום נשמר!',
    'checkty-translate-saved': 'התרגום נשמר!',
// 'checkty-empty-parameters': 'פרמטרים ריקים - דף זה מכיל תבניות עם פרמטרים ריקים. אם הם אינם רלוונטיים ניתן להסירם. ',
    // 'checkty-empty-parameters': 'פרמטרים ריקים - דף זה מכיל תבניות עם פרמטרים ריקים. אם הם אינם רלוונטיים ניתן להסירם. ',
// 'checkty-empty-parameters-summary': 'ניקוי קוד',
    // 'checkty-empty-parameters-summary': 'ניקוי קוד',
'checkty-main-articles-merge-summary': 'מיזוג הפניות לערכים מורחבים',
    'checkty-main-articles-merge-summary': 'מיזוג הפניות לערכים מורחבים',
'checkty-missing-ref-section-add': 'געפינען רעפערענצן אין ארטיקל אבער נישט א פאסיגן אפטיילונג. עס איז רעקאמענדירט צו צולייגן דעם אפטיילונג צום ארטיקל, וניתן להוסיף אותו אוטומטית במקום המשוער לכך.',
    'checkty-missing-ref-section-add': 'געפינען רעפערענצן אין ארטיקל אבער נישט א פאסיגן אפטיילונג. עס איז רעקאמענדירט צו צולייגן דעם אפטיילונג צום ארטיקל, וניתן להוסיף אותו אוטומטית במקום המשוער לכך.',
'checkty-missing-ref-section-added': 'רעפערענצן אפטיילונג צוגעלייגט.',
    'checkty-missing-ref-section-added': 'רעפערענצן אפטיילונג צוגעלייגט.',
'checkty-missing-ref-section-autofix': 'צולייגן אויטאמאטיש',
    'checkty-missing-ref-section-autofix': 'צולייגן אויטאמאטיש',
'checkty-please-position-caret' : 'אנא מקמו את הסמן במקום בו יש להוסיף ',
    'checkty-please-position-caret': 'אנא מקמו את הסמן במקום בו יש להוסיף ',
'checkty-ref-dir-fix' : 'תיקון כיווניות להערת שוליים',
    'checkty-ref-dir-fix': 'תיקון כיווניות להערת שוליים',
'checkty-ref-merge' : 'צונויפגיסן רעפערענצן',
    'checkty-ref-merge': 'צונויפגיסן רעפערענצן',
'checkty-naked-link-found' : 'געטראפן נאקעטע דרויסנדע לינק: $1',
    'checkty-naked-link-found': 'געטראפן נאקעטע דרויסנדע לינק: $1',
'checkty-naked-link-fix' : 'פארריכטן',
    'checkty-naked-link-fix': 'פארריכטן',
'checkty-broken-link': 'חשש פון א צעבראכן לינק: ',
    'checkty-broken-link': 'חשש פון א צעבראכן לינק: ',
'checkty-naked-link-fix-fail': 'פעלער אין פארריכטן נאַקעט לינק',
    'checkty-naked-link-fix-fail': 'פעלער אין פארריכטן נאַקעט לינק',
'checkty-naked-link-fixed': 'הקישור $1 הוחלף במוסטער. יש לבדוק את תקינות התוצאה והאם יש לעטוף במוסטער הערה<br> $2',
    'checkty-naked-link-fixed': 'הקישור $1 הוחלף במוסטער. יש לבדוק את תקינות התוצאה והאם יש לעטוף במוסטער הערה<br> $2',
'checkty-external-links-many': 'קישורים חיצוניים - פרק הקישורים החיצוניים מכיל $1 קישורים. מומלץ להעביר קישורים העוסקים בנושאים ספציפיים לרעפערענצן, ולהסיר קישורים שלא מוסיפים. (ראו עוד ב<a href="' + mw.util.getUrl('המכלול:קישורים חיצוניים') + '">המכלול:קישורים חיצוניים</a>)',
    'checkty-external-links-many': 'קישורים חיצוניים - פרק הקישורים החיצוניים מכיל $1 קישורים. מומלץ להעביר קישורים העוסקים בנושאים ספציפיים לרעפערענצן, ולהסיר קישורים שלא מוסיפים. (ראו עוד ב<a href="' + mw.util.getUrl('המכלול:קישורים חיצוניים') + '">המכלול:קישורים חיצוניים</a>)',
'checkty-external-links-diversity': 'קישורים חיצוניים - פרק הקישורים החיצוניים מכיל מספר קישורים למקורות זהים: $1. כאשר הקישור עוסק באספקט צר של הערך מומלץ להפכו להערת שוליים. (ראו עוד ב<a href="' + mw.util.getUrl('המכלול:קישורים חיצוניים') + '">המכלול:קישורים חיצוניים</a>)',
    'checkty-external-links-diversity': 'קישורים חיצוניים - פרק הקישורים החיצוניים מכיל מספר קישורים למקורות זהים: $1. כאשר הקישור עוסק באספקט צר של הערך מומלץ להפכו להערת שוליים. (ראו עוד ב<a href="' + mw.util.getUrl('המכלול:קישורים חיצוניים') + '">המכלול:קישורים חיצוניים</a>)',
'checkty-nonsense-edit': 'עריכה זו כוללת שינויים אוטומטיים בלבד. האם ברצונך לשמור למרות זאת?',
    'checkty-nonsense-edit': 'עריכה זו כוללת שינויים אוטומטיים בלבד. האם ברצונך לשמור למרות זאת?',
'checkty-category-sort': 'ניתן למיין את הקטגוריות בדף על פי סדר אלפביתי ',
    'checkty-category-sort': 'ניתן למיין את הקטגוריות בדף על פי סדר אלפביתי ',
'checkty-defaultsort-suggest': 'דער ארטיקל האט נישט אנגעשטעלט דיפאלט סארטיר. ארטיקלען וואס באהאנדלען מענטשן סארטירט מען לויט פאמיליע נאמען. ',
    'checkty-defaultsort-suggest': 'דער ארטיקל האט נישט אנגעשטעלט דיפאלט סארטיר. ארטיקלען וואס באהאנדלען מענטשן סארטירט מען לויט פאמיליע נאמען. ',
'checkty-language-check': 'אין דעם ארטיקל געפינט זיך דער אויסדרוק "$1". ',
    'checkty-language-check': 'אין דעם ארטיקל געפינט זיך דער אויסדרוק "$1". ',
'checkty-wrong-use-discussion': 'דף זה עשוי להיות דף דיונים. אין לערוך תגובות של עורכים אחרים והשימוש בבדיקה של דף כזה אינו מומלץ. האם ברצונך להפעיל את הכלי למרות זאת?',
    'checkty-wrong-use-discussion': 'דף זה עשוי להיות דף דיונים. אין לערוך תגובות של עורכים אחרים והשימוש בבדיקה של דף כזה אינו מומלץ. האם ברצונך להפעיל את הכלי למרות זאת?',
'checkty-vav-warning': 'כאשר ו עיצורית מופיעה באמצע מילה נהוג להכפילה. ייתכן שיש מופעים שדורשים תיקון.',
    'checkty-vav-warning': 'כאשר ו עיצורית מופיעה באמצע מילה נהוג להכפילה. ייתכן שיש מופעים שדורשים תיקון.',
'checkty-inuse-warning': 'הדף כולל מוסטער בעבודה. אנא הימנעו מעריכה של ערך בעבודה כאשר משתמשים אחרים עובדים עליו במקביל. האם ברצונכם להפעיל בדיקה אוטומטית בכל זאת?'
    'checkty-inuse-warning': 'הדף כולל מוסטער בעבודה. אנא הימנעו מעריכה של ערך בעבודה כאשר משתמשים אחרים עובדים עליו במקביל. האם ברצונכם להפעיל בדיקה אוטומטית בכל זאת?'
});
});


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;
}
    }
}
}


var chectTyTool = {
var chectTyTool = {
origText: null,
    origText: null,
textbox: null,
    textbox: null,
skipCheckty: false,
    skipCheckty: false,
isSection: mw.util.getParamValue('section'),
    isSection: mw.util.getParamValue('section'),
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: 'פישוט קישור'
}, { // simplify common links prefix
        }, { // simplify common links prefix
from: / \[\[([^|\]]+)\|([בהו])\1\]\]/g,
            from: / \[\[([^|\]]+)\|([בהו])\1\]\]/g,
to: ' $2[[$1]]',
            to: ' $2[[$1]]',
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.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.formatChecks();
this.mainArticlesMerge();
        this.linkChecks();
this.numberRangeDash(false);
        if (!this.isSection) {
},
            this.articleOrgChecks();
decodeExternalLinks: function() {
            this.checkImages();
var t = this.textbox.value, newTxt = t,
        }
externalLinkRgx = /http[^ \]|]+/g,
        this.languageCheck();
decodeRgx = /(?:%[0-9a-z]{2}){2,}/ig,
        this.vavCheck();
m, mm, newLink;
        this.expandWikidata();
while ( m = externalLinkRgx.exec(t) ) {
        this.duplicatedCategory();
newLink = m[0];
    },
while (mm = decodeRgx.exec(m[0])) {
    formatChecks: function () {
try {
        if (!this.isSection)
// decode URL except special chars
            this.build_regexes();
var niceLink = decodeURI(mm[0]).replace(/[ |"\n\[\]{}<>]/g, encodeURI);
        this.formatReplace();
if (niceLink == niceLink.normalize()) newLink = newLink.replace(mm[0], niceLink);
        this.decodeExternalLinks();
} 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 (/\{\{(מיון רגיל|גרונטסארטיר|DEFAULTSORT):/.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
        // format - semi manual
if (!isPerson) return; // skip for non biographic pages
        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 (/\{\{(מיון רגיל|גרונטסארטיר|DEFAULTSORT):/.exec(txt)) return; // skip if already exists
        if (!firstFamilyRgx.exec(mw.config.get('wgTitle'))) return; // skip if can't suggest


if (!execute) {
        isPerson = /== ?(ביאגראפיע|לעבנס געשיכטע|לעבן|תולדות) ?==/.exec(txt); // heuristic to identify biographic articles
defaultSortMsg = $('<div>', { text: mw.msg('checkty-defaultsort-suggest') }).append($('<a>', {
        if (!isPerson) return; // skip for non biographic pages
href: '#',
text: 'צולייגן DEFAULTSORT',
}).click(function(){ chectTyTool.defaultSortSuggest(true); return false;}));
this.writeMsg(defaultSortMsg, 'info');
} else {
name = firstFamilyRgx.exec(mw.config.get('wgTitle'));
txt = txt.replace(/\[\[(קאַטעגאָריע|קאטעגאריע)/, '{{DEFAULTSORT:' + name[2] + ', ' + name[1] + '}}\n[[קאַטעגאָריע');
this.addSummary('DEFAULTSORT');
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
        if (!execute) {
            defaultSortMsg = $('<div>', { text: mw.msg('checkty-defaultsort-suggest') }).append($('<a>', {
                href: '#',
                text: 'צולייגן DEFAULTSORT',
            }).click(function () { chectTyTool.defaultSortSuggest(true); return false; }));
            this.writeMsg(defaultSortMsg, 'info');
        } else {
            name = firstFamilyRgx.exec(mw.config.get('wgTitle'));
            txt = txt.replace(/\[\[(קאַטעגאָריע|קאטעגאריע)/, '{{DEFAULTSORT:' + name[2] + ', ' + name[1] + '}}\n[[קאַטעגאָריע');
            this.addSummary('DEFAULTSORT');
            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;
        });


newTxt = newTxt.trimEnd();
        if (cats.length == permutedCats.length) return; // no duplicates
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( {
        newTxt = newTxt.trimEnd();
action: 'templatedata',
        newTxt += '\n' + permutedCats.join('\n');
titles: 'Template:' + CiteTemplates[ d[0].itemType ]
        if (newTxt != txt)
}).done(function(tdq){
            this.addSummary('אראפגענומען דאפלטע קאטעגאריע');
for(var pid in tdq.pages){
        this.updateText(newTxt);
var td = tdq.pages[pid],
    },
params = [];
    linkChecks: function () {
for(var k in d[0]) {
        if (mw.config.get('wgNamespaceNumber') in [0, 3000, 8000]) {
if (td.maps['citoid'][k]) {
            this.rawLinks();
if ($.isArray(td.maps['citoid'][k]) && $.isArray(d[0][k])) {
        }
for(var i = 0;i < d[0][k].length; i++) {
        this.overlinkify();
if ($.isArray(d[0][k][i]) && $.isArray(td.maps['citoid'][k][i])) {
        this.nakedLinks();
for(var j = 0;j < d[0][k][i].length; j++) {
        this.checkExternalLinks();
params.push(td.maps['citoid'][k][i][j] + '=' + d[0][k][i][j].replace(/\|/g, '{{!}}'));
        this.disambigCheck();
}
    },
}
    expandWikidata: function () {
}
        this.wikidataLabelsMissing();
}
        this.extractWikidataLabelsSuggestions();
else {
        if (!this.isSection) {
if ($.isArray(d[0][k])) {
            this.addAuthorityControl();
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(', ');
    },
}
    createSearchLink: function (v) {
params.push(td.maps['citoid'][k] + '=' + d[0][k].replace(/\|/g, '{{!}}'));
        var highlightStr = this.highlightString,
}
            searchLink = $('<a href="#">' + mw.msg('checkty-search') + '</a>').data({ 'search': v }).click(function (e) {
}
                highlightStr($(this).data('search')); e.preventDefault();
}
            });
var template = '{{'+CiteTemplates[d[0].itemType]+'|' + params.join('|')+'}}',
        return searchLink;
wikitext = self.textbox.value;
    },
if ( inRefTemplate ) {
    onSaveProtection: function () {
wikitext = wikitext.replace(new RegExp('\\{\\{הערה *\\| *(?:1 *= *)?'+mw.util.escapeRegExp(searchUrl)+'\\}\\}', 'g'), '{{הערה|' + template + '}}');
        $('#wpSave').click(function (e) {
} else if ( inRef ) {
            if (chectTyTool.textbox.value === chectTyTool.origText) {
wikitext = wikitext.replace(new RegExp('(<ref[^>]*>)'+mw.util.escapeRegExp(searchUrl)+'(</ref>)', 'g'), '$1' + template + '$2');
                OO.ui.confirm(mw.msg('checkty-nonsense-edit')).done(function (confirmed) {
} else {
                    if (confirmed) {
// this is more context sensitive - sometimes we may or may not want to wrap with ref
                        chectTyTool.origText = '';
wikitext = wikitext.replace(new RegExp('\\['+mw.util.escapeRegExp(searchUrl)+'\\]', 'g'), template);
                        $('#editform').submit();
}
                    } else {
self.textbox.value = wikitext;
                        e.preventDefault();
self.writeMsg($('<div>').append(mw.msg('checkty-naked-link-fixed', searchUrl, template)).append(self.createSearchLink(template)));
                    }
chectTyTool.addSummary('הלבשת קישורים עירומים');
                });
}
                e.preventDefault();
})
            }
});
        });
}).fail(function(){
    },
self.writeMsg($('<div>').append(mw.msg('checkty-broken-link') + searchUrl));
    updateText: function (val) {
});
        if (this.textbox.value === chectTyTool.origText) {
e.preventDefault();
            chectTyTool.origText = val;
});
        }
this.writeMsg($('<div>').append([mw.msg('checkty-naked-link-found', nakedUrl)+'" [',fixNakedLink, '&nbsp;-&nbsp;', this.createSearchLink(m[0]), ']']), 'alert');
        this.textbox.value = val;
}
    },
},
    nakedLinks: function () {
checkExternalLinks: function() {
        var t = this.textbox.value,
var t = this.textbox.value,
            nakeRegex = /\[(http[^ ]+?)\]|\{\{הערה *\| *(?:1 *= *)?(https?:\/\/[^ }|]+)\}\}|<ref(?: [^/>]*)?>(https?:\/\/[^ }|]+?)<\/ref>/g,
externalLinksRgx = /== *קישורים חיצוניים *==(?:\n\{\{.+)*((?:\n\*.+|\n\{\{.+\}\})+)/mg,
            nakeErrors = [], m, self = this;
tplCounterRgx = /\n\* *\{\{([^|]+)/g,
        while (m = nakeRegex.exec(t)) {
externalLinks = externalLinksRgx.exec(t), tplCounter={}, sameSources=[], m;
            var nakedUrl = m[1] || m[2] || m[3],
if (!externalLinks) return;
                fixNakedLink = $('<a href="#">' + mw.msg('checkty-naked-link-fix') + '</a>').data({ 'search': nakedUrl, 'inRefTemplate': m[2], 'inRef': m[3] }).click(function (e) {
externalLinks = externalLinks[1];
                    var searchUrl = $(this).data('search'),
if (externalLinks.split('\n').length > 8) {
                        inRef = $(this).data('inRef'),
this.writeMsg('<div>' + mw.msg('checkty-external-links-many', externalLinks.split('\n').length) + '</div>', 'alert');
                        inRefTemplate = $(this).data('inRefTemplate'),
}
                        citoidTemplatesPromise = new mw.Api().loadMessagesIfMissing(['citoid-template-type-map.json']);
else {
                    // Common case: pasting a URI into this field. Citoid expects
while(m = tplCounterRgx.exec(externalLinks)) tplCounter[m[1]] = (tplCounter[m[1]]? tplCounter[m[1]]+1 : 1);
                    // minimally encoded input, so do some speculative decoding here to
delete tplCounter['קישור כללי'];
                    // avoid 404 fetches. T146539
for(m in tplCounter) {
                    searchUrl = decodeURIComponent(searchUrl);
if (tplCounter[m] > 1) sameSources.push(m + ' {{כ}}(' + tplCounter[m] + ')');
                    citoidPromise = $.ajax('/api/rest_v1/data/citation/mediawiki/' + encodeURIComponent(searchUrl), {
}
                        headers: { 'accept-language': mw.config.get('wgContentLanguage') },
if (sameSources.length) {
                        timeout: 20 * 1000, // 20 seconds
this.writeMsg('<div>' + mw.msg('checkty-external-links-diversity', sameSources.join(', ')) + '</div>', 'alert');
                        type: 'GET'
}
                    });
}
                    citoidPromise.done(function (d) {
},
                        citoidTemplatesPromise.done(function () {
checkRefs: function() {
                            var CiteTemplates = JSON.parse(mw.message('citoid-template-type-map.json').plain());
this.refsConsistencyCheck();
                            if (d.length === 0 || !CiteTemplates[d[0].itemType]) {
this.ibidWarning();
                                self.writeMsg(mw.msg('checkty-naked-link-fix-fail'));
this.mergeRefs();
                                return;
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, '')));
console.log(this.regexes[i][1]);
console.log(actual_replaced[i]);
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.replace('[[', ''));
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(', ')));
                            var api = new mw.Api().get({
},
                                action: 'templatedata',
fetchDisambigLinks: function (next) {
                                titles: 'Template:' + CiteTemplates[d[0].itemType]
var dfd = new jQuery.Deferred();
                            }).done(function (tdq) {
var api = new mw.Api();
                                for (var pid in tdq.pages) {
var params = {
                                    var td = tdq.pages[pid],
action: 'query',
                                        params = [];
generator: 'links',
                                    for (var k in d[0]) {
titles: mw.config.get('wgPageName'),
                                        if (td.maps['citoid'][k]) {
prop: 'pageprops',
                                            if ($.isArray(td.maps['citoid'][k]) && $.isArray(d[0][k])) {
ppprop: 'disambiguation',
                                                for (var i = 0; i < d[0][k].length; i++) {
gpllimit: '500',
                                                    if ($.isArray(d[0][k][i]) && $.isArray(td.maps['citoid'][k][i])) {
redirects: 1
                                                        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, '{{!}}'));
if (next !== undefined) {
                                                        }
params.gplcontinue = next;
                                                    }
}
                                                }
api.get(params).done(function (data) {
                                            }
//extract disambig pages
                                            else {
if (!data.hasOwnProperty('query')) {
                                                if ($.isArray(d[0][k])) {
dfd.reject();
                                                    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(' ');
return;
                                                    d[0][k] = d[0][k].join(', ');
}
                                                }
var redirects = {};
                                                params.push(td.maps['citoid'][k] + '=' + d[0][k].replace(/\|/g, '{{!}}'));
if (data.query.redirects) {
                                            }
$.each(data.query.redirects, function(i,r) { redirects[r.to] = r.from; });
                                        }
}
                                    }
var disambigs = [];
                                    var template = '{{' + CiteTemplates[d[0].itemType] + '|' + params.join('|') + '}}',
for (var pid in data.query.pages) {
                                        wikitext = self.textbox.value;
var p = data.query.pages[pid],
                                    if (inRefTemplate) {
isDisambigPage = p.pageprops && p.title != mw.config.get('wgTitle') + mw.msg( 'checkty-disambig-suffix' );
                                        wikitext = wikitext.replace(new RegExp('\\{\\{הערה *\\| *(?:1 *= *)?' + mw.util.escapeRegExp(searchUrl) + '\\}\\}', 'g'), '{{הערה|' + template + '}}');
//list only real disambig links
                                    } else if (inRef) {
if (isDisambigPage && (chectTyTool.getLinkRegex(p.title).exec(chectTyTool.textbox.value) || (redirects[p.title] && chectTyTool.getLinkRegex(redirects[p.title]).exec(chectTyTool.textbox.value)))) {
                                        wikitext = wikitext.replace(new RegExp('(<ref[^>]*>)' + mw.util.escapeRegExp(searchUrl) + '(</ref>)', 'g'), '$1' + template + '$2');
disambigs.push(redirects[p.title] || p.title);
                                    } 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);
if (data['query-continue'] !== undefined) {
                                    }
var nextReq = chectTyTool.fetchDisambigLinks(data['query-continue'].links.gplcontinue);
                                    self.textbox.value = wikitext;
nextReq.done(function (more) {
                                    self.writeMsg($('<div>').append(mw.msg('checkty-naked-link-fixed', searchUrl, template)).append(self.createSearchLink(template)));
dfd.resolve($.merge(disambigs, more));
                                    chectTyTool.addSummary('הלבשת קישורים עירומים');
});
                                }
} else {
                            })
dfd.resolve(disambigs);
                        });
}
                    }).fail(function () {
});
                        self.writeMsg($('<div>').append(mw.msg('checkty-broken-link') + searchUrl));
return dfd.promise();
                    });
},
                    e.preventDefault();
mainArticlesMerge: function() {
                });
var origTxt = this.textbox.value, txt = this.textbox.value, m;
            this.writeMsg($('<div>').append([mw.msg('checkty-naked-link-found', nakedUrl) + '" [', fixNakedLink, '&nbsp;-&nbsp;', this.createSearchLink(m[0]), ']']), 'alert');
        }
while (m = /(\{\{(?:הפניה לערך מורחב|ערך מורחב)\|[^=\n]+?\}\}\n){2,}/g.exec(txt)) {
    },
var articles = [], expArticleRE = /\{\{(?:הפניה לערך מורחב|ערך מורחב)\|([^=\n]+?)\}\}/g;
    checkExternalLinks: function () {
while (ma = expArticleRE.exec(m[0])) articles.push(ma[1]);
        var t = this.textbox.value,
txt = txt.replace(m[0], '{{הפניה לערך מורחב|ערכים=[['+articles.join(']], [[')+']]}}\n');
            externalLinksRgx = /== *קישורים חיצוניים *==(?:\n\{\{.+)*((?:\n\*.+|\n\{\{.+\}\})+)/mg,
}
            tplCounterRgx = /\n\* *\{\{([^|]+)/g,
this.textbox.value = txt;
            externalLinks = externalLinksRgx.exec(t), tplCounter = {}, sameSources = [], m;
if (origTxt != txt) chectTyTool.addSummary( mw.msg( 'checkty-main-articles-merge-summary' ) );
        if (!externalLinks) return;
},
        externalLinks = externalLinks[1];
formatReplace: function () {
        if (externalLinks.split('\n').length > 8) {
var txt = this.textbox.value, newTxt;
            this.writeMsg('<div>' + mw.msg('checkty-external-links-many', externalLinks.split('\n').length) + '</div>', 'alert');
// Format autofix
        }
var specials=[], match;
        else {
// var emptyParametersRgx = /\n *\| *[^|=]+?= *(?=\n(?: *\||\}\}))/mg, emptyParametersMsg, emptyParametersBtn;
            while (m = tplCounterRgx.exec(externalLinks)) tplCounter[m[1]] = (tplCounter[m[1]] ? tplCounter[m[1]] + 1 : 1);
$(this.formatReplacesConfigSafe).each(function (i, o) {
            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, '')));
                console.log(this.regexes[i][1]);
                console.log(actual_replaced[i]);
                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.replace('[[', ''));
                            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');


newTxt = txt.replace(o.from, o.to);
        if (actual_replaced.length) chectTyTool.addSummary(mw.msg('checkty-replace-summary', actual_replaced.join(', ')));
if ( newTxt!=txt && o.comment) {
    },
chectTyTool.addSummary( o.comment );
    fetchDisambigLinks: function (next) {
}
        var dfd = new jQuery.Deferred();
txt = newTxt;
        var api = new mw.Api();
});
        var params = {
            action: 'query',
//extract inner links, inner templates and inner params - we don't want to sptit those.
            generator: 'links',
while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those. Also syntaxhighlight
            titles: mw.config.get('wgPageName'),
match = txt.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])|<syntaxhighlight.*>[\s\S]*?<\/syntaxhighlight>/);
            prop: 'pageprops',
if (!match || !match.length) break;
            ppprop: 'disambiguation',
specials.push(match[0]);
            gpllimit: '500',
txt = txt.replace(match[0], "\0" + specials.length + "\0");
            redirects: 1
}
        };
        if (next !== undefined) {
$(this.formatReplacesConfig).each(function (i, o) {
            params.gplcontinue = next;
newTxt = txt.replace(o.from, o.to);
        }
if (o.skippable && (chectTyTool.skipCheckty || this.isSection)) return; // skip this one respecting {ללא בוט}
        api.get(params).done(function (data) {
if ( newTxt!=txt && o.comment) {
            //extract disambig pages
chectTyTool.addSummary( o.comment );
            if (!data.hasOwnProperty('query')) {
}
                dfd.reject();
txt = newTxt;
                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 (true) {
        while (m = /(\{\{(?:הפניה לערך מורחב|ערך מורחב)\|[^=\n]+?\}\}\n){2,}/g.exec(txt)) {
match = txt.match(/\0(\d+)\0/);
            var articles = [], expArticleRE = /\{\{(?:הפניה לערך מורחב|ערך מורחב)\|([^=\n]+?)\}\}/g;
if (!match || !match.length) break;
            while (ma = expArticleRE.exec(m[0])) articles.push(ma[1]);
txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]);
            txt = txt.replace(m[0], '{{הפניה לערך מורחב|ערכים=[[' + articles.join(']], [[') + ']]}}\n');
}
        }
this.updateText(txt);
        this.textbox.value = txt;
// if (!emptyParametersRgx.test(txt)) return;
        if (origTxt != txt) chectTyTool.addSummary(mw.msg('checkty-main-articles-merge-summary'));
// emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', {
    },
// href: '#',
    formatReplace: function () {
// text: 'ניקוי'
        var txt = this.textbox.value, newTxt;
// }).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; }));
        // Format autofix
// this.writeMsg(emptyParametersMsg, 'info');
        var specials = [], match;
},
        // var emptyParametersRgx = /\n *\| *[^|=]+?= *(?=\n(?: *\||\}\}))/mg, emptyParametersMsg, emptyParametersBtn;
vavCheck: function () {
        $(this.formatReplacesConfigSafe).each(function (i, o) {
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: 'yi',
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)) && !(/\| ?תמונה *= *.+jpg/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=yi&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]]
            newTxt = txt.replace(o.from, o.to);
var wikilinkInExtLink = /[^\[]\[[^\[\]]+\[\[.+?\]\]/;
            if (newTxt != txt && o.comment) {
if (wikilinkInExtLink.test(txt)) {
                chectTyTool.addSummary(o.comment);
checkWarnings.append(this.createSearchLink(wikilinkInExtLink));
            }
checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-wikilink-in-extlink' ));
            txt = newTxt;
}
        });


// Design checks: Elements width
        //extract inner links, inner templates and inner params - we don't want to sptit those.
var largeElement = /[6789][0-9][0-9]px/;
        while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those. Also syntaxhighlight
if (largeElement.test(txt)) checkWarnings.append(mw.msg( 'checkty-large-element' ) + '<br/>');
            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");
        }


// Design checks: Long lists can have hint to use columns
        $(this.formatReplacesConfig).each(function (i, o) {
var manyLi = new RegExp('(?:\n\\*.*){20}');
            newTxt = txt.replace(o.from, o.to);
if (manyLi.test(txt)) {
            if (o.skippable && (chectTyTool.skipCheckty || this.isSection)) return; // skip this one respecting {ללא בוט}
checkWarnings.append(this.createSearchLink(manyLi));
            if (newTxt != txt && o.comment) {
checkWarnings.append('&nbsp;-&nbsp;' + mw.msg( 'checkty-long-list' ));
                chectTyTool.addSummary(o.comment);
}
            }
if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
            txt = newTxt;
} 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');
});


}
        while (true) {
},
            match = txt.match(/\0(\d+)\0/);
refsConsistencyCheck: function () {
            if (!match || !match.length) break;
function safeRegexFix(fixRegex, fixReplace, check){
            txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]);
var txt = $('#wpTextbox1').val(),
        }
m;
        this.updateText(txt);
//remove templates within templates
        // if (!emptyParametersRgx.test(txt)) return;
var specials = [];
        // emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', {
while (m = /\{\{(?!הערה\|)[^\{]*?\}\}/g.exec(txt)) {
        // href: '#',
txt = txt.replace(m[0], '\0' + specials.length + '\0')
        // text: 'ניקוי'
specials.push(m[0])
        // }).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; }));
}
        // this.writeMsg(emptyParametersMsg, 'info');
if (check) {
    },
var counterA = 0, counterB = 0;
    vavCheck: function () {
while (fixRegex.exec(txt)) counterA++;
        var text = this.textbox.value,
while (fixReplace.exec(txt)) counterB++;
            vavRegex = /[כלבמשה]\[\[^ו][א-ת ]+\]\]/g, self = this;
return [counterA, counterB];
        if (!vavRegex.exec(text)) return;
} else {
        var vavWarning = $('<div>').text(mw.msg('checkty-vav-warning')).append(this.createSearchLink(vavRegex));
txt = txt.replace(/(\{\{הערה\|.*?\}\}|<ref>.*?<\/ref>)\s+(?=(\{\{הערה\||<ref>))/g, '$1'); // remove spaces between refs
        // TODO: add semi-automatic fix option?
txt = txt.replace(fixRegex, fixReplace);
        chectTyTool.writeMsg(vavWarning);
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) {
    disambigCheck: function () {
var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext),
        var disambigMsg = this.writeMsg($('<div>', {
shortRef = chectTyTool.named_comment + k + '}}';
            id: 'waitForDisambigs'
i = 0;
        }).text(mw.msg('checkty-waiting-disambig-query')), 'info'), self = this;
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('<r' + 'ef 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) {
        this.fetchDisambigLinks().fail(function () {
if (mergedRefs.length) this.writeMsg( $('<div>').text('מיזוג הערות: ' + mergedRefs.join(', ')) );
            disambigMsg.remove();
if (mergedRefsNames.length) this.writeMsg( $('<div>').text('מיזוג הערות עם שמות שונים: ' + mergedRefsNames.join(', ')) );
            self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-no-links') }), 'check');
this.addSummary( 'מיזוג הערות אוטומטי' );
        }).done(function (res) {
this.textbox.value = wikitext;
            var disambigs;
}
            disambigMsg.remove();
},
            if (res.length === 0) {
mergeRefsWithoutName: function() { // merge refs with same content
                self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-success') }), 'check');
var references = {},// a dictionary where key is the ref content and the value is list of uses
                return;
refTemplateRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g,
            }
refTagRE = /<ref>(.+?)<\/ref>/g,
            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');
wikitext = this.textbox.value, m;
            $.each(res, function (i, disTitle) {
while ( m = refTemplateRE.exec( wikitext ) ){
                if (i > 0) {
references[m[1]] = references[m[1]] || [];
                    disambigs.append(', ');
references[m[1]].push(m[0]);
                }
}
                disambigs.append($('<a href="' + mw.util.getUrl(disTitle) + '">' + disTitle + '</a>').click(function () {
while ( m = refTagRE.exec( wikitext ) ){
                    var disambigName = $(this).text();
references[m[1]] = references[m[1]] || [];
                    new mw.Api().get({
references[m[1]].push(m[0]);
                        action: 'parse',
}
                        page: disambigName,
for (var refContet in references) {
                        prop: 'text',
var refUses = references[refContet];
                        redirects: 1
if ( refUses.length === 1 ) continue;
                    }).done(function (data) {
if(/^שם[ .,]|^שם$/.test(refContet) || /\bibid(?![^a-z])/i.test(refContet)) continue; // skip ibid refs
                        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: 'yi',
                    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)) && !(/\| ?תמונה *= *.+jpg/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=yi&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/>');
                }
            }


var commonRefStructure = /(.+?) .+ (?:עמ|p).? ?([0-9]+)/.exec(refContet);
            // Lint checker: wikilink-in-extlink. see [[mw:Help:Lint_errors/wikilink-in-extlink]]
var defaultRefName = '';
            var wikilinkInExtLink = /[^\[]\[[^\[\]]+\[\[.+?\]\]/;
if (commonRefStructure) {
            if (wikilinkInExtLink.test(txt)) {
defaultRefName = commonRefStructure[1]+commonRefStructure[2];
                checkWarnings.append(this.createSearchLink(wikilinkInExtLink));
}
                checkWarnings.append('&nbsp;-&nbsp;' + mw.msg('checkty-wikilink-in-extlink'));
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))
            // Design checks: Elements width
{
            var largeElement = /[6789][0-9][0-9]px/;
var fixRefDirLink = $('<a href="#">'+mw.msg( 'checkty-ref-dir-fix' )+'</a>').data({'search': m[0]}).click(function(e){
            if (largeElement.test(txt)) checkWarnings.append(mw.msg('checkty-large-element') + '<br/>');
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]);
            // Design checks: Long lists can have hint to use columns
this.writeMsg($('<div>').append(['נמצאה הערת שוליים ללא הגדרת כיווניות "'+m[1]+'" [',searchRef, '&nbsp;-&nbsp;', fixRefDirLink, ']']), 'alert');
            var manyLi = new RegExp('(?:\n\\*.*){20}');
}
            if (manyLi.test(txt)) {
},
                checkWarnings.append(this.createSearchLink(manyLi));
refSection: function(fix) {
                checkWarnings.append('&nbsp;-&nbsp;' + mw.msg('checkty-long-list'));
var wikitext = this.textbox.value, newText = wikitext, self = this,
            }
refRE = /<ref>|\{\{הערה\|/g,
            if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
refSectionRE = /\{\{רעפערענצן|\{\{הערות[ _]שוליים|<references[ >]/g,
        } else {
hasRef = refRE.exec(wikitext) != null,
            var api = new mw.Api();
hasRefSection = refSectionRE.exec(wikitext) != null;
            api.get({
if (hasRefSection) return; //not missing
                action: 'parse',
if (!hasRef) return; // not needed
                page: 'המכלול:בדיקה אוטומטית',
if (fix) { // fix only when when explictly asked
                prop: 'wikitext'
var autoRefSection = '\n== רעפערענצן ==\n{{רעפערענצן}}\n'
            }).done(function (data) {
var lastItems = [/(\n{{בקרת זהויות)/, /(\n{{שטומף)/,/\n({{הבהרה (?:רפואית|הלכתית|משפטית))/,/(\n{{מיון רגיל:)/, /(\n\[\[קאטעגאריע:)/];
                if (!(data && data.parse && data.parse.wikitext)) return;
for (var i=0; (i < lastItems.length) && (wikitext == newText); i++ ) newText = wikitext.replace(lastItems[i], autoRefSection + '$1');
                var DictionaryText = data.parse.wikitext['*'].split('-----')[1]
if ( wikitext === newText ) newText = wikitext + autoRefSection;
                var genrealWarningWords = DictionaryText.split('\n*');
this.textbox.value = newText;
                var checks = [];
this.addSummary('רעפערענצן אפטיילונג');
                for (var i = 0; i < genrealWarningWords.length; i++) {
this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-added' )+'</div>'), 'info');
                    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');
            });


} 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');
    },
}
    refsConsistencyCheck: function () {
},
        function safeRegexFix(fixRegex, fixReplace, check) {
overlinkify: function() {
            var txt = $('#wpTextbox1').val(),
function removeOverlink(context, link){
                m;
var newcontext = context;
            //remove templates within templates
do {
            var specials = [];
context = newcontext;
            while (m = /\{\{(?!הערה\|)[^\{]*?\}\}/g.exec(txt)) {
newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[\\1\\|(.+?)\\]\\]', 'g'), '[[$1$2$3');
                txt = txt.replace(m[0], '\0' + specials.length + '\0')
newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[(\\1)\\]\\]', 'g'), '[[$1$2$3');
                specials.push(m[0])
} while( newcontext != context )
            }
return newcontext;
            if (check) {
}
                var counterA = 0, counterB = 0;
// using [^{}\n] as a quick hack to counting links within templates
                while (fixRegex.exec(txt)) counterA++;
var wikitext = this.textbox.value,
                while (fixReplace.exec(txt)) counterB++;
overlinkingRgx = /\[\[([^\[\]\|]+?)(?:\]\]|\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\[\[\1(?:\]\]|\|.+?\]\])/g,
                return [counterA, counterB];
m;
            } else {
                txt = txt.replace(/(\{\{הערה\|.*?\}\}|<ref>.*?<\/ref>)\s+(?=(\{\{הערה\||<ref>))/g, '$1'); // remove spaces between refs
while ( m = overlinkingRgx.exec(wikitext) ) {
                txt = txt.replace(fixRegex, fixReplace);
if (/(?:File|קובץ|תמונה|טעקע):.+/.test(m[1])) {
                while (m = specials.pop()) txt = txt.replace('\0' + specials.length + '\0', m);
continue; // skip files
                $('#wpTextbox1').val(txt);
}
            }
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 refAfter = /([\.\,])\s*((\{\{הערה.*?\}\}|<ref>.*?<\/ref>)+)\.?/g,
var wikitext = $('#wpTextbox1').val(), m;
            refBefore = /\.?((\{\{הערה\|([^\{]|\{(?!\{הערה\|))*\}\}|<ref>([^<]|<(?!\/ref>))*<\/ref>)+)\s*([\.\,])/g,
while( m = specificOverlinkingRgx.exec( wikitext ) )
            refCounter = safeRegexFix(refAfter, refBefore, true);
{
        if (refCounter[0] > 0 && refCounter[1] > 0) {
wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
            this.writeMsg($('<div>', {
}
                text: 'חוסר תאימות ברעפערענצן: ' + refCounter[0] + ' הערות אחרי סימן פיסוק, ' + refCounter[1] + ' הערות לפני סימן פיסוק [תיקון: '
$('#wpTextbox1').val(wikitext);
            }).append($('<a>', {
chectTyTool.addSummary('אראפגענומען איבריגע לינקס');
                text: 'אחרי',
e.preventDefault();
                href: '#'
});
            }).click(function () {
var searchLink = this.createSearchLink( new RegExp( '\\[\\[' + mw.util.escapeRegExp(m[1]) + '(?:\\||\\]\\])' ) );
                safeRegexFix(refBefore, '$5$1', false);
this.writeMsg($('<div>').append(['געטראפן איבריגע לינקס צו"'+m[1]+'" [',searchLink, '&nbsp;-&nbsp;', removeLink, ']']), 'alert');
                chectTyTool.addSummary('איינהייטליכקייט אין רעפערענצן פלאצירונג');
wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
            })).append(' | ').append($('<a>', {
}
                text: 'לפני',
},
                href: '#'
getWikidataApi: function(callback) {
            }).click(function () {
return new mw.ForeignApi( 'https://www.wikidata.org/w/api.php' );
                safeRegexFix(refAfter, '$2$1', false);
},
                chectTyTool.addSummary('איינהייטליכקייט אין רעפערענצן פלאצירונג');
extractWikidataLabelsSuggestions: function() {
            })).append(']'), 'alert');
var suggestLabelsREen = /(?:\[\[|\|)([א-ת' \-]+?)\]\](?: \('*([a-z][^א-ת]+?)'*\)| *\{\{אנג?\|(.+?)\}\})/gi,
        }
langLink = /\{\{קישור שפה\|(?:([א-ת]*)\|)?(?: *2=)? *([^|]+?)\|(?: *3=)? *([א-ת '\-]+?)\}\}/gi,
    },
langTable = { 'ספרדית': 'es', 'אנגלית': 'en' },
    ibidWarning: function () {
self = this,
        var refRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g,
text = this.textbox.value,
            wikitext = this.textbox.value, self = this, m;
suggestionsByLang={}, // lang -> { foreign title -> hebrew label }
        var checkWarnings = $('<div></div>');
foreignTitles= [],
        while (m = refRE.exec(wikitext)) {
m, lang, suggestions;
            if (/^שם[ .,]|^שם$/.test(m[1]) || /\bibid(?![^a-z])/i.test(m[1])) {
                checkWarnings.append(this.createSearchLink(m[0]));
suggestionsByLang['en'] = {};
                checkWarnings.append('&nbsp;-&nbsp;נמצאה הערת שוליים המפנה להערה הקודמת בצורה של שם. יש להחליף לציון מקור מדויק. ראו עוד: <a href="' + mw.util.getUrl('המכלול:רעפערענצן') + '">המכלול:רעפערענצן</a><br/>');
// populate suggestions
            }
while(m = suggestLabelsREen.exec(text)) suggestionsByLang['en'][m[2] || m[3]] = (m[1]||'אנגלית');
        }
while(m = langLink.exec(text)) {
        if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert');
if(!m[1]) m[1] = 'אנגלית'
    },
if (!langTable.hasOwnProperty(m[1]))  
    mergeRefs: function () { // merge refs with same content
{
        this.autoMergeRefs(); // merge refs with name and content that are equal
console.log('wikidataLabelsSuggested: Missing lang: ' + m[1]);
        this.mergeRefsWithoutName(); // merge refs with same content and assign name. requires some manual work
continue;
    },
}
    autoMergeRefs: function () { // merge refs with same content and same name
lang = langTable[m[1]]; // lang code
        var references = {},// a dictionary where key is the ref name and value is count
if (!suggestionsByLang[lang]) suggestionsByLang[lang] = {};
            refsContent = {},// a dictionary where key is the ref name and value is the content
suggestionsByLang[lang][m[2]] = m[3];
            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] };
        }


// query wikidata by lang
        for (k in references) {
for (lang in suggestionsByLang) {
            if (references[k] > 1) {
self.suggestWikidataLabelTranslate(suggestionsByLang[lang], lang);
                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('<r' + 'ef 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) {
suggestWikidataLabelTranslate: function(suggestions, lang) {
            if (mergedRefs.length) this.writeMsg($('<div>').text('מיזוג הערות: ' + mergedRefs.join(', ')));
var foreignTitles = [], batchsize = 50, self = this;
            if (mergedRefsNames.length) this.writeMsg($('<div>').text('מיזוג הערות עם שמות שונים: ' + mergedRefsNames.join(', ')));
for(var v in suggestions) foreignTitles.push(v);
            this.addSummary('מיזוג הערות אוטומטי');
if (foreignTitles.length === 0) return;
            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 extWikiApi = new mw.ForeignApi('//'+lang+'.wikipedia.org/w/api.php'),
            var commonRefStructure = /(.+?) .+ (?:עמ|p).? ?([0-9]+)/.exec(refContet);
queries = Math.ceil(foreignTitles.length/batchsize),
            var defaultRefName = '';
def = $.Deferred(), dataEntities = {}, redirects = {};
            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;


for(var i=0; i<queries; i++)
        while (m = nonDefaultRefRegex.exec(wikitext)) {
{
            var fixRefDirLink = $('<a href="#">' + mw.msg('checkty-ref-dir-fix') + '</a>').data({ 'search': m[0] }).click(function (e) {
// go through enwiki API, to resolve redirects instead of direct approach with wikidataApi.getEntitiesByPage
                var specificRefRgx = new RegExp('\\[\\[(' + mw.util.escapeRegExp($(this).data('search')) + ')(\\]\\]|\\|).+\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g'),
extWikiApi.get({
                    wikitext = $('#wpTextbox1').val();
action: 'query',
                wikitext = wikitext.replace($(this).data('search'), $(this).data('search').replace('}}', '|כיוון=' + uncommonDir + '}}'));
titles: foreignTitles.slice(i*batchsize,(i+1)*batchsize).join('|'),
                $('#wpTextbox1').val(wikitext);
redirects: 1,
                chectTyTool.addSummary(mw.msg('checkty-ref-dir-fix'));
prop: 'pageprops',
                e.preventDefault();
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;
            var searchRef = this.createSearchLink(m[1]);
self.getWikidataApi().get({
            this.writeMsg($('<div>').append(['נמצאה הערת שוליים ללא הגדרת כיווניות "' + m[1] + '" [', searchRef, '&nbsp;-&nbsp;', fixRefDirLink, ']']), 'alert');
action: 'wbgetentities',
        }
ids: '\x1f' + wikidataIds.join( '\x1f' ),
    },
props: '\x1f' + ['labels', 'sitelinks'].join( '\x1f' ),
    refSection: function (fix) {
languages: '\x1f' + ['yi', lang].join( '\x1f' )
        var wikitext = this.textbox.value, newText = wikitext, self = this,
}).done(function(d){
            refRE = /<ref>|\{\{הערה\|/g,
queries--;
            refSectionRE = /\{\{רעפערענצן|\{\{הערות[ _]שוליים|<references[ >]/g,
$.extend(dataEntities, d.entities);
            hasRef = refRE.exec(wikitext) != null,
if (queries === 0) def.resolve(dataEntities);
            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');


def.done(function(data) {
        } else {
var found = false,
            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');
translations = $('<div>ייתכן שהערך מכיל תוויות חסרות לישויות בוויקינתונים:</div>'),
        }
langSite = lang + 'wiki'; // example: enwiki
    },
for(var en in data)
    rawLinks: function () {
{
        var wikitext = this.textbox.value;
if (/^-/.exec(en)) continue;
        wikitext = wikitext.replaceAll('רוי:', '');
if (data[en].labels && data[en].labels.hasOwnProperty('yi')) continue; // already have hebrew label
    },
found = true;
    overlinkify: function () {
var suggestion = suggestions[data[en].sitelinks[langSite].title] || suggestions[redirects[data[en].sitelinks[langSite].title]];
        function removeOverlink(context, link) {
            var newcontext = context;
translations.append($('<li>').append($('<a>', {
            do {
href: 'https://www.wikidata.org/wiki/'+en,
                context = newcontext;
text: en + ' ('+data[en].labels[lang].value+')',
                newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link) + ')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[\\1\\|(.+?)\\]\\]', 'g'), '[[$1$2$3');
target:'_blank'
                newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link) + ')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[(\\1)\\]\\]', 'g'), '[[$1$2$3');
}).data({
            } while (newcontext != context)
'yi': suggestion,
            return newcontext;
'foreignLabel': data[en].sitelinks[langSite].title,
        }
'q': en
        // using [^{}\n] as a quick hack to counting links within templates
}).click(function(){
        var wikitext = this.textbox.value,
self.wikidataLabelTranslate($(this).data('q'), $(this).data('foreignLabel'), $(this).data('yi'));
            overlinkingRgx = /\[\[([^\[\]\|]+?)(?:\]\]|\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\[\[\1(?:\]\]|\|.+?\]\])/g,
return false;
            m;
})));
}
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({
        while (m = overlinkingRgx.exec(wikitext)) {
action: 'wbgetentities',
            if (/(?:File|קובץ|תמונה|טעקע):.+/.test(m[1])) {
ids: '\x1f' + needTranslateQ.join( '\x1f' ),
                continue; // skip files
props: '\x1f' + ['labels'].join( '\x1f' ),
            }
languages: mw.config.get('wgContentLanguage')
            var removeLink = $('<a href="#">' + mw.msg('checkty-remove-link') + '</a>').data({ 'search': m[1] }).click(function (e) {
}).done( function(d) {
                var specificOverlinkingRgx = new RegExp('\\[\\[(' + $(this).data('search') + ')(\\]\\]|\\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g');
var needTranslateIndeedQ = [];
                var wikitext = $('#wpTextbox1').val(), m;
if (!d.entities) return;
                while (m = specificOverlinkingRgx.exec(wikitext)) {
for(var q in d.entities) {
                    wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
if (d.entities[q].labels && !d.entities[q].labels.hasOwnProperty(mw.config.get('wgContentLanguage'))) needTranslateIndeedQ.push(q);
                }
}
                $('#wpTextbox1').val(wikitext);
                chectTyTool.addSummary('אראפגענומען איבריגע לינקס');
if(needTranslateIndeedQ.length === 0) return;
                e.preventDefault();
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');
            var searchLink = this.createSearchLink(new RegExp('\\[\\[' + mw.util.escapeRegExp(m[1]) + '(?:\\||\\]\\])'));
$('a', msg).click(function(){
            this.writeMsg($('<div>').append(['געטראפן איבריגע לינקס צו"' + m[1] + '" [', searchLink, '&nbsp;-&nbsp;', removeLink, ']']), 'alert');
self.wikidataLabelTranslate(/Q[0-9]+/.exec($(this).prop('href'))[0], $(this).text());
            wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
return false;
        }
});
    },
});
    getWikidataApi: function (callback) {
        return new mw.ForeignApi('https://www.wikidata.org/w/api.php');
    },
    extractWikidataLabelsSuggestions: function () {
        var suggestLabelsREen = /(?:\[\[|\|)([א-ת' \-]+?)\]\](?: \('*([a-z][^א-ת]+?)'*\)| *\{\{אנג?\|(.+?)\}\})/gi,
            langLink = /\{\{קישור שפה\|(?:([א-ת]*)\|)?(?: *2=)? *([^|]+?)\|(?: *3=)? *([א-ת '\-]+?)\}\}/gi,
            langTable = { 'ספרדית': 'es', 'אנגלית': 'en' },
            self = this,
            text = this.textbox.value,
            suggestionsByLang = {}, // lang -> { foreign title -> hebrew label }
            foreignTitles = [],
            m, lang, suggestions;


},
        suggestionsByLang['en'] = {};
numberRangeDash: function(fix) {
        // populate suggestions
// 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
        while (m = suggestLabelsREen.exec(text)) suggestionsByLang['en'][m[2] || m[3]] = (m[1] || 'אנגלית');
var numberRangeReNoMinus = /([^|\n]*[א-ת]+'?[-\ ]*)((?:\[\[|\()?[0-9]+(?:\]\])?)-((?:\[\[)?[0-9]+)((?:\]\]|\))?[.:,]?(?:[ \|]|\n)(?!לפנה"ס))/g,
        while (m = langLink.exec(text)) {
wikitext = this.textbox.value, replacements = [], m, i;
            if (!m[1]) m[1] = 'אנגלית'
while(m = numberRangeReNoMinus.exec(wikitext))
            if (!langTable.hasOwnProperty(m[1])) {
{
                console.log('wikidataLabelsSuggested: Missing lang: ' + m[1]);
if (/^קובץ:|בואינג [0-9]/.exec(m[1])) continue; // skip wrong suggestion
                continue;
// 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, '')) ) {
            lang = langTable[m[1]]; // lang code
replacements.push([m[1]+m[2] + '-' + m[3], m[1]+m[2] + '–' + m[3]]);
            if (!suggestionsByLang[lang]) suggestionsByLang[lang] = {};
}
            suggestionsByLang[lang][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;
        // query wikidata by lang
if (fix) {
        for (lang in suggestionsByLang) {
for(i = 0; i < replacements.length; i++) {
            self.suggestWikidataLabelTranslate(suggestionsByLang[lang], lang);
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: 'yi',
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) {
    suggestWikidataLabelTranslate: function (suggestions, lang) {
chectTyTool.addAuthorityControlTemplate();
        var foreignTitles = [], batchsize = 50, self = this;
}
        for (var v in suggestions) foreignTitles.push(v);
chectTyTool.viafSearch(entity, entityId, hasAC);
        if (foreignTitles.length === 0) return;
});
},
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();


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


}
        for (var i = 0; i < queries; i++) {
chectTyTool.writeMsg(viafOptions);
            // go through enwiki API, to resolve redirects instead of direct approach with wikidataApi.getEntitiesByPage
} );
            extWikiApi.get({
},
                action: 'query',
createClaim: function ( entityId, baseRevId, snakType, propertyId, value ) {
                titles: foreignTitles.slice(i * batchsize, (i + 1) * batchsize).join('|'),
if (
                redirects: 1,
typeof entityId !== 'string'
                prop: 'pageprops',
|| typeof baseRevId !== 'number'
                ppprop: 'wikibase_item'
|| typeof snakType !== 'string'
            }).done(function (d) {
|| typeof propertyId !== 'string'
                for (var i in d.query.redirects) redirects[d.query.redirects[i].to] = d.query.redirects[i].from;
|| value && typeof value !== 'string' && typeof value !== 'object'
                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);
throw new Error( 'Parameter not specified properly' );
 
}
                if (wikidataIds.length === 0) return;
var params = {
                self.getWikidataApi().get({
action: 'wbcreateclaim',
                    action: 'wbgetentities',
entity: entityId,
                    ids: '\x1f' + wikidataIds.join('\x1f'),
baserevid: baseRevId,
                    props: '\x1f' + ['labels', 'sitelinks'].join('\x1f'),
snaktype: snakType,
                    languages: '\x1f' + ['yi', lang].join('\x1f')
property: propertyId
                }).done(function (d) {
};
                    queries--;
if ( value ) {
                    $.extend(dataEntities, d.entities);
params.value = JSON.stringify( value );
                    if (queries === 0) def.resolve(dataEntities);
}
                });
            });
return this.getWikidataApi().postWithToken( 'csrf', params );
        }
},
 
addAuthorityControlTemplate: function(){
        def.done(function (data) {
var t = this.textbox.value,
            var found = false,
viafTemplate = /\{\{בקרת זהויות[\}|]/g,
                translations = $('<div>ייתכן שהערך מכיל תוויות חסרות לישויות בוויקינתונים:</div>'),
acTemplate = '{{' + 'בקרת זהויות}}',
                langSite = lang + 'wiki'; // example: enwiki
newText;
            for (var en in data) {
if ( viafTemplate.exec( t ) ) return; // viaf already exist
                if (/^-/.exec(en)) continue;
newText = t.replace(/{{שטומף/, acTemplate + '\n{{שטומף'); // before stub
                if (data[en].labels && data[en].labels.hasOwnProperty('yi')) continue; // already have hebrew label
if (newText == t) newText = t.replace(/{{מיון רגיל:/, acTemplate + '\n{{מיון רגיל:'); //before default sort
                found = true;
if (newText == t) newText = t.replace(/\[\[קאטעגאריע:/, acTemplate + '\n[[קאטעגאריע:'); // before categories
                var suggestion = suggestions[data[en].sitelinks[langSite].title] || suggestions[redirects[data[en].sitelinks[langSite].title]];
if (newText == t) newText = t + '\n' + acTemplate;
 
this.textbox.value = newText;
                translations.append($('<li>').append($('<a>', {
this.addSummary('בקרת זהויות');
                    href: 'https://www.wikidata.org/wiki/' + en,
}
                    text: en + ' (' + data[en].labels[lang].value + ')',
                    target: '_blank'
                }).data({
                    'yi': suggestion,
                    'foreignLabel': data[en].sitelinks[langSite].title,
                    'q': en
                }).click(function () {
                    self.wikidataLabelTranslate($(this).data('q'), $(this).data('foreignLabel'), $(this).data('yi'));
                    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: 'yi',
            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('בקרת זהויות');
    }
};
};


$(document).ready(function () {
$(document).ready(function () {
chectTyTool.origText = $('#wpTextbox1').val();
    chectTyTool.origText = $('#wpTextbox1').val();
var checktyBtn = new OO.ui.ButtonInputWidget({ label: 'בדיקה', title: 'טשעקטי - געצייג צו בודק זיין אפטע פראבלעמען', accessKey: (window.checkToolKey || 'e'), id:'btnCheckTool' });
    var checktyBtn = new OO.ui.ButtonInputWidget({ label: 'בדיקה', title: 'טשעקטי - געצייג צו בודק זיין אפטע פראבלעמען', accessKey: (window.checkToolKey || 'e'), id: 'btnCheckTool' });
checktyBtn.$button.updateTooltipAccessKeys();
    checktyBtn.$button.updateTooltipAccessKeys();
$('#wpPreviewWidget').after(checktyBtn.$element.click(chectTyTool.run));
    $('#wpPreviewWidget').after(checktyBtn.$element.click(chectTyTool.run));
});
});

רעוויזיע פון 16:52, 16 אקטאבער 2023

// הוספת כפתור "בדיקה" שמבצע החלפות נפוצות של בוט ההחלפות וכן מתריע על בעיות סגנון ועיצוב שונות
// נכתב על ידי [[משתמש:ערן]] ו[[משתמש:קיפודנחש]]
// לעזרה ראו [[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: 'פישוט קישור'
        }, { // simplify common links prefix
            from: / \[\[([^|\]]+)\|([בהו])\1\]\]/g,
            to: ' $2[[$1]]',
            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 (/\{\{(מיון רגיל|גרונטסארטיר|DEFAULTSORT):/.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: 'צולייגן DEFAULTSORT',
            }).click(function () { chectTyTool.defaultSortSuggest(true); return false; }));
            this.writeMsg(defaultSortMsg, 'info');
        } else {
            name = firstFamilyRgx.exec(mw.config.get('wgTitle'));
            txt = txt.replace(/\[\[(קאַטעגאָריע|קאטעגאריע)/, '{{DEFAULTSORT:' + name[2] + ', ' + name[1] + '}}\n[[קאַטעגאָריע');
            this.addSummary('DEFAULTSORT');
            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 () {
        if (mw.config.get('wgNamespaceNumber') in [0, 3000, 8000]) {
            this.rawLinks();
        }
        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, '')));
                console.log(this.regexes[i][1]);
                console.log(actual_replaced[i]);
                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.replace('[[', ''));
                            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: 'yi',
                    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)) && !(/\| ?תמונה *= *.+jpg/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=yi&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('<r' + 'ef 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');
        }
    },
    rawLinks: function () {
        var wikitext = this.textbox.value;
        wikitext = wikitext.replaceAll('רוי:', '');
    },
    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 = /\{\{קישור שפה\|(?:([א-ת]*)\|)?(?: *2=)? *([^|]+?)\|(?: *3=)? *([א-ת '\-]+?)\}\}/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 (!m[1]) m[1] = 'אנגלית'
            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' + ['yi', 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('yi')) 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({
                    'yi': suggestion,
                    'foreignLabel': data[en].sitelinks[langSite].title,
                    'q': en
                }).click(function () {
                    self.wikidataLabelTranslate($(this).data('q'), $(this).data('foreignLabel'), $(this).data('yi'));
                    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: 'yi',
            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('בקרת זהויות');
    }
};

$(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));
});