MediaWiki:Gadget-OrangeLinks.js
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.
// <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 pathname = link.pathname;
var linkTitle;
if (pathname.startsWith("/w/")) {
linkTitle = pathname.split("/w/")[1];
} else if (pathname.startsWith("/wiki/")) {
linkTitle = pathname.split("/wiki/")[1];
} else {
linkTitle = ""; // fallback
}
linkTitle = decodeURIComponent(linkTitle);
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://linguifex.com/w/") !== 0 || link.href.indexOf("https://linguifex.com/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 !== 120) {
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>