מדיה ויקי:Gadget-Checkty.js: הבדלים בין גרסאות בדף
קפיצה לניווט
קפיצה לחיפוש
קער א וועלט (שיחה | תרומות) (עדכון מויקיפדיה והתאמה לויקישיבה) |
קער א וועלט (שיחה | תרומות) (חיפוש תמונות אוטומטי באתר www.inn.co.il) |
||
שורה 927: | שורה 927: | ||
}, | }, | ||
fistURL: function (p) { | fistURL: function (p) { | ||
return 'https:// | return 'https://www.inn.co.il/search' + $.param(p); | ||
}, | }, | ||
languageCheck: function (checks) { //style and language check | languageCheck: function (checks) { //style and language check |
גרסה מ־04:37, 5 באוקטובר 2021
|
// הוספת כפתור "בדיקה" שמבצע החלפות נפוצות של בוט ההחלפות וכן מתריע על בעיות סגנון ועיצוב שונות // נכתב על ידי [[משתמש:ערן]], [[משתמש:קיפודנחש]] מויקיפדיה והותאם לאתר ע"י [[משתמש:חלוקת קונטרסים]] מחב"דפדיה // לעזרה ראו [[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': 'כאשר ו עיצורית מופיעה באמצע מילה נהוג להכפילה. ייתכן שיש מופעים שדורשים תיקון.' }); 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: 'הסרת תווים בלתי נראים' }, { from: / +$/mg, to: '' }, { // remove accidental nowiki and simplify code from: /\[\[([^|\[\]]+)([^|\[\]]+?)\|\1\]\](?:<nowiki\/>)?\2/g, to: '[[$1$2]]', comment: 'פישוט קישור' }, { // trim beginning from redundant spaces from: /^\s+/g, to: '', comment: 'הסרת רווחים מיותרים' }, { // trim redundant spaces from category links from: /\[\[קטגוריה: */g, to: '[[קטגוריה:' }], formatReplacesConfig: [{ // piped link has identical text before and after the pipe from: /\[\[(.*?)\|\1([.,a-zא-ת]*)\]\]/g, to: '[[$1]]$2' }, { 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: ']],' }, { // section between two headings without content from: /\n==[^=\n]+?==\n*(\n==[^=\n]+?==\n)/g, to: '$1', comment: 'הסרת כותרות ריקות' }], regexes: [], ignoreRegexes: [], run: function () { if (this != chectTyTool) { chectTyTool.run(); return; } var t = $('#wpTextbox1'); this.textbox = t.length ? t[0] : null; if (!this.textbox || this.textbox.value.length === 0) return; // 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 (!prompt(mw.msg('checkty-wrong-use-discussion'))) return; } // indication that skippable replacements should be ignored in the page this.skipCheckty = this.textbox.value.match(/{{ללא[_ ]בוט\|\s*צ'קטי\s*}}/g); if (!($('#checktyResults').length)) $('.editButtons').after('<div id="checktyResults"><div class="checktyResultsTitle">'+mw.msg( 'checkty-warnings-title' )+'</div></div>'); //first call to remote functions than to local if ( ( chectTyTool.textbox.value === chectTyTool.origText ) && ( mw.config.get('wgAction') === 'edit') ) this.onSaveProtection(); this.formatChecks(); this.linkChecks(); if(!this.isSection) { this.articleOrgChecks(); this.checkImages(); } this.languageCheck(); this.vavCheck(); this.expandWikidata(); }, formatChecks: function() { if (!this.isSection) this.build_regexes(); this.formatReplace(); this.decodeExternalLinks(); // format - semi manual this.mainArticlesMerge(); this.numberRangeDash(false); }, decodeExternalLinks: function() { var t = this.textbox.value, newTxt = t, externalLinkRgx = /http[^ \]|]+/g, decodeRgx = /(?:%[0-9a-z]{2}){2,}/ig, m, mm, newLink; while ( m = externalLinkRgx.exec(t) ) { newLink = m[0]; while (mm = decodeRgx.exec(m[0])) { try { // decode URL except special chars var niceLink = decodeURI(mm[0]).replace(/[ |"\n\[\]{}<>]/g, encodeURI); if (niceLink == niceLink.normalize()) newLink = newLink.replace(mm[0], niceLink); } catch(ex) { } } newTxt = newTxt.replace(m[0], newLink); } if (newTxt === t) return; this.updateText(newTxt); chectTyTool.addSummary('קידוד קישורים'); }, articleOrgChecks: function() { this.titleOrderCheck(); this.checkRefs(); this.checkGallery(); this.defaultSortSuggest(); this.categoryOrder(); }, defaultSortSuggest: function(execute) { var txt = this.textbox.value, isPerson = false, firstFamilyRgx = /^([^ ]+) ([^ ]+)$/, name, defaultSortMsg; if (/\{\{מיון רגיל:/.exec(txt)) return; // skip if already exists if (!firstFamilyRgx.exec(mw.config.get('wgTitle'))) return; // skip if can't suggest isPerson = /== ?(ביוגרפיה|קורות חיים|חיי[וה]) ?==/.exec(txt); // heuristic to identify biographic articles if (!isPerson) return; // skip for non biographic pages if (!execute) { defaultSortMsg = $('<div>', { text: mw.msg('checkty-defaultsort-suggest') }).append($('<a>', { href: '#', text: 'הוספת מיון רגיל', }).click(function(){ chectTyTool.defaultSortSuggest(true); return false;})); this.writeMsg(defaultSortMsg, 'info'); } else { name = firstFamilyRgx.exec(mw.config.get('wgTitle')); txt = txt.replace('[[קטגוריה', '{{מיון רגיל:' + name[2] + ', ' + name[1] + '}}\n[[קטגוריה'); this.addSummary('מיון רגיל'); this.updateText(txt); } }, categoryOrder: function(execute) { var txt = this.textbox.value, newTxt = txt, self = this; categoryRE = /(\[\[קטגוריה:.+\]\])(?:$|\n)/g, cats = [], m = null, oldCats = null, categorySortMsg = null; while(m=categoryRE.exec(txt)) { cats.push(m[1]); newTxt = newTxt.replace(m[0], ''); } oldCats = JSON.stringify(cats); cats.sort(function(a,b){ if (/\|\*\]\]/.exec(a)) return -1; if (/\|\*\]\]/.exec(b)) return 1; if (/נפטרים ב-|נפטרות|שנפטרו/.exec(a)) return 1; if(/נפטרים ב-|נפטרות|שנפטרו/.exec(b)) return -1; if (/(ילידי|ילידות|שנולדו).*[0-9]/.exec(a)) return 1; if(/(ילידי|ילידות|שנולדו).*[0-9]/.exec(b)) return -1; if (/אישים במאה ה-|אישים שחיו במאה ה-|רבנים במאה ה-/.exec(a)) return 1; if(/אישים במאה ה-|אישים שחיו במאה ה-|רבנים במאה ה-/.exec(b)) return -1; return a>=b; }); if (oldCats == JSON.stringify(cats)) return; // same order - nothing to do if (!execute) { categorySortMsg = $('<div>', { text: mw.msg('checkty-category-sort') }).append($('<a>', { href: '#', text: 'סידור', }).click(function(){ chectTyTool.categoryOrder(true); return false;})); this.writeMsg(categorySortMsg, 'info'); } else { newTxt = newTxt.trimEnd(); newTxt += '\n' + cats.join('\n'); if (newTxt != txt) OO.ui.confirm( 'יש לאשר סדר הקטגוריות המוצע:' + cats.join(', ').replace(/\[\[קטגוריה:([^\[\]]+)\]\]/g, '$1') ).done( function ( confirmed ) { if ( !confirmed ) return; self.addSummary('סידור קטגוריות'); self.updateText(newTxt); } ); } }, linkChecks: function() { this.overlinkify(); this.nakedLinks(); this.checkExternalLinks(); this.disambigCheck(); }, expandWikidata: function() { this.wikidataLabelsMissing(); this.extractWikidataLabelsSuggestions(); if (!this.isSection) { this.addAuthorityControl(); } }, createSearchLink: function(v) { var highlightStr = this.highlightString, searchLink = $('<a href="#">'+mw.msg( 'checkty-search' )+'</a>').data({'search': v}).click(function(e){ highlightStr($(this).data('search')); e.preventDefault(); }); return searchLink; }, onSaveProtection: function() { $('#wpSave').click(function(e){ if (chectTyTool.textbox.value === chectTyTool.origText) { OO.ui.confirm( mw.msg('checkty-nonsense-edit') ).done( function ( confirmed ) { if ( confirmed ) { chectTyTool.origText = ''; $('#editform').submit(); } else { e.preventDefault(); } } ); e.preventDefault(); } }); }, updateText: function( val ) { if (this.textbox.value === chectTyTool.origText) { chectTyTool.origText = val; } this.textbox.value = val; }, nakedLinks: function() { var t = this.textbox.value, nakeRegex=/\[(http[^ ]+?)\]|\{\{הערה *\| *(?:1 *= *)?(https?:\/\/[^ }|]+)\}\}/g, nakeErrors=[], m, self= this; while (m = nakeRegex.exec(t)) { var nakedUrl = m[1] || m[2], fixNakedLink = $( '<a href="#">' + mw.msg( 'checkty-naked-link-fix' )+'</a>' ).data( { 'search': nakedUrl, 'inRef': m[2] }).click( function ( e ) { var searchUrl = $(this).data( 'search' ), inRef = $(this).data('inRef'), citoidTemplatesPromise = new mw.Api().loadMessagesIfMissing( [ 'citoid-template-type-map.json' ] ); // Common case: pasting a URI into this field. Citoid expects // minimally encoded input, so do some speculative decoding here to // avoid 404 fetches. T146539 searchUrl = decodeURIComponent(searchUrl); citoidPromise = $.ajax('/api/rest_v1/data/citation/mediawiki/'+encodeURIComponent(searchUrl), { headers: { 'accept-language': mw.config.get( 'wgContentLanguage' ) }, timeout: 20 * 1000, // 20 seconds type: 'GET' }); citoidPromise.done(function(d){ citoidTemplatesPromise.done(function(){ var CiteTemplates = JSON.parse( mw.message( 'citoid-template-type-map.json' ).plain() ); if ( d.length === 0 || !CiteTemplates[ d[0].itemType ] ) { self.writeMsg( mw.msg( 'checkty-naked-link-fix-fail' ) ); return; } var api = new mw.Api().get( { action: 'templatedata', titles: 'Template:' + CiteTemplates[ d[0].itemType ] }).done(function(tdq){ for(var pid in tdq.pages){ var td = tdq.pages[pid], params = []; for(var k in d[0]) { if (td.maps['citoid'][k]) { if ($.isArray(td.maps['citoid'][k]) && $.isArray(d[0][k])) { for(var i = 0;i < d[0][k].length; i++) { if ($.isArray(d[0][k][i]) && $.isArray(td.maps['citoid'][k][i])) { for(var j = 0;j < d[0][k][i].length; j++) { params.push(td.maps['citoid'][k][i][j] + '=' + d[0][k][i][j].replace(/\|/g, '{{!}}')); } } } } else { if ($.isArray(d[0][k])) { for(var i = 0;i < d[0][k].length; i++) if ($.isArray(d[0][k][i])) d[0][k][i] = d[0][k][i].join(' '); d[0][k] = d[0][k].join(', '); } params.push(td.maps['citoid'][k] + '=' + d[0][k].replace(/\|/g, '{{!}}')); } } } var template = '{{'+CiteTemplates[d[0].itemType]+'|' + params.join('|')+'}}', wikitext = self.textbox.value; if ( inRef ) { wikitext = wikitext.replace(new RegExp('\\{\\{הערה *\\| *(?:1 *= *)?'+mw.util.escapeRegExp(searchUrl)+'\\}\\}', 'g'), '{{הערה|' + template + '}}'); } else { // this is more context sensitive - sometimes we may or may not want to wrap with ref wikitext = wikitext.replace(new RegExp('\\['+mw.util.escapeRegExp(searchUrl)+'\\]', 'g'), template); } self.textbox.value = wikitext; self.writeMsg($('<div>').append(mw.msg('checkty-naked-link-fixed', searchUrl, template)).append(self.createSearchLink(template))); chectTyTool.addSummary('הלבשת קישורים עירומים'); } }) }); }).fail(function(){ self.writeMsg($('<div>').append(mw.msg('checkty-broken-link') + searchUrl)); }); e.preventDefault(); }); this.writeMsg($('<div>').append([mw.msg('checkty-naked-link-found', nakedUrl)+'" [',fixNakedLink, ' - ', 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 + ' ').append(this.createSearchLink(this.regexes[matches[1]][0]))); } } var specials = [], ignoreRegex = new RegExp('(' + this.ignoreRegexes.join('|') + ')'); for (i in this.regexes) // assume regexs on templates are safe if contain template wikicode if (/\\{\\{/.test(this.regexes[i][0]) && this.regexes[i][0].test(t)) { t = t.replace(this.regexes[i][0], this.regexes[i][1]); actual_replaced.push($.trim(this.regexes[i][1].replace(/\$\d*/g, ''))); actual_replaced_details.push(i + ': ' + $.trim(this.regexes[i][1].replace(/\$\d*/g, ''))); } while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those. match = t.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])/); if ((!match || !match.length) && this.ignoreRegexes.length ) match = t.match(ignoreRegex); if (!match || !match.length) break; specials.push(match[0]); t = t.replace(match[0], "\0" + specials.length + "\0"); } for (i in this.regexes) if (!chectTyTool.skip_dict[i] && !isNaN(i)) if (this.regexes[i][0].test(t)) { var before = t, tries=0, befText, afterText; /* repeat replacement for 3 times as sometimes need to converge for more than a single run Such as boundary [^a-z][a-z][^a-z] replacing [a|a]. Use of negative char match is useful for different regex engines with different support of look ahead and lookbehind */ do { before = t; t = t.replace(this.regexes[i][0], this.regexes[i][1]); if ((tries==0) && (t != before)) { // 1st match as representative example for summary befText = this.regexes[i][0].exec(before)[0]; afterText = befText.replace(this.regexes[i][0], this.regexes[i][1]); actual_replaced.push(afterText); actual_replaced_details.push(i + ': ' + befText + ' ← ' + afterText); } tries++; } while ((tries < 3) && (t != before)) } while (true) { match = t.match(/\0(\d+)\0/); if (!match || !match.length) break; t = t.replace(match[0], specials[parseInt(match[1], 10) - 1]); } this.updateText(t); var msg = ['החלפות - בוצעו ' + actual_replaced.length + ' החלפות' + (actual_replaced_details.length==0? '.' : ': ' + actual_replaced_details.join(', '))]; if (skip_ar.length) { msg.push('<br />החלפות שלא התבצעו בגלל תבנית "ללא בוט": '); msg.push($('<ul></ul>').append(skip_ar)); } if(actual_replaced.length) { msg.push(' אנא בצעו "הצגת שינויים" לפני שמירה, כדי לוודא שהסקריפט לא גרם נזק.'); } this.writeMsg($('<div></div>').append(msg), 'info'); if (actual_replaced.length) chectTyTool.addSummary(mw.msg('checkty-replace-summary', actual_replaced.join(', '))); }, fetchDisambigLinks: function (next) { var dfd = new jQuery.Deferred(); var api = new mw.Api(); var params = { action: 'query', generator: 'links', titles: mw.config.get('wgPageName'), prop: 'pageprops', ppprop: 'disambiguation', gpllimit: '500', redirects: 1 }; if (next !== undefined) { params.gplcontinue = next; } api.get(params).done(function (data) { //extract disambig pages if (!data.hasOwnProperty('query')) { dfd.reject(); return; } var redirects = {}; if (data.query.redirects) { $.each(data.query.redirects, function(i,r) { redirects[r.to] = r.from; }); } var disambigs = []; for (var pid in data.query.pages) { var p = data.query.pages[pid], isDisambigPage = p.pageprops && p.title != mw.config.get('wgTitle') + mw.msg( 'checkty-disambig-suffix' ); //list only real disambig links if (isDisambigPage && (chectTyTool.getLinkRegex(p.title).exec(chectTyTool.textbox.value) || (redirects[p.title] && chectTyTool.getLinkRegex(redirects[p.title]).exec(chectTyTool.textbox.value)))) { disambigs.push(redirects[p.title] || p.title); } } if (data['query-continue'] !== undefined) { var nextReq = chectTyTool.fetchDisambigLinks(data['query-continue'].links.gplcontinue); nextReq.done(function (more) { dfd.resolve($.merge(disambigs, more)); }); } else { dfd.resolve(disambigs); } }); return dfd.promise(); }, mainArticlesMerge: function() { var origTxt = this.textbox.value, txt = this.textbox.value, m; while (m = /(\{\{(?:הפניה לערך מורחב|ערך מורחב)\|[^=\n]+?\}\}\n){2,}/g.exec(txt)) { var articles = [], expArticleRE = /\{\{(?:הפניה לערך מורחב|ערך מורחב)\|([^=\n]+?)\}\}/g; while (ma = expArticleRE.exec(m[0])) articles.push(ma[1]); txt = txt.replace(m[0], '{{הפניה לערך מורחב|ערכים=[['+articles.join(']], [[')+']]}}\n'); } this.textbox.value = txt; if (origTxt != txt) chectTyTool.addSummary( mw.msg( 'checkty-main-articles-merge-summary' ) ); }, formatReplace: function () { var txt = this.textbox.value, newTxt; // Format autofix var specials=[], match; // var emptyParametersRgx = /\n *\| *[^|=]+?= *(?=\n(?: *\||\}\}))/mg, emptyParametersMsg, emptyParametersBtn; $(this.formatReplacesConfigSafe).each(function (i, o) { newTxt = txt.replace(o.from, o.to); if ( newTxt!=txt && o.comment) { chectTyTool.addSummary( o.comment ); } txt = newTxt; }); //extract inner links, inner templates and inner params - we don't want to sptit those. while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those. match = txt.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])/); if (!match || !match.length) break; specials.push(match[0]); txt = txt.replace(match[0], "\0" + specials.length + "\0"); } $(this.formatReplacesConfig).each(function (i, o) { newTxt = txt.replace(o.from, o.to); if (o.skippable && (chectTyTool.skipCheckty || this.isSection)) return; // skip this one respecting {ללא בוט} if ( newTxt!=txt && o.comment) { chectTyTool.addSummary( o.comment ); } txt = newTxt; }); while (true) { match = txt.match(/\0(\d+)\0/); if (!match || !match.length) break; txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]); } this.updateText(txt); // if (!emptyParametersRgx.test(txt)) return; // emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', { // href: '#', // text: 'ניקוי' // }).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; })); // this.writeMsg(emptyParametersMsg, 'info'); }, vavCheck: function () { var text = this.textbox.value, vavRegex = /[כלבמשה]\[\[ו[^ו][א-ת ]+\]\]/g, self = this; if (!vavRegex.exec( text )) return; var vavWarning = $('<div>').text( mw.msg( 'checkty-vav-warning' ) ).append(this.createSearchLink(vavRegex)); // TODO: add semi-automatic fix option? chectTyTool.writeMsg(vavWarning); }, disambigCheck: function () { var disambigMsg = this.writeMsg($('<div>', { id: 'waitForDisambigs' }).text( mw.msg( 'checkty-waiting-disambig-query' ) ), 'info'), self = this; this.fetchDisambigLinks().fail(function () { disambigMsg.remove(); self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-no-links') }), 'check'); }).done(function (res) { var disambigs; disambigMsg.remove(); if (res.length === 0) { self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-success') }), 'check'); return; } disambigs = $('<div id="disambigWarnning">'+mw.msg( 'checkty-disambig-links-title' )+'</div>').prepend('<img src="//upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Disambig_RTL.svg/15px-Disambig_RTL.svg.png">').css('padding', '0 5px'); $.each(res, function (i, disTitle) { if (i > 0) { disambigs.append(', '); } disambigs.append($('<a href="' + mw.util.getUrl(disTitle) + '">' + disTitle + '</a>').click(function () { var disambigName = $(this).text(); new mw.Api().get({ action: 'parse', page: disambigName, prop: 'text', redirects: 1 }).done(function (data) { if (data && data.parse && data.parse.text) { var disambig = data.parse.text['*']; mw.loader.using( ['jquery.ui'] ).done ( function() { chectTyTool.resolveDisambig( disambigName, disambig ); } ); } else { console.error(data); } }); return false; })); }); chectTyTool.writeMsg(disambigs); }); }, getLinkRegex: function(name) { return new RegExp('(?:\\.|^)([^\\.\n]*(\\[\\[' + mw.util.escapeRegExp(name) + '[\\|\\]]).*?)[\\.\\n]', 'm'); }, resolveDisambig: function (name, data) { var offset = 0, textbox = this.textbox, linkRgx = this.getLinkRegex(name), orgPos = $(textbox).textSelection('getCaretPosition'), cSentence = $('<div>'); var options = $('<div>').append($('li', data).filter(function() { return $(this).closest( '.checkty-ignore' ).length === 0; } ).map(function () { var a = $(this).children('a').get(0); if (a) { var storeTitle = $(this).text(); var anchor = '', h = a.href; if (h.indexOf('#') + 1) anchor = decodeURI(h.substr(h.indexOf('#')).replace(/\./g, '%').replace(/_/g, ' ')); $(a).text( a.title.replace(mw.msg( 'checkty-page-doesnt-exist' ), "") + anchor); a.title = storeTitle; } return a || null; }).click(resolve)) .append($('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').click(removeLink)); var disambigDialog = $('<div>').append( mw.msg('checkty-disambig-meaning', name) + '<hr/>').append(cSentence).append(options.buttonset()).dialog({ title: mw.msg( 'checkty-dismabig-dialog-title' ), close: function () { $(textbox).textSelection('setSelection', { start: orgPos }); } }); findSentence(); function findSentence() { var text = textbox.value.substr(offset), m = text.match(linkRgx); if (!m) { disambigDialog.dialog('close'); return; } offset += text.indexOf(m[1]) + m[1].indexOf(m[2]); var linkIndex = m[1].indexOf(m[2]) + 2, html = m[1].substr(0, linkIndex) + '<big>' + name + '</big>' + m[1].substr(linkIndex + name.length); cSentence.html(html); } function resolve() { var answer = $(this).text(), text = textbox.value, startLink = text.indexOf('[[' + name, offset); if (text.charAt(startLink + 2 + name.length) != '|') answer += '|' + name; offset += answer.length + 2; text = text.substr(0, startLink + 2) + answer + text.substr(startLink + 2 + name.length); textbox.value = text; findSentence(); chectTyTool.addSummary( mw.msg( 'checkty-dismabig-fix-summary' ) ); return false; } function removeLink() { var text = textbox.value, startLink = text.indexOf('[[' + name, offset), endLink = text.indexOf(']]', startLink), pipeChar = startLink + 2 + name.length, linkText = (text.charAt(pipeChar) != '|') ? name : text.substr(pipeChar + 1, endLink - pipeChar - 1); offset += (endLink - startLink) + linkText.length; text = text.substr(0, startLink) + linkText + text.substr(endLink + 2); textbox.value = text; findSentence(); return false; } }, addSummary: function (msg) { var editSummary = $('#wpSummary').val(); if (editSummary.indexOf(msg) === -1) $('#wpSummary').val(editSummary + (editSummary.length === 0 ? '' : ', ') + msg); // tag the edit if ( $('#checktyTag').length === 0 ) { $('#editform').append('<input type="hidden" name="wpChangeTags" id="checktyTag" value="צ\'קטי">'); } }, checkGallery: function() { var text = this.textbox.value, longGalleryThreshold = 16, galleryRgx = /<gallery.+?\n(\n|.)+?<\/gallery>/mg, m, longGallery=false; while ( m=galleryRgx.exec( text ) ) { var galLength = m[0].split('\n').length-2; longGallery |= (galLength > longGalleryThreshold); } if (longGallery) { this.writeMsg('<div>' + mw.msg('checkty-long-gallery') + '</div>', 'alert'); } }, checkImages: function (data) { var fairUsageTemplates = ['תבנית:שימוש הוגן', 'תבנית:תמונת חבר כנסת']; if (!data) { if (!(/\{\{(ויקישיתוף בשורה|מיזמים)/.test(this.textbox.value))) { $.getJSON('//www.wikidata.org/w/api.php?callback=?', { languages: 'he', action: 'wbgetentities', sites: mw.config.get('wgDBname'), titles: mw.config.get('wgTitle'), format: 'json', props: 'claims' }).done(function (data) { if (data.success === undefined || !data.success) return; for (var entityId in data.entities) { var claims = data.entities[entityId].claims; if (claims && claims.hasOwnProperty('P373')) { chectTyTool.writeMsg($('<div>', { text: mw.msg('checkty-missing-commons-link') }).prepend('<img src="//upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Commons-logo.svg/15px-Commons-logo.svg.png">').css('padding', '0 5px').append($('<a>', { href: '#', text: 'להוספה' }).click(function (e) { e.preventDefault(); var ta = $('#wpTextbox1'); if (ta.textSelection('getCaretPosition') >= ta.val().length) { chectTyTool.writeMsg($('<div>').text(mw.msg('checkty-please-position-caret'))); } else { ta.textSelection('encapsulateSelection',{pre:'{{ויקישיתוף בשורה}}'}); chectTyTool.addSummary('ויקישיתוף בשורה'); } }))); } } }); } //in case there are no images in page if (!(/\[\[(תמונה|קובץ|File|Image):/i.test(this.textbox.value))) { var articleName = mw.config.get('wgPageName'); var that = this; // we want to use "this" in the done method of the api call. new mw.Api().post( { action: 'parse', title: articleName, text: this.textbox.value } ).done( function( data ) { if ( data && data.parse && data.parse.text && $( data.parse.text['*'] ).find( 'a.image img' ).filter(function() { var width = $(this).attr('width'); if (isNaN(width)) width = $(this).width(); else width = parseInt(width); return (width >= 100) && $(this).parents('.navbox').length==0; } ).length === 0 ) { var fistURL = that.fistURL({ datatype: 'articles', data: articleName }); var msg = $('<div>', { text: 'בדף זה אין תמונות. ניתן לחפש תמונות חופשיות ממקורות שונים. ' }).append($('<a>', { href: decodeURI(fistURL), text: 'חיפוש תמונות', target: '_blank' })); that.writeMsg(msg, 'info'); } }); return; } new mw.Api().get({ action: 'query', generator: 'images', titles: mw.config.get('wgPageName'), prop: 'templates', tltemplates: fairUsageTemplates.join('|') }).done(function (data) { if (data && data.query && data.query.pages) chectTyTool.checkImages(data.query.pages); }); } else { var fairUseImgs = $.map(data, function (o) { if (!o.templates) return; var isFairUsage; $.each(o.templates, function (k, license) { if ($.inArray(license.title, fairUsageTemplates) != -1) { isFairUsage = true; return false; } }); if (isFairUsage) return o.title; }); if (fairUseImgs.length === 0) return; //add message with fair usage images var fistURL = this.fistURL({ data: fairUseImgs.join('\r\n'), datatype: 'replaceimages' }); var msg = $('<div>', { text: 'הדף מכיל תמונות בשימוש הוגן, שמומלץ להחליפן בחלופות חופשיות במידת האפשר. ' }).append($('<a>', { href: fistURL, text: 'חיפוש חלופות חופשיות', target: '_blank' })); if (!(new RegExp('\{\{'+mw.msg('checkty-fairuse-img-replace-template')+'\}\}').test($('#wpTextbox1').val()))) msg.append(' - ').append($('<a>', { text: 'סימון להחלפה', href: '#' }).click(function () { var t = $('#wpTextbox1'); $.each(fairUseImgs, function (i, fiImg) { var imgName = mw.util.escapeRegExp(/.:(.+)$/.exec(fiImg)[1]), imgDescRE = new RegExp(imgName.replace(' ', '[ _]') + '((?:[^\\[\\]]|\\[\\[[^\\[\\]]*?\\]\\])*?)\]\]', 'i'), matches; if (!(matches = imgDescRE.exec(t.val()))) { return; } //this is thumb img var imgDesc = matches[1].split('|'), isThumb = false, imgCaption = ''; for (var i in imgDesc) { if (/thumb|ממוזער/i.test(imgDesc[i])) { isThumb = true; } else if (!(/^(ימין|שמאל|מרכז|right|left|center|[0-9]+px)?$/i.test(imgDesc[i]))) { imgCaption = imgDesc[i]; //unknown parameter assumed to be description } } if (isThumb) { if (imgCaption) { imgDesc = matches[1].replace(imgCaption, imgCaption + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'); } else { imgDesc = matches[1] + '|{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'; } t.val(t.val().replace(matches[1], imgDesc)); chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'); } else { //is in infobox heuristic: = before image tag var isInInfobox = new RegExp('=\s*\\[\\[(?:file|image|קובץ|תמונה):' + imgName.replace(' ', '[ _]') + '[^\\]]*?\]\]', 'i'); if (isInInfobox.test(t.val())) { t.val(t.val().replace(matches[0], matches[0] + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}')); chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'); } } }); })); this.writeMsg(msg, 'alert'); } }, fistURL: function (p) { return 'https://www.inn.co.il/search' + $.param(p); }, languageCheck: function (checks) { //style and language check var txt = this.textbox.value; if (checks) { var checkWarnings = $('<div></div>'); for (var x in checks) { if (checks[x]['test'].test(txt)) { var m = checks[x]['test'].exec(txt), langCheckPrefix = ''; if (m[0].split(' ').length < 4 && checks[x]['test'].source.indexOf('\\]')==-1) langCheckPrefix = mw.msg('checkty-language-check', m[0]); checkWarnings.append(this.createSearchLink(checks[x]['test'])); checkWarnings.append(' - ' + 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(' - ' + 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(' - ' + mw.msg( 'checkty-long-list' )); } if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert'); } else { var api = new mw.Api(); api.get({ action:'parse', page: 'ויקישיבה:בדיקה אוטומטית', prop: 'wikitext' }).done(function (data) { if (!(data && data.parse && data.parse.wikitext)) return; var DictionaryText = data.parse.wikitext['*'].split('-----')[1] var genrealWarningWords = DictionaryText.split('\n*'); var checks = []; for (var i=0;i<genrealWarningWords.length;i++) { var splittedWarn = genrealWarningWords[i].split("//"); if ( splittedWarn.length !== 2 ) continue; checks.push({ 'test': new RegExp( splittedWarn[0], 'i' ), 'remark': splittedWarn[1] }); } chectTyTool.languageCheck(checks); }); var countRgx = /(?:[^ ]+ ){2}.?(?:ש[נת]י|שלוש[תה]?|ארבע[הת]?|חמשת?|חמישה|ששת?|שבע[הת]?|תשע[הת]?|עשר[הת]?) [א-ת]+/g, gramCheck = [], m, self = this; while (m = countRgx.exec(txt)) { gramCheck.push(m) } if (gramCheck.length) $.post('//tools.wmflabs.org/eranbot/shtei_shekel/heb_check.py', { wikitext: gramCheck.join('\n') } ).done(function(d){ if (!d.errs || d.errs.length === 0) return; var zaharNekevaWarns = $('<div></div>'); for ( var i = 0; i < d.errs.length; i++ ) { var origRgx = new RegExp(d.errs[i].orig); zaharNekevaWarns.append(self.createSearchLink(origRgx)); zaharNekevaWarns.append(' - ייתכן שיש אי התאמה במין ב"' + 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(' - נמצאה הערת שוליים המפנה להערה הקודמת בצורה של שם. יש להחליף לציון מקור מדויק. ראו עוד: <a href="'+mw.util.getUrl('ויקישיבה:הערות שוליים')+'">ויקישיבה:הערות שוליים</a><br/>'); } } if (checkWarnings.html().length) this.writeMsg(checkWarnings, 'alert'); }, mergeRefs: function() { // merge refs with same content this.autoMergeRefs(); // merge refs with name and content that are equal this.mergeRefsWithoutName(); // merge refs with same content and assign name. requires some manual work }, autoMergeRefs: function() { // merge refs with same content and same name var references = {},// a dictionary where key is the ref name and value is count refsContent = {},// a dictionary where key is the ref name and value is the content refReEn = /<ref name="([^"]+?)">(.+?)<\/ref>/g, wikitext = this.textbox.value, mergedRefs = [], mergedRefsNames = [], m, k, i; while ( m = refReEn.exec( wikitext ) ){ references[m[1]] = (references[m[1]] || 0) + 1; refsContent[m[1]] = { content: m[2], text: m[0] }; } for (k in references) { if (references[k] > 1) { var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext), shortRef = chectTyTool.named_comment + k + '}}'; i = 0; if (content) wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(content[0]), 'g'), function(m) { return (i++? shortRef : m); }); mergedRefs.push(k); } } // merge referecnes with same content but different name for (k in refsContent) { if ($.inArray(k,mergedRefsNames) != -1) continue; // skip name already merged for (i in refsContent) { if (k === i) continue; // skip same name if (refsContent[k].content == refsContent[i].content) { // two refs with same content but different name var oldRefName = new RegExp('<ref name="'+mw.util.escapeRegExp(i)+'" */>', 'g'); mergedRefsNames.push(i); shortRef = chectTyTool.named_comment + k + '}}'; wikitext = wikitext.replace(refsContent[i].text, shortRef); wikitext = wikitext.replace(oldRefName, shortRef); } } } if (mergedRefs.length + mergedRefsNames.length) { if (mergedRefs.length) this.writeMsg( $('<div>').text('מיזוג הערות: ' + mergedRefs.join(', ')) ); if (mergedRefsNames.length) this.writeMsg( $('<div>').text('מיזוג הערות עם שמות שונים: ' + mergedRefsNames.join(', ')) ); this.addSummary( 'מיזוג הערות אוטומטי' ); this.textbox.value = wikitext; } }, mergeRefsWithoutName: function() { // merge refs with same content var references = {},// a dictionary where key is the ref content and the value is list of uses refTemplateRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g, refTagRE = /<ref>(.+?)<\/ref>/g, wikitext = this.textbox.value, m; while ( m = refTemplateRE.exec( wikitext ) ){ references[m[1]] = references[m[1]] || []; references[m[1]].push(m[0]); } while ( m = refTagRE.exec( wikitext ) ){ references[m[1]] = references[m[1]] || []; references[m[1]].push(m[0]); } for (var refContet in references) { var refUses = references[refContet]; if ( refUses.length === 1 ) continue; if(/^שם[ .,]|^שם$/.test(refContet) || /\bibid(?![^a-z])/i.test(refContet)) continue; // skip ibid refs var commonRefStructure = /(.+?) .+ (?:עמ|p).? ?([0-9]+)/.exec(refContet); var defaultRefName = ''; if (commonRefStructure) { defaultRefName = commonRefStructure[1]+commonRefStructure[2]; } var refName = prompt('ישנה הערת שוליים החוזרת מספר פעמים. ניתן להפנות את כל המופעים אל הערה אחת באמצעות מתן שם קצר ובעל משמעות להערה.\nאנא הזינו שם להערה הבאה:\n'+refContet, defaultRefName); if ( !refName ) continue; wikitext = wikitext.replace( refUses[0], chectTyTool.named_comment+refName+'|'+refContet+'}}'); for (var refI = 1; refI<refUses.length; refI++) { wikitext = wikitext.replace( refUses[refI], chectTyTool.named_comment+refName+'}}'); this.addSummary( mw.msg( 'checkty-ref-merge' ) ); // addSummary will only add it once } this.textbox.value = wikitext; } }, titleOrderCheck: function(){ // validates the titles order is consistent var orderedTitles = ['ראו גם', 'לקריאה נוספת', 'קישורים חיצוניים', 'הערות שוליים'], isSorted = 1, titles = $('#wpTextbox1').val().match('==\\s*'+orderedTitles.join('|')+'\\s*==','g'), i, indexes; if (!titles) return; // no such titles indexes = $.map( titles, function(e){return orderedTitles.indexOf(e.replace(/\s*==\s*/g,''))}); for ( i=0; ( i < indexes.length-1 ) && isSorted; i++) { isSorted &= (indexes[i] < indexes[i+1]) }; if ( !isSorted ) { this.writeMsg($('<div>מומלץ לתקן את סדר הכותרות ל: ' + orderedTitles.join(', ') + '</div>'), 'alert' ); } }, refDirSuggest: function() { // suggest adding direction for refs var wikitext = this.textbox.value, defaultDir = (/{{הערות שוליים *\| *יישור *= *שמאל}}/.exec( wikitext ))? 'ltr' : 'rtl', ltrRefRegex = /\{\{הערה\|(?:שם ?=[^|]*\|)?(?:1= *)?(?! *\[?https?:\/\/[^ ]+\]? *\}\})( *\[?[a-z][^א-ת{|]+?)\}\}/ig, rtlRefRegex = /\{\{הערה\|(?!שם ?=)(?:1= *)?([א-ת][^a-z{|]+?|\[http:[^ ]+ [א-ת][^a-z{|]+?)\}\}/ig, nonDefaultRefRegex = (defaultDir == 'rtl') ? ltrRefRegex : rtlRefRegex, uncommonDir = (defaultDir == 'rtl') ? 'שמאל' : 'ימין', m; while( m = nonDefaultRefRegex.exec(wikitext)) { var fixRefDirLink = $('<a href="#">'+mw.msg( 'checkty-ref-dir-fix' )+'</a>').data({'search': m[0]}).click(function(e){ var specificRefRgx = new RegExp('\\[\\[('+mw.util.escapeRegExp($(this).data('search'))+')(\\]\\]|\\|).+\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g'), wikitext = $('#wpTextbox1').val(); wikitext = wikitext.replace($(this).data('search'), $(this).data('search').replace('}}', '|כיוון='+uncommonDir+'}}')); $('#wpTextbox1').val(wikitext); chectTyTool.addSummary(mw.msg('checkty-ref-dir-fix')); e.preventDefault(); }); var searchRef = this.createSearchLink(m[1]); this.writeMsg($('<div>').append(['נמצאה הערת שוליים ללא הגדרת כיווניות "'+m[1]+'" [',searchRef, ' - ', 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' var lastItems = [/(\n{{בקרת זהויות)/, /(\n{{קצרמר)/,/\n({{הבהרה (?:רפואית|הלכתית|משפטית))/,/(\n{{מיון רגיל:)/, /(\n\[\[קטגוריה:)/]; for (var i=0; (i < lastItems.length) && (wikitext == newText); i++ ) newText = wikitext.replace(lastItems[i], autoRefSection + '$1'); if ( wikitext === newText ) newText = wikitext + autoRefSection; this.textbox.value = newText; this.addSummary('פרק הערות שוליים'); this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-added' )+'</div>'), 'info'); } else { this.writeMsg($('<div>'+mw.msg( 'checkty-missing-ref-section-add' )+'</div>').append($('<a href="#">'+mw.msg( 'checkty-missing-ref-section-autofix' )+'</a>').click(function(){ self.refSection(true); return false; })), 'info'); } }, overlinkify: function() { function removeOverlink(context, link){ var newcontext = context; do { context = newcontext; newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[\\1\\|(.+?)\\]\\]', 'g'), '[[$1$2$3'); newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[(\\1)\\]\\]', 'g'), '[[$1$2$3'); } while( newcontext != context ) return newcontext; } // using [^{}\n] as a quick hack to counting links within templates var wikitext = this.textbox.value, overlinkingRgx = /\[\[([^\[\]\|]+?)(?:\]\]|\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\[\[\1(?:\]\]|\|.+?\]\])/g, m; while ( m = overlinkingRgx.exec(wikitext) ) { if (/(?:File|קובץ|תמונה|מדיה):.+/.test(m[1])) { continue; // skip files } var removeLink = $('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').data({'search': m[1]}).click(function(e){ var specificOverlinkingRgx = new RegExp('\\[\\[('+$(this).data('search')+')(\\]\\]|\\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g'); var wikitext = $('#wpTextbox1').val(), m; while( m = specificOverlinkingRgx.exec( wikitext ) ) { wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1])); } $('#wpTextbox1').val(wikitext); chectTyTool.addSummary('הסרת קישורים עודפים'); e.preventDefault(); }); var searchLink = this.createSearchLink( new RegExp( '\\[\\[' + mw.util.escapeRegExp(m[1]) + '(?:\\||\\]\\])' ) ); this.writeMsg($('<div>').append(['נמצאו קישורים עודפים ל"'+m[1]+'" [',searchLink, ' - ', removeLink, ']']), 'alert'); wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1])); } }, getWikidataApi: function(callback) { return new mw.ForeignApi( 'https://www.wikidata.org/w/api.php' ); }, extractWikidataLabelsSuggestions: function() { var suggestLabelsREen = /(?:\[\[|\|)([א-ת' \-]+?)\]\](?: \('*([a-z][^א-ת]+?)'*\)| *\{\{אנג?\|(.+?)\}\})/gi, langLink = /\{\{קישור שפה\|([א-ת]+)\| *([^|]+?)\| *([א-ת '\-]+?)\}\}/gi, langTable = { 'ספרדית': 'es', 'אנגלית': 'en' }, self = this, text = this.textbox.value, suggestionsByLang={}, // lang -> { foreign title -> hebrew label } foreignTitles= [], m, lang, suggestions; suggestionsByLang['en'] = {}; // populate suggestions while(m = suggestLabelsREen.exec(text)) suggestionsByLang['en'][m[2] || m[3]] = m[1]; while(m = langLink.exec(text)) { if (!langTable.hasOwnProperty(m[1])) { console.log('wikidataLabelsSuggested: Missing lang: ' + m[1]); continue; } lang = langTable[m[1]]; // lang code if (!suggestionsByLang[lang]) suggestionsByLang[lang] = {}; suggestionsByLang[lang][m[2]] = m[3]; } // query wikidata by lang for (lang in suggestionsByLang) { self.suggestWikidataLabelTranslate(suggestionsByLang[lang], lang); } }, suggestWikidataLabelTranslate: function(suggestions, lang) { var foreignTitles = [], batchsize = 50, self = this; for(var v in suggestions) foreignTitles.push(v); if (foreignTitles.length === 0) return; var extWikiApi = new mw.ForeignApi('//'+lang+'.wikipedia.org/w/api.php'), queries = Math.ceil(foreignTitles.length/batchsize), def = $.Deferred(), dataEntities = {}, redirects = {}; for(var i=0; i<queries; i++) { // go through enwiki API, to resolve redirects instead of direct approach with wikidataApi.getEntitiesByPage extWikiApi.get({ action: 'query', titles: foreignTitles.slice(i*batchsize,(i+1)*batchsize).join('|'), redirects: 1, prop: 'pageprops', ppprop: 'wikibase_item' }).done(function(d) { for(var i in d.query.redirects) redirects[d.query.redirects[i].to]=d.query.redirects[i].from; var wikidataIds = []; for(var i in d.query.pages) if(d.query.pages[i].pageprops && d.query.pages[i].pageprops.wikibase_item) wikidataIds.push(d.query.pages[i].pageprops.wikibase_item); if (wikidataIds.length === 0) return; self.getWikidataApi().get({ action: 'wbgetentities', ids: '\x1f' + wikidataIds.join( '\x1f' ), props: '\x1f' + ['labels', 'sitelinks'].join( '\x1f' ), languages: '\x1f' + ['he', lang].join( '\x1f' ) }).done(function(d){ queries--; $.extend(dataEntities, d.entities); if (queries === 0) def.resolve(dataEntities); }); }); } def.done(function(data) { var found = false, translations = $('<div>ייתכן שהערך מכיל תוויות חסרות לישויות בוויקינתונים:</div>'), langSite = lang + 'wiki'; // example: enwiki for(var en in data) { if (/^-/.exec(en)) continue; if (data[en].labels && data[en].labels.hasOwnProperty('he')) continue; // already have hebrew label found = true; var suggestion = suggestions[data[en].sitelinks[langSite].title] || suggestions[redirects[data[en].sitelinks[langSite].title]]; translations.append($('<li>').append($('<a>', { href: 'https://www.wikidata.org/wiki/'+en, text: en + ' ('+data[en].labels[lang].value+')', target:'_blank' }).data({ 'he': suggestion, 'foreignLabel': data[en].sitelinks[langSite].title, 'q': en }).click(function(){ self.wikidataLabelTranslate($(this).data('q'), $(this).data('foreignLabel'), $(this).data('he')); return false; }))); } if (found) self.writeMsg(translations, 'articleSearch'); }); }, wikidataLabelTranslate: function(entityId, foreignLabel, suggestion) { var localLabel = prompt(mw.msg('checkty-set-label', foreignLabel), suggestion); if (localLabel) { this.getWikidataApi().postWithToken( 'csrf', { action: 'wbsetlabel', id: entityId, value: localLabel, language: mw.config.get('wgContentLanguage') } ).done(function(d) { if (d.success) mw.notify(mw.msg('checkty-translate-saved')); }) } }, wikidataLabelsMissing: function() { var self = this, batchSize = 50, needTranslateQ = $( 'a.wb-entity-link[href*="Q"]' ) .filter( function( i, e ) { return /[a-z]/i.test( e.text ) } ) .map( function() { var m=/(Q[0-9]+)/.exec(this.href); if (m) return m[0]; }) .toArray(); if (needTranslateQ.length === 0 ) return; if (needTranslateQ.length>batchSize) needTranslateQ = needTranslateQ.slice(0, batchSize); // limit to batch size this.getWikidataApi().get({ action: 'wbgetentities', ids: '\x1f' + needTranslateQ.join( '\x1f' ), props: '\x1f' + ['labels'].join( '\x1f' ), languages: mw.config.get('wgContentLanguage') }).done( function(d) { var needTranslateIndeedQ = []; if (!d.entities) return; for(var q in d.entities) { if (d.entities[q].labels && !d.entities[q].labels.hasOwnProperty(mw.config.get('wgContentLanguage'))) needTranslateIndeedQ.push(q); } if(needTranslateIndeedQ.length === 0) return; var msg = $('<div>הישויות הבאות חסרות תווית בעברית בוויקינתונים: </div>').append($( 'a.wb-entity-link[href*="Q"]' ).filter( function( i, e ) { return $.inArray(/Q[0-9]+/.exec(e.href)[0], needTranslateIndeedQ)+1 } ).clone().css('margin', '0 3px')); self.writeMsg(msg, 'alert'); $('a', msg).click(function(){ self.wikidataLabelTranslate(/Q[0-9]+/.exec($(this).prop('href'))[0], $(this).text()); return false; }); }); }, numberRangeDash: function(fix) { // replace minus => dash foreach x-y s.t x<y and swap y and x otherwise. prefix/suffix requirement in regex to make sure it is within sentence var numberRangeReNoMinus = /([א-ת]+'?[-\ ]*)((?:\[\[|\()?[0-9]+(?:\]\])?)-((?:\[\[)?[0-9]+)((?:\]\]|\))?[.:,]?(?:[ \|]|\n)(?!לפנה"ס))/g, wikitext = this.textbox.value, replacements = [], m, i; while(m = numberRangeReNoMinus.exec(wikitext)) { if (m[1]=='בואינג ') continue; // skip wrong suggestion // note - in replacement we dont include the prefix/suffix to make consistent replacement if ( parseInt(m[2].replace(/[^0-9]/g, '')) < parseInt(m[3].replace(/[^0-9]/g, '')) ) { replacements.push([m[1]+m[2] + '-' + m[3], m[1]+m[2] + '–' + m[3]]); } else if ( (parseInt(m[2].replace(/[^0-9]/g, '')) > parseInt(m[3].replace(/[^0-9]/g, ''))) && (/^[0-9]+$/.test(m[2])) && (/^[0-9]+$/.test(m[3])) ) { replacements.push([m[1]+m[2] + '-' + m[3], m[1]+m[3] + '–' + m[2]]); } } if (replacements.length === 0) return; if (fix) { for(i = 0; i < replacements.length; i++) { wikitext = wikitext.replace(new RegExp(mw.util.escapeRegExp(replacements[i][0]), 'g'), replacements[i][1]); } this.textbox.value = wikitext; this.addSummary( 'קו מפריד בטווח מספרים' ); } else { this.writeMsg($('<div><a href="#">'+mw.msg( 'checkty-fix-numberRangeDash' )+'</a></div>').click(function(e){ chectTyTool.numberRangeDash(true); e.preventDefault(); })); } }, //original version from http://code.google.com/p/proveit-js/source/browse/ProveIt_Wikipedia.js#384 //thanks to Georgia Tech Research Corporation. Atlanta, GA 30332-0415 highlightString: function (toFind) { var txtArea = $('#wpTextbox1'); // cast to string if this is regex if ( RegExp.prototype.isPrototypeOf(toFind) ) { toFind = toFind.exec(txtArea.val()); if (!toFind) return; toFind = toFind[0]; } var nextPlace = txtArea.val().indexOf(toFind, txtArea.textSelection('getCaretPosition') + 1); if (nextPlace === -1) nextPlace = txtArea.val().indexOf(toFind); //start from begining if (nextPlace === -1) return; //not found... nothing to do var origText = txtArea.val(); txtArea.val(origText.substring(0, nextPlace)); txtArea.focus(); txtArea.scrollTop(1000000); //Larger than any real textarea (hopefully) var curScrollTop = txtArea.scrollTop(); txtArea.val(origText); if (curScrollTop > 0) { var HALF_EDIT_BOX_HEIGHT = 200; txtArea.scrollTop(curScrollTop + HALF_EDIT_BOX_HEIGHT); } txtArea.focus().textSelection('setSelection', { start: nextPlace, end: nextPlace + toFind.length }); }, addAuthorityControl: function(v) { var t = this.textbox.value, acTemplate = /\{\{בקרת זהויות[\}|]/g, artsTitle = /== *(?:מ?ספרי[הו]|מ?יצירותי[הו]|מ?חיבורי[הו]|מאמרים נבחרים|פילמוגרפיה.*|(?:מבחר)? (?:כתבי)|דיסקוגרפיה|יצירות) *==/, //cheap hint for art occuption in text artsCategory = /\[\[קטגוריה:(מוזיקאיות|מוזיקאים|זמרות|זמרים|סופרים|סופרות|מתרגמים|ציירות|ציירים|במאי|רבנים|רבניות)(?!.+\*)/; //cheap hint for art occuption in category if ( acTemplate.exec( t ) ) return; // AC already exist if ( !artsTitle.exec( t ) && !artsCategory.exec( t ) ) return; // no hint will have authority control this.getWikidataApi().get({ action: 'wbgetentities', languages: 'he', sites: mw.config.get('wgDBname'), titles: mw.config.get('wgPageName'), props: '\x1f' + ['claims', 'info'].join( '\x1f' ) }).done(function(d){ var hasAC = false, authControlProps = [ 'P3372', 'P864', 'P1907', 'P6804', 'P2558', 'P4186', 'P3293', 'P1015', 'P2092', 'P1890', 'P950', 'P268', 'P428', 'P651', 'P1273', 'P271', 'P1908', 'P1707', 'P2456', 'P2349', 'P6792', 'P227', 'P902', 'P1146', 'P396', 'P1736', 'P213', 'P347', 'P1248', 'P244', 'P886', 'P1368', 'P640', 'P434', 'P982', 'P1330', 'P966', 'P1004', 'P436', 'P1407', 'P435', 'P549', 'P1225', 'P1048', 'P349', 'P2041', 'P691', 'P409', 'P3348', 'P949', 'P5034', 'P1695', 'P1003', 'P1375', 'P1006', 'P496', 'P2750', 'P1053', 'P3065', 'P650', 'P350', 'P947', 'P906', 'P781', 'P3430', 'P269', 'P4012', 'P1323', 'P7314', 'P1693', 'P3544', 'P1694', 'P1362', 'P1315', 'P6213', 'P245', 'P1157', 'P8034', 'P214', 'P7859' ], entityId, entity; for (entityId in d.entities) { entity = d.entities[entityId]; }; if (!entityId) return; // no entity if (entity.hasOwnProperty('claims')) authControlProps.forEach(function(p) { hasAC |= entity.claims.hasOwnProperty(p); }) if (hasAC) { chectTyTool.addAuthorityControlTemplate(); } chectTyTool.viafSearch(entity, entityId, hasAC); }); }, viafSearch: function(entity, entityId, hasAC){ if (entity.hasOwnProperty('claims') && entity.claims.hasOwnProperty('P214')) { return; } $.getJSON('ttps://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: 'ttps://viaf.org/viaf/' + d.result[i].viafid, target: '_blank' }).text(d.result[i].term), viafAddLink = $('<a>', { href: '#' }).text('הוספה').data({ 'viaf': d.result[i].viafid }).click(function(e){ var viafId = $(this).data('viaf'); chectTyTool.createClaim(entityId, entity.lastrevid, 'value', 'P214', viafId); if (!hasAC) chectTyTool.addAuthorityControlTemplate(); e.preventDefault(); }); viafOptions.append($('<li>').append(viafLink, ' - ', viafAddLink)); } chectTyTool.writeMsg(viafOptions); } ); }, createClaim: function ( entityId, baseRevId, snakType, propertyId, value ) { if ( typeof entityId !== 'string' || typeof baseRevId !== 'number' || typeof snakType !== 'string' || typeof propertyId !== 'string' || value && typeof value !== 'string' && typeof value !== 'object' ) { throw new Error( 'Parameter not specified properly' ); } var params = { action: 'wbcreateclaim', entity: entityId, baserevid: baseRevId, snaktype: snakType, property: propertyId }; if ( value ) { params.value = JSON.stringify( value ); } return this.getWikidataApi().postWithToken( 'csrf', params ); }, addAuthorityControlTemplate: function(){ var t = this.textbox.value, viafTemplate = /\{\{בקרת זהויות[\}|]/g, newText; if ( viafTemplate.exec( t ) ) return; // viaf already exist newText = t.replace(/{{קצרמר/, '{{בקרת זהויות}}\n{{קצרמר'); // before stub if (newText == t) newText = t.replace(/{{מיון רגיל:/, '{{בקרת זהויות}}\n{{מיון רגיל:'); //before default sort if (newText == t) newText = t.replace(/\[\[קטגוריה:/, '{{בקרת זהויות}}\n[[קטגוריה:'); // before categories if (newText == t) newText = t += '\n{{בקרת זהויות}}'; this.textbox.value = newText; this.addSummary('בקרת זהויות'); } }; if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) + 1) $(document).ready(function () { chectTyTool.origText = $('#wpTextbox1').val(); var checktyBtn = new OO.ui.ButtonInputWidget({ label: 'בדיקה', title: 'צ\'קטי - כלי לבדיקת בעיות נפוצות ועוד', accessKey: (window.checkToolKey || 'e'), id:'btnCheckTool' }); checktyBtn.$button.updateTooltipAccessKeys(); $('#wpPreviewWidget').after(checktyBtn.$element.click(chectTyTool.run)); });