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

از ویکی پاسخ

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

  • فایرفاکس / سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload کلیک کنید، یا کلید‌های Ctrl-F5 یا Ctrl-R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-R)
  • گوگل کروم: کلیدهای Ctrl+Shift+R را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های ⌘-Shift-R)
  • اینترنت اکسپلورر/ Edge: کلید Ctrl را نگه‌دارید و روی دکمهٔ Refresh کلیک کنید، یا کلید‌های Ctrl-F5 را با هم فشار دهید
  • اپرا: Ctrl-F5 را بفشارید.
$.when($.ready, mw.loader.using(['mediawiki.api', 'mediawiki.util'])).then(function() {
    'use strict';

    var projectPageAllowedCats = [
        'رهنمودهای ویکی پاسخ',
        'سیاست‌های ویکی پاسخ',
        'راهنمای ویکی پاسخ',
        'انشاهای ویکی پاسخ',
        'انشاهای مکمل ویکی پاسخ',
        'ابزارهای ویکی پاسخ',
        'خودآموز ویکی پاسخ'
    ];

    var projectPageAllowedTitles = [
        'ویکی پاسخ:اشتباه‌یاب/تست',
        'ویکی پاسخ:اشتباه‌یاب/تمرین',
        'ویکی پاسخ:صفحه تمرین'
    ];

    var projectPageWrongListedTitles = 'ویکی پاسخ:اشتباه‌یاب/موارد_درست/';

    if (mw.config.get('wgAction') !== 'view' ||
    	([0, 4, 12, 118].indexOf(mw.config.get('wgNamespaceNumber')) === -1 &&
    	 mw.config.get('wgPageName') !== 'کاربر:' + mw.config.get('wgUserName') + '/صفحه_تمرین') ||
        mw.util.getParamValue('diff') ||
        mw.util.getParamValue('oldid') ||
        $('.noarticletext').length) {
        return;
    }
    
    var siteSub = $('#siteSub');
    if (mw.config.get('skin') === 'timeless') {
    	siteSub = $('#p-namespaces');
    }

    if (mw.config.get('wgNamespaceNumber') === 4 && mw.config.get('wgPageName').search(projectPageWrongListedTitles) === 0) {
        var returnTitle = mw.config.get('wgPageName').split(projectPageWrongListedTitles)[1]
        siteSub.append(' ', $('<span>', {
            html: 'این صفحه حاوی موارد مستثنی‌شده برای صفحهٔ <a href="//fa.wikipasokh.com/view/' + returnTitle + '">' + returnTitle.replace(/\_/g, ' ') + '</a> است.',
            class: 'CheckDictation-allgood-label'
        }));
    }

    if (mw.config.get('wgNamespaceNumber') === 4 &&
        projectPageAllowedTitles.indexOf(mw.config.get('wgPageName').replace(/_/g, ' ')) === -1 &&
        mw.config.get("wgCategories").every(function(x) {
            return projectPageAllowedCats.indexOf(x) === -1;
        })) {
        return;
    }
    if ($('ul[class="redirectText"]')[0]) {
        return;
    } //صفحه تغییرمسیر را بررسی نکند
    var pageContentCache;

    function getPageTextCache() {
        return pageContentCache ? $.Deferred().resolve(pageContentCache) : loadPage(mw.config.get('wgPageName'));
    }

    // Copyedited from https://de.wikipasokh.com/view/MediaWiki:Gadget-Rechtschreibpruefung.js
    function markWord(node, text, word, hint, color, preparedId) {
        var pos, len, newnodes = 0;
        var newnode, middlenode, endnode;

        // textnode - search for word
        if (node.nodeType == 3) {
            pos = node.data.search(text);
            if (pos >= 0) {
                // create new span-element
                newnode = $('<span>', {
                    title: hint,
                    class: 'CheckDictation-marked CheckDictation-marked-' + word.replace(/ /g, '_'),
                    id: preparedId
                }).css('background-color', color)[0];

                // get length of the matching part
                len = node.data.match(text)[0].length;

                // splits content in three parts: begin, middle and end
                middlenode = node.splitText(pos);
                endnode = middlenode.splitText(len);

                // appends a copy of the middle to the new span-node
                newnode.appendChild(middlenode.cloneNode(true));
                // replace middlenode with the new span-node
                middlenode.parentNode.replaceChild(newnode, middlenode);

                newnodes = 1;
            }
        } else if ((node.nodeType == 1) // element node
            &&
            (node.hasChildNodes()) // with child nodes
            &&
            (node.tagName.toLowerCase() != "script") // no script, style and form
            &&
            (node.tagName.toLowerCase() != "style") && (node.tagName.toLowerCase() != "form")) {
            var this_child;
            for (this_child = 0; this_child < node.childNodes.length; this_child++) {
                this_child = this_child + markWord(node.childNodes[this_child], text, word, hint, color, preparedId);
            }
        }
        return newnodes;
    }

    function markWord2(node, text, word, hint, preparedId) {
        var pos, len, newnodes = 0;
        var newnode, middlenode, endnode;

        // textnode - search for word
        if (node.nodeType == 3) {
            pos = node.data.search(text);
            if (pos >= 0) {
                // create new span-element
                newnode = $('<span>', {
                    title: hint,
                    class: 'CheckDictation-marked CheckDictation-marked-' + word.replace(/ /g, '_'),
                    id: preparedId
                })[0];

                // get length of the matching part
                len = node.data.match(text)[0].length;

                // splits content in three parts: begin, middle and end
                middlenode = node.splitText(pos);
                endnode = middlenode.splitText(len);

                // appends a copy of the middle to the new span-node
                newnode.appendChild(middlenode.cloneNode(true));
                // replace middlenode with the new span-node
                middlenode.parentNode.replaceChild(newnode, middlenode);

                newnodes = 1;
            }
        } else if ((node.nodeType == 1) // element node
            &&
            (node.hasChildNodes()) // with child nodes
            &&
            (node.tagName.toLowerCase() != "script") // no script, style and form
            &&
            (node.tagName.toLowerCase() != "style") && (node.tagName.toLowerCase() != "form")) {
            var this_child;
            for (this_child = 0; this_child < node.childNodes.length; this_child++) {
                this_child = this_child + markWord2(node.childNodes[this_child], text, word, hint, preparedId);
            }
        }
        return newnodes;
    }

    function loadPage(title) {
        return (new mw.Api()).get({
            action: 'query',
            prop: 'revisions',
            titles: title,
            rvprop: 'content',
            format: 'json'
        }).then(function(data) {
            return ((data.query.pages[Object.keys(data.query.pages)[0] || ''].revisions || '')[0] || '')['*'];
        });
    }

    function savePage(title, text, summary) {
        return (new mw.Api()).post({
            action: 'edit',
            title: title,
            text: text,
            summary: summary,
            minor: '',
            token: mw.user.tokens.get('csrfToken')
        }).then(function(data) {
            if (data.error && data.error.info) {
                mw.notify(data.error.info);
            }
        }, function(data) {
            mw.notify(data);
        });
    }

    function postEdit(text){
        // رفع مشکل [[Special:Permalink/25174868#متن هایلایت‌شده]]
        var otext = ''
        while (otext!=text){
            otext = text
            text=text.replace(/\<span[^>]+CheckDictation\-marked[^>]+\>([^<>]+)\<\/span\>/g, '$1')
        }
        return text
    }

    function dictationReplaceDialog(title, diatext, word, suggestions) {


        var defer = $.Deferred();
        $('#CheckDictation-form, #CheckDictation-form-input').remove();
        $('<div>', {
            html: title
        }).append('<br><br><br>' + diatext).append(
            '<br><br>',
            $('<input>', {
                id: 'CheckDictation-form-input',
                value: word,
                style: 'line-height: 2;'
            }),
            ' ',
            persianWikiTools && persianWikiTools.superTool ? $('<img>', {
                src: '//upload.wikimedia.org/wikipedia/fa/f/fc/Button_super_tool.png',
                alt: 'ابرابزار',
                title: 'ابرابزار'
            }).click(function retrySuperTool() {
                $('#CheckDictation-form-input').val((persianWikiTools.superTool(' ' + $('#CheckDictation-form-input').val() + ' ')).trim());
            }) : '<br><br>',
            $('<div>').append(suggestions.map(function(text) {
                return $('<button>', {
                    text: text.replace('|', '❙')
                }).css({
                    'margin-left': '8px'
                }).click(function() {
                    $('#CheckDictation-form-input').val(text);
                });
            })),
            '<br>جایگزینی موارد بیشتر در متن:<br><br>',
            $('<input>', {
                id: 'CheckDictation-form-input1',
                value: '',
                style: 'line-height: 2;'
            }), ' > ',
            $('<input>', {
                id: 'CheckDictation-form-input2',
                value: '',
                style: 'line-height: 2;'
            })
        ).dialog({
            width: 800,
            title: 'اصلاح یک کلمه به طور عمومی در متن',
            buttons: [{
                text: 'افزودن به فهرست کلمات درست و پرکاربرد',
                class: 'ui-button-red',
                click: function() {
                    if (confirm('کلماتی که به فهرست افزوده می‌شوند باید درست و پرکاربرد باشند. اگر کلمه درست و پرکاربرد است دکمهٔ Ok را کلیک کنید در غیر این صورت دکمهٔ Cancel را کلیک کنید.')) {
                        defer.reject();
                    }
                    $(this).dialog('close');
                }
            }, {
                text: 'فقط برای این مقاله درست است',
                class: 'ui-button-blue',
                click: function() {
                    var exceptionsPage = 'ویکی پاسخ:اشتباه‌یاب/موارد درست/' + mw.config.get('wgPageName').replace(/_/g, ' ');
                    var exceptionsUrl = mw.util.getUrl(exceptionsPage);
                    loadPage(exceptionsPage)
                    .then(function(exceptionsText) {
                        // Turn exceptions into an array
                        var exceptions = [];
                        if (exceptionsText !== undefined) {
                            var pattern = /(?:\* )([^\n\r]+)(?:[\r\n]|$)/g,
                                matches;
                            while (matches = pattern.exec(exceptionsText)) {
                                exceptions.push(matches[1]);
                            }
                        }
                        var newExceptions = exceptions;
                        newExceptions.push($('#CheckDictation-form-input').val());
                        newExceptions = '* ' + newExceptions.join('\n* ');
                        savePage(exceptionsPage, newExceptions, 'افزودن >' + $('#CheckDictation-form-input').val()).then(function() {
                            location.href = location.href;
                        });
                        $('#CheckDictation-form, #CheckDictation-form-input').remove();
                        $(this).dialog('close');
                    })
                }
            }, {
                text: 'اصلاح شود',
                class: 'ui-button-green',
                click: function() {
                    var box1 = $('#CheckDictation-form-input1', this).val();
                    var box2 = $('#CheckDictation-form-input2', this).val();
                    if (box1 === box2) {
                        box1 = '';
                        box2 = '';
                    }
                    defer.resolve($('#CheckDictation-form-input', this).val(), box1, box2);
                    $(this).dialog('close');
                }
            }],
            close: function() {
                $('#CheckDictation-form, #CheckDictation-form-input').remove();
            }
        }).parent().prop('id', 'CheckDictation-form');
        return defer;
    }

    var exceptionsPage = 'ویکی پاسخ:اشتباه‌یاب/موارد درست/' + mw.config.get('wgPageName').replace(/_/g, ' ');
    var exceptionsUrl = mw.util.getUrl(exceptionsPage);
    $.when(
        $.getJSON('//checkdictation-fa.toolforge.org/check/' + mw.config.get('wgPageName')),
        loadPage(exceptionsPage)
    ).then(
    	function(result, exceptionsText) {
	        result = result[0];
	        if (!Array.isArray(result.result)) {
	            console.error(result.error);
	            return;
	        }
	
	        var issues = result.result;
	        if (issues.length === 0) {
	            siteSub.append(' ', $('<span>', {
	                text: 'اشتباه‌یاب: اشتباهی پیدا نشد!',
	                class: 'CheckDictation-allgood-label',
	            }));
	            return;
	        }
	
	        // Turn exceptions into an array
	        var exceptions = [];
	        if (exceptionsText !== undefined) {
	            var pattern = /(?:\* )([^\n\r]+)(?:[\r\n]|$)/g,
	                matches;
	            while (matches = pattern.exec(exceptionsText)) {
	                exceptions.push(matches[1]);
	            }
	        }
	
	        if (exceptions.length > 0) {
	            var numberOfExceptions = exceptions.length.toLocaleString('fa');
	            siteSub.append(' ', $('<span>', {
	                'class': 'CheckDictation-exceptions-label'
	            }).append(
	                'اشتباه‌یاب: ' + numberOfExceptions + ' کلمهٔ مشکوک به اشتباه ',
	                $('<a>', {
	                    href: exceptionsUrl,
	                    text: 'مستثنی شده‌اند'
	                })
	            ));
	        }
	
	        // Remove those words that are in the exceptions list from the issues list
	        issues = issues.filter(function(issue) {
	            return exceptions.indexOf(issue.word) === -1;
	        });
	
	        if (issues.length === 0) {
	            return;
	        }
	
	        var availableTypes = {};
	        issues.forEach(function(x) {
	            availableTypes[x.type] = true;
	        });
	        var types = result.types;
	
	        var legend = Object.keys(types).filter(function(x) {
	            return availableTypes[x];
	        }).map(function(x) {
	            var type = types[x];
	            return [
	                $('<div>').css({
	                    width: '12px',
	                    height: '12px',
	                    display: 'inline-block',
	                    'background-color': type.color
	                }),
	                ' ',
	                $('<span>', {
	                    text: type.title
	                }).css({
	                    'font-size': '10pt'
	                })
	            ];
	        }).reduce(function(x, y) {
	            return x.concat('، ', y);
	        });
	
	        $('#CheckDictation-tool').remove();
	
	        // رفع تداخل با provit.js
	        var anchor1 = mw.config.get('wgAction') === 'edit' ?
	            '#firstHeading' :
	            'h1:first';
	        var numberOfIssues = issues.length.toLocaleString('fa');
	        siteSub.append(' ', $('<span>', {
	            text: 'اشتباه‌یاب: ' + numberOfIssues + ' مشکل نوشتاری یا شیوه‌نامه‌ای یافت شد؛ برای بررسی و اصلاح اینجا کلیک کنید',
	            class: 'CheckDictation-issues-label'
	        }).click(function() {
	            $(this).hide();
	            $('#CheckDictation-tool').show();
	        }));
	        $(anchor1).after($('<div>', {
	            id: 'CheckDictation-tool'
	        }).hide().append(
	            $('<big>', {
	                text: numberOfIssues + ' مورد مشکوک به اشتباه نوشتاری یا شیوه‌نامه‌ای یافت شد!'
	            }).css('font-style', 'italic'),
	            ' (',
	            legend,
	            ')',
	            $('<div>', {
	                id: 'spellmarkedwords',
	                text: 'موارد مشکوک به اشتباه: '
	            }),
	            '<br><br>',
	            $('<div>', {
	                id: 'CheckDictation-button-place'
	            }),
	            $('<div>', {
	                id: 'CheckDictation-button-place-after',
	            }).css('font-size', '10pt').append(
	                'در صورت کلیک بر روی دکمهٔ فوق موارد درست در ',
	                $('<a>', {
	                    href: exceptionsUrl,
	                    text: exceptionsPage
	                }),
	                ' ذخیره می‌شوند.',
	                '<br>',
	                $('<div>', {
	                    id: 'CheckDictation-button-place-after-2',
	                    text: 'استفادهٔ نادرست از این دکمه، باعث می‌شود دسترسی شما به ابزار بسته شود. پیش از کلیک بر روی دکمه، مطمئن شوید که همهٔ موارد پیشنهادی درست هستند. پیش از کلیک بر روی دکمه، حتماً از ابرابزار استفاده کنید. بسیاری از خطاهای مقاله توسط ابرابزار رفع می‌شوند.'
	                }).css({
	                    'font-size': '10pt',
	                    'font-weight': 'bold',
	                    'color': 'red'
	                }),
	                '<br>', [
	                    'نکتهٔ ۱: بعضی از این موارد، فقط در حالت ویرایش دیده‌ می‌شوند!',
	                    'نکتهٔ ۲: با کلیک کردن بر روی کلمات در بالا، بدون رفتن به پنجرهٔ ویرایش به صورت خودکار می‌توانید کلمهٔ درست را جایگزین کنید.',
	                    'نکتهٔ ۳: می‌توانید چند مورد را پشت سر هم با کلیک انتخاب کنید و با زدن دکمه‌ای که ظاهر می‌شود همهٔ آنها را در یک ویرایش جایگزین کنید.'
	                ].map(function(x) {
	                    return $('<div>', {
	                        text: x
	                    }).css('font-size', '8pt');
	                })
	            )
	        ));
	        $('<button>', {
	            text: 'ابهام‌زدایی با ابزاری دیگر',
	            style: 'margin-right: 2em',
	            id: 'CheckDictation-Disambig'
	        }).click(function() {
	            var my_url = 'https://dispenser.info.tm/~dispenser/cgi-bin/dab_solver.py?lang=fa&page=' + mw.config.get('wgPageName')
	            window.open(my_url, '_blank');
	        }).appendTo('#CheckDictation-button-place').append(
	            '<br><br>')
	        $('#CheckDictation-Disambig').hide();
	
	        if (mw.config.get('wgUserGroups').indexOf('sysop') > -1 || mw.config.get('wgUserGroups').indexOf('eliminator') > -1 || mw.config.get('wgUserGroups').indexOf('patroller') > -1) {
	            $('<button>', {
	                text: 'ذخیره در زیرصفحه: همهٔ موارد برای این مقاله درست است!',
	                style: 'margin-right: 2em',
	                id: 'CheckDictation-close'
	            }).click(function() {
	                var newExceptions = exceptions;
	                var addToExceptions = issues.map(function(issue) {
	                    return issue.word;
	                });
	                addToExceptions.forEach(function(word) {
	                    newExceptions.push(word);
	                });
	                newExceptions = '* ' + newExceptions.join('\n* ');
	
	                savePage(exceptionsPage, newExceptions, 'افزودن >' + addToExceptions.join('، ')).then(function() {
	                    location.href = location.href;
	                });
	
	            }).appendTo('#CheckDictation-button-place');
	        } else {
	            $('#CheckDictation-button-place-after').hide();
	            $('#CheckDictation-button-place-after-2').hide();
	        }
	
	        var arabic_diacritics = "ًٌٍَُِّْٔ"
	        var main_regex = '\[؛؟\\s\\n\\r\\•●⚫⬤\\„\\”\\‚\\’\\‘\\“\\[\\]\\{\\}\\t\\<\\>\\.\\,\\"' + "\\'\\+\\!\\?\\-\\/\\»«،\\:\\|\\(\\)\۰۱۲۳۴۵۶۷۸۹]";
	        var start_regex = '\(\^\|' + main_regex + '\)';
	        var end_regex = '\(\$\|[' + arabic_diacritics + ']*' + main_regex + '\)';
	        var articleBody = $('#bodyContent, #article')[0];
	        var replacements = [];
	        var markedItems = [];
	
	        issues.forEach(function(item, i) {
	            var word = item.word,
	                type = types[item.type],
	                suggestions = item.suggestions.sort(),
	                cleanedWord = item.cleaned_word,
	                regexp, preparedId;
	            var myhint = type.hint
	            if (type.autofix == 'D') {
	                $('#CheckDictation-Disambig').show();
	                myhint = suggestions.join(' | ')
	            }
	            if (i !== 0) {
	                markedItems.push('، ');
	            }
	            regexp = new RegExp(type.syntax ?
	                mw.util.escapeRegExp(word) :
	                (start_regex + '(' +
	                    word.substring(0, word.length - 1).replace(/[ء-يٓ-ٕپچژگکكڪﻙﻚیﻱﻲكﮑﮐﮏﮎﻜﻛﻚﻙىﻯيہەھﻰ-ﻴ]/g, '$&\[ً-ِّْٰٔ\]\*') + word.slice(-1) +
	                    ')' + end_regex),
	                'g'
	            );
	            preparedId = 'tool-' + encodeURI(word).replace(/%/g, '.');
	            if (type.autofix == 'D') {
	                markWord2(articleBody, regexp, word, myhint || suggestions[0], preparedId);
	                $("a.mw-disambig").css("background-color", "#fadbd8");
	                $("a.mw-disambig").css("color", "#999933");
	            } else {
	                markWord(articleBody, regexp, word, myhint || suggestions[0], type.color, preparedId);
	            }
	            var element = $('<span>', {
	                style: 'background-color: ' + type.color,
	                text: word,
	                title: myhint || suggestions[0]
	            });
	            element.css('cursor', 'pointer');
	            element.click(function() {
	                if (!type.autofix) {
	                    location.hash = preparedId;
	                    return;
	                }
	                getPageTextCache().then(function(content) {
	                    var nearWordsRegex = new RegExp('((?:\\S+\\s+){0,5}|\^)(?:[«\\[\\(\\)\\|\\-۰۱۲۳۴۵۶۷۸۹0-9\\u200c\\]])?(' + word.substring(0, word.length - 1).replace(/[^ ]/g, '$&\[ً-ِّْٰٔ\]\*') + word.slice(-1) + ')(\\s*(?:\\S+\\s+){0,5}|\$)', 'g')
	                    var nearWordsList = [],
	                        found;
	                    while (found = nearWordsRegex.exec(content)) {
	                        var myfound = found[0]
	                        if (myfound[0] == '[') {
	                            myfound = '[' + myfound
	                        }
	                        if (type.autofix == 'D') {
	                            if (myfound.includes('[[' + word + ']]') || myfound.includes('[[' + word + '|')) {
	                                nearWordsList.push(myfound);
	                            } else {
	                                continue;
	                            }
	                        } else {
	                            nearWordsList.push(myfound);
	                        }
	                    }
	                    if (nearWordsList != null) {
	                        nearWordsList = '… ' + nearWordsList.join(' …<br>… ') + ' …'
	                        nearWordsList = nearWordsList.replace(/\t/g, '	')
	                        nearWordsList = nearWordsList.replace(/\n\n/g, '<br>')
	                        nearWordsList = nearWordsList.replace(/\n(\*|\#|\;|\=)/g, '<br>$1')
	                    } else {
	                        nearWordsList = ''
	                    }
	                    dictationReplaceDialog(
	                        ('در متن یا متن‌های زیر عبارت «' + word + '» با چه چیزی جایگزین شود؟'),
	                        (nearWordsList.replace(new RegExp('(' + word.substring(0, word.length - 1).replace(/[^ ]/g, '$&\[ً-ِّْٰٔ\]\*') + word.slice(-1) + ')', 'g'), '<big><b> $1 </b></big>')),
	                        word,
	                        suggestions
	                    ).then(function(toWord, toWord1, toWord2) {
	                        // Hide mark as valid button and comments, it confuses the users
	                        $('#CheckDictation-close, #CheckDictation-button-place-after').hide();
	
	                        element.css('background-color', '').css('color', 'grey').text(word + '⟸' + toWord).off();
	                        toWord = toWord.replace(/\200c /g, ' ').replace(/ \200c/g, ' ');
	                        if (mw.config.get('wgAction') === 'edit') {
	                            $('#wpTextbox1').val($('#wpTextbox1').val().replace(regexp, '$1' + toWord + '$3'));
	                            $('#wpTextbox1').val($('#wpTextbox1').val().replace(toWord1, toWord2));
	                        } else {
	                            if (toWord !== word) {
	                                if (type.autofix == 'D') {
	                                    regexp = new RegExp('(\\[\\[) \*(' + word + ') \*(\\]\\]|\\|)', 'g')
	                                }
	                                replacements.push([regexp, '$1' + toWord + '$3', word + '⟸' + toWord]);
	                            }
	                            if (toWord1 !== toWord2) {
	                                replacements.push([toWord1, toWord2, toWord1 + '⟸' + toWord2]);
	                            }
	                            $('#CheckDictation-apply').show();
	                        }
	                    }, function() {
	                        if (/[كڪﻙﻚيىےۍېہەھﭖﭗﭘﭙﭺﭻﭼﭽﮊﮋﮎﮏﮐﮑﻙﻚﻛﻜﮒﮓﮔﮕﮤﮥﯼﯽﯾﯿﻯﻰﻱﻲﻳﻴﺁﺂﺄﺃﺅﺆﺇﺈﺉﺊﺋﺌﺎﺏﺐﺑﺒﺕﺖﺗﺘﺙﺚﺛﺜﺝﺞﺟﺠﺡﺢﺣﺤﺥﺦﺧﺨﺩﺪﺫﺬﺭﺮﺯﺰﺱﺲﺳﺴﺵﺶﺷﺸﺹﺺﺻﺼﺽﺾﺿﻀﻁﻂﻃﻄﻅﻆﻇﻈﻉﻊﻋﻌﻍﻎﻏﻐﻑﻒﻓﻔﻕﻖﻗﻘﻝﻞﻟﻠﻡﻢﻣﻤﻥﻦﻧﻨﻩﻪﻫﻬﻫﻭﻮﻰﻲﻶﻸﻺﻼ]/.exec(word)) {
	                            alert('لغت پیشنهادی نویسهٔ غیرفارسی یا نویسهٔ نادرست دارد. قبل از گزارش لغت، لطفاً ابرابزار را در صفحه برانید!');
	                            return;
	                        }
	                        if (/((.*\u200c)$|^(\u200c.*))/.exec(word)) {
	                            alert('در انتها یا ابتدای لغت پیشنهادی نویسهٔ فاصلهٔ مجازی اضافی وجود دارد. لطفاً آن را به کمک ابزار جایگزینی یا ابرابزار حذف کنید');
	                            return;
	                        }
	                        $('CheckDictation-marked-' + word.replace(/ /g, '_')).css('background-color', '');
	                        element.css('background-color', '').css('color', 'grey').off();
	                        loadPage('ویکی پاسخ:اشتباه‌یاب/فهرست موارد درست').then(function(text) {
	                            if ((text + '\n').indexOf('* ' + (cleanedWord || word) + '\n') !== -1) {
	                                return;
	                            }
	                            return savePage('ویکی پاسخ:اشتباه‌یاب/فهرست موارد درست', text + '\n* ' + (cleanedWord || word), 'افزودن لغت درست و پرکاربرد «' + (cleanedWord || word) + '» به فهرست کلمات [[وپ:اشتباه|اشتباه‌یاب]]. موجود در مقالهٔ [[' + mw.config.get('wgPageName') + ']]');
	                        }).then(function() {
	                            mw.notify('کلمهٔ «' + word + '» به فهرست کلمات درست و پرکاربرد افزوده شد.');
	                        });
	                        $.get('//checkdictation-fa.toolforge.org/check/Botupdate').then(function() {}, function() {});
	                    });
	                });
	            });
	            markedItems.push(element[0]);
	
	        });
	
	        $('#spellmarkedwords').append(markedItems);
	
	        // reset page location to intended hash linked place
	        var hash = location.hash;
	        if (hash) {
	            location.hash = '';
	            location.hash = hash;
	        }
	
	        $('<button>', {
	            text: 'جایگزینی مواردی که انتخاب کردید!',
	            style: 'margin-right: 2em',
	            id: 'CheckDictation-apply'
	        }).click(function() {
	            $(this).prop('disabled', 'disabled').text('در حال دریافت و جایگزینی صفحه...');
	            loadPage(mw.config.get('wgPageName')).then(function(text) {
	                replacements.forEach(function(x) {
	                    text = text.replace(x[0], x[1]);
	                    //solving bug: [[Special:Permalink/24532423#اشتباه‌یاب، ایجاد پیوند درونی با دو آرگومان.مان]]
	                    if (x[1].indexOf("|")!==-1){
	                        var wrong_replacment=x[1].split('|')[1].replace(/\[/g, '').replace(/\$[13]/g, '');
	                        text = text.replace('|'+wrong_replacment+'|', '|');
	                    }
	                });
	                return savePage(
	                    mw.config.get('wgPageName'),
	                    text,
	                    'جایگزینی با [[وپ:اشتباه|اشتباه‌یاب]]: ' + replacements.map(function(x) {
	                        return x[2];
	                    }).join('، ')
	                );
	            }).then(function() {
	                mw.notify('انجام شد، لطفاً بررسی کنید');
	                location.href = mw.util.getUrl(mw.config.get('wgPageName'), {
	                    diff: 'last'
	                });
	            });
	        }).hide().appendTo('#spellmarkedwords');
	    },
	    // if the AJAX call to the webservice failed, show a nice notification to the user
	    function(){
	    	siteSub.append(' ', $('<span>', {
                'class': 'CheckDictation-exceptions-label'
            }).append(
                'اشتباه‌یاب: خدمات‌دهنده در دسترس نیست؛ لطفاً در صورت استمرار این مشکل، در وپ:فنی گزارش دهید. '
            ));
	    }
    );
    // ویرایش بعد از ذخیره برای رفع تداخل با ویرایشگر دیداری
    //در صورتی که ویرایشگر دیداری برای کاربر فعال باشد
    // در مقاله برچسب نادرست توسط ابزار قرار گرفته باشد
    mw.hook('ve.saveDialog.stateChanged').add(function() {
        mw.hook('ve.deactivationComplete').add(function() {
            loadPage(mw.config.get('wgPageName')).then(function(text) {
                    return savePage(
                        mw.config.get('wgPageName'),
                        text = postEdit(text),
                        'ویرایش خودکار: اصلاح برچسب‌های نادرست'
                    );
            });
        });
    });
});