Jump to content

User:DreamRimmer/NoRedCat.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//<nowiki>
(function () {
    var defaultSummary = 'Removed redlinked categories';
    var customSummary = mw.user.options.get('customNoRedCatSummary') || defaultSummary;

    function escapeRegex(str) {
        return str.replace(/[-\/\\^$*+?.()|[\]{}&',’]/g, '\\$&');
    }

    function getCats() {
        return $('#mw-normal-catlinks ul li a').map(function () {
            var cat = $(this).text().trim();
            return /^[\w\s\-()&',’]+$/.test(cat) ? cat : null;
        }).get().filter(Boolean);
    }

    function isRedcat(cat) {
        var ignoredCats = [
            'Wikipedians with red-linked categories on their user page',
            'Wikipedians with red-linked categories on their user talk page'
        ];
        if (ignoredCats.includes(cat)) {
            return Promise.resolve(null);
        }
        return new mw.Api().get({
            action: 'query',
            titles: 'Category:' + cat,
            format: 'json'
        }).then(data => ('-1' in data.query.pages) ? cat : null);
    }

    function confirmAndRemove(redCats) {
        if (!redCats.length) {
            alert('No redlinked categories found.');
            return;
        }

        function NoRedCatDialog(config) {
            NoRedCatDialog.super.call(this, config);
        }
        OO.inheritClass(NoRedCatDialog, OO.ui.ProcessDialog);

        NoRedCatDialog.static.name = 'noRedCatDialog';
        NoRedCatDialog.static.title = 'NoRedCat';
        NoRedCatDialog.static.actions = [
            { action: 'accept', label: 'Submit', flags: ['primary', 'progressive'] },
            { action: 'cancel', label: 'Cancel', flags: 'safe' }
        ];

        NoRedCatDialog.prototype.initialize = function () {
            NoRedCatDialog.super.prototype.initialize.apply(this, arguments);

            this.message = new OO.ui.PanelLayout({
                padded: true,
                expanded: false
            });

            this.message.$element.append(
                $('<div>').append(
                    $('<p>').css({
                        'font-size': '16px',
                        'font-weight': 'bold'
                    }).text('Remove these categories?')
                ).append(
                    $('<ul>').append(redCats.map(function (c) {
                        return $('<li>').html('<a href="/wiki/Category:' + c + '" class="new" target="_blank" style="font-size: 14px;">Category:' + c + '</a>');
                    }))
                )
            );

            this.summaryInput = new OO.ui.TextInputWidget({
                value: customSummary
            });

            this.message.$element.append(
                $('<div>').append(
                    $('<p>').css({
                        'font-size': '16px',
                        'font-weight': 'bold'
                    }).text('Edit Summary:')
                ).append(this.summaryInput.$element)
            );

            this.$body.append(this.message.$element);
        };

        NoRedCatDialog.prototype.getBodyHeight = function () {
            return this.message.$element[0].scrollHeight + 10;
        };

        NoRedCatDialog.prototype.getActionProcess = function (action) {
            var dialog = this;

            if (action === 'accept') {
                return new OO.ui.Process(function () {
                    var summary = dialog.summaryInput.getValue() + ' (using [[User:DreamRimmer/NoRedCat|NoRedCat.js]])';
                    editPage(redCats, summary);
                    dialog.close({ action: action });
                });
            }

            if (action === 'cancel') {
                return new OO.ui.Process(function () {
                    dialog.close({ action: action });
                });
            }

            return NoRedCatDialog.super.prototype.getActionProcess.call(this, action);
        };

        var windowManager = new OO.ui.WindowManager();
        $(document.body).append(windowManager.$element);
        var dialog = new NoRedCatDialog({
            size: 'medium'
        });
        windowManager.addWindows([dialog]);
        windowManager.openWindow(dialog);
    }

    function editPage(redCats, summary) {
        var api = new mw.Api();
        api.get({
            action: 'query',
            prop: 'revisions',
            titles: mw.config.get('wgPageName'),
            rvprop: 'content',
            format: 'json'
        }).then(function (res) {
            var pages = res.query.pages;
            var pageId = Object.keys(pages)[0];
            if (pageId === '-1' || !pages[pageId].revisions) return alert('Error fetching page content');
            var content = pages[pageId].revisions[0]['*'];
            
            redCats.forEach(function (cat) {
                var regex = new RegExp("^[ \t]*\\[\\[Category\\s*:\\s*" + escapeRegex(cat) + "\\s*(\\|[^\\]]*)?\\]\\][ \t]*\\n?", "gmi");
                content = content.replace(regex, '');
            });
            
            api.postWithToken('csrf', {
                action: 'edit',
                title: mw.config.get('wgPageName'),
                text: content,
                summary: summary,
                minor: true
            }).done(function (data) {
                if (data && data.edit && data.edit.newrevid) {
                    var newRevId = data.edit.newrevid;
                    alert('Removed redlinked categories.');
                    window.location.href = mw.util.getUrl(mw.config.get('wgPageName'), { diff: newRevId });
                } else {
                    alert('Edit completed, but could not retrieve diff.');
                    location.reload();
                }
            }).fail(function () {
                alert('Error saving changes');
            });
        });
    }

    mw.util.addPortletLink('p-tb', '#', 'NoRedCat', 'ca-check-remove-redcat-categories', 'Check and remove redlinked categories from this page');
    $('#ca-check-remove-redcat-categories').click(function (e) {
        e.preventDefault();
        Promise.all(getCats().map(isRedcat)).then(function (res) {
            confirmAndRemove(res.filter(c => c));
        });
    });
})();
//</nowiki>