|
|
| שורה 1: |
שורה 1: |
| תור "בדיקה" שמבצע החלפות נפוצות של בוט ההחלפות וכן מתריע על בעיות סגנון ועיצוב שונות
| | [[שיחת מדיה ויקי:Gadget-Checkty|הוספת כפתור לבדיקת בעיות סגנון ולשון]] נפוצות, להחלפות של [[חב"דפדיה:בוט|בוט ההחלפות]], תיקון קישורים ל[[חב"דפדיה:פירושונים|פירושונים]] ועוד <span style="color: red;font-size:70%">לא תואם לגאדג'ט "wikEd"{{כ}}</span> |
| // נכתב על ידי [[משתמש:ערן]] ו[[משתמש:קיפודנחש]]
| |
| // לעזרה ראו [[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-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': 'דף זה עשוי להיות דף דיונים. אין לערוך תגובות של עורכים אחרים והשימוש בבדיקה של דף כזה אינו מומלץ. האם ברצונך להפעיל את הכלי למרות זאת?'
| |
| });
| |
| | |
| function dotSpaceRegex() {
| |
| try {
| |
| // proper spacing around , and . using negative lookahead and lookbehind (ES2018) to acronyms (b.b.c)
| |
| return /(?<!\.[א-ת]*)([א-ת]\]?\]?) ?([,\.]) ?(?=[א-ת]?\[?\[?[א-ת]{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 begining from redundant spaces
| |
| from: /^\s+/g,
| |
| to: '',
| |
| comment: 'הסרת רווחים מיותרים'
| |
| }],
| |
| formatReplacesConfig: [{
| |
| from: /\[\[(.*?)\|\1([a-zא-ת]*)\]\]/g,
| |
| to: '[[$1]]$2'
| |
| }, {
| |
| from: /\[\[(.+?)\|([במל])\1([א-ת]*)\]\]/g,
| |
| to: "$2[[$1]]$3"
| |
| }, { // proper spacing around , and . 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: ']],'
| |
| }],
| |
| 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.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();
| |
| },
| |
| 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)) {
| |
| disambigs.push(redirects[p.title] || p.title);
| |
| }
| |
| }
| |
| if (data['query-continue'] !== undefined) {
| |
| var nextReq = chectTyTool.fetchDisambigLinks(data['query-continue'].links.gplcontinue);
| |
| nextReq.done(function (more) {
| |
| dfd.resolve($.merge(disambigs, more));
| |
| });
| |
| } else {
| |
| dfd.resolve(disambigs);
| |
| }
| |
| });
| |
| return dfd.promise();
| |
| },
| |
| mainArticlesMerge: function() {
| |
| var origTxt = this.textbox.value, txt = this.textbox.value, m;
| |
|
| |
| while (m = /(\{\{(?:הפניה לערך מורחב|ערך מורחב)\|[^=]+?\}\}\n){2,}/g.exec(txt)) {
| |
| var articles = [], expArticleRE = /\{\{(?:הפניה לערך מורחב|ערך מורחב)\|([^=]+?)\}\}/g;
| |
| while (ma = expArticleRE.exec(m[0])) articles.push(ma[1]);
| |
| txt = txt.replace(m[0], '{{הפניה לערך מורחב|ערכים=[['+articles.join(']], [[')+']]}}\n');
| |
| }
| |
| this.textbox.value = txt;
| |
| if (origTxt != txt) chectTyTool.addSummary( mw.msg( 'checkty-main-articles-merge-summary' ) );
| |
| },
| |
| formatReplace: function () {
| |
| var txt = this.textbox.value, newTxt;
| |
| // Format autofix
| |
| var specials=[], match;
| |
| // var emptyParametersRgx = /\n *\| *[^|=]+?= *(?=\n(?: *\||\}\}))/mg, emptyParametersMsg, emptyParametersBtn;
| |
| $(this.formatReplacesConfigSafe).each(function (i, o) {
| |
| | |
| newTxt = txt.replace(o.from, o.to);
| |
| if ( newTxt!=txt && o.comment) {
| |
| chectTyTool.addSummary( o.comment );
| |
| }
| |
| txt = newTxt;
| |
| });
| |
|
| |
| //extract inner links, inner templates and inner params - we don't want to sptit those.
| |
| while (true) { //extract inner links, inner templates and inner params - we don't want to sptit those.
| |
| match = txt.match(/(\{\{[^\{\}]*\}\}|(\n|\[\[)(?:File|קובץ|תמונה|Image):.*?[\|\n]|[^\[\0]\[[^\{\}\[]*\])/);
| |
| if (!match || !match.length) break;
| |
| specials.push(match[0]);
| |
| txt = txt.replace(match[0], "\0" + specials.length + "\0");
| |
| }
| |
|
| |
| $(this.formatReplacesConfig).each(function (i, o) {
| |
| newTxt = txt.replace(o.from, o.to);
| |
| if (o.skippable && (chectTyTool.skipCheckty || this.isSection)) return; // skip this one respecting {ללא בוט}
| |
| if ( newTxt!=txt && o.comment) {
| |
| chectTyTool.addSummary( o.comment );
| |
| }
| |
| txt = newTxt;
| |
| });
| |
| | |
| while (true) {
| |
| match = txt.match(/\0(\d+)\0/);
| |
| if (!match || !match.length) break;
| |
| txt = txt.replace(match[0], specials[parseInt(match[1], 10) - 1]);
| |
| }
| |
| this.updateText(txt);
| |
| // if (!emptyParametersRgx.test(txt)) return;
| |
| // emptyParametersMsg = $('<div>', { text: mw.msg('checkty-empty-parameters') }).addClass('checkty-empty-params-warning').append($('<a>', {
| |
| // href: '#',
| |
| // text: 'ניקוי'
| |
| // }).click(function(){ $('#wpTextbox1').val($('#wpTextbox1').val().replace(emptyParametersRgx, '')); chectTyTool.addSummary( mw.msg( 'checkty-empty-parameters-summary' ) ); return false; }));
| |
| // this.writeMsg(emptyParametersMsg, 'info');
| |
| },
| |
| disambigCheck: function () {
| |
| var disambigMsg = this.writeMsg($('<div>', {
| |
| id: 'waitForDisambigs'
| |
| }).text( mw.msg( 'checkty-waiting-disambig-query' ) ), 'info'), self = this;
| |
|
| |
| this.fetchDisambigLinks().fail(function () {
| |
| disambigMsg.remove();
| |
| self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-no-links') }), 'check');
| |
| }).done(function (res) {
| |
| var disambigs;
| |
| disambigMsg.remove();
| |
| if (res.length === 0) {
| |
| self.writeMsg($('<div>', { text: mw.msg('checkty-disambig-success') }), 'check');
| |
| return;
| |
| }
| |
| disambigs = $('<div id="disambigWarnning">'+mw.msg( 'checkty-disambig-links-title' )+'</div>').prepend('<img src="//upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Disambig_RTL.svg/15px-Disambig_RTL.svg.png">').css('padding', '0 5px');
| |
| $.each(res, function (i, disTitle) {
| |
| if (i > 0) {
| |
| disambigs.append(', ');
| |
| }
| |
| disambigs.append($('<a href="' + mw.util.getUrl(disTitle) + '">' + disTitle + '</a>').click(function () {
| |
| var disambigName = $(this).text();
| |
| new mw.Api().get({
| |
| action: 'parse',
| |
| page: disambigName,
| |
| prop: 'text',
| |
| redirects: 1
| |
| }).done(function (data) {
| |
| if (data && data.parse && data.parse.text) {
| |
| var disambig = data.parse.text['*'];
| |
| mw.loader.using( ['jquery.ui'] ).done ( function() { chectTyTool.resolveDisambig( disambigName, disambig ); } );
| |
| } else {
| |
| console.error(data);
| |
| }
| |
| });
| |
| return false;
| |
| }));
| |
| });
| |
| chectTyTool.writeMsg(disambigs);
| |
| });
| |
| },
| |
| getLinkRegex: function(name) {
| |
| return new RegExp('(?:\\.|^)([^\\.\n]*(\\[\\[' + mw.util.escapeRegExp(name) + '[\\|\\]]).*?)[\\.\\n]', 'm');
| |
| },
| |
| resolveDisambig: function (name, data) {
| |
| var offset = 0,
| |
| textbox = this.textbox,
| |
| linkRgx = this.getLinkRegex(name),
| |
| orgPos = $(textbox).textSelection('getCaretPosition'),
| |
| cSentence = $('<div>');
| |
| var options = $('<div>').append($('li', data).filter(function() { return $(this).closest( '.checkty-ignore' ).length === 0; } ).map(function () {
| |
| var a = $(this).children('a').get(0);
| |
| if (a) {
| |
| var storeTitle = $(this).text();
| |
| var anchor = '',
| |
| h = a.href;
| |
| if (h.indexOf('#') + 1) anchor = decodeURI(h.substr(h.indexOf('#')).replace(/\./g, '%').replace(/_/g, ' '));
| |
| $(a).text( a.title.replace(mw.msg( 'checkty-page-doesnt-exist' ), "") + anchor);
| |
| a.title = storeTitle;
| |
| }
| |
| return a || null;
| |
| }).click(resolve))
| |
| .append($('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').click(removeLink));
| |
| var disambigDialog = $('<div>').append( mw.msg('checkty-disambig-meaning', name) + '<hr/>').append(cSentence).append(options.buttonset()).dialog({
| |
| title: mw.msg( 'checkty-dismabig-dialog-title' ),
| |
| close: function () {
| |
| $(textbox).textSelection('setSelection', {
| |
| start: orgPos
| |
| });
| |
| }
| |
| });
| |
| findSentence();
| |
| function findSentence() {
| |
| var text = textbox.value.substr(offset),
| |
| m = text.match(linkRgx);
| |
| if (!m) {
| |
| disambigDialog.dialog('close');
| |
| return;
| |
| }
| |
| offset += text.indexOf(m[1]) + m[1].indexOf(m[2]);
| |
| var linkIndex = m[1].indexOf(m[2]) + 2,
| |
| html = m[1].substr(0, linkIndex) + '<big>' + name + '</big>' + m[1].substr(linkIndex + name.length);
| |
| cSentence.html(html);
| |
| }
| |
| function resolve() {
| |
| var answer = $(this).text(),
| |
| text = textbox.value,
| |
| startLink = text.indexOf('[[' + name, offset);
| |
| if (text.charAt(startLink + 2 + name.length) != '|') answer += '|' + name;
| |
| offset += answer.length + 2;
| |
| text = text.substr(0, startLink + 2) + answer + text.substr(startLink + 2 + name.length);
| |
| textbox.value = text;
| |
| findSentence();
| |
| chectTyTool.addSummary( mw.msg( 'checkty-dismabig-fix-summary' ) );
| |
| return false;
| |
| }
| |
| function removeLink() {
| |
| var text = textbox.value,
| |
| startLink = text.indexOf('[[' + name, offset),
| |
| endLink = text.indexOf(']]', startLink),
| |
| pipeChar = startLink + 2 + name.length,
| |
| linkText = (text.charAt(pipeChar) != '|') ? name : text.substr(pipeChar + 1, endLink - pipeChar - 1);
| |
| offset += (endLink - startLink) + linkText.length;
| |
| text = text.substr(0, startLink) + linkText + text.substr(endLink + 2);
| |
| textbox.value = text;
| |
| findSentence();
| |
| return false;
| |
| }
| |
| },
| |
| addSummary: function (msg) {
| |
| var editSummary = $('#wpSummary').val();
| |
| if (editSummary.indexOf(msg) === -1) $('#wpSummary').val(editSummary + (editSummary.length === 0 ? '' : ', ') + msg);
| |
| // tag the edit
| |
| if ( $('#checktyTag').length === 0 ) {
| |
| $('#editform').append('<input type="hidden" name="wpChangeTags" id="checktyTag" value="צ\'קטי">');
| |
| }
| |
| },
| |
| checkGallery: function() {
| |
| var text = this.textbox.value,
| |
| longGalleryThreshold = 16,
| |
| galleryRgx = /<gallery.+?\n(\n|.)+?<\/gallery>/mg,
| |
| m, longGallery=false;
| |
| while ( m=galleryRgx.exec( text ) ) { var galLength = m[0].split('\n').length-2; longGallery |= (galLength > longGalleryThreshold); }
| |
| if (longGallery) {
| |
| this.writeMsg('<div>' + mw.msg('checkty-long-gallery') + '</div>', 'alert');
| |
| }
| |
| },
| |
| checkImages: function (data) {
| |
| var fairUsageTemplates = ['תבנית:שימוש הוגן', 'תבנית:תמונת חבר כנסת'];
| |
| if (!data) {
| |
| if (!(/\{\{(ויקישיתוף בשורה|מיזמים)/.test(this.textbox.value))) {
| |
| $.getJSON('//www.wikidata.org/w/api.php?callback=?', {
| |
| languages: 'he',
| |
| action: 'wbgetentities',
| |
| sites: mw.config.get('wgDBname'),
| |
| titles: mw.config.get('wgTitle'),
| |
| format: 'json',
| |
| props: 'claims'
| |
| }).done(function (data) {
| |
| if (data.success === undefined || !data.success) return;
| |
| for (var entityId in data.entities) {
| |
| var claims = data.entities[entityId].claims;
| |
| if (claims && claims.hasOwnProperty('P373')) {
| |
| chectTyTool.writeMsg($('<div>', {
| |
| text: mw.msg('checkty-missing-commons-link')
| |
| }).prepend('<img src="//upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Commons-logo.svg/15px-Commons-logo.svg.png">').css('padding', '0 5px').append($('<a>', {
| |
| href: '#',
| |
| text: 'להוספה'
| |
| }).click(function (e) {
| |
| e.preventDefault();
| |
| var ta = $('#wpTextbox1');
| |
| if (ta.textSelection('getCaretPosition') >= ta.val().length) {
| |
| chectTyTool.writeMsg($('<div>').text(mw.msg('checkty-please-position-caret')));
| |
| } else {
| |
| ta.textSelection('encapsulateSelection',{pre:'{{ויקישיתוף בשורה}}'});
| |
| chectTyTool.addSummary('ויקישיתוף בשורה');
| |
| }
| |
| })));
| |
| }
| |
| }
| |
| });
| |
| }
| |
| //in case there are no images in page
| |
| if (!(/\[\[(תמונה|קובץ|File|Image):/i.test(this.textbox.value))) {
| |
| var articleName = mw.config.get('wgPageName');
| |
| var that = this; // we want to use "this" in the done method of the api call.
| |
| new mw.Api().post( {
| |
| action: 'parse',
| |
| title: articleName,
| |
| text: this.textbox.value
| |
| } ).done( function( data ) {
| |
| if ( data && data.parse && data.parse.text && $( data.parse.text['*'] ).find( 'a.image img' ).filter(function() {
| |
| var width = $(this).attr('width');
| |
| if (isNaN(width)) width = $(this).width();
| |
| else width = parseInt(width);
| |
| return (width >= 100) && $(this).parents('.navbox').length==0;
| |
| } ).length === 0 ) {
| |
| var fistURL = that.fistURL({
| |
| datatype: 'articles',
| |
| data: articleName
| |
| });
| |
| var msg = $('<div>', {
| |
| text: 'בדף זה אין תמונות. ניתן לחפש תמונות חופשיות ממקורות שונים. '
| |
| }).append($('<a>', {
| |
| href: decodeURI(fistURL),
| |
| text: 'חיפוש תמונות',
| |
| target: '_blank'
| |
| }));
| |
| that.writeMsg(msg, 'info');
| |
| }
| |
| });
| |
| return;
| |
| }
| |
| new mw.Api().get({
| |
| action: 'query',
| |
| generator: 'images',
| |
| titles: mw.config.get('wgPageName'),
| |
| prop: 'templates',
| |
| tltemplates: fairUsageTemplates.join('|')
| |
| }).done(function (data) {
| |
| if (data && data.query && data.query.pages) chectTyTool.checkImages(data.query.pages);
| |
| });
| |
| } else {
| |
| var fairUseImgs = $.map(data, function (o) {
| |
| if (!o.templates) return;
| |
| var isFairUsage;
| |
| $.each(o.templates, function (k, license) {
| |
| if ($.inArray(license.title, fairUsageTemplates) != -1) {
| |
| isFairUsage = true;
| |
| return false;
| |
| }
| |
| });
| |
| if (isFairUsage) return o.title;
| |
| });
| |
| if (fairUseImgs.length === 0) return;
| |
| //add message with fair usage images
| |
| var fistURL = this.fistURL({
| |
| data: fairUseImgs.join('\r\n'),
| |
| datatype: 'replaceimages'
| |
| });
| |
| var msg = $('<div>', {
| |
| text: 'הדף מכיל תמונות בשימוש הוגן, שמומלץ להחליפן בחלופות חופשיות במידת האפשר. '
| |
| }).append($('<a>', {
| |
| href: fistURL,
| |
| text: 'חיפוש חלופות חופשיות',
| |
| target: '_blank'
| |
| }));
| |
| if (!(new RegExp('\{\{'+mw.msg('checkty-fairuse-img-replace-template')+'\}\}').test($('#wpTextbox1').val())))
| |
| msg.append(' - ').append($('<a>', {
| |
| text: 'סימון להחלפה',
| |
| href: '#'
| |
| }).click(function () {
| |
| var t = $('#wpTextbox1');
| |
| $.each(fairUseImgs, function (i, fiImg) {
| |
| var imgName = mw.util.escapeRegExp(/.:(.+)$/.exec(fiImg)[1]),
| |
| imgDescRE = new RegExp(imgName.replace(' ', '[ _]') + '((?:[^\\[\\]]|\\[\\[[^\\[\\]]*?\\]\\])*?)\]\]', 'i'),
| |
| matches;
| |
| if (!(matches = imgDescRE.exec(t.val()))) {
| |
| return;
| |
| }
| |
| //this is thumb img
| |
| var imgDesc = matches[1].split('|'), isThumb = false, imgCaption = '';
| |
| for (var i in imgDesc) {
| |
| if (/thumb|ממוזער/i.test(imgDesc[i])) {
| |
| isThumb = true;
| |
| } else if (!(/^(ימין|שמאל|מרכז|right|left|center|[0-9]+px)?$/i.test(imgDesc[i]))) {
| |
| imgCaption = imgDesc[i]; //unknown parameter assumed to be description
| |
| }
| |
| }
| |
| if (isThumb) {
| |
| if (imgCaption) {
| |
| imgDesc = matches[1].replace(imgCaption, imgCaption + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
| |
| } else {
| |
| imgDesc = matches[1] + '|{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}';
| |
| }
| |
| t.val(t.val().replace(matches[1], imgDesc));
| |
| chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
| |
| } else {
| |
| //is in infobox heuristic: = before image tag
| |
| var isInInfobox = new RegExp('=\s*\\[\\[(?:file|image|קובץ|תמונה):' + imgName.replace(' ', '[ _]') + '[^\\]]*?\]\]', 'i');
| |
| if (isInInfobox.test(t.val())) {
| |
| t.val(t.val().replace(matches[0], matches[0] + '{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}'));
| |
| chectTyTool.addSummary('{{'+mw.msg('checkty-fairuse-img-replace-template')+'}}');
| |
| }
| |
| }
| |
| });
| |
| }));
| |
| this.writeMsg(msg, 'alert');
| |
| }
| |
| },
| |
| fistURL: function (p) {
| |
| return 'https://chabad.info/?s=' + $.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
| |
| refReEn = /<ref name="([^"]+?)">(.+?)<\/ref>/g,
| |
| wikitext = this.textbox.value, mergedRefs = [], m, k, i;
| |
| while ( m = refReEn.exec( wikitext ) ){
| |
| references[m[1]] = (references[m[1]] || 0) + 1;
| |
| }
| |
| | |
| for (k in references) {
| |
| if (references[k] > 1) {
| |
| var content = new RegExp('<ref name="'+mw.util.escapeRegExp(k)+'">(.+?)</ref>', 'g').exec(wikitext),
| |
| shortRef = 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);
| |
| }
| |
|
| |
| }
| |
| if (mergedRefs.length) {
| |
| this.writeMsg( $('<div>').text('מיזוג הערות: ' + mergedRefs.join(', ')) );
| |
| this.addSummary( 'מיזוג הערות אוטומטי' );
| |
| this.textbox.value = wikitext;
| |
| }
| |
| },
| |
| mergeRefsWithoutName: function() { // merge refs with same content
| |
| var references = {},// a dictionary where key is the ref content and the value is list of uses
| |
| refRE = /\{\{הערה\|(?! *שם *=)(?:1=)?((?:[^\{\}]|\{\{.*?\}\})+)(?!\|=שם=)\}\}/g,
| |
| wikitext = this.textbox.value, m;
| |
| while ( m = refRE.exec( wikitext ) ){
| |
| references[m[1]] = references[m[1]] || [];
| |
| references[m[1]].push(m[0]);
| |
| }
| |
| for (var refContet in references) {
| |
| var refUses = references[refContet];
| |
| if ( refUses.length === 1 ) continue;
| |
| if(/^שם[ .,]|^שם$/.test(refContet) || /\bibid(?![^a-z])/i.test(refContet)) continue; // skip ibid refs
| |
| | |
| var commonRefStructure = /(.+?) .+ (?:עמ|p).? ?([0-9]+)/.exec(refContet);
| |
| var defaultRefName = '';
| |
| if (commonRefStructure) {
| |
| defaultRefName = commonRefStructure[1]+commonRefStructure[2];
| |
| }
| |
| var refName = prompt('ישנה הערת שוליים החוזרת מספר פעמים. ניתן להפנות את כל המופעים אל הערה אחת באמצעות מתן שם קצר ובעל משמעות להערה.\nאנא הזינו שם להערה הבאה:\n'+refContet, defaultRefName);
| |
| if ( !refName ) continue;
| |
| wikitext = wikitext.replace( refUses[0], 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');
| |
| }
| |
| },
| |
| overlinkify: function() {
| |
| function removeOverlink(context, link){
| |
| var newcontext = context;
| |
| do {
| |
| context = newcontext;
| |
| newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[\\1\\|(.+?)\\]\\]', 'g'), '[[$1$2$3');
| |
| newcontext = newcontext.replace(new RegExp('\\[\\[(' + mw.util.escapeRegExp(link)+')([^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?)\\[\\[(\\1)\\]\\]', 'g'), '[[$1$2$3');
| |
| } while( newcontext != context )
| |
| return newcontext;
| |
| }
| |
| // using [^{}\n] as a quick hack to counting links within templates
| |
| var wikitext = this.textbox.value,
| |
| overlinkingRgx = /\[\[([^\[\]\|]+?)(?:\]\]|\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\[\[\1(?:\]\]|\|.+?\]\])/g,
| |
| m;
| |
|
| |
| while ( m = overlinkingRgx.exec(wikitext) )
| |
| {
| |
| var removeLink = $('<a href="#">'+mw.msg( 'checkty-remove-link' )+'</a>').data({'search': m[1]}).click(function(e){
| |
| var specificOverlinkingRgx = new RegExp('\\[\\[('+$(this).data('search')+')(\\]\\]|\\|)[^{}\n]*(?:\{\{[^{]+\}\})?(?:[^{}\n]*)(?:\n\*[^{}\n]*)?\\[\\[\\1(\\]\\]|\\|.+?\\]\\])', 'g');
| |
| var wikitext = $('#wpTextbox1').val(), m;
| |
| while( m = specificOverlinkingRgx.exec( wikitext ) )
| |
| {
| |
| wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
| |
| }
| |
| $('#wpTextbox1').val(wikitext);
| |
| chectTyTool.addSummary('הסרת קישורים עודפים');
| |
| e.preventDefault();
| |
| });
| |
| var searchLink = this.createSearchLink( new RegExp( '\\[\\[' + mw.util.escapeRegExp(m[1]) + '(?:\\||\\]\\])' ) );
| |
| this.writeMsg($('<div>').append(['נמצאו קישורים עודפים ל"'+m[1]+'" [',searchLink, ' - ', removeLink, ']']), 'alert');
| |
| wikitext = wikitext.replace(m[0], removeOverlink(m[0], m[1]));
| |
| }
| |
| },
| |
| getWikidataApi: function(callback) {
| |
| return new mw.ForeignApi( 'ttps://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: 'ttps://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 ttp://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));
| |
| });
| |