MediaWiki:Gadget-OrangeLinks.js: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
Tag: Reverted
No edit summary
Tag: Reverted
Line 6: Line 6:


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



Revision as of 18:44, 16 September 2025

/* eslint-env es5, browser, jquery */
/* eslint semi: "error" */
/* jshint esversion: 5, eqeqeq: true */
/* globals $, mw */
/* requires mw.cookie, mw.storage */

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

function HTML_unescape(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: var(--wikt-palette-gold, #b88d00); }" +
	".orange-link:visited { color: var(--wikt-palette-dullgold, #826f34); }" +
	".orange-link:hover, .orange-link:visited:hover { color: var(--wikt-palette-honey, #81540e); }"
);

// Use plain object instead of Map
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.match(/^https:\/\/(en|en\.m)\.wiktionary\.org\/wiki\//)) continue;
		if (link.matches(".orange-link, .not-orange-link, .new, .external")) continue;

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

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

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

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

	// Process the array in chunks.
	var queries = [];
	for (var k = 0; k < pagesToProcess.length; k += 100) {
		(function(chunk) {
			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(response) {
				// Integrate the results into `pageIDsOf`.
				var pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
				for (var m = 0; m < chunk.length; m++) {
					pageIDsOf[chunk[m]] = pageIDs[m].split(" ");
				}
			}));
		})(pagesToProcess.slice(k, k + 100));
	}

	// 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 linkParts = getTitleAndAnchor(link);
			var linkTitle = linkParts[0];
			var linkAnchor = linkParts[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>