MediaWiki:Gadget-OrangeLinks.js: Difference between revisions

From Linguifex
Jump to navigation Jump to search
Created page with "// <nowiki> let actionAPI = new mw.Api({ ajax: { headers: { "Api-User-Agent": "Gadget developed by User:Ioaxxere" } } }); let HTML_unescape = text => new DOMParser().parseFromString(text, "text/html").body.textContent; // Why isn't this a builtin...? function getTitleAndAnchor(link) { let linkTitle = decodeURIComponent(link.pathname.split("/wiki/")[1]); let linkAnchor = decodeURIComponent(link.hash.slice(1) || ""); return [linkTitle, linkAnchor]; } mw.util.addCS..."
 
No edit summary
Line 1: Line 1:
// <nowiki>
// <nowiki>
let 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]]" } } });
let HTML_unescape = text => new DOMParser().parseFromString(text, "text/html").body.textContent; // Why isn't this a builtin...?
 
function HTML_unescape(text) {
return new DOMParser().parseFromString(text, "text/html").body.textContent;
}


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: var(--wikt-palette-gold, #b88d00); }" +
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); }"
.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.
// Use plain object instead of Map
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");
 
for (var i = 0; i < links.length; i++) {
var link = links[i];
 
// Check whether the link needs to be processed.
// 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.href.match(/^https:\/\/(en|en\.m)\.wiktionary\.org\/wiki\//)) continue;
if (link.matches(".orange-link, .not-orange-link, .new, .external")) continue;
if (link.matches(".orange-link, .not-orange-link, .new, .external")) continue;


let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
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;
if (!linkAnchor || /^[a-z]/.test(linkAnchor) || (new mw.Title(linkTitle)).namespace !== 0) continue;
Line 42: Line 45:


// Filter out duplicates.
// Filter out duplicates.
pagesToProcess = Array.from(new Set(pagesToProcess));
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.
// Process the array in chunks.
let queries = [];
var queries = [];
for (let i = 0; i < pagesToProcess.length; i += 100) {
for (var k = 0; k < pagesToProcess.length; k += 100) {
let chunk = pagesToProcess.slice(i, i + 100);
(function(chunk) {
 
var wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}";
// Query the IDs for all the pages using [[Module:get IDs]].
var params = {
let wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}";
action: "expandtemplates",
let params = {
format: "json",
action: "expandtemplates",
prop: "wikitext",
format: "json",
text: wikitext
prop: "wikitext",
};
text: wikitext
};


queries.push(actionAPI.post(params).then(response => {
queries.push(actionAPI.post(params).then(function(response) {
// Integrate the results into `pageIDsOf`.
// Integrate the results into `pageIDsOf`.
let pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
var pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
for (let j = 0; j < chunk.length; j++) {
for (var m = 0; m < chunk.length; m++) {
pageIDsOf.set(chunk[j], pageIDs[j].split(" "));
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.
// After all the queries have returned, determine whether each link needs to be orange.
Promise.all(queries).then(() => {
Promise.all(queries).then(function() {
for (let link of linksToProcess) {
for (var n = 0; n < linksToProcess.length; n++) {
let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
var link = linksToProcess[n];
if (pageIDsOf.get(linkTitle).includes(linkAnchor)) {
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");
link.classList.add("not-orange-link");
} else {
} else {
Line 81: Line 94:


// 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 18:22, 16 September 2025

// <nowiki>
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>