MediaWiki:Gadget-readableRC-core.js

Revision as of 16:12, 9 June 2020 by Banri (talk | contribs)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// Formats the rows on Special:RecentChanges where all the information runs together
// into three columns (page, diff/byte change, and user links) to make it more readable
//
// @author Iiii_I_I_I
//
// @todo make it run automatically instead of on button click?

(function($, mw) {
    function readableRC($content) {
        if ($content.hasClass('mw-changeslist')) {
            var rows = document.getElementsByClassName('mw-changeslist-line');

            function select(className) {
                return row.getElementsByClassName(className)[0];
            }

            function insert(newNode, referenceNode) {
                return select(referenceNode).parentNode.insertBefore(select(newNode), select(referenceNode));
            }

            function wrap(referenceNode, wrapperEl, wrapperClass) {
                var wrapper = document.createElement(wrapperEl);

                referenceNode.parentNode.insertBefore(wrapper, referenceNode);
                wrapper.appendChild(referenceNode);
                wrapper.classList.add(wrapperClass);
            }

            function cleanUserLinks() {
                // (talk | contribs | block) -> (t | c | b)
                // possible variations: (talk), (talk | contribs), (talk | block), (talk | contribs | block)
                select('mw-usertoollinks-talk').childNodes[0].nodeValue = 't';
                if (select('mw-usertoollinks-contribs')) select('mw-usertoollinks-contribs').childNodes[0].nodeValue = 'c';
                if (select('mw-usertoollinks-block')) select('mw-usertoollinks-block').childNodes[0].nodeValue = 'b';

                // remove spaces around pipes
                var toolLinks = select('mw-usertoollinks').childNodes;

                if (toolLinks.length > 3) {
                    toolLinks[2].nodeValue = '|';
                    if (toolLinks[4].nodeValue === ' | ') toolLinks[4].nodeValue = '|';
                }
            }

            for (var i = 0, rowTotal = rows.length; i < rowTotal; ++i) {
                var row = rows[i];

                // top-level rows
                if (row.classList.contains('mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested') === false) {
                    // multiple logs
                    if (row.classList.contains('mw-changeslist-log') && row.classList.contains('mw-collapsible')) {
                        // log name
                        wrap(select('mw-rc-unwatched'), 'td', 'gadget-rc-logname');

                        // remove parentheses (added back with css)
                        var parentheses = select('mw-rc-unwatched').childNodes;

                        select('mw-rc-unwatched').removeChild(parentheses[0]); // (
                        select('mw-rc-unwatched').removeChild(parentheses[1]); // )

                        // remove square brackets from grouped usernames
                        var brackets = select('changedby').childNodes;
                        var lastBracket = brackets[brackets.length - 1];

                        select('changedby').removeChild(brackets[0]); // [
                        lastBracket.nodeValue = lastBracket.nodeValue.slice(0, -1); // ]

                        // placeholder column with separator dots
                        wrap(select('mw-changeslist-separator'), 'td', 'gadget-rc-logdots');

                        // rename <td>
                        select('mw-changeslist-line-inner').className = 'gadget-rc-logentry';

                        // rearrange newly created <td>s
                        insert('gadget-rc-logname', 'gadget-rc-logentry');
                        insert('gadget-rc-logdots', 'gadget-rc-logentry');

                        // stupid empty node
                        select('gadget-rc-logentry').removeChild(select('gadget-rc-logentry').childNodes[1]);
                    }
                    // single log
                    else if (row.className.includes('mw-changeslist-log')) {
                        // log name
                        wrap(select('mw-changeslist-line-inner').childNodes[1], 'td', 'gadget-rc-logname');

                        // remove leftover parentheses
                        var parentheses = select('mw-changeslist-line-inner').childNodes;

                        select('mw-changeslist-line-inner').removeChild(parentheses[0]); // (
                        select('mw-changeslist-line-inner').removeChild(parentheses[1]); // )

                        // placeholder column with separator dots
                        wrap(select('mw-changeslist-separator'), 'td', 'gadget-rc-logdots');

                        cleanUserLinks();

                        // rename <td>
                        select('mw-changeslist-line-inner').className = 'gadget-rc-logentry';

                        // rearrange newly created <td>s
                        insert('gadget-rc-logname', 'gadget-rc-logentry');
                        insert('gadget-rc-logdots', 'gadget-rc-logentry');
                    }
                    // multiple edits
                    else if (row.classList.contains('mw-collapsible')) {
                        // page name
                        wrap(select('mw-title'), 'td', 'gadget-rc-pagename');

                        // "x changes" -> "x diffs"
                        if (select('mw-changeslist-groupdiff')) {
                            var newDiff = select('mw-changeslist-groupdiff').childNodes[0].nodeValue.replace('changes', 'diffs');
                            select('mw-changeslist-groupdiff').childNodes[0].nodeValue = newDiff;
                        }
                        // new pages have a text node instead of a link
                        else {
                            var newDiff = select('mw-changeslist-line-inner').childNodes[2].nodeValue.replace('changes', 'diffs');
                            select('mw-changeslist-line-inner').childNodes[2].nodeValue = newDiff;
                        }

                        // "history" -> "hist"
                        if (select('mw-changeslist-history')) {
                            select('mw-changeslist-history').childNodes[0].nodeValue = 'hist';
                        }
                        // nonexistent pages (redirect-suppressed move or deleted) have a text node instead of a link
                        else {
                            var newHist = select('mw-changeslist-line-inner').childNodes[4].nodeValue.replace('history', 'hist');
                            select('mw-changeslist-line-inner').childNodes[4].nodeValue = newHist;
                        }

                        // list of user(s)
                        wrap(select('changedby'), 'td', 'gadget-rc-userlinks');

                        // remove square brackets from grouped usernames
                        var brackets = select('changedby').childNodes;
                        var lastBracket = brackets[brackets.length - 1];

                        select('changedby').removeChild(brackets[0]); // [
                        lastBracket.nodeValue = lastBracket.nodeValue.slice(0, -1); // ]

                        // rename <td>
                        select('mw-changeslist-line-inner').className = 'gadget-rc-diff';

                        // rearrange newly created <td>s
                        insert('gadget-rc-userlinks', 'gadget-rc-diff');
                        insert('gadget-rc-pagename', 'gadget-rc-userlinks');
                        insert('gadget-rc-diff', 'gadget-rc-userlinks');
                    }
                    // single edit
                    else {
                        // page name
                        wrap(select('mw-title'), 'td', 'gadget-rc-pagename');

                        // "rollback x edits" -> "rollback"
                        // link does not exist if it is a page creation or user does not have the right
                        if (select('mw-rollback-link')) row.querySelector('.mw-rollback-link a').childNodes[0].nodeValue = 'rollback';

                        // user info
                        $('.mw-userlink, .mw-usertoollinks, .comment, .mw-rollback-link, .mw-tag-markers', row).wrapAll('<td class="gadget-rc-userlinks" />');

                        cleanUserLinks();

                        // rename <td>
                        select('mw-changeslist-line-inner').className = 'gadget-rc-diff';

                        // rearrange newly created <td>s
                        insert('gadget-rc-userlinks', 'gadget-rc-diff');
                        insert('gadget-rc-pagename', 'gadget-rc-userlinks');
                        insert('gadget-rc-diff', 'gadget-rc-userlinks');
                    }
                }
                // nested rows
                else {
                    var nested = row.getElementsByClassName('mw-enhanced-rc-nested')[1];
                    nested.setAttribute('colspan', '3');
                    nested.classList.add('gadget-rc-nested');

                    cleanUserLinks();
                }
            }

            $content.addClass('gadget-rc-enabled');
        }
    }

	function init() {
        var button = new OO.ui.ButtonWidget({
            icon: 'viewCompact',
            label: 'ReadableRC',
            title: 'Format RecentChanges into columns for readability',
            classes: ['gadget-rc-button']
        });

        button.on('click', function() {
            readableRC($('.mw-changeslist'));
            mw.hook('wikipage.content').add(readableRC);
            button.setDisabled(true);
        });
        mw.hook('structuredChangeFilters.ui.initialized').add(function() {
            $('.mw-rcfilters-ui-liveUpdateButtonWidget').append(button.$element);
        });
    }

	$(init);
})(jQuery, mediaWiki);

// </nowiki>