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

פון המכלול
קפיצה לניווט קפיצה לחיפוש
ק (רעדאגירונגען דורך תנא קמא (שמועס) צוריקגעשטעלט צו דער לעצטער ווערסיע פון צמא לדעת)
צייכן: צוריקדריי
(אויך מוסטער)
 
(13 מיטלסטע ווערסיעס פון 2 באַניצער נישט געוויזן.)
שורה 4: שורה 4:
Author: [[:he:User:ערן]]
Author: [[:he:User:ערן]]
*/
*/
if (mw.config.get('wgContentNamespaces').includes(mw.config.get('wgNamespaceNumber'))) $(function(){
if (mw.config.get('wgContentNamespaces').includes(mw.config.get('wgNamespaceNumber'))) $(function () {
var titleNoBrackets = /(.+?)( \(|$)/.exec(mw.config.get('wgTitle')), allowedSuffix, allowedPrefix;
    var titleNoBrackets = /(.+?)( \(|$)/.exec(mw.config.get('wgTitle')), allowedSuffix, allowedPrefix;
if (titleNoBrackets) titleNoBrackets = titleNoBrackets[1];
    if (titleNoBrackets) titleNoBrackets = titleNoBrackets[1];
else return;
    else return;


// allowedSuffix and allowedPrefix to have strict match for valid words (BOOK => BOOKs and not BOOKmark). default is non strict (which works better for long title)
    // allowedSuffix and allowedPrefix to have strict match for valid words (BOOK => BOOKs and not BOOKmark). default is non strict (which works better for long title)
switch ( mw.config.get('wgContentLanguage') ) {
    switch (mw.config.get('wgContentLanguage')) {
case 'he':
        case 'he':
allowedSuffix = '(?=ים|ות|[^א-ת])';
            allowedSuffix = '(?=ים|ות|[^א-ת])';
allowedPrefix = '(?:[כלבמשהו]|[^א-ת])';
            allowedPrefix = '(?:[כלבמשהו]|[^א-ת])';
break;
            break;
default:
        default:
allowedSuffix = 's?[^a-z]';
            allowedSuffix = 's?[^a-z]';
allowedPrefix = '';
            allowedPrefix = '';
}
    }


switch (mw.config.get('wgUserLanguage') ) {
    switch (mw.config.get('wgUserLanguage')) {
case 'he':
        case 'yi':
mw.messages.set({
            mw.messages.set({
'qlinker-edit' : 'עריכה מהירה',
                'qlinker-edit': 'שנעלע רעדאגירונג',
'qlinker-cancel' : 'ביטול',
                'qlinker-cancel': 'אנולירן',
'linkify-summary': 'הוספת קישור ל[[$1]]',
                'linkify-summary': 'צולייגן לינק צו [[$1]]',
'qlinker-save-success': 'שמירת $1 בוצעה בהצלחה!',
                'qlinker-save-success': '$1 איז אויסגעפירט בס"ד!',
'qlinker-save-continue': 'שמירה',
                'qlinker-save-continue': 'היטן',
'qlinker-skip': 'דילוג דף',
                'qlinker-skip': 'איבערהיפּן בלאט',
'qlinker-skip-match': 'דילוג מופע',
                'qlinker-skip-match': 'איבערהיפּן אינסטאנץ',
'qlinker-safe-search': 'חיפוש בטוח',
                'qlinker-safe-search': 'זיכערע זוך',
'qlinker-invoke': 'הוספת בזק של קישורים',
                'qlinker-invoke': 'שנעל צולייגן לינקס',
'qlinker-sidelink': 'הוספת קישורים',
                'qlinker-sidelink': 'צולייגן לינקס',
'qlinker-no-results': 'לא נמצאו תוצאות',
                'qlinker-no-results': 'קיין רעזולטאטן געפונען',
'qlinker-confirm-masslink': 'לדף זה יש כבר הרבה קישורים, ונדרשת זהירות בהוספת הקישורים. האם נחוצים קישורים נוספים?'
                'qlinker-confirm-masslink': 'דער בלאט האט שוין אסאך לינקס, און פאדערט פאָרזיכטיגקייט ביים צולייגן נאך. פעלט אויס נאך לינקס?'
});
            });
break;
            break;
default:
        default:
mw.messages.set({
            mw.messages.set({
'qlinker-edit' : 'Quick edit',
                'qlinker-edit': 'Quick edit',
'qlinker-cancel' : 'Cancel',
                'qlinker-cancel': 'Cancel',
'linkify-summary': 'Adding link to [[$1]]',
                'linkify-summary': 'Adding link to [[$1]]',
'qlinker-save-success': '$1 has been saved successfully!',
                'qlinker-save-success': '$1 has been saved successfully!',
'qlinker-save-continue': 'Save',
                'qlinker-save-continue': 'Save',
'qlinker-skip': 'Skip page',
                'qlinker-skip': 'Skip page',
'qlinker-skip-match': 'Skip match',
                'qlinker-skip-match': 'Skip match',
'qlinker-safe-search': 'Safe search',
                'qlinker-safe-search': 'Safe search',
'qlinker-invoke': 'Quickly add links',
                'qlinker-invoke': 'Quickly add links',
'qlinker-sidelink': 'Add links',
                'qlinker-sidelink': 'Add links',
'qlinker-no-results': 'No results found',
                'qlinker-no-results': 'No results found',
'qlinker-confirm-masslink': 'This page already has many links. Are you sure?'
                'qlinker-confirm-masslink': 'This page already has many links. Are you sure?'
});
            });
break;
            break;
}
    }




function createQuickEditorDialog(searchRes, safeMode){
    function createQuickEditorDialog(searchRes, safeMode) {
function QuickEditorDialog( config ) {
        function QuickEditorDialog(config) {
  this.contextRgx = new RegExp('(.*[^\\[])(' + mw.util.escapeRegExp(titleNoBrackets) +')((?![^\\[\\{]*[\\]\\}]).*)', 'ig');
            this.contextRgx = new RegExp('(.*[^\\[])(' + mw.util.escapeRegExp(titleNoBrackets) + ')((?![^\\[\\{]*[\\]\\}]).*)', 'ig');
  this.contextRgxLink = new RegExp('(.*\\[\\[)([^\\]]+?)\\|(' + mw.util.escapeRegExp(titleNoBrackets) +')(\\]\\].*)', 'ig');
            this.contextRgxLink = new RegExp('(.*\\[\\[)([^\\]]+?)\\|(' + mw.util.escapeRegExp(titleNoBrackets) + ')(\\]\\].*)', 'ig');
  this.pageI = -1;
            this.pageI = -1;
  this.matchI = 0;
            this.matchI = 0;
  this.searchData = null;
            this.searchData = null;
  this.curPage = null;
            this.curPage = null;
  this.safeMode = safeMode;
            this.safeMode = safeMode;
  this.skipsCounter = 0;
            this.skipsCounter = 0;
  this.starttimestamp = null;
            this.starttimestamp = null;
  this.timestamp = null;
            this.timestamp = null;
  QuickEditorDialog.super.call( this, config );
            QuickEditorDialog.super.call(this, config);
}
        }
OO.inheritClass( QuickEditorDialog, OO.ui.ProcessDialog );  
        OO.inheritClass(QuickEditorDialog, OO.ui.ProcessDialog);


// Specify a name for .addWindows()
        // Specify a name for .addWindows()
QuickEditorDialog.static.name = 'QuickEditorDialog';
        QuickEditorDialog.static.name = 'QuickEditorDialog';
// Specify a title statically (or, alternatively, with data passed to the opening() method).  
        // Specify a title statically (or, alternatively, with data passed to the opening() method).  
QuickEditorDialog.static.title = mw.msg('qlinker-edit');
        QuickEditorDialog.static.title = mw.msg('qlinker-edit');


QuickEditorDialog.static.actions = [
        QuickEditorDialog.static.actions = [
  { action: 'saveContinue', label: mw.msg('qlinker-save-continue'), flags: [ 'other', 'progressive' ], icon: 'link' },
            { action: 'saveContinue', label: mw.msg('qlinker-save-continue'), flags: ['other', 'progressive'], icon: 'link' },
  { action: 'skipOne', label: mw.msg('qlinker-skip'), flags: [ 'other', 'progressive' ], icon: 'next' },
            { action: 'skipOne', label: mw.msg('qlinker-skip'), flags: ['other', 'progressive'], icon: 'next' },
  { action: 'skipMatch', label: mw.msg('qlinker-skip-match'), flags: [ 'other', 'progressive' ], icon: 'arrowNext' },
            { action: 'skipMatch', label: mw.msg('qlinker-skip-match'), flags: ['other', 'progressive'], icon: 'arrowNext' },
  { action: 'safeSearch', label: mw.msg('qlinker-safe-search'), flags: [ 'other' ], icon: 'search' },
            { action: 'safeSearch', label: mw.msg('qlinker-safe-search'), flags: ['other'], icon: 'search' },
  { label: mw.msg('qlinker-cancel'), flags: 'safe' }
            { label: mw.msg('qlinker-cancel'), flags: 'safe' }
];
        ];


// Customize the initialize() function: This is where to add content to the dialog body and set up event handlers.  
        // Customize the initialize() function: This is where to add content to the dialog body and set up event handlers.  
QuickEditorDialog.prototype.initialize = function () {
        QuickEditorDialog.prototype.initialize = function () {
  // Call the parent method
            // Call the parent method
  QuickEditorDialog.super.prototype.initialize.call( this );
            QuickEditorDialog.super.prototype.initialize.call(this);
  // Create and append a layout and some content.
            // Create and append a layout and some content.
  this.content = new OO.ui.PanelLayout( { padded: true, expanded: true } );
            this.content = new OO.ui.PanelLayout({ padded: true, expanded: true });
  this.$body.append( this.content.$element );
            this.$body.append(this.content.$element);
};
        };
 
QuickEditorDialog.prototype.getBodyHeight = function () {
  return 400;
};


QuickEditorDialog.prototype.getSetupProcess = function ( data ) {
        QuickEditorDialog.prototype.getBodyHeight = function () {
  data = data || {};
            return 400;
  return QuickEditorDialog.super.prototype.getSetupProcess.call( this, data )
        };
  .next( function () {
// Set up contents based on data
    this.searchData = data.searchData.query;
    this.starttimestamp = data.searchData.curtimestamp;
this.nextPage();
  }, this );
};


// Use the getActionProcess() method to specify a process to handle the
        QuickEditorDialog.prototype.getSetupProcess = function (data) {
// actions (for the 'save' action, in this example).
            data = data || {};
QuickEditorDialog.prototype.getActionProcess = function ( action ) {
            return QuickEditorDialog.super.prototype.getSetupProcess.call(this, data)
  var dialog = this;
                .next(function () {
  switch ( action ) {
                    // Set up contents based on data
case 'skipOne':
                    this.searchData = data.searchData.query;
return new OO.ui.Process( function () {
                    this.starttimestamp = data.searchData.curtimestamp;
  dialog.skipsCounter++;
                    this.nextPage();
  dialog.nextPage();
                }, this);
}, this );
        };
case 'skipMatch':
return new OO.ui.Process( function () {
  dialog.skipsCounter++;
  dialog.nextMatch();
}, this );
case 'saveContinue':
return new OO.ui.Process( function () {
  dialog.savePage();
}, this );
case 'safeSearch':
return new OO.ui.Process( function () {
  dialog.close();
  protectedSearchQuery(true);
}, this );
  }


  // Fallback to parent handler.
        // Use the getActionProcess() method to specify a process to handle the
  return QuickEditorDialog.super.prototype.getActionProcess.call( this, action );
        // actions (for the 'save' action, in this example).
};
        QuickEditorDialog.prototype.getActionProcess = function (action) {
            var dialog = this;
            switch (action) {
                case 'skipOne':
                    return new OO.ui.Process(function () {
                        dialog.skipsCounter++;
                        dialog.nextPage();
                    }, this);
                case 'skipMatch':
                    return new OO.ui.Process(function () {
                        dialog.skipsCounter++;
                        dialog.nextMatch();
                    }, this);
                case 'saveContinue':
                    return new OO.ui.Process(function () {
                        dialog.savePage();
                    }, this);
                case 'safeSearch':
                    return new OO.ui.Process(function () {
                        dialog.close();
                        protectedSearchQuery(true);
                    }, this);
            }


QuickEditorDialog.prototype.savePage = function ( ) {
            // Fallback to parent handler.
if (this.curPage)
            return QuickEditorDialog.super.prototype.getActionProcess.call(this, action);
{
        };
var api = new mw.Api(), pagename = this.curPage;
api.postWithToken('csrf', {
action: 'edit',
title: this.curPage,
summary: mw.msg('linkify-summary', mw.config.get('wgTitle')),
minor: 1,
basetimestamp: this.timestamp,
starttimestamp: this.starttimestamp,
text: this.text,
tags: 'quick linker'
}).done(function(d) {
if (d && d.edit && d.edit.result == 'Success') mw.notify(mw.msg('qlinker-save-success', pagename));
});
}
var self = this;
if(this.safeMode) setTimeout(function(){ self.nextPage(); }, 5000/(self.skipsCounter+1));
else self.nextPage();
};


QuickEditorDialog.prototype.nextMatch = function ( ) {
        QuickEditorDialog.prototype.savePage = function () {
var m, contextPre, contextPost, contextInner, contextInnerOld, newContext, context;
            if (this.curPage) {
this.matchI++;
                var api = new mw.Api(), pagename = this.curPage;
if (this.searchData.pageids.length <= this.pageI) {
                api.postWithToken('csrf', {
return this.nextPage();
                    action: 'edit',
}
                    title: this.curPage,
                    summary: mw.msg('linkify-summary', mw.config.get('wgTitle')),
                    minor: 1,
                    basetimestamp: this.timestamp,
                    starttimestamp: this.starttimestamp,
                    text: this.text,
                //  tags: 'quick linker'
                }).done(function (d) {
                    if (d && d.edit && d.edit.result == 'Success') mw.notify(mw.msg('qlinker-save-success', pagename));
                }).fail(function (d) {
                mw.notify(d);
                });
            }
            var self = this;
            if (this.safeMode) setTimeout(function () { self.nextPage(); }, 5000 / (self.skipsCounter + 1));
            else self.nextPage();
        };


var page = this.searchData.pages[this.searchData.pageids[this.pageI]],
        QuickEditorDialog.prototype.nextMatch = function () {
pagecontent = page.revisions[0]['*'];
            var m, contextPre, contextPost, contextInner, contextInnerOld, newContext, context;
if (page.title == mw.config.get('wgTitle')) {
            this.matchI++;
return this.nextPage();
            if (this.searchData.pageids.length <= this.pageI) {
}
                return this.nextPage();
            }


if (m = this.contextRgx.exec(pagecontent)) {
            var page = this.searchData.pages[this.searchData.pageids[this.pageI]],
contextPost = m[3];
                pagecontent = page.revisions[0]['*'];
contextInner = (m[2] == mw.config.get('wgTitle')) ? '[['+mw.config.get('wgTitle')+']]' : '[['+mw.config.get('wgTitle')+'|' + m[2] + ']]';
            if (page.title == mw.config.get('wgTitle')) {
contextInnerOld = '';
                return this.nextPage();
}
            }
else if (m = this.contextRgxLink.exec(pagecontent)) {
if(m[2].endsWith(')'))
{
m = null; // other existing meaning
}
else
{
contextPost = m[3] == mw.config.get('wgTitle')? m[4] : '|' + m[3] + m[4];
contextInner = mw.config.get('wgTitle');
contextInnerOld = '<s>' + m[2] + (m[3] == mw.config.get('wgTitle')? '|' : '') + '</s>';
}
}


if (!m) return this.nextPage();
            if (m = this.contextRgx.exec(pagecontent)) {
                contextPost = m[3];
                contextInner = (m[2] == mw.config.get('wgTitle')) ? '[[' + mw.config.get('wgTitle') + ']]' : '[[' + mw.config.get('wgTitle') + '|' + m[2] + ']]';
                contextInnerOld = '';
            }
            else if (m = this.contextRgxLink.exec(pagecontent)) {
                if (m[2].endsWith(')')) {
                    m = null; // other existing meaning
                }
                else {
                    contextPost = m[3] == mw.config.get('wgTitle') ? m[4] : '|' + m[3] + m[4];
                    contextInner = mw.config.get('wgTitle');
                    contextInnerOld = '<s>' + m[2] + (m[3] == mw.config.get('wgTitle') ? '|' : '') + '</s>';
                }
            }


context = m[0];
            if (!m) return this.nextPage();
contextPre = m[1];
newContext = contextPre+contextInner+contextPost;
this.content.$element.html('<h1><a href="/'+encodeURI(page.title)+'" target="_blank">'+page.title+'</a></h1><p>'+contextPre+contextInnerOld+'<b>'+contextInner+'</b>'+contextPost+'</p>');
this.curPage = page.title;
this.text = pagecontent.replace(context, newContext);
this.timestamp = page.revisions[0].timestamp;
};


QuickEditorDialog.prototype.nextPage = function ( ) {
            context = m[0];
var m, contextPre, contextPost, contextInner, contextInnerOld, newContext;
            contextPre = m[1];
this.pageI++;
            newContext = contextPre + contextInner + contextPost;
this.matchI = 0;
            this.content.$element.html('<h1><a href="/' + encodeURI(page.title) + '" target="_blank">' + page.title + '</a></h1><p>' + contextPre + contextInnerOld + '<b>' + contextInner + '</b>' + contextPost + '</p>');
if (this.searchData.pageids.length <= this.pageI)
            this.curPage = page.title;
{
            this.text = pagecontent.replace(context, newContext);
if(this.curPage === null) {
            this.timestamp = page.revisions[0].timestamp;
this.content.$element.html('<h1><a target="_blank" href="/Special:Search/'+encodeURI('"' + titleNoBrackets +'" -linksto:"'+mw.config.get('wgPageName') + '"')+'">'+mw.msg('qlinker-no-results')+'</a></h1>');
this.actions.setAbilities( {
saveContinue: false, skipOne: false
} );
} else {
this.close();
}
return;
}


this.nextMatch();
        };
}


// Make the window.
        QuickEditorDialog.prototype.nextPage = function () {
var qlinkerEditor = new QuickEditorDialog( {
            var m, contextPre, contextPost, contextInner, contextInnerOld, newContext;
  size: 'medium'
            this.pageI++;
} );
            this.matchI = 0;
            if (this.searchData.pageids.length <= this.pageI) {
                if (this.curPage === null) {
                    this.content.$element.html('<h1><a target="_blank" href="/Special:Search/' + encodeURI('"' + titleNoBrackets + '" -linksto:"' + mw.config.get('wgTitle') + '"') + '">' + mw.msg('qlinker-no-results') + '</a></h1>');
                    this.actions.setAbilities({
                        saveContinue: false, skipOne: false
                    });
                } else {
                    this.close();
                }
                return;
            }


// Create and append a window manager, which will open and close the window.  
            this.nextMatch();
var windowManager = new OO.ui.WindowManager();
        }
$( 'body' ).append( windowManager.$element );


// Add the window to the window manager using the addWindows() method.
        // Make the window.
windowManager.addWindows( [ qlinkerEditor ] );
        var qlinkerEditor = new QuickEditorDialog({
            size: 'medium'
        });


// Open the window!
        // Create and append a window manager, which will open and close the window.
windowManager.openWindow( qlinkerEditor,  { searchData: searchRes } );
        var windowManager = new OO.ui.WindowManager();
}
        $('body').append(windowManager.$element);


function createAddLinksButton(){
        // Add the window to the window manager using the addWindows() method.
var addLinksWizard = $(mw.util.addPortletLink(
        windowManager.addWindows([qlinkerEditor]);
'p-tb',
'#',
mw.msg('qlinker-sidelink'),
't-quicklinker',
mw.msg('qlinker-invoke'),
null,
'#t-whatlinkshere'
));
addLinksWizard.click(function(e){
protectedSearchQuery(false);
e.preventDefault();
});
return addLinksWizard;
}
function protectedSearchQuery(safeSearch)
{
var api = new mw.Api();
api.get( {
action: 'query',
prop: 'linkshere',
lhlimit: 500,
titles: mw.config.get('wgPageName'),
indexpageids: 1
}).done(function(d) {
var isValid = true, safeMode = false;
if(d.query && d.query.pages && d.query.pages[d.query.pageids[0]] && d.query.pages[d.query.pageids[0]].linkshere && d.query.pages[d.query.pageids[0]].linkshere.length > 100)
{
isValid = confirm(mw.msg('qlinker-confirm-masslink'));
safeMode = true;
}
if (!isValid) return;
searchLinksApi(safeSearch).done(function(q){
if (q.error) mw.notify(q.error.info);
if (!q.query || !q.query.pageids || q.query.pageids.length<=1) {
mw.notify(mw.msg('qlinker-no-results'));
return;
}
mw.loader.using(['oojs-ui-windows', 'oojs-ui.styles.icons-movement', 'oojs-ui.styles.icons-editing-core'], function() { createQuickEditorDialog(q, safeMode) } );
});
})
}


function searchLinksApi(protectPrefixSuffix) {
        // Open the window!
var api = new mw.Api(),
        windowManager.openWindow(qlinkerEditor, { searchData: searchRes });
searchRegexPreSufFix = 'insource:/' + allowedPrefix + mw.util.escapeRegExp(titleNoBrackets) + allowedSuffix +'/',
    }
searchRegexNonSafe = 'insource:/' + mw.util.escapeRegExp(titleNoBrackets) +'/',
 
searchRegex = protectPrefixSuffix? searchRegexPreSufFix : searchRegexNonSafe;
    function createAddLinksButton() {
return api.get( {
        var addLinksWizard = $(mw.util.addPortletLink(
action: 'query',
            'p-tb',
generator: 'search',
            '#',
gsrnamespace: 0,
            mw.msg('qlinker-sidelink'),
gsrsearch: searchRegex + ' -linksto:'+mw.config.get('wgPageName'),
            't-quicklinker',
gsrlimit: 50,
            mw.msg('qlinker-invoke'),
prop: 'revisions',
            null,
rvprop: 'content|timestamp',
            '#t-whatlinkshere'
indexpageids: 1,
        ));
curtimestamp: 1
 
});
        addLinksWizard.click(function (e) {
}
            console.log(e);
if ($('.dmbox').length === 0) { // Don't show the tool at Disambiguation pages because it is useless
            protectedSearchQuery(false);
if ($('.orphanpage, .stub').length>0) {
            e.preventDefault();
searchLinksApi().done(function(d){
        });
if (d.query && d.query.pageids && d.query.pageids.length>1) createAddLinksButton().css('font-weight', 'bold')
        return addLinksWizard;
});
    }
}
    function protectedSearchQuery(safeSearch) {
else {
        var api = new mw.Api();
createAddLinksButton();
        api.get({
}
            action: 'query',
}
            prop: 'linkshere',
            lhlimit: 500,
            titles: mw.config.get('wgTitle'),
            indexpageids: 1
        }).done(function (d) {
            var isValid = true, safeMode = false;
            if (d.query && d.query.pages && d.query.pages[d.query.pageids[0]] && d.query.pages[d.query.pageids[0]].linkshere && d.query.pages[d.query.pageids[0]].linkshere.length > 100) {
                isValid = confirm(mw.msg('qlinker-confirm-masslink'));
                safeMode = true;
            }
            if (!isValid) return;
            searchLinksApi(safeSearch).done(function (q) {
                if (q.error) mw.notify(q.error.info);
                if (!q.query || !q.query.pageids || q.query.pageids.length <= 1) {
                    mw.notify(mw.msg('qlinker-no-results'));
                    return;
                }
                mw.loader.using(['oojs-ui-windows', 'oojs-ui.styles.icons-movement', 'oojs-ui.styles.icons-editing-core'], function () { createQuickEditorDialog(q, safeMode) });
            });
        })
    }
 
    function searchLinksApi(protectPrefixSuffix) {
        var api = new mw.Api(),
            searchRegexPreSufFix = 'insource:/' + allowedPrefix + mw.util.escapeRegExp(titleNoBrackets) + allowedSuffix + '/',
            searchRegexNonSafe = 'insource:/' + mw.util.escapeRegExp(titleNoBrackets) + '/',
            searchRegex = protectPrefixSuffix ? searchRegexPreSufFix : searchRegexNonSafe;
        return api.get({
            action: 'query',
            generator: 'search',
            gsrnamespace: '0|10|8000',
            //gsrsearch: searchRegex + ' -linksto:' + mw.config.get('wgPageName'),
            gsrsearch: 'insource:' + mw.config.get('wgTitle') + ' -linksto:' + mw.config.get('wgTitle'), // רעגעקס ארבעט נישט ביי אונז
            gsrlimit: 50,
            prop: 'revisions',
            rvprop: 'content|timestamp',
            indexpageids: 1,
            curtimestamp: 1
        });
    }
    if ($('.dmbox').length === 0) { // Don't show the tool at Disambiguation pages because it is useless
        if ($('.orphanpage, .stub').length > 0) {
            searchLinksApi().done(function (d) {
                if (d.query && d.query.pageids && d.query.pageids.length > 1) createAddLinksButton().css('font-weight', 'bold')
            });
        }
        else {
            createAddLinksButton();
        }
    }
});
});

יעצטיגע רעוויזיע זינט 16:25, 4 יאנואר 2024

/*
This is script for quickly adding links to article from related articles. It is especially useful for orphan articles (invoked automatically), stub articles (invoked automatically) and new articles which usually have less links compared to long existing articles.

Author: [[:he:User:ערן]]
*/
if (mw.config.get('wgContentNamespaces').includes(mw.config.get('wgNamespaceNumber'))) $(function () {
    var titleNoBrackets = /(.+?)( \(|$)/.exec(mw.config.get('wgTitle')), allowedSuffix, allowedPrefix;
    if (titleNoBrackets) titleNoBrackets = titleNoBrackets[1];
    else return;

    // allowedSuffix and allowedPrefix to have strict match for valid words (BOOK => BOOKs and not BOOKmark). default is non strict (which works better for long title)
    switch (mw.config.get('wgContentLanguage')) {
        case 'he':
            allowedSuffix = '(?=ים|ות|[^א-ת])';
            allowedPrefix = '(?:[כלבמשהו]|[^א-ת])';
            break;
        default:
            allowedSuffix = 's?[^a-z]';
            allowedPrefix = '';
    }

    switch (mw.config.get('wgUserLanguage')) {
        case 'yi':
            mw.messages.set({
                'qlinker-edit': 'שנעלע רעדאגירונג',
                'qlinker-cancel': 'אנולירן',
                'linkify-summary': 'צולייגן לינק צו [[$1]]',
                'qlinker-save-success': '$1 איז אויסגעפירט בס"ד!',
                'qlinker-save-continue': 'היטן',
                'qlinker-skip': 'איבערהיפּן בלאט',
                'qlinker-skip-match': 'איבערהיפּן אינסטאנץ',
                'qlinker-safe-search': 'זיכערע זוך',
                'qlinker-invoke': 'שנעל צולייגן לינקס',
                'qlinker-sidelink': 'צולייגן לינקס',
                'qlinker-no-results': 'קיין רעזולטאטן געפונען',
                'qlinker-confirm-masslink': 'דער בלאט האט שוין אסאך לינקס, און פאדערט פאָרזיכטיגקייט ביים צולייגן נאך. פעלט אויס נאך לינקס?'
            });
            break;
        default:
            mw.messages.set({
                'qlinker-edit': 'Quick edit',
                'qlinker-cancel': 'Cancel',
                'linkify-summary': 'Adding link to [[$1]]',
                'qlinker-save-success': '$1 has been saved successfully!',
                'qlinker-save-continue': 'Save',
                'qlinker-skip': 'Skip page',
                'qlinker-skip-match': 'Skip match',
                'qlinker-safe-search': 'Safe search',
                'qlinker-invoke': 'Quickly add links',
                'qlinker-sidelink': 'Add links',
                'qlinker-no-results': 'No results found',
                'qlinker-confirm-masslink': 'This page already has many links. Are you sure?'
            });
            break;
    }


    function createQuickEditorDialog(searchRes, safeMode) {
        function QuickEditorDialog(config) {
            this.contextRgx = new RegExp('(.*[^\\[])(' + mw.util.escapeRegExp(titleNoBrackets) + ')((?![^\\[\\{]*[\\]\\}]).*)', 'ig');
            this.contextRgxLink = new RegExp('(.*\\[\\[)([^\\]]+?)\\|(' + mw.util.escapeRegExp(titleNoBrackets) + ')(\\]\\].*)', 'ig');
            this.pageI = -1;
            this.matchI = 0;
            this.searchData = null;
            this.curPage = null;
            this.safeMode = safeMode;
            this.skipsCounter = 0;
            this.starttimestamp = null;
            this.timestamp = null;
            QuickEditorDialog.super.call(this, config);
        }
        OO.inheritClass(QuickEditorDialog, OO.ui.ProcessDialog);

        // Specify a name for .addWindows()
        QuickEditorDialog.static.name = 'QuickEditorDialog';
        // Specify a title statically (or, alternatively, with data passed to the opening() method). 
        QuickEditorDialog.static.title = mw.msg('qlinker-edit');

        QuickEditorDialog.static.actions = [
            { action: 'saveContinue', label: mw.msg('qlinker-save-continue'), flags: ['other', 'progressive'], icon: 'link' },
            { action: 'skipOne', label: mw.msg('qlinker-skip'), flags: ['other', 'progressive'], icon: 'next' },
            { action: 'skipMatch', label: mw.msg('qlinker-skip-match'), flags: ['other', 'progressive'], icon: 'arrowNext' },
            { action: 'safeSearch', label: mw.msg('qlinker-safe-search'), flags: ['other'], icon: 'search' },
            { label: mw.msg('qlinker-cancel'), flags: 'safe' }
        ];

        // Customize the initialize() function: This is where to add content to the dialog body and set up event handlers. 
        QuickEditorDialog.prototype.initialize = function () {
            // Call the parent method
            QuickEditorDialog.super.prototype.initialize.call(this);
            // Create and append a layout and some content.
            this.content = new OO.ui.PanelLayout({ padded: true, expanded: true });
            this.$body.append(this.content.$element);
        };

        QuickEditorDialog.prototype.getBodyHeight = function () {
            return 400;
        };

        QuickEditorDialog.prototype.getSetupProcess = function (data) {
            data = data || {};
            return QuickEditorDialog.super.prototype.getSetupProcess.call(this, data)
                .next(function () {
                    // Set up contents based on data
                    this.searchData = data.searchData.query;
                    this.starttimestamp = data.searchData.curtimestamp;
                    this.nextPage();
                }, this);
        };

        // Use the getActionProcess() method to specify a process to handle the 
        // actions (for the 'save' action, in this example).
        QuickEditorDialog.prototype.getActionProcess = function (action) {
            var dialog = this;
            switch (action) {
                case 'skipOne':
                    return new OO.ui.Process(function () {
                        dialog.skipsCounter++;
                        dialog.nextPage();
                    }, this);
                case 'skipMatch':
                    return new OO.ui.Process(function () {
                        dialog.skipsCounter++;
                        dialog.nextMatch();
                    }, this);
                case 'saveContinue':
                    return new OO.ui.Process(function () {
                        dialog.savePage();
                    }, this);
                case 'safeSearch':
                    return new OO.ui.Process(function () {
                        dialog.close();
                        protectedSearchQuery(true);
                    }, this);
            }

            // Fallback to parent handler.
            return QuickEditorDialog.super.prototype.getActionProcess.call(this, action);
        };

        QuickEditorDialog.prototype.savePage = function () {
            if (this.curPage) {
                var api = new mw.Api(), pagename = this.curPage;
                api.postWithToken('csrf', {
                    action: 'edit',
                    title: this.curPage,
                    summary: mw.msg('linkify-summary', mw.config.get('wgTitle')),
                    minor: 1,
                    basetimestamp: this.timestamp,
                    starttimestamp: this.starttimestamp,
                    text: this.text,
                //  tags: 'quick linker'
                }).done(function (d) {
                    if (d && d.edit && d.edit.result == 'Success') mw.notify(mw.msg('qlinker-save-success', pagename));
                }).fail(function (d) {
                	mw.notify(d);
                });
            }
            var self = this;
            if (this.safeMode) setTimeout(function () { self.nextPage(); }, 5000 / (self.skipsCounter + 1));
            else self.nextPage();
        };

        QuickEditorDialog.prototype.nextMatch = function () {
            var m, contextPre, contextPost, contextInner, contextInnerOld, newContext, context;
            this.matchI++;
            if (this.searchData.pageids.length <= this.pageI) {
                return this.nextPage();
            }

            var page = this.searchData.pages[this.searchData.pageids[this.pageI]],
                pagecontent = page.revisions[0]['*'];
            if (page.title == mw.config.get('wgTitle')) {
                return this.nextPage();
            }

            if (m = this.contextRgx.exec(pagecontent)) {
                contextPost = m[3];
                contextInner = (m[2] == mw.config.get('wgTitle')) ? '[[' + mw.config.get('wgTitle') + ']]' : '[[' + mw.config.get('wgTitle') + '|' + m[2] + ']]';
                contextInnerOld = '';
            }
            else if (m = this.contextRgxLink.exec(pagecontent)) {
                if (m[2].endsWith(')')) {
                    m = null; // other existing meaning
                }
                else {
                    contextPost = m[3] == mw.config.get('wgTitle') ? m[4] : '|' + m[3] + m[4];
                    contextInner = mw.config.get('wgTitle');
                    contextInnerOld = '<s>' + m[2] + (m[3] == mw.config.get('wgTitle') ? '|' : '') + '</s>';
                }
            }

            if (!m) return this.nextPage();

            context = m[0];
            contextPre = m[1];
            newContext = contextPre + contextInner + contextPost;
            this.content.$element.html('<h1><a href="/' + encodeURI(page.title) + '" target="_blank">' + page.title + '</a></h1><p>' + contextPre + contextInnerOld + '<b>' + contextInner + '</b>' + contextPost + '</p>');
            this.curPage = page.title;
            this.text = pagecontent.replace(context, newContext);
            this.timestamp = page.revisions[0].timestamp;

        };

        QuickEditorDialog.prototype.nextPage = function () {
            var m, contextPre, contextPost, contextInner, contextInnerOld, newContext;
            this.pageI++;
            this.matchI = 0;
            if (this.searchData.pageids.length <= this.pageI) {
                if (this.curPage === null) {
                    this.content.$element.html('<h1><a target="_blank" href="/Special:Search/' + encodeURI('"' + titleNoBrackets + '" -linksto:"' + mw.config.get('wgTitle') + '"') + '">' + mw.msg('qlinker-no-results') + '</a></h1>');
                    this.actions.setAbilities({
                        saveContinue: false, skipOne: false
                    });
                } else {
                    this.close();
                }
                return;
            }

            this.nextMatch();
        }

        // Make the window.
        var qlinkerEditor = new QuickEditorDialog({
            size: 'medium'
        });

        // Create and append a window manager, which will open and close the window. 
        var windowManager = new OO.ui.WindowManager();
        $('body').append(windowManager.$element);

        // Add the window to the window manager using the addWindows() method.
        windowManager.addWindows([qlinkerEditor]);

        // Open the window!
        windowManager.openWindow(qlinkerEditor, { searchData: searchRes });
    }

    function createAddLinksButton() {
        var addLinksWizard = $(mw.util.addPortletLink(
            'p-tb',
            '#',
            mw.msg('qlinker-sidelink'),
            't-quicklinker',
            mw.msg('qlinker-invoke'),
            null,
            '#t-whatlinkshere'
        ));

        addLinksWizard.click(function (e) {
            console.log(e);
            protectedSearchQuery(false);
            e.preventDefault();
        });
        return addLinksWizard;
    }
    function protectedSearchQuery(safeSearch) {
        var api = new mw.Api();
        api.get({
            action: 'query',
            prop: 'linkshere',
            lhlimit: 500,
            titles: mw.config.get('wgTitle'),
            indexpageids: 1
        }).done(function (d) {
            var isValid = true, safeMode = false;
            if (d.query && d.query.pages && d.query.pages[d.query.pageids[0]] && d.query.pages[d.query.pageids[0]].linkshere && d.query.pages[d.query.pageids[0]].linkshere.length > 100) {
                isValid = confirm(mw.msg('qlinker-confirm-masslink'));
                safeMode = true;
            }
            if (!isValid) return;
            searchLinksApi(safeSearch).done(function (q) {
                if (q.error) mw.notify(q.error.info);
                if (!q.query || !q.query.pageids || q.query.pageids.length <= 1) {
                    mw.notify(mw.msg('qlinker-no-results'));
                    return;
                }
                mw.loader.using(['oojs-ui-windows', 'oojs-ui.styles.icons-movement', 'oojs-ui.styles.icons-editing-core'], function () { createQuickEditorDialog(q, safeMode) });
            });
        })
    }

    function searchLinksApi(protectPrefixSuffix) {
        var api = new mw.Api(),
            searchRegexPreSufFix = 'insource:/' + allowedPrefix + mw.util.escapeRegExp(titleNoBrackets) + allowedSuffix + '/',
            searchRegexNonSafe = 'insource:/' + mw.util.escapeRegExp(titleNoBrackets) + '/',
            searchRegex = protectPrefixSuffix ? searchRegexPreSufFix : searchRegexNonSafe;
        return api.get({
            action: 'query',
            generator: 'search',
            gsrnamespace: '0|10|8000',
            //gsrsearch: searchRegex + ' -linksto:' + mw.config.get('wgPageName'),
            gsrsearch: 'insource:' + mw.config.get('wgTitle') + ' -linksto:' + mw.config.get('wgTitle'), // רעגעקס ארבעט נישט ביי אונז
            gsrlimit: 50,
            prop: 'revisions',
            rvprop: 'content|timestamp',
            indexpageids: 1,
            curtimestamp: 1
        });
    }
    if ($('.dmbox').length === 0) { // Don't show the tool at Disambiguation pages because it is useless
        if ($('.orphanpage, .stub').length > 0) {
            searchLinksApi().done(function (d) {
                if (d.query && d.query.pageids && d.query.pageids.length > 1) createAddLinksButton().css('font-weight', 'bold')
            });
        }
        else {
            createAddLinksButton();
        }
    }
});