مدیاویکی:Gadget-AutoSign.js

از اسلامیکال
پرش به ناوبری پرش به جستجو

نکته: پس از انتشار ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • اینترنت اکسپلورر/ Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
  • اپرا: Ctrl-F5 را بفشارید.
//https://meta.wikimedia.org/wiki/User:Perhelion/signing.js
/** Description: AUTOMATIC SIGNING: if not sure, warn.
*** aut. signing / (automatische Unterschrift) ***
* @documentation: see [[w:de:User:Perhelion/signing]]
* @revision: 20:41, 15 July 2016 (UTC)
* @authors:
*  created 23.04.2006 [[w:de:User:Olliminatore]] version 1.56 13.03.2007
*  updated 23.04.2006 [[w:en:User:Ilmari Karonen]]
*  updated 19.09.2011 – 29.12.2011 [[User:Perhelion]], FIX for non Gecko
*  updated 31.12.2011 [[w:de:User:PerfektesChaos]], some code improvements
*  updated 19.06.2014 Perhelion, fixes (code tidy up, jshint) gimmicks added
*  updated 09.09.2014 [[w:de:User:Schnark]] (code cosmetic)
*  –2016 Perhelion
* tested only on modern browsers <nowiki>
* @license released dual-licensed under the terms of the GFDL v1.2 or the GPL v2.
* required modules: 'jquery.textSelection','mediawiki.language','mediawiki.util', 'mediawiki.action.edit.preview'
todo:
**/
(function($, mw) {
    'use strict';
    if (!mw.libs || mw.libs.threadSign)
        return;
    var ns = mw.config.get('wgNamespaceNumber');
    var name = 'امضاء کردن';

    function useLivePreview() {
        if (!Number(mw.user.options.get('uselivepreview')) && (!$('#wpMinoredit').prop('checked') || $('#wpSigning').prop('checked'))) {
            mw.user.options.set('uselivepreview', 1);
            mw.loader.load('mediawiki.action.edit.preview');
        }
    }
    var threadSign = {
        version: '1.91j',
        init: function() {
            var c = $.extend({
                usersignature: (window.usersignature) ? usersignature : '-- ~~\~~',
                sigAccessKey: '>',
                sigText: null
            }, threadSign.config, mw.config.get(['wgDBname', 'wgAction', 'wgContentLanguage', 'wgRelevantUserName', 'wgFormattedNamespaces', 'wgUserName', 'wgPageName', 'wgIsArticle']));
            if (!/^(edit|submit)$/.test(c.wgAction))
                return;
            var newSection = /section=new/.test(location.search);
            if (!c.sigText)
                c.sigText = c.usersignature;
            c.sigText = ' ' + $.trim(c.sigText) + '\n';
            var regpages = null,
                whitelist = [],
                blacklist = [],
                p, len;
            if (newSection)
                c.dSum = '';
            if (ns === 4) {
                if (c.regpages) {
                    regpages = c.regpages;
                    if (!$.isArray(regpages) || typeof regpages[0] !== 'string')
                        return alert('Config error: "' + regpages + '" must be of type string array.');
                }
                blacklist = [/\/[Ii]ntro$/, /\/[Hh]eader$/, /\/بایگانی?[ _/]/, /\/[Aa]rchive?[ _/]/, /\/\d{4}\/\d\d\/\d\d$/];
                switch (c.wgDBname) {
                    case 'enwiki':
                        whitelist = [':Requests for undeletion', ':Requests for adminship/', ':Requests for arbitration/', ':Requests for permissions', ' for deletion', ' for discussion', ':Dispute resolution noticeboard', ':Adminship survey', ':Deletion review', ':Cleanup', ':SVG help', ':Arbitration/', ':Village pump', ':Articles for deletion', '.*noticeboard.*', ':page protection', 'mediation)', ':Bot requests', ':Help desk', ':Editor review', ':Media copyright questions'];
                        break;
                    case 'fawiki':
                        whitelist = [':نظرخواهی.*',':درخواست.*',':قهوه‌خانه.*',':تابلوی اعلانات.*'];
                        break;
                }
                for (p = 0, len = blacklist.length; p < len; p++) {
                    if (blacklist[p].test(c.wgPageName)) {
                        whitelist = '';
                        break;
                    }
                }
                regpages = (regpages && whitelist) ? whitelist.concat(regpages) : whitelist;
                if (newSection)
                    regpages = '';
                if (whitelist) {
                    if ($.isArray(regpages))
                        for (p = 0, len = regpages.length; p < len; p++) {
                            if (c.wgPageName.indexOf(regpages[p].replace(/ /g, '_')) !== -1) {
                                regpages = '';
                                break;
                            }
                        }
                    if (c.wgDBname === 'enwiki') {
                        $('.hiddencats li').children('a').each(function() {
                            if (this.text && /Non-talk pages that are automatically signed$/.test(this.text))
                                regpages = '';
                        });
                    }
                    if (regpages) {
                        $.when(mw.loader.load('mediawiki.util'), $.ready).then(function() {
                            $.getJSON(mw.util.wikiScript('api'), {
                                action: 'query',
                                prop: 'pageprops',
                                indexpageids: true,
                                titles: c.wgPageName,
                                cache: true,
                                format: 'json',
                                timeout: 3000
                            }).done(function(json) {
                                if (!json || !json.query || !json.query.pages)
                                    return console.log('could not get page info!');
                                json = json.query.pages[json.query.pageids];
                                if (json && json.pageprops && typeof json.pageprops.newsectionlink !== 'undefined') {
                                    if ('Perhelion' === c.wgUserName) alert('Page was still not registered!');
                                    c.regpages = '';
                                }
                            }).always(function() {
                                threadSign.exec(c);
                            });
                        });
                    } else {
                        c.regpages = '';
                        return threadSign.exec(c);
                    }
                }
            } else {
                if (ns % 2 === 1)
                    regpages = '';
                c.regpages = regpages;
                if (regpages === '' || ns === 2)
                    return threadSign.exec(c);
            }
        },
        _cntOcc: function(txt) {
            var sig = /~{3}/g,
                falseRe = /(\{\{subst\:unsig.*?\}\})|(<nowiki>[\s\S]*?<\/nowiki>)|(<!--[\s\S]*?-->)/g,
                count = 0,
                cnt2 = 0,
                cnt = 0;
            while (sig.test(txt))
                cnt++;
            count = txt.match(falseRe) || [];
            for (var i = 0; i < count.length; i++) {
                while (sig.test(count[i]))
                    cnt2++;
            }
            return [cnt, cnt2];
        },
        setIndentation: function(e) {
            var $textarea = $(e.target);
            var txt = $textarea.val();
            var pos = $textarea.textSelection('getCaretPosition');
            if (!pos)
                return;
            var txtE = txt.slice(pos);
            txt = txt.slice(0, pos);
            var lrI = txt.lastIndexOf('\n');
            var line = txt.slice(lrI + 1, pos);
            this.indent = "";
            if (line) {
                var lrM = line.match(/^[:*#]+ ?/);
                if (lrM) {
                    var lrLen = lrM[0].length;
                    if (lrLen) {
                        $textarea.val(txt + '\n' + lrM[0] + txtE);
                        this.indent = [pos, lrLen];
                        lrLen++;
                        $textarea.textSelection('setSelection', {
                            start: pos + lrLen
                        });
                        e.preventDefault();
                    }
                }
            }
            return;
        },
        rmvIndentation: function(e) {
            var $textarea = $(e.target);
            var txt = $textarea.val();
            var pos = this.indent[0];
            if (pos) {
                pos++;
                var txtE = txt.slice(pos + this.indent[1]);
                txt = txt.slice(0, pos);
                this.indent = "";
                $textarea.val(txt + txtE);
                $textarea.textSelection('setSelection', {
                    start: pos
                });
                return e.preventDefault();
            }
        },
        exec: function(c) {
            var $Minoredit = $('#wpMinoredit'),
                $editform = $('#editform'),
                signTxt = [],
                $textarea = $('#wpTextbox1'),
                $sum = $editform.find('input#wpSummary, #wpSummary > input'),
                n = /\n/,
                maxlLength = 40,
                bSig = !(c.regpages !== '' || ns === 2);
            if (window.wikEd instanceof Object)
                return console.log(name, 'is not compatible with wikEd');
            if (bSig) useLivePreview();
            $textarea.on('keypress', function(e) {
                if (e.which === 13)
                    return threadSign.setIndentation(e);
                if (e.which === 8 && threadSign.indent)
                    return threadSign.rmvIndentation(e);
                threadSign.indent = "";
            });
            if (mw.language && $.inArray('de', mw.language.getFallbackLanguageChain()) !== -1)
                signTxt = {
                    boxTitle: 'Diese Bearbeitung automatisch unterschreiben.',
                    boxText: 'Signieren',
                    btnAlt: 'Manuelle Signatur',
                    confirm: 'Es wurde keine Signierung gefunden. Trotzdem fortfahren?'
                };
            else
                signTxt = {
                    boxTitle: 'امضای خودکار این متن',
                    boxText: 'امضاء کردن',
                    btnAlt: 'امضاء به صورت دستی',
                    confirm: 'امضایی یافت نشد ادامه دهم؟'
                };
            signTxt.hi = ($.inArray(c.wgContentLanguage, ['de', 'nn', 'da']) !== -1) ? 'Hallo ' : 'درود';
            if (!$editform.length)
                return;
            threadSign.setPing = function() {
                var reUser = getUser();
                reUser = (reUser && reUser[1] && reUser[1] !== c.wgRelevantUserName) ? reUser[1] : '';
                return $textarea.textSelection('encapsulateSelection', {
                    pre: '{{پینگ|',
                    peri: reUser,
                    post: '}}'
                });
            };
            threadSign.setOutdent = function() {
                var txt = $textarea.val();
                var outdent = (c.wgDBname === 'fawiki') ? '\n{{تورفتگی}}' : '\n:┘{{padleft:┌|22|─}}\n';
                var pos = $textarea.textSelection('getCaretPosition');
                if (pos < 0)
                    pos = txt.length;
                if (n.test(txt[pos]) && !n.test(txt[pos - 1]))
                    pos++;
                if (txt[pos + 1] && n.test(txt[pos + 1]))
                    pos++;
                rmvIndent($.trim(txt.slice(0, pos)) + outdent + txt.slice(pos), CmtE);
            };
            var doSig = threadSign.doSig = function(e, pos) {
                var txt = $textarea.val();
                var sigText = c.sigText;
                if (!pos) {
                    pos = $textarea.textSelection('getCaretPosition');
                    sigText = sigText.replace(/\n+$/, '');
                } else {
                    if (pos < 0)
                        pos = txt.length;
                    var tmpRe = /\}\}\s*$/;
                    if (tmpRe.test(txt.slice(pos - 4, pos))) {
                        var lrIndex = txt.slice(0, pos).replace(/\s+$/, '').lastIndexOf(r);
                        var tmpTxt = txt.slice(lrIndex, pos);
                        if (/\|1\s*=[^\n]*(\}\})\s*$/.test(tmpTxt)) {
                            tmpRe = tmpTxt.search(tmpRe);
                            pos = lrIndex + tmpRe;
                            sigText = sigText.replace(/\n+$/, '');
                        }
                    }
                }
                sigText = (pos > maxlLength && !n.test(txt.slice(pos - maxlLength, pos).replace(/\n+$/, ''))) ? sigText : sigText.replace(/white-space:nowrap;?/, '').replace(' style=""', '');
                if (n.test(txt[pos]) && !n.test(txt[pos - 1]))
                    pos++;
                if (txt[pos + 1] && n.test(txt[pos + 1]))
                    pos++;
                rmvIndent(txt.slice(0, pos).replace(/\s+$/, '') + sigText + txt.slice(pos), CmtE, pos);
                if (c.dSum) {
                    if (!/^(?:(\/\*.+?\*\/ *))([^ ])|^([^/]+?)(?!\/\*.+?\*\/ *)/.test($sum.val())) {
                        $sum[0].value += c.dSum;
                    }
                    c.dSum = '';
                }
                return e;
            };
            var $sigBox = $('<input>', {
                type: 'checkbox',
                name: 'wpSigning',
                id: 'wpSigning',
                checked: bSig,
                change: function() {
                    useLivePreview();
                    $(this).next().toggleClass('usermessage');
                },
                'class': 'not-patrolled',
                accessKey: c.sigAccessKey
            });
            var cURL = 'https://upload.wikimedia.org/wikipedia/commons/thumb/';
            var $sBtn = $('<img>', {
                src: cURL + '5/52/Tango_style_insert-signature_icon.svg/22px-Tango_style_insert-signature_icon.svg.png',
                title: 'امضاء کردن',
                rel: 'امضاء کردن',
                alt: signTxt.btnAlt,
                width: '22',
                onclick: 'mw.libs.threadSign.doSig(event)',
                height: '22',
                style: 'cursor:pointer',
                'class': 'tool'
            });
            var $pBtn = $sBtn.clone().attr({
                src: cURL + 'f/fa/Tango_style_ping_icon.svg/22px-Tango_style_ping_icon.svg.png',
                title: 'Ping',
                alt: '',
                rel: 'Ping',
                onclick: 'mw.libs.threadSign.setPing()'
            });
            var $oBtn = $sBtn.clone().attr({
                src: cURL + 'b/bb/Tango_style_outdent_icon.svg/22px-Tango_style_outdent_icon.svg.png',
                title: 'Outdent',
                alt: '',
                rel: 'Outdent',
                onclick: 'mw.libs.threadSign.setOutdent()'
            });
            if (!$('#wpSigning').length) {
                $('#wpWatchthis').parent().parent().append($sigBox, $('<label>', {
                    'for': 'wpSigning',
                    'class': (bSig) ? 'usermessage' : '',
                    title: signTxt.boxTitle,
                    style: 'padding:2px 6px;' + ((!bSig) ? 'border-color:#C00;color:#A00' : ''),
                    text: signTxt.boxText
                }), $sBtn, $oBtn, $pBtn);
            }
            if ($sigBox.updateTooltipAccessKeys)
                $sigBox.updateTooltipAccessKeys();

            function stripeCmt(txt) {
                var cmtRe = /(<!--[\s\S]*?-->)(?!\n*<!--)/g;
                var cmtRight = '';
                CmtE = '';
                while (cmtRe.test(txt)) {
                    CmtE = '\n' + RegExp.lastMatch;
                }
                if (CmtE) {
                    var cmtEndI = cmtRe.lastIndex;
                    if (cmtEndI < txt.length && cmtEndI > txtLen) {
                        cmtRight = txt.slice(cmtEndI);
                    }
                    txt = $.trim(txt.slice(0, cmtEndI - CmtE.length));
                    CmtE += cmtRight;
                }
                return txt;
            }

            function rmvIndent(txt, cmtE, pos) {
                var lrLi = 0;
                if (lrLen) {
                    if (cmtE) {
                        txt = stripeCmt(txt);
                        cmtE = CmtE;
                    }
                    lrLi = txt.lastIndexOf(r);
                    txt = txt.slice(0, lrLi) + txt.slice(lrLi).replace(new RegExp('\\n[:*# ]+ *' + $.trim(reUser) + ' *$'), '') + cmtE;
                    reUser = '';
                    lrLen = '';
                }
                $textarea.val(txt);
                if (pos)
                    $textarea.textSelection('setSelection', {
                        start: pos
                    }).textSelection('scrollToCaretPosition').focus();
                return txt;
            }

            function getUser() {
                var strRe = new RegExp('\\[\\[(?:' + c.wgFormattedNamespaces[2] + '(?:in)?|' + c.wgFormattedNamespaces[3] + '|User(?:[ _]talk)?): ?([^\\]\\|[]+)(?:\\|([^\\]\[]+))?\\]\\]', 'ig');
                var reUser = '';
                while (strRe.test(lrR)) {
                    reUser = [RegExp.lastMatch, RegExp.$1, RegExp.$2];
                }
                if (reUser) {
                    if (reUser[2]) {
                        if (new RegExp(c.wgFormattedNamespaces[3] + '|User[ _]talk', 'i').test(reUser[0]))
                            reUser.pop();
                        else {
                            reUser[2] = $.trim(reUser[2]);
                            if (reUser[2].indexOf(' ') > 1)
                                reUser.pop();
                        }
                    }
                    var user = $.trim(reUser[1].replace(strRe, '$1'));
                    if (user) {
                        if (user.indexOf('/') !== -1)
                            user = user.split('/')[0];
                        else if (user.indexOf('#') !== -1)
                            user = user.split('#')[0];
                    }
                    reUser[1] = (user !== c.wgUserName) ? user : '';
                }
                return reUser;
            }
            var txtOld = $.trim($textarea.val()),
                CmtE = '',
                txt = txtOld,
                r = '\n';
            if (!txt) {
                c.dSum = '';
                if (ns === 3 && !$Minoredit.length && c.wgRelevantUserName !== c.wgUserName) {
                    txt = signTxt.hi + '،\n';
                    $textarea.val(txt).textSelection('setSelection', {
                        start: txt.length - 1
                    }).focus();
                }
            } else if (/-->$/.test(txt))
                txt = stripeCmt(txt);
            var txtLen = txt.length,
                lrI = txt.lastIndexOf(r) + 1,
                lrR = txt.slice(lrI),
                lrM = lrR.match(/^[:*#]+/),
                lrLen = (lrM) ? lrM[0].length : 0,
                txtEndLen = -18 - lrLen,
                txtOldEnd = txtOld.slice(txtEndLen),
                reUser = '',
                txtOldL = txtOld.length;
            if (c.wgAction === 'edit') {
                if (lrLen && lrI + lrLen + 1 < txtLen) {
                    lrI = ':';
                    lrLen++;
                    if (lrLen === 2 && lrM[0] !== ':') {
                        lrI = '';
                        lrLen = 1;
                    }
                    $textarea.val(txt + r + lrM[0] + lrI + ' ' + CmtE);
                    txtLen += lrLen + 2;
                } else if (!lrLen && c.autoSalut && txtOldEnd && /\d{4} \((?:CES?T|UTC)\)[^\d]*?$/.test(lrR)) {
                    lrLen++;
                    reUser = getUser();
                    lrI = '';
                    if (reUser) {
                        lrI = ': ';
                        reUser = (reUser[2] && /\w+/.test(reUser[2])) ? reUser[2] : reUser[1];
                        if (reUser)
                            reUser = signTxt.hi + reUser.replace(/\d+$/g, '') + ', ';
                        lrLen += reUser.length;
                    }
                    txtLen += lrLen + lrI.length;
                    $textarea.val(txt + r + lrI + reUser + CmtE);
                } else {
                    lrLen = 0;
                    if (txt) {
                        txtLen++;
                        $textarea.val(txt + r + CmtE);
                    }
                }
            }
            if (bSig)
                $(window).on( 'load', function() {
                    $textarea.textSelection('setSelection', {
                        start: txtLen
                    }).textSelection('scrollToCaretPosition').focus();
                });

            function offSigBox(e) {
                if (e.type === 'click')
                    e = $(e.target);
                e = e.prop('checked');
                if (e)
                    useLivePreview();
                $sigBox.prop('disabled', e);
            }
            if ($Minoredit.length) {
                offSigBox($Minoredit);
                $Minoredit.click(offSigBox);
            }
            threadSign.doSign = function(e) {
                function _chkEdit(c, pos) {
                    pos = txt.indexOf(c, pos--);
                    if (pos > 1) {
                        var txtEnd = txt.substr(pos, 24).replace(/(^\s+)/, '');
                        var txtNewEnd = txt.slice(pos - 16, pos);
                        var oldp = (c === r) ? txtOld.lastIndexOf(txtEnd) : 0;
                        if (!oldp && /-->$/.test(txtEnd)) {
                            c = txt.lastIndexOf('<!--');
                            if (c < pos)
                                pos = c--;
                        }
                        if (oldp !== -1 && oldp < pos - 3 && txtOld.indexOf(txtNewEnd + RegExp.$1 + txtEnd) === -1) {
                            return pos;
                        }
                    }
                }
                var tolerance = 4;
                var $textarea = $('#wpTextbox1');
                var txt = $.trim($textarea.val());
                if ($('#wpMinoredit').prop('checked') || !$('#wpSigning').prop('checked'))
                    return rmvIndent(txt, CmtE);
                if (!txt)
                    return;
                var cOld = threadSign._cntOcc(txtOld),
                    cNew = threadSign._cntOcc(txt),
                    oldp, txtEnd, pos;
                if (cNew[0] - cNew[1])
                    return rmvIndent(txt, CmtE);
                if (cNew[0] <= cOld[1]) {
                    if (!CmtE) {
                        txtEnd = [txt.substr(txtEndLen - (lrLen ? lrLen + 1 : 0), -txtEndLen), txt.slice(txtEndLen)];
                        oldp = txtOldL + txtEndLen;
                        if (!txtOld || $.inArray(txtOldEnd, txtEnd) < 0) {
                            return doSig(e, -1);
                        }
                    }
                    pos = $textarea.textSelection('getCaretPosition');
                    pos = _chkEdit(r, pos);
                    if (pos) {
                        return doSig(e, pos);
                    }
                    txt = rmvIndent(txt, CmtE);
                    if (txt.length > (txtOldL + tolerance)) {
                        var lines = txt.match(/.+/gm) || [],
                            linesOld = txtOld.match(/.+/gm) || [];
                        if (lines.length > linesOld.length) {
                            lines = lines.filter(function(x) {
                                return linesOld.indexOf(x) < 0;
                            }).pop() || [];
                            if (lines.length) {
                                pos = txt.lastIndexOf(lines);
                                return doSig(e, pos + lines.length);
                            }
                        }
                    }
                    if (CmtE) {
                        pos = _chkEdit('<!--', txtLen);
                        if (pos)
                            return doSig(e, pos);
                    }
                }
                if ('Perhelion' === c.wgUserName && /^wp(Diff|Preview)$/.test(e.target.name)) return console.warn(name + ' main-edit, but no auto signature position found!');
                if (e.target.name === 'wpSave') {
                    $editform.submit(function(e) {
                        if (!confirm(signTxt.confirm))
                            return e.preventDefault();
                    });
                }
            };
            $('#wpSave, #wpPreview, #wpDiff, #wpMinoredit').click(threadSign.doSign);
        }
    };
    mw.libs.threadSign = threadSign;
    if (mw.config.get('wgPageContentModel') === 'wikitext') {
        $(document).trigger('loadWikiScript', ['Gadget-AutoSign.js', threadSign]);
        $.when(mw.loader.using(['jquery.textSelection', 'mediawiki.language', 'user.options']), $.ready).then(threadSign.init);
    }
}(jQuery, mediaWiki));