User:Chlod/Scripts/DummyEdit.js

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.
// DummyEdit
// Author: Chlod
// Version: 1.0.0

// Make dummy edits on a page. Adds whitespace to unnoticeable spots on
// the page, with a customizable edit summary. To be used for WP:PATT/WP:RIA.
// <nowiki>
$( function () {
    mw.util.addPortletLink(
        'p-tb', '#', 'Dummy edit', 'dummy-edit', 'Make a dummy edit on this page'
    ).addEventListener('click', function () {
        mw.loader.using( [
            'mediawiki.api',
            'mediawiki.Title',
            'oojs-ui-windows'
        ], async function () {
            var title = new mw.Title(mw.config.get('wgPageName'));
            if (title.namespace == mw.config.get('wgNamespaceIds').template) {
                if (!(await OO.ui.confirm("This page is a template. Continue?"))) {
                    return;
                }
            }

            var summaryText = await OO.ui.prompt("Enter edit summary text:");
    
            // Get revision data
            var api = new mw.Api();
            var slot = await api.get({
                "action": "query",
                "format": "json",
                "prop": "revisions",
                "titles": mw.config.get('wgPageName'),
                "formatversion": "2",
                "rvprop": "content",
                "rvslots": "main"
            }).then(function (v) {
                return v && v.query && v.query.pages && v.query.pages[0]
                    && v.query.pages[0].revisions && v.query.pages[0].revisions[0]
                    && v.query.pages[0].revisions[0].slots
                    && v.query.pages[0].revisions[0].slots.main;
            });
    
            if (!slot) {
                OO.ui.alert("Could not find a revision to edit. Does this page exist?");
                return;
            }
    
            if (slot.contentmodel !== "wikitext") {
                if (!(await OO.ui.confirm("Page is not wikitext. Continue?"))) {
                    return;
                }
            }
    
            // Extract wikitext
            var originalWikitext = slot.content;
    
            // Place the dummy whitespace
            var newWikitext = (function () {
                var wikitext = slot.content;
                // Find a place to put the whitespace
    
                // First, try right after any infobox-like template
                wikitext = wikitext.replace(/^([^\S\r\n]*)}}([^\S\r\n]*)$/m, '$1}}$2 ');
                if ( originalWikitext !== wikitext && !wikitext.endsWith(" ") ) {
                    console.log("[DummyEdit] method: infobox-like");
                    return wikitext;
                }
                
                // Next, try after any block-like template at the top of the page
                var foundBlockTemplateAtStart = false;
                var wikitextLines = wikitext.split("\n");
                for (var lineIndex in wikitextLines) {
                    var line = wikitextLines[lineIndex];
                    var trimmedLine = line.trim();

                    if ( trimmedLine.startsWith("{{") && line.endsWith("}}") ) {
                        console.log("[DummyEdit] Found block template at " + lineIndex);
                        wikitextLines[lineIndex] += " ";
                        foundBlockTemplateAtStart = true;
                        break;
                    } else if ( trimmedLine.length > 0 && /^[=\w]/.test(trimmedLine) ) {
                        // Page text. Probably content. Stop looking.
                        break;
                    }
                }

                if (foundBlockTemplateAtStart) {
                    console.log("[DummyEdit] method: block-template-start");
                    return wikitextLines.join("\n");
                }

                // Next, try after any block-like template at the bottom of the page.
                // This should skip categories.
                // Reuse wikitextLines, since it would have not been changed for us
                // to reach here.
                var foundBlockTemplateAtEnd = false;
                for (var revLineIndex in wikitextLines) {
                    var lineIndex = wikitextLines.length - 1 - revLineIndex;

                    var line = wikitextLines[lineIndex];
                    var trimmedLine = line.trim();

                    if ( trimmedLine.startsWith("{{") && line.endsWith("}}") ) {
                        console.log("[DummyEdit] Found block template at " + revLineIndex);
                        wikitextLines[lineIndex] += " ";
                        foundBlockTemplateAtEnd = true;
                        break;
                    } else if ( trimmedLine.length > 0 && /^[=\w]/.test(trimmedLine) ) {
                        // Page text. Probably content. Stop looking.
                        break;
                    }
                }

                if (foundBlockTemplateAtEnd) {
                    console.log("[DummyEdit] method: block-template-end");
                    return wikitextLines.join("\n");
                }

                // Next, try after any image
                wikitext = wikitext.replace(/^(\[\[[^\]]+]])$/m, '$1 ');
                if ( originalWikitext !== wikitext && !wikitext.endsWith(" ") ) {
                    console.log("[DummyEdit] method: after-image");
                    return wikitext;
                }

                // Lastly, just place the space after any paragraph.
                wikitext = wikitext.replace(/^(\w.+)$/m, '$1 ');
                if ( originalWikitext !== wikitext && !wikitext.endsWith(" ") ) {
                    console.log("[DummyEdit] method: give-up");
                    return wikitext;
                }
            })();
    
            if (newWikitext === originalWikitext) {
                OO.ui.alert("Could not find a suitable location for the dummy edit.");
                return;
            }

            // Make the edit
            api.postWithEditToken({
                "action": "edit",
                "title": mw.config.get("wgPageName"),
                "text": newWikitext,
                "summary": summaryText,
                "minor": true,
                "nocreate": true
            })
                .then(function ( response ) {
                    if ( response.error ) {
                        throw response;
                    }

                    if ( response.edit.nochange !== undefined ) {
                        OO.ui.alert("No change was made. Please make the dummy edit manually.\n\nYour summary was: " + summaryText);
                    } else {
                        mw.notify("Page edited", { type: "success" });
                    }
                })
                .catch(function (e) {
                    OO.ui.alert(
                        "Error trying to save dummy edit: " +
                            (e.error ? e.error.info : String(e))
                    )
                });
        } );
    } );
} );
// </nowiki>