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.
// Category Sorting Script
// <nowiki>
// Original script: [[User:Alex 21/script-categoriessort.js]]
// Edited to use Pathoschild's TemplateScript https://meta.wikimedia.org/wiki/TemplateScript
// Because of this request: https://en.wikipedia.org/wiki/Wikipedia:Village_pump_(technical)#User:Alex_21/script-categoriessort

(function() {
    const DEBUG = false;
    function debug(...args) {
        if (DEBUG) {
            console.log('[CatSort]', ...args);
        }
    }

    function extractCategories(text) {
        const start = text.indexOf('[[Category:');
        if (start === -1) return { before: text, categories: '' };
        return {
            before: text.substr(0, start).trim(),
            categories: text.substr(start).trim()
        };
    }

    function reorderCategories(categories) {
        const eponymousCategory = '[[Category:' + mw.config.get("wgTitle");
        return categories.split('\n').sort((a, b) => {
            if (a.startsWith(eponymousCategory)) return -1e8;
            if (b.startsWith(eponymousCategory)) return 1e8;
            
            const normalizeCategory = (cat) => {
                if (cat.startsWith('[[Category:A ')) {
                    return [cat.replace('[[Category:A ', '[[Category:'), -1];
                }
                if (cat.startsWith('[[Category:The ')) {
                    return [cat.replace('[[Category:The ', '[[Category:'), -1];
                }
                return [cat, 0];
            };
            
            const [normA, prioA] = normalizeCategory(a);
            const [normB, prioB] = normalizeCategory(b);
            
            if (prioA !== prioB) return prioA - prioB;
            return normA.localeCompare(normB);
        }).join('\n');
    }

    function sortCats() {
        if (mw.config.get('wgNamespaceNumber') !== 0 || mw.config.get('wgAction') !== 'edit') {
            debug("Not the correct namespace or action, script terminated");
            return;
        }

        debug("Sorting categories...");
        
        const content = document.querySelector('#wpTextbox1')?.value;
        if (!content) {
            debug("Textbox not found or empty");
            return;
        }
        
        const { before, categories } = extractCategories(content);
        if (!categories) {
            debug("No categories found");
            return;
        }
        
        const sortedCategories = reorderCategories(categories);
        const textboxElement = document.querySelector('#wpTextbox1');
        if (textboxElement) textboxElement.value = `${before}\n${sortedCategories}\n`;
        
        const summaryElement = document.querySelector('#wpSummary');
        if (summaryElement) {
            summaryElement.value += (summaryElement.value ? ' ' : '') + "Sorted categories alphabetically.";
        }

        const minorEditElement = document.querySelector('#wpMinoredit');
        if (minorEditElement) {
            minorEditElement.checked = true;
        }
        
        debug("Categories sorted successfully");
    }

    $.when(
        $.ajax("//tools-static.wmflabs.org/meta/scripts/pathoschild.templatescript.js", { dataType: "script", cache: true })
    ).then(function() {
        pathoschild.TemplateScript.add(
            [{
                name: "sortCats",
                tooltip: "Sort all categories alphabetically",
                script: sortCats
            }],
            { forActions: "edit", category: "CatSort" }
        );

        debug("Category sorting script loaded and ready.");
    });
})();
// </nowiki>