ميدياويكي:Gadget-QuickEdit.js

من ويكي مصدر، المكتبة الحرة

ملاحظة: بعد النشر، أنت قد تحتاج إلى إفراغ الكاش الخاص بمتصفحك لرؤية التغييرات.

  • فايرفوكس / سافاري: أمسك Shift أثناء ضغط Reload، أو اضغط على إما Ctrl-F5 أو Ctrl-R (⌘-R على ماك)
  • جوجل كروم: اضغط Ctrl-Shift-R (⌘-Shift-R على ماك)
  • إنترنت إكسبلورر/إيدج: أمسك Ctrl أثناء ضغط Refresh، أو اضغط Ctrl-F5
  • أوبرا: اضغط Ctrl-F5.
/**
 * QuickEdit
 * 
 * Origin name Wikiplus
 * source: https://github.com/Wikiplus/Wikiplus/blob/master/Main.js
 * Past Arabic maintainer: زكريا
 * Current Arabic maintainer: حبيشان
 */

/* global mw */
/// <reference path="../typings/jquery/jquery.d.ts"/>
/**
 * Wikiplus
 * Author: +Eridanus Sora/@妹空酱
 * Github: https://github.com/Last-Order/Wikiplus
 */
/**
 * 依赖组件: MoeNotification
 * https://github.com/Last-Order/MoeNotification
 */
'use strict';

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

function MoeNotification() {
    var self = this;
    this.display = function () {
        var text = arguments.length <= 0 || arguments[0] === undefined ? '喵~' : arguments[0];
        var type = arguments.length <= 1 || arguments[1] === undefined ? 'success' : arguments[1];
        var callback = arguments.length <= 2 || arguments[2] === undefined ? function () {} : arguments[2];

        $('#MoeNotification').append($('<div>').addClass('MoeNotification-notice').addClass('MoeNotification-notice-' + type).append('<span>' + text + '</span>'));
        $('#MoeNotification').find('.MoeNotification-notice').last().fadeIn(300);
        self.bind();
        self.clear();
        callback($('#MoeNotification').find('.MoeNotification-notice').last());
    };
    this.create = {
        success: function success(text, callback) {
            var _callback = callback || function () {};
            self.display(text, 'success', _callback);
        },
        warning: function warning(text, callback) {
            var _callback = callback || function () {};
            self.display(text, 'warning', _callback);
        },
        error: function error(text, callback) {
            var _callback = callback || function () {};
            self.display(text, 'error', _callback);
        }
    };
    this.clear = function () {
        if ($('.MoeNotification-notice').length >= 10) {
            $('#MoeNotification').children().first().fadeOut(150, function () {
                $(this).remove();
            });
            setTimeout(self.clear, 300);
        } else {
            return false;
        }
    };
    this.empty = function (f) {
        $('.MoeNotification-notice').each(function (i) {
            var isFunction = function isFunction(f) {
                if (typeof f === 'function') return true;
                var t = Object.prototype.toString(f);
                return t === '[object Function]' || t === '[object GeneratorFunction]';
            };
            if (isFunction(f)) {
                var object = this;
                setTimeout(function () {
                    f($(object));
                }, 200 * i);
            } else {
                $(this).delay(i * 200).fadeOut('fast', function () {
                    $(this).remove();
                });
            }
        });
    };
    this.bind = function () {
        $('.MoeNotification-notice').mouseover(function () {
            self.slideRight($(this));
        });
    };
    this.slideRight = function (object, speed) {
        object.css('position', 'relative');
        object.animate({
            right: '200%'
        }, speed || 150, function () {
            $(this).fadeOut('fast', function () {
                $(this).remove();
            });
        });
    };
    this.init = function () {
        $('body').append('<div id="MoeNotification"></div>');
    };
    if (!($('#MoeNotification').length > 0)) {
        this.init();
    }
}

$(function () {
    var i18nData = {};
    var scriptPath = location.protocol + '//wikiplus-app.com';
    // #مقطع معدل
    i18nData['ar'] = {
        "__language": "ar",
        "__author": ["زكريا", "حبيشان"],
        "__version": "212",
        "summaryrequired": "لم تكتب ملخصا",
        "redirect_to_summary": "حول إلى [[$1]] بالمحرر السريع",
        "redirect_from_summary": "حول [[$1]] إلى [[$2]] بالمحرر السريع",
        "quickedit_topbtn": "تحرير سريع",
        "quickedit_sectionbtn": "تحرير سريع",
        "back": "رجوع",
        "goto_editbox": "انتقل لصندوق الكتابة",
        "summary_placehold": "الملخص",
        "submit": "احفظ",
        "publish_page": "احفظ الصفحة",
        "publish_change": "احفظ التعديل",
        "preview": "معاينة",
        "cancel": "إلغاء",
        "mark_minoredit": "التعديل طفيف",
        "loading_preview": "المعاينة تحمل",
        "submitting_edit": "التعديل يحفظ",
        "edit_success": "التعديل حفظ في $1 جزء ثانية للألف",
        "cross_page_edit_submit": "يحفظ...",
        "accept": "نعم",
        "decline": "لا",
        "install_finish": "المحرر السريع مشغل",
        "loading": "تحميل...",
        "wikiplus_settings": "إعدادات المحرر السريع",
        "wikiplus_settings_saved": "حفظت الإعدادات",
        "redirect_from": "حول إلى هنا",
        "redirect_desc": "اكتب العنوان المرادف الذي تريد أن يحيل إلى هذه الصفحة",
        "continue": "كمل",
        "default_summary_suffix": "// تحرير سريع",
    };
    i18nData['en'] = {
        "__language": "en",
        "__author": ["Eridanus Sora", "AnnAngela", "YinYan"],
        "__version": "212",
        "unknown_error_name": "Unknown error",
        "api_unaccessiable": "API of this wiki is not available",
        "api_unwriteable": "Write API of this wiki is not available",
        "fail_to_get_timestamp": "Failed to get the timestamp of this page.",
        "fail_to_get_edittoken": "Failed to get the EditToken of this page.",
        "fail_to_get_pageinfo": "Failed to load infomation of this page",
        "not_autoconfirmed_user": "You are not an autoconfiremd user",
        "hit_abusefilter": "Your edit hit the abusefilter(s)",
        "unknown_edit_error": "Unknown edit error",
        "unknown_edit_error_message": "Unknown edit error($1)",
        "notitle": "The title parameter must be set",
        "notext": "The text parameter must be set",
        "notoken": "The token parameter must be set",
        "invalidsection": "The section parameter must be set to an integer or 'new'",
        "protectedtitle": "This title has been protected from creation",
        "cantcreate": "You don't have permission to create new pages",
        "cantcreate_anon": "Anonymous users can't create new pages",
        "articleexists": "The article you tried to create has already existed",
        "noimageredirect_anon": "Anonymous users can't create image redirects",
        "noimageredirect": "You don't have the permission to create image redirects",
        "spamdetected": "Your edit was rejected because it contained a spam fragment",
        "filtered": "The filter callback function rejected your edit",
        "contenttoobig": "The content you submitted exceeds the article size limit",
        "noedit_anon": "Anonymous users can't edit pages",
        "noedit": "You don't have the permission to edit pages",
        "pagedeleted": "The page was deleted during your edit",
        "emptypage": "Creating new, empty pages is not allowed",
        "emptynewsection": "Creating empty new sections is not possible.",
        "editconflict": "Edit Conflict! Don't panic. Please check the difference between your content below and the existing revision, then refresh the page to make another submit",
        "revwrongpage": "The revision you are editing now is not one a valid reversions of this page",
        "undofailure": "Undo failed due to conflicts.",
        "missingtitle": "Missing title in your edit/creation",
        "mustbeposted": "The edit must be submited by POST method",
        "readapidenied": "Read API Denied",
        "writeapidenied": "Write API Denied",
        "noapiwrite": "No available write API in this wiki",
        "badtoken": "Invalid EditToken",
        "missingparam": "One of the parameters title, pageid is required",
        "invalidparammix": "The parameters title, pageid can not be used together",
        "invalidtitle": "Invalid page title",
        "nosuchpageid": "Inexistent page ID",
        "pagecannotexist": "No access to create a new page in this namespace",
        "nosuchrevid": "Inexisting reversion ID",
        "badmd5": "Invalid MD5",
        "hookaborted": "Your edit was rejected by the hook(s)",
        "parseerror": "Failed to parse the wikitext of this page",
        "summaryrequired": "No summary in your edit",
        "blocked": "You have been already BLOCKED",
        "ratelimited": "You've exceeded your rate limit. Please have a tea and try again later",
        "unknownerror": "Unknown error",
        "nosuchsection": "There is no such section",
        "sectionsnotsupported": "Can't edit in this section",
        "editnotsupported": "Can't edit in this section by writing section",
        "appendnotsupported": "Can't append/prepend wikitext to this page",
        "redirect_appendonly": "Only append/prepend can be made to this page because of the rules of the redirect page",
        "badformat": "The requested serialization format can not be applied to the page's content model",
        "customcssprotected": "You're not allowed to edit custom CSS pages",
        "customjsprotected": "You're not allowed to edit custom JavaScript pages",
        "cascadeprotected": "This page is under a cascading protection",
        "network_edit_error": "Failed to edit this page because of network errors",
        "redirect_to_summary": "Redirect to [[$1]] \/\/ Wikiplus",
        "redirect_from_summary": "Redirect [[$1]] to [[$2]] \/\/ Wikiplus",
        "need_init": "Wikiplus haven't been loaded completely. It's a rare occasion so you can try to refresh and try again.",
        "fail_to_get_wikitext": "Failed to load the wikitext of this page",
        "quickedit_topbtn": "QuickEdit",
        "quickedit_sectionbtn": "QuickEdit",
        "fail_to_init_quickedit": "Failed to initialize Wikiplus",
        "back": "Back",
        "goto_editbox": "Jump to editbox",
        "summary_placehold": "Edit summary",
        "submit": "Submit",
        "publish_page": "Publish Page",
        "publish_change": "Publish Changes",
        "preview": "Preview",
        "cancel": "Cancel",
        "mark_minoredit": "Mark this edit as a minor edit",
        "onclose_confirm": "[Wikiplus] Do you really want to close this page when you are still editing it, as you will lose all your unsaved work?",
        "fail_to_get_wikitext_when_edit": "Failed to load wikitext for your edit",
        "cant_parse_wikitext": "Failed to parse the wikitext",
        "loading_preview": "Loading the preview",
        "submitting_edit": "Submitting your edit",
        "edit_success": "Your edit is submitted within $1ms",
        "empty_page_confirm": "The wikitext in your edit is empty, which will empty this page.\r\nPlease set the value of key \"empty\" true to allow this kind of edits. (This is a tip for developers)",
        "cross_page_edit": "The content you are editing belongs to another page, please wait...",
        "cross_page_edit_submit": "Submitting your edit...",
        "cross_page_edit_error": "Failed to load the infomation",
        "install_tip": "Do you allow Wikiplus to collect insensitive data to help us develop Wikiplus and provide feedback to current site: $1 ?",
        "accept": "Yes",
        "decline": "No",
        "install_finish": "Wikiplus is installed, enjoy it",
        "loading": "Loading",
        "cant_add_funcbtn": "Failed to add buttons for Wikiplus",
        "wikiplus_settings": "Wikiplus Setting",
        "wikiplus_settings_desc": "Please modify your setting according to the standards below",
        "wikiplus_settings_placeholder": "Your setting is empty, please modify your setting according to the documentation.",
        "wikiplus_settings_grammar_error": "Syntax error in your setting",
        "wikiplus_settings_saved": "Your settings have been saved",
        "redirect_from": "Redirect from",
        "redirect_desc": "Which page do you want to redirect here?",
        "empty_input": "Empty input",
        "redirect_saved": "Redirection is finished",
        "uninited": "Wikiplus is not completely initialized, please refeash this page",
        "cant_parse_i18ncache": "Failed to parse the cache of i18n file",
        "cant_load_language": "Failed to load i18n file",
        "history_edit_warning": " // You are trying to edit a history revision of this page. This will apply to the latest revision. Please be careful.",
        "create_page_tip": "<!-- You are now creating a new page. Please delete this line and be careful. -->",
        "continue": "Continue anyway",
        "default_summary_suffix": "// Edit via Wikiplus",
        "cross_page_history_revision_edit_warning": "Cross-page edit in history revision is not supported yet."
    };


    /**
     * 加载其他语言文件
     * @param {string} language 语言名
     */
    function loadLanguage(language) {
        $.ajax({
            url: scriptPath + '/languages/get.php?lang=' + language,
            dataType: 'json',
            success: function success(data) {
                if (data.__language && data.__version) {
                    if (i18nData[data.__language]) {
                        if (data.__version >= i18nData[data.__language].__version) {
                            i18nData[data.__language] = data;
                            console.log('Update the language ' + data.___language + ' version to ' + data.___version);
                        } else {
                            // 服务端未跟进语言版本 不更新本地缓存
                        }
                    } else {
                            i18nData[data.__language] = data;
                        }
                    localStorage.Wikiplus_i18nCache = JSON.stringify(i18nData); //更新缓存
                }
            },
            error: function error(e) {
                console.log('Unable to load language ' + language);
            }
        });
    }
    /**
     * 多语言转换
     * @param {stirng} key 字段标识名
     * @return {string} 经过转换的内容 如未找到对应的多语言字段 则返回简体中文
     */
    function i18n(key) {
        //# معدل
        var language = (i18nData[mw.config.get('wgUserLanguage')] && mw.config.get('wgUserLanguage')) || "ar";
        /* # مقطع معلق
        try {
            language = JSON.parse(localStorage.Wikiplus_Settings)['language'] || window.navigator.language.toLowerCase();
        } catch (e) {
            language = window.navigator.language.toLowerCase();
        } */

        if (i18nData[language] && i18nData[language][key]) {
            return i18nData[language][key];
        } else if (i18nData['en'][key]) {
            return i18nData['en'][key];
        } else {
            return;
        }
    }
    /**
     * 获得错误信息
     * @param {stirng} name
     * @return {object} {number,message}
     */
    function getErrorInfo(name) {
        var errorList = {
            unknown_error_name: {
                number: 1001,
                message: i18n('unknown_error_name')
            },
            api_unaccessiable: {
                number: 1002
            },
            api_unwriteable: {
                number: 1003
            },
            fail_to_get_timestamp: {
                number: 1004
            },
            fail_to_get_edittoken: {
                number: 1005
            },
            fail_to_get_pageinfo: {
                number: 1006
            },
            not_autoconfirmed_user: {
                number: 1007
            },
            hit_abusefilter: {
                number: 1008
            },
            unknown_edit_error: {
                number: 1009
            },
            unknown_edit_error_message: {
                number: 1010
            },
            notitle: {
                number: 1011
            },
            notext: {
                number: 1012
            },
            notoken: {
                number: 1013
            },
            invalidsection: {
                number: 1014
            },
            protectedtitle: {
                number: 1015
            },
            cantcreate: {
                number: 1016
            },
            cantcreate_anon: {
                number: 1017
            },
            articleexists: {
                number: 1018
            },
            noimageredirect_anon: {
                number: 1019
            },
            noimageredirect: {
                number: 1020
            },
            spamdetected: {
                number: 1021
            },
            filtered: {
                number: 1022
            },
            contenttoobig: {
                number: 1023
            },
            noedit_anon: {
                number: 1025
            },
            noedit: {
                number: 1026
            },
            pagedeleted: {
                number: 1027
            },
            emptypage: {
                number: 1028
            },
            emptynewsection: {
                number: 1029
            },
            editconflict: {
                number: 1030
            },
            revwrongpage: {
                number: 1031
            },
            undofailure: {
                number: 1032
            },
            missingtitle: {
                number: 1033
            },
            mustbeposted: {
                number: 1034
            },
            readapidenied: {
                number: 1035
            },
            writeapidenied: {
                number: 1036
            },
            noapiwrite: {
                number: 1037
            },
            badtoken: {
                number: 1038
            },
            missingparam: {
                number: 1039
            },
            invalidparammix: {
                number: 1040
            },
            invalidtitle: {
                number: 1041
            },
            nosuchpageid: {
                number: 1042
            },
            pagecannotexist: {
                number: 1043
            },
            nosuchrevid: {
                number: 1044
            },
            badmd5: {
                number: 1045
            },
            hookaborted: {
                number: 1046
            },
            parseerror: {
                number: 1047
            },
            summaryrequired: {
                number: 1048
            },
            blocked: {
                number: 1049
            },
            ratelimited: {
                number: 1050
            },
            unknownerror: {
                number: 1051
            },
            nosuchsection: {
                number: 1052
            },
            sectionsnotsupported: {
                number: 1053
            },
            editnotsupported: {
                number: 1054
            },
            appendnotsupported: {
                number: 1055
            },
            redirect_appendonly: {
                number: 1056
            },
            badformat: {
                number: 1057
            },
            customcssprotected: {
                number: 1058
            },
            customjsprotected: {
                number: 1059
            },
            cascadeprotected: {
                number: 1060
            },
            network_edit_error: {
                number: 1061
            },
            need_init: {
                number: 1062
            },
            fail_to_get_wikitext: {
                number: 1063
            },
            fail_to_init_quickedit: {
                number: 1064
            },
            fail_to_get_wikitext_when_edit: {
                number: 1065
            },
            cant_parse_wikitext: {
                number: 1066
            },
            empty_page_confirm: {
                number: 1067
            },
            uninited: {
                number: 1068
            },
            cant_parse_i18ncache: {
                number: 1069
            },
            cant_load_language: {
                number: 1070
            }
        };
        if (errorList[name]) {
            if (errorList[name].message) {
                return {
                    number: errorList[name].number,
                    message: errorList[name].message
                };
            } else if (i18n(name) !== 'undefined') {
                return {
                    number: errorList[name].number,
                    message: i18n(name)
                };
            } else {
                return {
                    number: errorList[name].number,
                    message: i18n('unknownerror')
                };
            }
        } else {
            return {
                number: errorList.unknown_error_name.number,
                message: errorList.unknown_error_name.message
            };
        }
    }
    /**
     * 抛出错误
     * @param {string} name
     * @return boolean
     */
    function throwError(name, message) {
        var errInfo = getErrorInfo(name);
        var e = new Error();
        e.number = errInfo.number;
        e.message = message || errInfo.message;
        console.log('%cFatal Error [' + e.number + ']:' + e.message, 'color:red');
        console.log(e);
        return e;
    }
    /**
     * 将mw的段落的id转换为可显示的文本
     * @param {string} URL
     * @return string
     */

    var Wikipage = (function () {
        function Wikipage() {
            var pageName = arguments.length <= 0 || arguments[0] === undefined ? window.mw.config.get('wgPageName') : arguments[0];

            _classCallCheck(this, Wikipage);

            console.log('فئة الصفحة قيد الإنشاء');
            //可用性和权限检测
            if (!window.mw) {
                console.log('The page JavaScript doesn\'t load completely or it\'s not a MediaWiki site');
                return;
            }
            if (!window.mw.config.get('wgUserGroups').includes('autoconfirmed') && !window.mw.config.get('wgUserGroups').includes('confirmed')) {
                throwError('not_autoconfirmed_user');
                return;
            }
            //从MediaWiki定义的全局变量中获得信息
            this.pageName = pageName.replace(/ /ig, '_'); // MediaWiki处理空格时可能会出错
            this.revisionId = window.mw.config.get('wgRevisionId');
            this.articleId = window.mw.config.get('wgArticleId');
            this.API = location.protocol + '//' + location.host + window.mw.config.get('wgScriptPath') + '/api.php';
            //从API获得编辑令牌和起始时间戳
            this.editToken = {};
            this.timeStamp = {};
            this.init(this.pageName, {
                success: function success() {
                    console.log('Wikiplus loaded');
                },
                fail: function fail(e) {
                    console.log('Wikiplus failed to load properly (' + e.message + ')');
                }
            });
        }

        /**
         * 针对非本页面的编辑 提供重定义时间戳和权标接口
         * @param {string} titile 标题
         * @param {object} callback 回调函数
         */

        _createClass(Wikipage, [{
            key: 'reConstruct',
            value: function reConstruct(title) {
                var callback = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

                this.init(title, callback);
            }

            /**
             * 获取页面基础信息并记录
             */
        }, {
            key: 'init',
            value: function init(title, callback, config) {
                if (title === undefined) title = this.pageName;
                if (callback === undefined) callback = {};

                var self = this;
                callback.success = callback.success || new Function();
                callback.fail = callback.success || new Function();
                $.ajax({
                    type: 'GET',
                    dataType: 'json',
                    url: this.API,
                    data: {
                        'action': 'query',
                        'prop': 'revisions|info',
                        'titles': title,
                        'rvprop': 'timestamp',
                        'format': 'json'
                    },
                    beforeSend: function beforeSend(request) {
                        request.setRequestHeader('Api-User-Agent', 'Wikiplus/2 (' + mw.config.get('wgWikiID') + ')');
                        console.time('يستغرق الحصول على المعلومات الأساسية للصفحة بعض الوقت');
                    },
                    success: function success(data) {
                        if (data && data.query && data.query.pages) {
                            var info = data.query.pages;
                            for (var key in info) {
                                if (key !== '-1') {
                                    if (info[key].revisions && info[key].revisions.length > 0) {
                                        self.timeStamp[title] = info[key].revisions[0].timestamp;
                                    } else {
                                        callback.fail(throwError('fail_to_get_timestamp'));
                                    }
                                    if (mw.user.tokens.get('csrfToken') && mw.user.tokens.get('csrfToken') !== '+\\') {
                                        self.editToken[title] = mw.user.tokens.get('csrfToken');
                                        console.log('حصل بنجاح على رمز تحرير من الواجهة الأمامية API');
                                    } else {
                                        //前端拿不到Token 尝试通过API
                                        $.ajax({
                                            url: self.API,
                                            type: 'GET',
                                            dataType: 'json',
                                            data: {
                                                'action': 'query',
                                                'meta': 'tokens',
                                                'format': 'json'
                                            },
                                            beforeSend: function beforeSend(request) {
                                                request.setRequestHeader('Api-User-Agent', 'Wikiplus/2 (' + mw.config.get('wgWikiID') + ')');
                                            },
                                            success: function success(data) {
                                                if (data.query && data.query.tokens && data.query.tokens.csrftoken && data.query.tokens.csrftoken !== '+\\') {
                                                    self.editToken[title] = data.query.tokens.csrftoken;
                                                    console.log('Successfully obtain an edit token through the backend API');
                                                } else {
                                                    callback.fail(throwError('fail_to_get_edittoken'));
                                                }
                                            },
                                            error: function error(e) {
                                                callback.fail(throwError('fail_to_get_edittoken'));
                                            }
                                        });
                                        callback.fail(throwError('fail_to_get_edittoken'));
                                    }
                                } else {
                                    if (mw.config.get('wgArticleId') === 0) {
                                        // 如果是空页面就只拿一个edittoken
                                        if (mw.user.tokens.get('csrfToken') && mw.user.tokens.get('csrfToken') !== '+\\') {
                                            self.editToken[title] = mw.user.tokens.get('csrfToken');
                                            console.log('Successfully obtain an edit token from the front-end API');
                                            self.inited = true;
                                        } else {
                                            self.inited = false;
                                            callback.fail(throwError('fail_to_get_edittoken'));
                                        }
                                    } else {
                                        // 如果不是 那就是失败了 抛出错误
                                        self.inited = false;
                                        callback.fail(throwError('fail_to_get_pageinfo'));
                                    }
                                }
                            }
                        }
                    }
                }).done(function () {
                    console.timeEnd('يستغرق الحصول على المعلومات الأساسية للصفحة بعض الوقت');
                    self.inited = self.inited === false ? false : true;
                    callback.success();
                });
            }

            /**
             * 页面编辑
             * @param {string} content 页面内容
             * @param {string} title  页面标题 默认为当前页面标题
             * @param {object} callback 回调函数
             * @param {object} config 设置 覆盖到默认的设置
             */
        }, {
            key: 'edit',
            value: function edit(content) {
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
                var config = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

                var self = this;
                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                if (content === undefined) {
                    if (!config.empty === true) {
                        callback.fail(throwError('empty_page_confirm'));
                        return false;
                    }
                }
                if (self.inited) {
                    $.ajax({
                        type: 'POST',
                        url: self.API,
                        data: $.extend({
                            'action': 'edit',
                            'format': 'json',
                            'text': content,
                            'title': title,
                            'token': self.editToken[title] || self.editToken[self.pageName],
                            'basetimestamp': self.timeStamp[title]
                        }, config),
                        beforeSend: function beforeSend(request) {
                            request.setRequestHeader('Api-User-Agent', 'Wikiplus/2 (' + mw.config.get('wgWikiID') + ')');
                        },
                        success: function success(data) {
                            if (data && data.edit) {
                                if (data.edit.result && data.edit.result === 'Success') {
                                    callback.success();
                                } else {
                                    if (data.edit.code) {
                                        //防滥用过滤器
                                        callback.fail(throwError('hit_abusefilter', i18n('hit_abusefilter') + ':' + data.edit.info.replace('/Hit AbuseFilter: /ig', '') + '<br><small>' + data.edit.warning + '</small>'));
                                    } else {
                                        callback.fail(throwError('unknown_edit_error'));
                                    }
                                }
                            } else if (data && data.error && data.error.code) {
                                callback.fail(throwError(data.error.code.replace(/-/ig, '_')), i18n('unknown_edit_error_message').replace(/\$1/ig, data.error.code));
                            } else if (data.code) {
                                callback.fail(throwError('unknown_edit_error'), i18n('unknown_edit_error_message').replace(/\$1/ig, data.code));
                            } else {
                                callback.fail(throwError('unknown_edit_error'));
                            }
                        },
                        error: function error(e) {
                            callback.fail(throwError('network_edit_error'));
                        }
                    });
                } else {
                    callback.fail(throwError('uninited'));
                }
            }

            /**
             * 编辑段落
             * @param {number} section 段落编号
             * @param {string} content 内容
             * @param {string} title 页面标题
             * @param {object} callback 回调函数
             * @param {object} config 设置
             */
        }, {
            key: 'editSection',
            value: function editSection(section, content) {
                var title = arguments.length <= 2 || arguments[2] === undefined ? this.pageName : arguments[2];
                var config = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
                var callback = arguments.length <= 4 || arguments[4] === undefined ? {} : arguments[4];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                this.edit(content, title, callback, $.extend({
                    'section': section
                }, config));
            }

            /**
             * 重定向页面至
             * @param {string} target 目标页面标题
             * @param {string} title 页面名 默认为当前页面
             * @param {object} callback 回调函数
             */
        }, {
            key: 'redirectTo',
            value: function redirectTo(target) {
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                this.edit('#تحويل [[' + target + ']]', title, callback, {
                    'summary': i18n('redirect_to_summary').replace(/\$1/ig, target)
                });
            }

            /**
             * 重定向自
             * @param {string} origin 重定向页标题
             * @param {string} title 重定向目标页标题 默认为当前页
             * @param {object} callback
             */
        }, {
            key: 'redirectFrom',
            value: function redirectFrom(origin) {
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
                var force = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                var data = {
                    summary: i18n('redirect_from_summary').replace(/\$1/ig, origin).replace(/\$2/ig, title)
                };
                if (!force) {
                    data.createonly = 'true';
                }
                this.edit('#تحويل [[' + title + ']]', origin, callback, data);
            }

            /**
             * 获得页面维基文本
             * @param {object} callback 回调函数
             * @param {string} title 页面标题 默认为当前页面
             * @param {object} config 设置
             */
        }, {
            key: 'getWikiText',
            value: function getWikiText() {
                var callback = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var config = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                $.ajax({
                    url: location.protocol + '//' + location.host + mw.config.get('wgScriptPath') + '/index.php',
                    type: 'GET',
                    dataType: 'text',
                    cache: false,
                    data: $.extend({
                        'title': title,
                        'action': 'raw'
                    }, config),
                    beforeSend: function beforeSend(request) {
                        request.setRequestHeader('Api-User-Agent', 'Wikiplus/2 (' + mw.config.get('wgWikiID') + ')');
                        console.time('يستغرق الحصول على نص الصفحة بعض الوقت');
                    },
                    success: function success(data) {
                        console.timeEnd('يستغرق الحصول على نص الصفحة بعض الوقت');
                        callback.success(data);
                    },
                    error: function error(e) {
                        callback.fail(throwError('fail_to_get_wikitext'));
                    }
                });
            }

            /**
             * 解析Wikitext
             * @param {string} wikitext 维基文本
             * @param {object} callback 回调函数
             * @param {object} config 设置
             */
        }, {
            key: 'parseWikiText',
            value: function parseWikiText(wikitext, callback, config) {
                if (wikitext === undefined) wikitext = '';
                if (callback === undefined) callback = {};

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    data: $.extend({
                        'format': 'json',
                        'action': 'parse',
                        'text': wikitext,
                        'title': this.pageName,
                        'pst': 'true'
                    }, config),
                    beforeSend: function beforeSend(request) {
                        request.setRequestHeader('Api-User-Agent', 'Wikiplus/2 (' + mw.config.get('wgWikiID') + ')');
                    },
                    url: this.API,
                    success: function success(data) {
                        if (data && data.parse && data.parse.text) {
                            callback.success(data.parse.text['*']);
                        } else {
                            callback.fail(throwError('cant_parse_wikitext'));
                        }
                    }
                });
            }
        }]);

        return Wikipage;
    })();

    $(document).ready(function () {
        var Wikiplus = (function () {
            _createClass(Wikiplus, [{
                key: 'initQuickEdit',

                /**
                 * 加载快速编辑 第一步 插入页面按钮并绑定入口事件
                 */
                value: function initQuickEdit() {
                    var callback = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

                    var self = this;
                    var checkRight = function checkRight() {
                        if (!mw.config.get('wgUserGroups').includes('autoconfirmed') && !mw.config.get('wgUserGroups').includes('confirmed')) {
                            new MoeNotification().create.error(getErrorInfo('not_autoconfirmed_user').message);
                            throwError('not_autoconfirmed_user');
                        }
                    };
                    callback.success = callback.success || new Function();
                    callback.fail = callback.fail || new Function();
                    if (!(mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgIsProbablyEditable'))) {
                        console.log('The page cannot be edited and the Quick Edit interface loads terminated');
                        return;
                    }
                    //顶部编辑入口
                    var topBtn = $('<li>').attr('id', 'Wikiplus-Edit-TopBtn').append($('<a>').attr('href', 'javascript:void(0)').text('' + i18n('quickedit_topbtn'))).data({
                        number: -1,
                        target: self.kotori.pageName
                    });
                    if (mw.config.get('skin') === 'minerva') {
                        $(topBtn).css({ 'align-items': 'center', 'display': 'flex' });
                        $(topBtn).find('span').addClass('page-actions-menu__list-item');
                        $(topBtn).find('a').addClass('mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-edit-base20 mw-ui-icon-with-label-desktop').css('vertical-align', 'middle');
                    } else if (mw.config.get('skin') === 'vector-2022') { //#مقطع مضاف
                        $(topBtn).addClass(' vector-tab-noicon mw-list-item');
                    }

                    if ($('#ca-edit').length > 0 && $('#Wikiplus-Edit-TopBtn').length === 0) {
                        mw.config.get('skin') === 'minerva' ? $('#ca-edit').parent().after(topBtn) : $('#ca-edit').after(topBtn);
                        $('#Wikiplus-Edit-TopBtn').click(function () {
                            checkRight();
                            self.initQuickEditInterface($(this)); //直接把DOM传递给下一步
                        });
                    } else if ($('#ca-edit').length === 0) {
                            throwError('fail_to_init_quickedit');
                        }
                    if ($('.mw-editsection').length > 0) {
                        self.sectionMap = {};
                        //段落快速编辑按钮
                        var sectionBtn = mw.config.get('skin') === 'minerva' ? $('<span>').append($('<a>').addClass('Wikiplus-Edit-SectionBtn mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-edit-base20 edit-page mw-ui-icon-flush-right').css('margin-left', '0.75em').attr('href', 'javascript:void(0)').attr('title', i18n('quickedit_sectionbtn'))) : $('<span>').append($('<span>').addClass('mw-editsection-divider').text(' | ')).append($('<a>').addClass('Wikiplus-Edit-SectionBtn').attr('href', 'javascript:void(0)').text(i18n('quickedit_sectionbtn')));
                        $('.mw-editsection').each(function (i) {
                            try {
                                var editURL = $(this).find("a[href*='action=edit']").first().attr('href');
                                var sectionNumber = editURL.match(/&[ve]*section\=([^&]+)/)[1].replace(/T-/ig, '');
                                var sectionTargetName;
                                if (editURL.match(/title=(.+?)&/)) {
                                    sectionTargetName = decodeURIComponent(editURL.match(/title=(.+?)&/)[1]);
                                } else {
                                    var regex = new RegExp(mw.config.get('wgArticlePath').replace('$1', '') + '(.+?)\\?');
                                    if (editURL.match(regex)) {
                                        sectionTargetName = decodeURIComponent(editURL.match(regex)[1]);
                                    } else {
                                        throwError('fail_to_init_quickedit');
                                    }
                                }
                                var cloneNode = $(this).prev().clone();
                                cloneNode.find('.mw-headline-number').remove();
                                var sectionName = cloneNode.text().trim();
                                self.sectionMap[sectionNumber] = {
                                    name: sectionName,
                                    target: sectionTargetName
                                };
                                var _sectionBtn = sectionBtn.clone();
                                _sectionBtn.find('.Wikiplus-Edit-SectionBtn').data({
                                    number: sectionNumber,
                                    name: sectionName,
                                    target: sectionTargetName
                                });
                                mw.config.get('skin') === 'minerva' ? $(this).append(_sectionBtn) : $(this).find('.mw-editsection-bracket').last().before(_sectionBtn);
                            } catch (e) {
                                throwError('fail_to_init_quickedit');
                            }
                        });
                        $('.Wikiplus-Edit-SectionBtn').click(function () {
                            checkRight();
                            self.initQuickEditInterface($(this)); //直接把DOM传递给下一步
                        });
                    }
                }

                /**
                 * 加载快速编辑主界面相关内容
                 */
            }, {
                key: 'initQuickEditInterface',
                value: function initQuickEditInterface(obj) {
                    var self = this;
                    var sectionNumber = obj.data('number');
                    var sectionTargetName = obj.data('target');
                    if (this.kotori.inited) {
                        if (sectionTargetName !== self.kotori.pageName && mw.config.get('wgCurRevisionId') !== mw.config.get('wgRevisionId')) {
                            // 在历史版本编辑其他页面有问题 暂时不支持
                            this.notice.create.error(i18n('cross_page_history_revision_edit_warning'));
                            return;
                        }
                        if ($('.noarticletext').length > 0) {
                            //这是一个空页面
                            this.preloadData[sectionTargetName + '.-1'] = i18n('create_page_tip');
                        }
                        if (mw.config.get('wgCurRevisionId') === mw.config.get('wgRevisionId')) {
                            var additionalConfig = {};
                            if (this.preloadData[sectionTargetName + '.' + sectionNumber] === undefined) {
                                if (sectionTargetName === this.kotori.pageName) {
                                    additionalConfig.oldid = mw.config.get('wgRevisionId');
                                }
                                this.notice.create.success(i18n('loading'));
                                this.preload(sectionNumber, sectionTargetName, {
                                    success: function success(data) {
                                        obj.data('content', data);
                                        self.notice.empty();
                                        self.displayQuickEditInterface(obj);
                                    },
                                    fail: function fail(e) {
                                        throwError('fail_to_get_wikitext_when_edit');
                                    }
                                }, additionalConfig);
                            } else {
                                obj.data('content', self.preloadData[sectionTargetName + '.' + sectionNumber]);
                                self.displayQuickEditInterface(obj);
                            }
                        } else {
                            this.notice.create.warning(i18n('history_edit_warning'));
                            this.notice.create.success(i18n('loading'));
                            this.preload(sectionNumber, sectionTargetName, {
                                success: function success(data) {
                                    obj.data('content', data);
                                    self.notice.empty();
                                    self.displayQuickEditInterface(obj, '' + i18n('history_edit_warning'));
                                },
                                fail: function fail(data) {
                                    throwError('fail_to_get_wikitext_when_edit');
                                }
                            }, {
                                'oldid': mw.config.get('wgRevisionId')
                            });
                        }
                    }
                }

                /**
                 * 显示快速编辑界面并绑定事件
                 */
            }, {
                key: 'displayQuickEditInterface',
                value: function displayQuickEditInterface(obj) {
                    var message = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1];

                    var self = this;
                    var isNewPage = $('.noarticletext').length > 0;
                    var sectionNumber = obj.data('number');
                    var sectionName = obj.data('name');
                    var sectionTargetName = obj.data('target');
                    var sectionContent = obj.data('content');
                    var summary = self.getSetting('defaultSummary', {
                        'sectionName': sectionName,
                        'sectionNumber': sectionNumber,
                        'sectionTargetName': sectionTargetName
                    });
                    if (summary === undefined) {
                        if (sectionName === undefined) {
                            summary = i18n('default_summary_suffix');
                        } else {
                            summary = '/* ' + sectionName + ' */ ' + i18n('default_summary_suffix');
                        }
                    }
                    //DOM定义
                    var heightBefore = $(document).scrollTop(); //记住当前高度
                    var backBtn = $('<span>').attr('id', 'Wikiplus-Quickedit-Back').addClass('Wikiplus-Btn').text('' + i18n('back')); //返回按钮
                    var jumpBtn = $('<span>').attr('id', 'Wikiplus-Quickedit-Jump').addClass('Wikiplus-Btn').append($('<a>').attr('href', '#Wikiplus-Quickedit').text('' + i18n('goto_editbox'))); //到编辑框
                    var inputBox = $('<textarea>').attr('id', 'Wikiplus-Quickedit'); //主编辑框
                    var previewBox = $('<div>').attr('id', 'Wikiplus-Quickedit-Preview-Output'); //预览输出
                    var summaryBox = $('<input>').attr('id', 'Wikiplus-Quickedit-Summary-Input').attr('placeholder', '' + i18n('summary_placehold')); //编辑摘要输入
                    var editSubmitBtn = $('<button>').attr('id', 'Wikiplus-Quickedit-Submit').text(i18n(isNewPage ? 'publish_page' : 'publish_change') + '(Ctrl+S)'); //提交按钮
                    var previewSubmitBtn = $('<button>').attr('id', 'Wikiplus-Quickedit-Preview-Submit').text('' + i18n('preview')); //预览按钮
                    var isMinorEdit = $('<div>').append($('<input>').attr({ 'type': 'checkbox', 'id': 'Wikiplus-Quickedit-MinorEdit' })).append($('<label>').attr('for', 'Wikiplus-Quickedit-MinorEdit').text(i18n('mark_minoredit') + '(Ctrl+Shift+S)')).css({ 'margin': '5px 5px 5px -3px', 'display': 'inline' });
                    //DOM定义结束
                    var editBody = $('<div>').append(backBtn, jumpBtn, previewBox, inputBox, summaryBox, $('<br>'), isMinorEdit, editSubmitBtn, previewSubmitBtn);
                    this.createDialogBox('' + i18n('quickedit_topbtn') + message, editBody, 1000, function () {
                        $('#Wikiplus-Quickedit').val(sectionContent);
                        $('#Wikiplus-Quickedit-Summary-Input').val(summary);
                        //事件绑定
                        //返回
                        $('#Wikiplus-Quickedit-Back').click(function () {
                            $('.Wikiplus-InterBox').fadeOut('fast', function () {
                                window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                                $(this).remove();
                            });
                        });
                        //预览
                        var onPreload = $('<div>').addClass('Wikiplus-Banner').text('' + i18n('loading_preview'));
                        $('#Wikiplus-Quickedit-Preview-Submit').click(function () {
                            var wikiText = $('#Wikiplus-Quickedit').val();
                            $(this).attr('disabled', 'disabled');
                            $('#Wikiplus-Quickedit-Preview-Output').fadeOut(100, function () {
                                $('#Wikiplus-Quickedit-Preview-Output').html('').append(onPreload);
                                $('#Wikiplus-Quickedit-Preview-Output').fadeIn(100);
                            });
                            $('html, body').animate({
                                scrollTop: heightBefore
                            }, 200); //返回顶部
                            self.kotori.parseWikiText(wikiText, {
                                success: function success(data) {
                                    $('#Wikiplus-Quickedit-Preview-Output').fadeOut('100', function () {
                                        $('#Wikiplus-Quickedit-Preview-Output').html('<hr><div class="mw-body-content">' + data + '</div><hr>');
                                        $('#Wikiplus-Quickedit-Preview-Output').fadeIn('100');
                                        $('#Wikiplus-Quickedit-Preview-Submit').prop('disabled', false);
                                    });
                                }
                            });
                        });
                        //提交
                        $('#Wikiplus-Quickedit-Submit').click(function () {
                            var wikiText = $('#Wikiplus-Quickedit').val();
                            var summary = $('#Wikiplus-Quickedit-Summary-Input').val();
                            var timer = new Date().valueOf();
                            var onEdit = $('<div>').addClass('Wikiplus-Banner').text('' + i18n('submitting_edit'));
                            var addtionalConfig = {
                                'summary': summary
                            };
                            if (sectionNumber !== -1) {
                                addtionalConfig['section'] = sectionNumber;
                            }
                            if ($('#Wikiplus-Quickedit-MinorEdit').is(':checked')) {
                                addtionalConfig['minor'] = 'true';
                            } else {
                                addtionalConfig['notminor'] = 'true';
                            }
                            //准备编辑 禁用各类按钮 返回顶部 显示信息
                            $('#Wikiplus-Quickedit-Submit,#Wikiplus-Quickedit,#Wikiplus-Quickedit-Preview-Submit').attr('disabled', 'disabled');
                            $('html, body').animate({
                                scrollTop: heightBefore
                            }, 200);

                            //开始提交编辑
                            if (sectionTargetName === self.kotori.pageName) {
                                $('#Wikiplus-Quickedit-Preview-Output').fadeOut(100, function () {
                                    $('#Wikiplus-Quickedit-Preview-Output').html('').append(onEdit);
                                    $('#Wikiplus-Quickedit-Preview-Output').fadeIn(100);
                                });
                                self.kotori.edit(wikiText, sectionTargetName, {
                                    success: function success() {
                                        var useTime = new Date().valueOf() - timer;
                                        $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').css('background', 'rgba(6, 239, 92, 0.44)');
                                        $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').text(('' + i18n('edit_success')).replace(/\$1/ig, useTime.toString()));
                                        self.sendStatistic(sectionTargetName, useTime);
                                        window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                                        setTimeout(function () {
                                            location.reload();
                                        }, 500);
                                    },
                                    fail: function fail(e) {
                                        console.log(e);
                                        $('#Wikiplus-Quickedit-Submit,#Wikiplus-Quickedit,#Wikiplus-Quickedit-Preview-Submit').prop('disabled', false);
                                        $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                        $('.Wikiplus-Banner').html(e.message);
                                    }
                                }, addtionalConfig);
                            } else {
                                //编辑目标非当前页面
                                $('#Wikiplus-Quickedit-Preview-Output').fadeOut(100, function () {
                                    $('#Wikiplus-Quickedit-Preview-Output').html('').append(onEdit.text(i18n('cross_page_edit')));
                                    $('#Wikiplus-Quickedit-Preview-Output').fadeIn(100);
                                });
                                self.kotori.reConstruct(sectionTargetName, {
                                    success: function success() {
                                        $('.Wikiplus-Banner').text(i18n('cross_page_edit_submit'));
                                        self.kotori.edit(wikiText, sectionTargetName, {
                                            success: function success() {
                                                var useTime = new Date().valueOf() - timer;
                                                $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').css('background', 'rgba(6, 239, 92, 0.44)');
                                                $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').text(('' + i18n('edit_success')).replace(/\$1/ig, '' + useTime));
                                                self.sendStatistic(sectionTargetName, useTime);
                                                window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                                                setTimeout(function () {
                                                    location.reload();
                                                }, 500);
                                            },
                                            fail: function fail(e) {
                                                $('#Wikiplus-Quickedit-Submit,#Wikiplus-Quickedit,#Wikiplus-Quickedit-Preview-Submit').prop('disabled', false);
                                                $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                                $('.Wikiplus-Banner').text(e.message);
                                            }
                                        }, addtionalConfig);
                                    },
                                    fail: function fail(e) {
                                        $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                        $('.Wikiplus-Banner').text(i18n('cross_page_edit_error'));
                                    }
                                });
                            }
                        });
                        //快捷键
                        //Ctrl+S提交 Ctrl+Shift+S小编辑
                        $('#Wikiplus-Quickedit,#Wikiplus-Quickedit-Summary-Input,#Wikiplus-Quickedit-MinorEdit').keydown(function (e) {
                            if (e.ctrlKey && e.which === 83) {
                                if (e.shiftKey) {
                                    $('#Wikiplus-Quickedit-MinorEdit').click();
                                }
                                $('#Wikiplus-Quickedit-Submit').click();
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        });
                        //由于是异步提交 Wikiplus即使编辑失败 也不会丢失数据 唯一丢失数据的可能性是手滑关了页面
                        //第一 关闭页面确认
                        $('#Wikiplus-Quickedit').keydown(function () {
                            window.onclose = window.onbeforeunload = function () {
                                return '' + i18n('onclose_confirm');
                            };
                        });

                        //Esc退出
                        if (self.getSetting('esc_to_exit_quickedit') === 'true') {
                            $(document).keydown(function (e) {
                                if (e.which === 27) {
                                    $('#Wikiplus-Quickedit-Back').click();
                                }
                            });
                        }
                    });
                }

                /**
                 * 编辑设置
                 */
            }, {
                key: 'editSettings',
                value: function editSettings() {
                    var self = this;
                    self.addFunctionButton(i18n('wikiplus_settings'), 'Wikiplus-Settings-Intro', function () {
                        var input = $('<textarea>').attr('id', 'Wikiplus-Setting-Input').attr('rows', '10');
                        var applyBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Apply').text(i18n('submit'));
                        var cancelBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Cancel').text(i18n('cancel'));
                        var content = $('<div>').append(input).append($('<hr>')).append(applyBtn).append(cancelBtn); //拼接
                        self.createDialogBox(i18n('wikiplus_settings_desc'), content, 600, function () {
                            if (localStorage.Wikiplus_Settings) {
                                $('#Wikiplus-Setting-Input').val(localStorage.Wikiplus_Settings);
                            } else {
                                $('#Wikiplus-Setting-Input').attr('placeholder', i18n('wikiplus_settings_placeholder'));
                            }
                            $('#Wikiplus-Setting-Apply').click(function () {
                                var settings = $('#Wikiplus-Setting-Input').val();
                                try {
                                    settings = JSON.parse(settings);
                                } catch (e) {
                                    self.notice.create.error(i18n('wikiplus_settings_grammar_error'));
                                    return;
                                }
                                localStorage.Wikiplus_Settings = JSON.stringify(settings);
                                $('.Wikiplus-InterBox-Content').html('').append($('<div>').addClass('Wikiplus-Banner').text(i18n('wikiplus_settings_saved')));

                                $('.Wikiplus-InterBox').fadeOut(300, function () {
                                    $(this).remove();
                                });
                            });
                            $('#Wikiplus-Setting-Cancel').click(function () {
                                $('.Wikiplus-InterBox').fadeOut(300, function () {
                                    $(this).remove();
                                });
                            });
                        });
                    });
                }

                /**
                 * 快速重定向页面至此页面
                 */
            }, {
                key: 'simpleRedirector',
                value: function simpleRedirector() {
                    var self = this;
                    self.addFunctionButton(i18n('redirect_from'), 'Wikiplus-SR-Intro', function () {
                        var input = $('<input>').addClass('Wikiplus-InterBox-Input');
                        var applyBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-SR-Apply').text(i18n('submit') + " - ctrl+s");
                        var cancelBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-SR-Cancel').text(i18n('cancel'));
                        var continueBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-SR-Continue').text(i18n('continue'));
                        var content = $('<div>').append(input).append($('<hr>')).append(applyBtn).append(cancelBtn); //拼接
                        self.createDialogBox(i18n('redirect_desc'), content, 600, function () {
                            applyBtn.click(function () {
                                if ($('.Wikiplus-InterBox-Input').val() != '') {
                                    var title = $('.Wikiplus-InterBox-Input').val();
                                    $('.Wikiplus-InterBox-Content').html('<div class="Wikiplus-Banner">' + i18n('submitting_edit') + '</div>');
                                    self.kotori.redirectFrom(title, self.kotori.pageName, {
                                        success: function success() {
                                            $('.Wikiplus-Banner').text(i18n('redirect_saved'));
                                            $('.Wikiplus-InterBox').fadeOut(300);
                                            location.href = mw.config.get('wgArticlePath').replace(/\$1/ig, title);
                                        },
                                        fail: function fail(e) {
                                            $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                            $('.Wikiplus-Banner').text(e.message);
                                            if (e.number === 1018) {
                                                // 目标页面已经存在 确认哟
                                                $('.Wikiplus-InterBox-Content').append($('<hr>')).append(continueBtn).append(cancelBtn);
                                                continueBtn.click(function () {
                                                    $('.Wikiplus-InterBox-Content').html('<div class="Wikiplus-Banner">' + i18n('submitting_edit') + '</div>');
                                                    self.kotori.redirectFrom(title, self.kotori.pageName, {
                                                        success: function success() {
                                                            $('.Wikiplus-Banner').text(i18n('redirect_saved'));
                                                            $('.Wikiplus-InterBox').fadeOut(300);
                                                            location.href = mw.config.get('wgArticlePath').replace(/\$1/ig, title);
                                                        },
                                                        fail: function fail(e) {
                                                            $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                                            $('.Wikiplus-Banner').text(e.message);
                                                        }
                                                    }, true);
                                                });
                                                cancelBtn.click(function () {
                                                    $('.Wikiplus-InterBox-Close').click();
                                                });
                                            }
                                        }
                                    });
                                } else {
                                    self.showNotice.create.warning(i18n('empty_input'));
                                }
                            });
                            $('#Wikiplus-SR-Cancel').click(function () {
                                $('.Wikiplus-InterBox').fadeOut(300, function () {
                                    $(this).remove();
                                });
                            });
                            //اختصار تأكيد التحميل
                        $('.Wikiplus-InterBox').keydown(function (e) {
                            if (e.ctrlKey && e.which == 83) {
                                $('#Wikiplus-SR-Apply').click();
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        });
                        });
                    });
                }

                /**
                 * 预读取相关事件绑定
                 */
            }, {
                key: 'preloadEventBinding',
                value: function preloadEventBinding() {
                    var self = this;
                    $('#toc').children('ul').find('a').each(function (i) {
                        $(this).mouseover(function () {
                            $(this).unbind('mouseover');
                            self.preload(i + 1);
                        });
                    });
                }

                /**
                 * 检查多语言定义缓存是否过期
                 */
            }, {
                key: 'checki18nCache',
                value: function checki18nCache() {
                    if (localStorage.Wikiplus_i18nCache) {
                        try {
                            var _i18nData = JSON.parse(localStorage.Wikiplus_i18nCache);
                            for (var languages in _i18nData) {
                                if (_i18nData[languages]['__version'] === this.langVersion) {
                                    i18nData[_i18nData[languages]['__language']] = _i18nData[languages];
                                } else {
                                    console.log('Multilingual documents[' + languages + '] expired');
                                    loadLanguage(_i18nData[languages]['__language']); //尝试重新取
                                }
                            }
                        } catch (e) {
                            throwError('cant_parse_i18ncache');
                        }
                    } else {
                        localStorage.Wikiplus_i18nCache = JSON.stringify(i18nData);
                    }
                }

                /**
                 * 为所有可能的编辑链接加上快速编辑按钮
                 */
            }, {
                key: 'editEveryWhere',
                value: function editEveryWhere() {
                    var self = this;
                    $('#mw-content-text a.external').each(function (i) {
                        var url = $(this).attr('href');
                        var reg = /(([^?&=]+)(?:=([^?&=]*))*)/g;
                        var params = {},
                            match;
                        while (match = reg.exec(url)) {
                            try {
                                params[match[2]] = decodeURIComponent(match[3]);
                            } catch (e) {
                                // cannot decode
                                params[match[2]] = match[3];
                            }
                        }
                        if (params.action === 'edit' && params.title !== undefined && params.section !== 'new') {
                            $(this).after($('<a>').attr({
                                'href': 'javascript:void(0)',
                                'class': 'Wikiplus-Edit-EveryWhereBtn'
                            }).text(' (' + i18n('quickedit_sectionbtn') + ') ').data({
                                'target': decodeURIComponent(params.title),
                                'number': params.section || -1
                            }));
                        }
                    });
                    $('.Wikiplus-Edit-EveryWhereBtn').click(function () {
                        self.initQuickEditInterface($(this));
                    });
                }

                /**
                 * ===========================
                 * 以上是功能函数 以下是通用函数
                 * ===========================
                 */

                /**
                 * 创建对话框
                 * @param {string} title 对话框标题
                 * @param {HTML} content 内容
                 * @param {interger} width 宽度 单位像素 默认600px
                 * @param {function} callback 回调函数
                 */
            }, {
                key: 'createDialogBox',
                value: function createDialogBox() {
                    var title = arguments.length <= 0 || arguments[0] === undefined ? 'Dialog Box' : arguments[0];
                    var content = arguments.length <= 1 || arguments[1] === undefined ? $('<div>') : arguments[1];
                    var width = arguments.length <= 2 || arguments[2] === undefined ? 600 : arguments[2];
                    var callback = arguments.length <= 3 || arguments[3] === undefined ? new Function() : arguments[3];

                    if ($('.Wikiplus-InterBox').length > 0) {
                        $('.Wikiplus-InterBox').each(function () {
                            $(this).remove();
                        });
                    }
                    var clientWidth = window.innerWidth;
                    var clientHeight = window.innerHeight;
                    var dialogWidth = Math.min(clientWidth, width);
                    var diglogBox = $('<div>').addClass('Wikiplus-InterBox').css({
                        'margin-right': clientWidth / 2 - dialogWidth / 2, // #معدل تنسيق عربي
                        'top': $(document).scrollTop() + clientHeight * 0.2,
                        'display': 'none'
                    }).append($('<div>').addClass('Wikiplus-InterBox-Header').html(title)).append($('<div>').addClass('Wikiplus-InterBox-Content').append(content)).append($('<span>').text('×').addClass('Wikiplus-InterBox-Close'));
                    $('body').append(diglogBox);
                    $('.Wikiplus-InterBox').width(dialogWidth);
                    $('.Wikiplus-InterBox-Close').click(function () {
                        $(this).parent().fadeOut('fast', function () {
                            window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                            $(this).remove();
                        });
                    });
                    //拖曳
                    var bindDragging = function bindDragging(element) {
                        element.mousedown(function (e) {
                            var baseX = e.clientX;
                            var baseY = e.clientY;
                            var baseOffsetX = element.parent().offset().left;
                            var baseOffsetY = element.parent().offset().top;
                            $(document).mousemove(function (e) {
                                element.parent().css({
                                    'margin-left': baseOffsetX + e.clientX - baseX,
                                    'top': baseOffsetY + e.clientY - baseY
                                });
                            });
                            $(document).mouseup(function () {
                                element.unbind('mousedown');
                                $(document).unbind('mousemove');
                                $(document).unbind('mouseup');
                                bindDragging(element);
                            });
                        });
                    };
                    bindDragging($('.Wikiplus-InterBox-Header'));
                    $('.Wikiplus-InterBox').fadeIn(500);
                    callback();
                }

                /**
                 * 增加功能按钮
                 * @param {string} text 按钮名
                 * @param {string} id 按钮id
                 * @param {function} clickEvent 点击事件
                 */
            }, {
                key: 'addFunctionButton',
                value: function addFunctionButton(text, id, clickEvent) {
                    var button = $('<li>').addClass('mw-list-item mw-list-item-js').attr('id', id);
                    var href = $('<a>').attr('href', 'javascript:void(0);');
                    button = mw.config.get('skin') === 'minerva' ? button.addClass('toggle-list-item').append(href.addClass('toggle-list-item__anchor').append($('<span>').addClass('mw-ui-icon mw-ui-icon-portletlink-' + id.toLowerCase())).append($('<span>').addClass('toggle-list-item__label').text(text))) : mw.config.get('skin') === 'vector' ? button.append(href.append($('<span>').text(text))) : button.append(href.text(text));
                    if (mw.config.get('skin') === 'minerva') {
                        if ($('#p-tb').length > 0) {
                            $('#p-tb').append(button);
                            $('#' + id).click(clickEvent);
                        }
                    } else if ($('#p-cactions').length > 0) {
                        $('#p-cactions ul').append(button);
                        $('#' + id).find('a').click(clickEvent);
                    } else {
                        throwError('cant_add_funcbtn');
                    }
                }

                /**
                 * 预读取内容
                 * @param {interger} section 段落编号 默认为-1即全页
                 * @param {string} title 页面名 默认为当前页面
                 * @param {object} callback 回调
                 */
            }, {
                key: 'preload',
                value: function preload() {
                    var section = arguments.length <= 0 || arguments[0] === undefined ? -1 : arguments[0];
                    var title = arguments.length <= 1 || arguments[1] === undefined ? this.kotori.pageName : arguments[1];
                    var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
                    var config = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

                    callback.success = callback.success || new Function();
                    callback.fail = callback.fail || new Function();
                    var self = this;
                    if (config.oldid !== undefined) {
                        // oldid 优先于 页面名
                        if (this.preloadData[config.oldid + '.' + section]) {
                            console.log('[Revisions' + config.oldid + '.' + section + ']Pre-read: Skip this pre-read');
                            callback.success(this.preloadData[config.oldid + '.' + section]);
                            return;
                        }
                    } else {
                        if (this.preloadData[title + '.' + section]) {
                            console.log('[' + title + '.' + section + ']Pre-read: Skip this pre-read');
                            callback.success(this.preloadData[title + '.' + section]);
                            return;
                        }
                    }
                    this.kotori.getWikiText({
                        success: function success(data) {
                            if (config.oldid !== undefined) {
                                self.preloadData[config.oldid + '.' + section] = data;
                                console.log('Pre-read [revision' + config.oldid + '.' + section + ']succeeded');
                            } else {
                                self.preloadData[title + '.' + section] = data;
                                console.log('Pre-read [' + title + '.' + section + ']succeeded');
                            }
                            callback.success(data);
                        },
                        fail: function fail(e) {
                            if (config.oldid !== undefined) {
                                console.log('Pre-read [revision' + config.oldid + '.' + section + ']failed');
                            } else {
                                console.log('Pre-read [' + title + '.' + section + ']failed:' + e.message);
                            }
                            callback.fail(e);
                        }
                    }, title, $.extend({
                        section: section === -1 ? '' : section
                    }, config));
                }

                /**
                 * 提交统计数据
                 * @param {string} title 页面名
                 * @param {interger} useTime 用时 单位毫秒
                 */
            }, {
                key: 'sendStatistic',
                value: function sendStatistic(title, useTime) {
                    if (title === undefined) title = mw.config.get('wgPageName');

                    if (localStorage.Wikiplus_SendStatistics === 'True') {
                        $.ajax({
                            url: scriptPath + '/statistics/api/submit',
                            type: 'POST',
                            dataType: 'json',
                            data: {
                                'wikiname': mw.config.get('wgSiteName'),
                                'usetime': useTime,
                                'username': mw.config.get('wgUserName'),
                                'pagename': title
                            },
                            success: function success(data) {
                                //提交成功
                            }
                        });
                    }
                }

                /**
                 * 检查安装
                 * @param {function} callback 回调函数
                 */
            }, {
                key: 'checkInstall',
                value: function checkInstall(callback) {
                    var self = this;
                    if (!localStorage.Wikiplus_Installed || localStorage.Wikiplus_Installed == 'False') {
                        //安装
                        var install = function install() {
                            localStorage.Wikiplus_Installed = 'True'; //标记已安装
                            localStorage.Wikiplus_Version = self.version;
                            localStorage.Wikiplus_StartUseAt = new Date().valueOf();
                            localStorage.Wikiplus_SrartEditCount = mw.config.get('wgUserEditCount');
                            localStorage.Wikiplus_Settings = JSON.stringify(self.defaultSettings);
                            $('.Wikiplus-InterBox').fadeOut('fast', function () {
                                self.notice.create.success(i18n('install_finish'));
                                $(this).remove();
                            });
                        };
                        /* #كود معلق
                        var notice = $('<div>').text(i18n('install_tip').replace(/\$1/ig, mw.config.get('wgSiteName'))).attr('id', 'Wikiplus-InterBox-Content');
                        var applyBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Apply').text(i18n('accept'));
                        var cancelBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Cancel').text(i18n('decline'));
                        var content = $('<div>').append(notice).append($('<hr>')).append(applyBtn).append(cancelBtn); //拼接
                        self.createDialogBox('安装Wikiplus', content, 600, function () {
                            $('#Wikiplus-InterBox-Content').css('text-align', 'left');
                            $('#Wikiplus-Setting-Apply').click(function () {
                                localStorage.Wikiplus_SendStatistics = 'True';
                                install();
                            });
                            $('#Wikiplus-Setting-Cancel').click(function () {
                                localStorage.Wikiplus_SendStatistics = 'False';
                                install();
                            });
                        }); */
                    }
                }

                /**
                 * 获取设置值
                 * @param {string} key 键名
                 * @param {object} object 传入可用参数
                 */
            }, {
                key: 'getSetting',
                value: function getSetting(key, object) {
                    var w = object;
                    try {
                        var settings = JSON.parse(localStorage.Wikiplus_Settings);
                    } catch (e) {
                        return localStorage.Wikiplus_Settings || '';
                    }
                    try {
                        var _setting = new Function('return ' + settings[key]);
                        if (typeof _setting === 'function') {
                            try {
                                if (_setting()(w) === true) {
                                    return undefined;
                                } else {
                                    return _setting()(w) || settings[key];
                                }
                            } catch (e) {
                                return settings[key];
                            }
                        } else {
                            return settings[key];
                        }
                    } catch (e) {
                        try {
                            return settings[key];
                        } catch (e) {
                            return undefined;
                        }
                    }
                }
            }, {
                key: 'initBasicFunctions',
                value: function initBasicFunctions() {
                    var self = this;
                    mw.hook('wikipage.content').add(function (item) {
                        if (item.attr('id') === 'mw-content-text') {
                            self.initQuickEdit(); //加载快速编辑
                            !self.getSetting('disableEditEveryWhere') && self.editEveryWhere(); //任意编辑
                        }
                    });
                    this.editSettings(); //编辑设置
                    this.simpleRedirector(); //快速重定向
                    this.preloadEventBinding(); //预读取
                }
            }, {
                key: 'initRecentChangesPageFunctions',
                value: function initRecentChangesPageFunctions() {}
            }, {
                key: 'initAdvancedFunctions',
                value: function initAdvancedFunctions() {}
            }]);

            function Wikiplus() {
                _classCallCheck(this, Wikiplus);

                this.version = '2.3.11';
                this.langVersion = '212';
                this.releaseNote = '修正一些问题';
                this.notice = new MoeNotification();
                this.inValidNameSpaces = [-1, 8964];
                this.defaultSettings = {
                    'key': 'value',
                    'documatation': 'https://zh.moegirl.org.cn/User:%E5%A6%B9%E7%A9%BA%E9%85%B1/Wikiplus/%E8%AE%BE%E7%BD%AE%E8%AF%B4%E6%98%8E'
                };
                console.log('تحميل Wikiplus ' + this.version);
                //载入CSS
                /* #مقطع معطل لتحميل نسخة مخصصة من الويكي 
                $('head').append('<link>');
                $('head').children(':last').attr({
                    rel: 'stylesheet',
                    type: 'text/css',
                    href: scriptPath + '/wikiplus.css'
                }); */
                //一些初始化工作
                this.preloadData = {};
                this.checkInstall(); //安装检查
                //语言检测
                // #معدل
                var language = (i18nData[mw.config.get('wgUserLanguage')] && mw.config.get('wgUserLanguage')) || "ar";  //this.getSetting('language') && this.getSetting('language').toLowerCase() || window.navigator.language.toLowerCase();
                //版本检查
                if (this.version !== localStorage.Wikiplus_Version) {
                    localStorage.Wikiplus_Version = this.version;
                    this.notice.create.success('Wikiplus ' + this.version);
                    this.notice.create.success(language === 'zh-cn' ? this.releaseNote : 'Minor bug fixes'); // 避免给其他语言用户不必要的理解困难
                }
                if (i18nData[language] === undefined) {
                    loadLanguage(language);
                }
                //真正的初始化
                if (!this.inValidNameSpaces.includes(mw.config.get('wgNamespaceNumber')) && mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view') {
                    this.kotori = new Wikipage();
                    this.checki18nCache();
                    this.initBasicFunctions();
                } else {
                    console.log('Not eligible for loading Wikiplus termination');
                }
            }

            return Wikiplus;
        })();

        window.Wikiplus = new Wikiplus();
    });
});