MediaWiki:Gadget-OrangeLinks.js: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
/* eslint-env es6, browser, jquery */
// <nowiki>
/* eslint semi: "error" */
var actionAPI = new mw.Api({ ajax: { headers: { "Api-User-Agent": "Gadget developed by [[User:Ioaxxere]]" } } });
/* jshint esversion: 6, eqeqeq: true */
/* globals $, mw */
/* requires mw.cookie, mw.storage */


// <nowiki>
var HTML_unescape = function(text) {
let actionAPI = new mw.Api({ ajax: { headers: { "Api-User-Agent": "Gadget developed by [[User:Ioaxxere]]" } } });
    return new DOMParser().parseFromString(text, "text/html").body.textContent;
let HTML_unescape = text => new DOMParser().parseFromString(text, "text/html").body.textContent; // Why isn't this a builtin...?
};


function getTitleAndAnchor(link) {
function getTitleAndAnchor(link) {
let linkTitle = decodeURIComponent(link.pathname.split("/wiki/")[1]);
    var linkTitle = decodeURIComponent(link.pathname.split("/wiki/")[1]);
let linkAnchor = decodeURIComponent(link.hash.slice(1) || "");
    var linkAnchor = decodeURIComponent(link.hash.slice(1) || "");
return [linkTitle, linkAnchor];
    return [linkTitle, linkAnchor];
}
}


mw.util.addCSS(`
mw.util.addCSS(
.orange-link {
    ".orange-link { color: #b88d00; }" +
color: var(--wikt-palette-gold, #b88d00);
    ".orange-link:visited { color: #826f34; }" +
}
    ".orange-link:hover, .orange-link:visited:hover { color: #81540e; }"
.orange-link:visited {
);
color: var(--wikt-palette-dullgold, #826f34);
}
.orange-link:hover, .orange-link:visited:hover {
color: var(--wikt-palette-honey, #81540e);
}
`);


// Maps each page to a list of IDs.
// Maps each page to a list of IDs.
let pageIDsOf = new Map();
var pageIDsOf = {};


function makeOrangeLinks(element) {
function makeOrangeLinks(element) {
// Get a list of pages and links to process.
    // Get a list of pages and links to process.
let pagesToProcess = [];
    var pagesToProcess = [];
let linksToProcess = [];
    var linksToProcess = [];
for (let link of element.querySelectorAll("a")) {
    var links = element.querySelectorAll("a");
// Check whether the link needs to be processed.
if (!link.href.startsWith("https://en.wiktionary.org/wiki/") && !link.href.startsWith("https://en.m.wiktionary.org/wiki/")) continue;
if (link.matches(".orange-link, .not-orange-link, .new, .external")) continue;


let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
    for (var i = 0; i < links.length; i++) {
        var link = links[i];


if (!linkAnchor || /^[a-z]/.test(linkAnchor) || (new mw.Title(linkTitle)).namespace !== 0) continue;
        // Check whether the link needs to be processed.
        if (link.href.indexOf("https://en.wiktionary.org/wiki/") !== 0 &&
            link.href.indexOf("https://en.m.wiktionary.org/wiki/") !== 0) {
            continue;
        }
        if (link.className.match(/orange-link|not-orange-link|new|external/)) {
            continue;
        }


pagesToProcess.push(linkTitle);
        var parts = getTitleAndAnchor(link);
linksToProcess.push(link);
        var linkTitle = parts[0];
}
        var linkAnchor = parts[1];


// Filter out duplicates.
        if (!linkAnchor || /^[a-z]/.test(linkAnchor) || (new mw.Title(linkTitle)).namespace !== 0) {
pagesToProcess = Array.from(new Set(pagesToProcess));
            continue;
        }


// Process the array in chunks.
        pagesToProcess.push(linkTitle);
let queries = [];
        linksToProcess.push(link);
for (let i = 0; i < pagesToProcess.length; i += 100) {
    }
let chunk = pagesToProcess.slice(i, i + 100);


// Query the IDs for all the pages using [[Module:get IDs]].
    // Filter out duplicates.
let wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}";
    var uniquePages = {};
let params = {
    var pages = [];
action: "expandtemplates",
    for (var j = 0; j < pagesToProcess.length; j++) {
format: "json",
        if (!uniquePages[pagesToProcess[j]]) {
prop: "wikitext",
            uniquePages[pagesToProcess[j]] = true;
text: wikitext
            pages.push(pagesToProcess[j]);
};
        }
    }
    pagesToProcess = pages;


queries.push(actionAPI.post(params).then(response => {
    // Process the array in chunks.
// Integrate the results into `pageIDsOf`.
    var queries = [];
let pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
    for (var k = 0; k < pagesToProcess.length; k += 100) {
for (let j = 0; j < chunk.length; j++) {
        var chunk = pagesToProcess.slice(k, k + 100);
pageIDsOf.set(chunk[j], pageIDs[j].split(" "));
}
}));
}


// After all the queries have returned, determine whether each link needs to be orange.
        // Query the IDs for all the pages using [[Module:get IDs]].
Promise.all(queries).then(() => {
        var wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}";
for (let link of linksToProcess) {
        var params = {
let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
            action: "expandtemplates",
if (pageIDsOf.get(linkTitle).includes(linkAnchor)) {
            format: "json",
link.classList.add("not-orange-link");
            prop: "wikitext",
} else {
            text: wikitext
link.classList.add("orange-link");
        };
}
 
}
        queries.push(
});
            actionAPI.post(params).then((function(chunkCopy) {
                return function(response) {
                    var pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
                    for (var m = 0; m < chunkCopy.length; m++) {
                        pageIDsOf[chunkCopy[m]] = pageIDs[m].split(" ");
                    }
                };
            })(chunk))
        );
    }
 
    // After all the queries have returned, determine whether each link needs to be orange.
    Promise.all(queries).then(function() {
        for (var n = 0; n < linksToProcess.length; n++) {
            var link = linksToProcess[n];
            var parts = getTitleAndAnchor(link);
            var linkTitle = parts[0];
            var linkAnchor = parts[1];
            if (pageIDsOf[linkTitle] && pageIDsOf[linkTitle].indexOf(linkAnchor) !== -1) {
                link.classList.add("not-orange-link");
            } else {
                link.classList.add("orange-link");
            }
        }
    });
}
}


// Activate the gadget.
// Activate the gadget.
let pageContent = document.querySelector(".mw-parser-output");
var pageContent = document.querySelector(".mw-parser-output");
if (pageContent)
if (pageContent) {
makeOrangeLinks(pageContent);
    makeOrangeLinks(pageContent);
}


// Create a global hook in case any other gadget or script would like to activate it.
// Create a global hook in case any other gadget or script would like to activate it.
window.makeOrangeLinks = makeOrangeLinks;
window.makeOrangeLinks = makeOrangeLinks;
// </nowiki>
// </nowiki>

Revision as of 19:09, 16 September 2025

// <nowiki>
var actionAPI = new mw.Api({ ajax: { headers: { "Api-User-Agent": "Gadget developed by [[User:Ioaxxere]]" } } });

var HTML_unescape = function(text) {
    return new DOMParser().parseFromString(text, "text/html").body.textContent;
};

function getTitleAndAnchor(link) {
    var linkTitle = decodeURIComponent(link.pathname.split("/wiki/")[1]);
    var linkAnchor = decodeURIComponent(link.hash.slice(1) || "");
    return [linkTitle, linkAnchor];
}

mw.util.addCSS(
    ".orange-link { color: #b88d00; }" +
    ".orange-link:visited { color: #826f34; }" +
    ".orange-link:hover, .orange-link:visited:hover { color: #81540e; }"
);

// Maps each page to a list of IDs.
var pageIDsOf = {};

function makeOrangeLinks(element) {
    // Get a list of pages and links to process.
    var pagesToProcess = [];
    var linksToProcess = [];
    var links = element.querySelectorAll("a");

    for (var i = 0; i < links.length; i++) {
        var link = links[i];

        // Check whether the link needs to be processed.
        if (link.href.indexOf("https://en.wiktionary.org/wiki/") !== 0 &&
            link.href.indexOf("https://en.m.wiktionary.org/wiki/") !== 0) {
            continue;
        }
        if (link.className.match(/orange-link|not-orange-link|new|external/)) {
            continue;
        }

        var parts = getTitleAndAnchor(link);
        var linkTitle = parts[0];
        var linkAnchor = parts[1];

        if (!linkAnchor || /^[a-z]/.test(linkAnchor) || (new mw.Title(linkTitle)).namespace !== 0) {
            continue;
        }

        pagesToProcess.push(linkTitle);
        linksToProcess.push(link);
    }

    // Filter out duplicates.
    var uniquePages = {};
    var pages = [];
    for (var j = 0; j < pagesToProcess.length; j++) {
        if (!uniquePages[pagesToProcess[j]]) {
            uniquePages[pagesToProcess[j]] = true;
            pages.push(pagesToProcess[j]);
        }
    }
    pagesToProcess = pages;

    // Process the array in chunks.
    var queries = [];
    for (var k = 0; k < pagesToProcess.length; k += 100) {
        var chunk = pagesToProcess.slice(k, k + 100);

        // Query the IDs for all the pages using [[Module:get IDs]].
        var wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}";
        var params = {
            action: "expandtemplates",
            format: "json",
            prop: "wikitext",
            text: wikitext
        };

        queries.push(
            actionAPI.post(params).then((function(chunkCopy) {
                return function(response) {
                    var pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
                    for (var m = 0; m < chunkCopy.length; m++) {
                        pageIDsOf[chunkCopy[m]] = pageIDs[m].split(" ");
                    }
                };
            })(chunk))
        );
    }

    // After all the queries have returned, determine whether each link needs to be orange.
    Promise.all(queries).then(function() {
        for (var n = 0; n < linksToProcess.length; n++) {
            var link = linksToProcess[n];
            var parts = getTitleAndAnchor(link);
            var linkTitle = parts[0];
            var linkAnchor = parts[1];
            if (pageIDsOf[linkTitle] && pageIDsOf[linkTitle].indexOf(linkAnchor) !== -1) {
                link.classList.add("not-orange-link");
            } else {
                link.classList.add("orange-link");
            }
        }
    });
}

// Activate the gadget.
var pageContent = document.querySelector(".mw-parser-output");
if (pageContent) {
    makeOrangeLinks(pageContent);
}

// Create a global hook in case any other gadget or script would like to activate it.
window.makeOrangeLinks = makeOrangeLinks;
// </nowiki>