Участница:Megitsune-chan/subst.js

// Скрипт для упрощённой подстановки шаблонов.
// Для установки, добавьте в свой common.js строку importScript('у:Megitsune-chan/subst.js');
// Имеется возможность выбора нескольких шаблонов, а так же выбора места ставки: начало или конец страницы.
// Для предложения добавить шаблоны в скрипт, обращайтесь на страницу обсуждения Участницы Megitsune-chan.

sigWarning = true;

// Добавляем стили
mw.loader.addStyleTag(`
.subst-modal {
    background: white;
    border: 1px solid #a2a9b1;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 9999;
    width: 750px;
    padding: 20px;
}

.subst-templates {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    max-height: 350px;
    overflow-y: auto;
    padding: 10px;
    border: 1px solid #eaecf0;
    border-radius: 4px;
    margin: 10px 0;
}

.template-checkbox {
    display: flex;
    align-items: center;
    padding: 5px;
    border-radius: 4px;
    transition: background 0.2s;
}

.template-checkbox:hover {
    background: #f8f9fa;
}

.subst-controls {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-top: 15px;
    padding-top: 15px;
    border-top: 1px solid #eaecf0;
}

.subst-position {
    margin: 10px 0;
}

.subst-button {
    padding: 8px 16px;
    border-radius: 4px;
    border: 1px solid #a2a9b1;
    cursor: pointer;
    transition: background 0.2s;
}

.subst-button.primary {
    background: #36c;
    color: white;
    border-color: #36c;
}

.subst-button:hover {
    background: #447ff5;
}

.subst-button.secondary:hover {
    background: #f8f9fa;
}
`);

//Список шаблонов
subst = {
    $reason: null,
    $token: null,
    $rev: null,

    $reasons: [{
            tmpl: 'автобиография',
            reason: 'Автобиография',
            ns: 0
        },
        {
            tmpl: 'аффилированные источники',
            reason: 'Аффилированные источники',
            ns: 0
        },
        {
            tmpl: 'взвешенность',
            reason: 'Взвешенность',
            ns: 0
        },
        {
            tmpl: 'грубый перевод',
            reason: 'Грубый перевод',
            ns: 0
        },
        {
            tmpl: 'дописать',
            reason: 'Дописать',
            ns: 0
        },
        {
            tmpl: 'длинное описание сюжета',
            reason: 'Длинное описание сюжета',
            ns: 0
        },
        {
            tmpl: 'значимость',
            reason: 'Значимость',
            ns: 0
        },
        {
            tmpl: 'излишние описания компьютерной игры',
            reason: 'Излишние описания компьютерной игры',
            ns: 0
        },
        {
            tmpl: 'конфликт интересов',
            reason: 'Конфликт интересов',
            ns: 0
        },
        {
            tmpl: 'много цитат',
            reason: 'Много цитат',
            ns: 0
        },
        {
            tmpl: 'неавторитетные источники',
            reason: 'Неавторитетные источники',
            ns: 0
        },
        {
            tmpl: 'недостаточно критики',
            reason: 'Недостаточно критики',
            ns: 0
        },
        {
            tmpl: 'нет источников',
            reason: 'Нет источников',
            ns: 0
        },
        {
            tmpl: 'нет карточки',
            reason: 'Нет карточки',
            ns: 0
        },
        {
            tmpl: 'нет преамбулы',
            reason: 'Нет преамбулы',
            ns: 0
        },
        {
            tmpl: 'нет сносок',
            reason: 'Нет сносок',
            ns: 0
        },
        {
            tmpl: 'неэнциклопедично',
            reason: 'Неэнциклопедично',
            ns: 0
        },
        {
            tmpl: 'обновить',
            reason: 'Обновить',
            ns: 0
        },
        {
            tmpl: 'орисс',
            reason: 'Орисс',
            ns: 0
        },
        {
            tmpl: 'отчество',
            reason: 'Отчество',
            ns: 0
        },
        {
            tmpl: 'пресс-релиз',
            reason: 'Пресс-релиз',
            ns: 0
        },
        {
            tmpl: 'проверить нейтральность',
            reason: 'Проверить нейтральность',
            ns: 0
        },
        {
            tmpl: 'редактирую',
            reason: 'Редактирую',
            ns: 666
        },
        {
            tmpl: 'Резюме',
            reason: 'Резюме',
            ns: 0
        },
        {
            tmpl: 'реклама',
            reason: 'Реклама',
            ns: 0
        },
        {
            tmpl: 'стиль статьи',
            reason: 'Стиль статьи',
            ns: 0
        },
        {
            tmpl: 'чистить',
            reason: 'Чистить',
            ns: 0
        },
        {
            tmpl: 'Ds-author',
            reason: 'К отсроченному удалению автором',
            ns: 666
        },
        {
            tmpl: 'помочь',
            reason: 'Инкубатор, Прошу помочь',
            ns: 102 && 103
        },
        {
            tmpl: 'проверить',
            reason: 'Инкубатор, Прошу проверить',
            ns: 102 && 103
        },
    ],

	//Создание окна
    initialise: function() {
        var $window = `
        <div id="subst-window" class="subst-modal">
            <h3>Выберите шаблоны для подстановки</h3>
            <form name="subst" id="subst">
                <div class="subst-templates">`;

        for (var $i in this.$reasons) {
            if (this.$reasons[$i].ns == 666 || this.$reasons[$i].ns == mw.config.get('wgNamespaceNumber')) {
                $window += `
                <label class="template-checkbox">
                    <input type="checkbox" name="subst" value="${$i}">
                    <span>${this.$reasons[$i].reason}</span>
                </label>`;
            }
        }

        $window += `
                </div>
                <div class="subst-position">
                    <label>Место добавления шаблонов:</label>
                    <select id="subst-position">
                        <option value="top">В начало страницы</option>
                        <option value="bottom">В конец страницы</option>
                    </select>
                </div>
                <div>
                    <input type="checkbox" id="subst-forcewrap">
                    <label for="subst-forcewrap">Обернуть шаблон в тег &lt;noinclude&gt;</label>
                </div>
                <div class="subst-controls">
                    <button type="button" id="subst-confirm" class="subst-button primary">Отправить</button>
                    <button type="button" id="subst-cancel" class="subst-button secondary">Отмена</button>
                </div>
            </form>
        </div>`;

        $('#bodyContent').append($window);

        $('#subst-confirm').on('click', function() {
            subst.execute();
        });
        $('#subst-cancel').on('click', function() {
            $('#subst-window').remove();
        });
    },


    execute: function() {
        var selectedTemplates = $("input[name='subst']:checked").map(function() {
            return $(this).val();
        }).get();

        if (selectedTemplates.length === 0) {
            alert('Выберите хотя бы один шаблон!');
            return;
        }

        this.$selectedTemplates = selectedTemplates;
        this.$position = $('#subst-position').val();

        $.getJSON(
            mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=info&titles=Foobar&meta=tokens&type=csrf',
            function($x) {
                subst.template($x);
            }
        );
    },

    template: function($data) {
        if (!$data || !$data['query']) {
            return;
        }

        this.$token = $data['query']['tokens']['csrftoken'];

        $.getJSON(mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&titles=' + subst._ae(mw.config.get('wgPageName')) + '&rvprop=user|content&rvlimit=1', function($data) {
            for (var $rev in $data['query']['pages']) {
                if (typeof $data['query']['pages'][$rev]['revisions'] == 'undefined') {
                    alert('Страница удалена или скрипт неправильно обработал её название.');
                    return false;
                }

                var $content = $data['query']['pages'][$rev]['revisions'][0]['*'];

                var self = subst; // Сохраняем ссылку на контекст
                var forcewrap = $('#subst-forcewrap').is(':checked');
                var nameSpace = mw.config.get('wgNamespaceNumber');
                var additionalParams = $("#subst-neob").val();

                // Создаем функцию форматирования шаблона
                function formatTemplate(reasonIndex) {
                    var reason = self.$reasons[reasonIndex];
                    var wrapStart = (forcewrap || nameSpace == 10) ? '<noinclude>' : '';
                    var wrapEnd = (forcewrap || nameSpace == 10) ? '</noinclude>' : '';

                    return wrapStart +
                        '{{' + (reason.ds ? 'subst:ds' : 'subst') +
                        ((reason.tmpl == '') ? '' : ':' + reason.tmpl) +
                        (additionalParams ? "|" + additionalParams : "") + '}}' +
                        wrapEnd + '\n';
                }

                // Формируем все выбранные шаблоны
                var templates = self.$selectedTemplates.map(function(index) {
                    return formatTemplate(index);
                }).join('');

                // Определяем итоговый контент в зависимости от выбранной позиции
                // Функция для поиска позиции перед категориями
                function findCategoryPosition(content) {
                    // Ищем первое вхождение категории
                    var categoryMatch = content.match(/\[\[\s*([Кк]атегория|Category)\s*:/);
                    if (categoryMatch) {
                        return categoryMatch.index;
                    }
                    return content.length;
                }

                // Определяем итоговый контент в зависимости от выбранной позиции
                var newContent;
                if (self.$position === 'top') {
                    newContent = templates + $content;
                } else {
                    // Если выбрано добавление в конец
                    var categoryPos = findCategoryPosition($content);
                    if (categoryPos === $content.length) {
                        // Если категорий нет, добавляем в самый конец
                        newContent = $content + templates;
                    } else {
                        // Если категории есть, вставляем перед ними
                        newContent = $content.slice(0, categoryPos) + templates + $content.slice(categoryPos);
                    }
                }

                // Отправляем изменения
                $.post(mw.config.get('wgScriptPath') + '/api.php', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    summary: 'Подстановка шаблонов с помощью [[user:Megitsune-chan/subst.js|subst.js]]',
                    token: self.$token,
                    notminor: '1',
                    text: newContent,
                    format: 'json'
                }, function($x) {
                    self.finalf($x)
                });
            }
        });
    },

    finalf: function($data) {
        this.$rev = $data['edit']['newrevid'];
        if ($('#subst-warn').is(':checked') && subst.$reasons[subst.$reason].warn) {
            $.getJSON(mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&rvdir=newer&prop=revisions&titles=' + subst._ae(mw.config.get('wgPageName')) + '&rvprop=user|content&rvlimit=1', function($x) {
                for (var $rev in $x['query']['pages']) {
                    var $talk = 'Обсуждение_участника:' + $x['query']['pages'][$rev]['revisions'][0]['user'];
                    $.post(mw.config.get('wgScriptPath') + '/api.php', {
                            action: 'edit',
                            appendtext: '\n{{subst:' + subst.$reasons[subst.$reason].warn +
                                ((subst.$reasons[subst.$reason].tmpl == 'copyvio') ? '|1=' + subst._sp(mw.config.get('wgPageName')) + '|2=' + $("#subst-field" + subst.$reason).val() : ((subst.$reasons[subst.$reason].tmpl == 'vand') ? '' : '|1=' + subst._sp(mw.config.get('wgPageName')))) + '}}' +
                                '\n~~' + '~~',
                            summary: ' ',
                            title: $talk,
                            token: subst.$token,
                            notminor: '1'
                        },
                        function() {
                            subst.review()
                        });
                }
            });
        } else {
            subst.review()
        }
    },

    review: function($data) {
        window.location = mw.config.get('wgServer') + '/wiki/' + encodeURIComponent(mw.config.get('wgPageName'));
    },

    _ae: function($i) {
        return $i.replace(/\+/g, '%2B').replace(/&/g, '%26');
    },
    _sp: function($i) {
        return $i.replace(/\+/g, '%2B').replace(/&/g, '%26').replace(/_/g, ' ');
    },
};

// Если мы не на служебной странице, не на странице файла (для него отдельный гаджет), а на существующей странице, которую можно править, добавляет вкладку
$(function() {
    if (mw.config.get('wgCanonicalNamespace') != 'Special' && mw.config.get('wgCanonicalNamespace') != 'File' && $("#ca-viewsource").length == 0 && mw.config.get('wgArticleId')) {
        mw.loader.using('mediawiki.util').done(function() {
            mw.util.addPortletLink("p-cactions", "javascript: subst.initialise()", "Подстановка", "ca-subst", "Подстановка шаблонов");
        });
    }
});
Prefix: a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9

Portal di Ensiklopedia Dunia

Kembali kehalaman sebelumnya