跳转到内容

User:ChasingAir/js/fixCat.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
//<nowiki>
(function($, mw, OO) {
    'use strict';

    if (!window.OO || !OO.ui) {
        mw.loader.using('oojs-ui-windows').then(function() {
            init();
        });
    } else {
        init();
    }

    function init() {
        var categoryName = 'Category:图像尺寸大小带有额外px字符的页面';
        if (mw.config.get('wgPageName') !== categoryName.replace(/ /g, '_')) {
            return;
        }

        mw.util.addPortletLink(
            'p-tb',
            '#',
            '清理px',
            'ca-fixcat',
            '清理图像尺寸px字符'
        );

        $('#ca-fixcat').on('click', function(e) {
            e.preventDefault();
            showCleanupDialog();
        });
    }

    function CleanupDialog(config) {
        CleanupDialog.parent.call(this, config);
        this.pages = [];
        this.currentPage = null;
        this.wikitext = '';
        this.baseRevId = null;
        this.matches = [];
        this.currentMatchIndex = -1;
    }

    OO.inheritClass(CleanupDialog, OO.ui.ProcessDialog);

    CleanupDialog.static.name = 'cleanupDialog';
    CleanupDialog.static.title = '清理图像尺寸px字符';
    CleanupDialog.static.size = 'full';
    CleanupDialog.static.actions = [
        {
            action: 'close',
            label: '关闭',
            flags: 'safe'
        }
    ];

    CleanupDialog.prototype.initialize = function() {
        CleanupDialog.parent.prototype.initialize.apply(this, arguments);

        var dialog = this;

        this.$mainContainer = $('<div>').css({
            'display': 'flex',
            'height': '700px',
            'gap': '15px'
        });

        this.$pageList = $('<div>').css({
            'width': '250px',
            'min-width': '250px',
            'border': '1px solid #ccc',
            'padding': '10px',
            'overflow-y': 'auto',
            'background': '#f9f9f9'
        });

        this.$editorArea = $('<div>').css({
            'flex': '1',
            'display': 'flex',
            'flex-direction': 'column',
            'gap': '10px'
        });

        // Wikitext显示区域
        this.$wikitextContainer = $('<div>').css({
            'flex': '1',
            'border': '1px solid #ccc',
            'padding': '10px',
            'overflow': 'auto',
            'background': '#fff',
            'font-family': 'monospace',
            'white-space': 'pre-wrap',
            'position': 'relative'
        });

        this.$controls = $('<div>').css({
            'display': 'flex',
            'gap': '10px',
            'align-items': 'center'
        });

        // 搜索按钮
        this.searchButton = new OO.ui.ButtonWidget({
            label: '搜索px',
            flags: ['progressive']
        });

        this.prevButton = new OO.ui.ButtonWidget({
            label: '上一个',
            disabled: true
        });

        this.nextButton = new OO.ui.ButtonWidget({
            label: '下一个',
            disabled: true
        });

        this.removeButton = new OO.ui.ButtonWidget({
            label: '去除px',
            flags: ['destructive'],
            disabled: true
        });

        this.$matchCount = $('<span>').css({
            'margin-left': '10px',
            'color': '#666'
        });

        this.$controls.append(
            this.searchButton.$element,
            this.prevButton.$element,
            this.nextButton.$element,
            this.removeButton.$element,
            this.$matchCount
        );

        this.$submitArea = $('<div>').css({
            'width': '200px',
            'min-width': '200px',
            'display': 'flex',
            'flex-direction': 'column',
            'gap': '10px'
        });

        this.summaryInput = new OO.ui.TextInputWidget({
            placeholder: '编辑摘要',
            value: '清理图像尺寸中的多余px字符'
        });

        this.submitButton = new OO.ui.ButtonWidget({
            label: '提交',
            flags: ['primary', 'progressive'],
            disabled: true
        });

        this.$submitArea.append(
            $('<label>').text('编辑摘要:'),
            this.summaryInput.$element,
            this.submitButton.$element
        );

        this.$editorArea.append(
            this.$wikitextContainer,
            this.$controls
        );

        this.$mainContainer.append(
            this.$pageList,
            this.$editorArea,
            this.$submitArea
        );

        this.$body.append(this.$mainContainer);

        this.searchButton.on('click', this.searchMatches.bind(this));
        this.prevButton.on('click', this.showPrevMatch.bind(this));
        this.nextButton.on('click', this.showNextMatch.bind(this));
        this.removeButton.on('click', this.removeCurrentPx.bind(this));
        this.submitButton.on('click', this.submitEdit.bind(this));

        this.loadPages();
    };

    CleanupDialog.prototype.getBodyHeight = function() {
        return 750;
    };

    // 加载分类下的页面
    CleanupDialog.prototype.loadPages = function() {
        var dialog = this;
        this.$pageList.html('<div>加载中...</div>');

        var api = new mw.Api();
        api.get({
            action: 'query',
            list: 'categorymembers',
            cmtitle: 'Category:图像尺寸大小带有额外px字符的页面',
            cmlimit: 100,
            format: 'json',
            formatversion: 2
        }).done(function(data) {
            if (data.query && data.query.categorymembers && data.query.categorymembers.length > 0) {
                var mainNamespacePages = data.query.categorymembers.filter(function(page) {
                    return page.ns === 0;
                }).slice(0, 10);
                
                if (mainNamespacePages.length > 0) {
                    dialog.pages = mainNamespacePages;
                    dialog.renderPageList();
                } else {
                    dialog.$pageList.html('<div>未找到主条目空间的页面</div>');
                }
            } else {
                dialog.$pageList.html('<div>未找到页面</div>');
            }
        }).fail(function(error) {
            dialog.$pageList.html('<div>加载失败: ' + error + '</div>');
        });
    };

    CleanupDialog.prototype.renderPageList = function() {
        var dialog = this;
        this.$pageList.empty();

        if (this.pages.length === 0) {
            this.$pageList.html('<div>暂无页面</div>');
            return;
        }

        this.pages.forEach(function(page) {
            var $pageItem = $('<div>').css({
                'padding': '8px',
                'margin': '5px 0',
                'cursor': 'pointer',
                'border': '1px solid #ddd',
                'border-radius': '3px',
                'background': '#fff',
                'word-wrap': 'break-word'
            }).text(page.title).on('click', function() {
                dialog.$pageList.find('div').css('background', '#fff');
                $(this).css('background', '#e6f3ff');
                dialog.loadPageContent(page.title);
            });

            dialog.$pageList.append($pageItem);
        });
    };

    // 加载页面内容
    CleanupDialog.prototype.loadPageContent = function(pageTitle) {
        var dialog = this;
        this.currentPage = pageTitle;
        this.$wikitextContainer.html('加载中...');
        this.submitButton.setDisabled(true);
        this.matches = [];
        this.currentMatchIndex = -1;
        this.updateMatchCount();

        var api = new mw.Api();
        api.get({
            action: 'query',
            titles: pageTitle,
            prop: 'revisions',
            rvprop: 'content|ids',
            rvslots: 'main',
            format: 'json'
        }).done(function(data) {
            var pages = data.query.pages;
            var pageId = Object.keys(pages)[0];
            var page = pages[pageId];

            if (page.revisions && page.revisions[0]) {
                dialog.wikitext = page.revisions[0].slots.main['*'];
                dialog.baseRevId = page.revisions[0].revid;
                dialog.renderWikitext();
                dialog.submitButton.setDisabled(false);
            } else {
                dialog.$wikitextContainer.html('无法加载页面内容');
            }
        }).fail(function() {
            dialog.$wikitextContainer.html('加载失败');
        });
    };

    // 渲染Wikitext
    CleanupDialog.prototype.renderWikitext = function() {
        this.$wikitextContainer.html($('<div>').text(this.wikitext));
    };

    CleanupDialog.prototype.searchMatches = function() {
        var dialog = this;
        this.matches = [];
        this.currentMatchIndex = -1;

        var regex = /\{\{[^}]*?\d+px[^}]*?\}\}/g;
        var match;

        while ((match = regex.exec(this.wikitext)) !== null) {
            var templateText = match[0];
            var innerRegex = /(\d+)(px)/g;
            var innerMatch;
            var templateStart = match.index;

            while ((innerMatch = innerRegex.exec(templateText)) !== null) {
                this.matches.push({
                    start: templateStart + innerMatch.index,
                    end: templateStart + innerMatch.index + innerMatch[0].length,
                    text: innerMatch[0],
                    numberPart: innerMatch[1],
                    pxPart: innerMatch[2]
                });
            }
        }

        if (this.matches.length > 0) {
            this.currentMatchIndex = 0;
            this.highlightCurrentMatch();
            this.prevButton.setDisabled(false);
            this.nextButton.setDisabled(false);
            this.removeButton.setDisabled(false);
        } else {
            mw.notify('未找到匹配项', { type: 'warn' });
            this.renderWikitext();
            this.prevButton.setDisabled(true);
            this.nextButton.setDisabled(true);
            this.removeButton.setDisabled(true);
        }

        this.updateMatchCount();
    };

    CleanupDialog.prototype.highlightCurrentMatch = function() {
        if (this.currentMatchIndex < 0 || this.currentMatchIndex >= this.matches.length) {
            return;
        }

        var parts = [];
        var lastEnd = 0;

        this.matches.forEach(function(match, index) {
            if (match.start > lastEnd) {
                parts.push($('<span>').text(this.wikitext.substring(lastEnd, match.start)));
            }

            var $highlight = $('<span>').text(match.text).css({
                'background-color': index === this.currentMatchIndex ? '#ffff00' : '#ffeb3b',
                'font-weight': index === this.currentMatchIndex ? 'bold' : 'normal',
                'padding': '2px 4px',
                'border-radius': '3px'
            });

            if (index === this.currentMatchIndex) {
                $highlight.attr('id', 'current-match');
            }

            parts.push($highlight);
            lastEnd = match.end;
        }, this);

        if (lastEnd < this.wikitext.length) {
            parts.push($('<span>').text(this.wikitext.substring(lastEnd)));
        }

        this.$wikitextContainer.empty();
        parts.forEach(function(part) {
            this.$wikitextContainer.append(part);
        }, this);

        var $current = this.$wikitextContainer.find('#current-match');
        if ($current.length) {
            $current[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
        }

        this.updateMatchCount();
    };

    CleanupDialog.prototype.showPrevMatch = function() {
        if (this.currentMatchIndex > 0) {
            this.currentMatchIndex--;
            this.highlightCurrentMatch();
        }
    };

    CleanupDialog.prototype.showNextMatch = function() {
        if (this.currentMatchIndex < this.matches.length - 1) {
            this.currentMatchIndex++;
            this.highlightCurrentMatch();
        }
    };

    CleanupDialog.prototype.updateMatchCount = function() {
        if (this.matches.length > 0) {
            this.$matchCount.text('匹配: ' + (this.currentMatchIndex + 1) + ' / ' + this.matches.length);
        } else {
            this.$matchCount.text('');
        }
    };

    CleanupDialog.prototype.removeCurrentPx = function() {
        if (this.currentMatchIndex < 0 || this.currentMatchIndex >= this.matches.length) {
            return;
        }

        var currentMatch = this.matches[this.currentMatchIndex];

        this.wikitext = this.wikitext.substring(0, currentMatch.start) +
                       currentMatch.numberPart +
                       this.wikitext.substring(currentMatch.end);

        var removedLength = currentMatch.pxPart.length;
        this.matches.splice(this.currentMatchIndex, 1);

        for (var i = this.currentMatchIndex; i < this.matches.length; i++) {
            this.matches[i].start -= removedLength;
            this.matches[i].end -= removedLength;
        }

        if (this.currentMatchIndex >= this.matches.length && this.matches.length > 0) {
            this.currentMatchIndex = this.matches.length - 1;
        }

        if (this.matches.length === 0) {
            this.currentMatchIndex = -1;
            this.renderWikitext();
            this.prevButton.setDisabled(true);
            this.nextButton.setDisabled(true);
            this.removeButton.setDisabled(true);
            mw.notify('所有px已清理完毕', { type: 'success' });
        } else {
            this.highlightCurrentMatch();
        }

        this.updateMatchCount();
    };

    CleanupDialog.prototype.submitEdit = function() {
        var dialog = this;

        if (!this.currentPage || !this.baseRevId) {
            mw.notify('请先选择一个页面', { type: 'error' });
            return;
        }

        this.submitButton.setDisabled(true);
        this.submitButton.setLabel('提交中...');

        var api = new mw.Api();
        api.postWithToken('csrf', {
            action: 'edit',
            title: this.currentPage,
            text: this.wikitext,
            summary: this.summaryInput.getValue(),
            baserevid: this.baseRevId,
            format: 'json'
        }).done(function(data) {
            if (data.edit && data.edit.result === 'Success') {
                mw.notify('编辑成功!', { type: 'success' });
                dialog.pages = dialog.pages.filter(function(page) {
                    return page.title !== dialog.currentPage;
                });
                dialog.renderPageList();
                dialog.$wikitextContainer.html('请从左侧选择一个页面');
                dialog.currentPage = null;
                dialog.submitButton.setDisabled(true);
            } else {
                mw.notify('编辑失败: ' + (data.error ? data.error.info : '未知错误'), { type: 'error' });
                dialog.submitButton.setDisabled(false);
            }
            dialog.submitButton.setLabel('提交');
        }).fail(function(code, data) {
            var errorMsg = '编辑失败';
            if (code === 'editconflict') {
                errorMsg = '编辑冲突,页面已被他人修改';
            } else if (data && data.error) {
                errorMsg = data.error.info;
            }
            mw.notify(errorMsg, { type: 'error' });
            dialog.submitButton.setDisabled(false);
            dialog.submitButton.setLabel('提交');
        });
    };

    CleanupDialog.prototype.getActionProcess = function(action) {
        var dialog = this;
        if (action === 'close') {
            return new OO.ui.Process(function() {
                dialog.close({ action: action });
            });
        }
        return CleanupDialog.parent.prototype.getActionProcess.call(this, action);
    };

    function showCleanupDialog() {
        var windowManager = new OO.ui.WindowManager();
        $(document.body).append(windowManager.$element);

        var dialog = new CleanupDialog({
            size: 'full'
        });

        windowManager.addWindows([dialog]);
        windowManager.openWindow(dialog);
    }

})(jQuery, mediaWiki, OO);
//</nowiki>