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..."
 
m 1 revision imported
 
(14 intermediate revisions by 2 users not shown)
Line 1: Line 1:
// <nowiki>
// <nowiki>
let actionAPI = new mw.Api({ ajax: { headers: { "Api-User-Agent": "Gadget developed by [[User:Ioaxxere]]" } } });
function HTML_unescape(text) {
let HTML_unescape = text => new DOMParser().parseFromString(text, "text/html").body.textContent; // Why isn't this a builtin...?
return new DOMParser().parseFromString(text, "text/html").body.textContent;
}


function getTitleAndAnchor(link) {
function getTitleAndAnchor(link) {
Line 11: Line 12:
mw.util.addCSS(`
mw.util.addCSS(`
.orange-link {
.orange-link {
color: var(--wikt-palette-gold, #b88d00);
color: var(--wikt-palette-gold);
}
}
.orange-link:visited {
.orange-link:visited {
color: var(--wikt-palette-dullgold, #826f34);
color: var(--wikt-palette-dullgold);
}
}
.orange-link:hover, .orange-link:visited:hover {
.orange-link:hover, .orange-link:visited:hover {
color: var(--wikt-palette-honey, #81540e);
color: var(--wikt-palette-honey);
}
}
`);
`);
let actionAPI = new mw.Api({ajax: {headers: {"Api-User-Agent": "Gadget developed by [[User:Ioaxxere]]"}}});


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


function makeOrangeLinks(element) {
async function makeOrangeLinks(element) {
// Get a list of pages and links to process.
// Get a list of pages and links to process.
let pagesToProcess = [];
let pagesToProcess = [];
Line 30: Line 33:
for (let link of element.querySelectorAll("a")) {
for (let link of element.querySelectorAll("a")) {
// 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.startsWith("https://en.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);
let [linkTitle, linkAnchor] = getTitleAndAnchor(link);


if (!linkAnchor || /^[a-z]/.test(linkAnchor) || (new mw.Title(linkTitle)).namespace !== 0) continue;
if (!linkAnchor || /^[a-z]/.test(linkAnchor)) continue;
 
if (![0, 100, 118].includes(new mw.Title(linkTitle).namespace)) continue; // Main, Appendix, Reconstruction


pagesToProcess.push(linkTitle);
pagesToProcess.push(linkTitle);
Line 42: Line 47:


// Filter out duplicates.
// Filter out duplicates.
pagesToProcess = Array.from(new Set(pagesToProcess));
pagesToProcess = [...new Set(pagesToProcess)];


// Process the array in chunks.
// Process the array in chunks.
Line 50: Line 55:


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


Line 61: Line 65:
// Integrate the results into `pageIDsOf`.
// Integrate the results into `pageIDsOf`.
let pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
let pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
for (let j = 0; j < chunk.length; j++) {
for (let j = 0; j < chunk.length; j++)
pageIDsOf.set(chunk[j], pageIDs[j].split(" "));
pageIDsOf.set(chunk[j], pageIDs[j].split(" "));
}
}));
}));
}
}
await Promise.all(queries);


// 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(() => {
for (let link of linksToProcess) {
for (let link of linksToProcess) {
let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
let anchorExists = pageIDsOf.get(linkTitle).includes(linkAnchor);
if (pageIDsOf.get(linkTitle).includes(linkAnchor)) {
link.classList.add(anchorExists ? "not-orange-link" : "orange-link");
link.classList.add("not-orange-link");
}
} else {
link.classList.add("orange-link");
}
}
});
}
}



Latest revision as of 17:52, 4 November 2025

// <nowiki>
function HTML_unescape(text) {
	return new DOMParser().parseFromString(text, "text/html").body.textContent;
}

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

mw.util.addCSS(`
	.orange-link {
		color: var(--wikt-palette-gold);
	}
	.orange-link:visited {
		color: var(--wikt-palette-dullgold);
	}
	.orange-link:hover, .orange-link:visited:hover {
		color: var(--wikt-palette-honey);
	}
`);

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

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

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

		let [linkTitle, linkAnchor] = getTitleAndAnchor(link);

		if (!linkAnchor || /^[a-z]/.test(linkAnchor)) continue;

		if (![0, 100, 118].includes(new mw.Title(linkTitle).namespace)) continue; // Main, Appendix, Reconstruction

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

	// Filter out duplicates.
	pagesToProcess = [...new Set(pagesToProcess)];

	// Process the array in chunks.
	let queries = [];
	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]].
		let params = {
			action: "expandtemplates",
			format: "json",
			prop: "wikitext",
			text: `{{#invoke:get IDs|show|${chunk.join("|")}}}`
		};

		queries.push(actionAPI.post(params).then(response => {
			// Integrate the results into `pageIDsOf`.
			let pageIDs = HTML_unescape(response.expandtemplates.wikitext).split("\n\n");
			for (let j = 0; j < chunk.length; j++)
				pageIDsOf.set(chunk[j], pageIDs[j].split(" "));
		}));
	}
	await Promise.all(queries);

	// After all the queries have returned, determine whether each link needs to be orange.
	for (let link of linksToProcess) {
		let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
		let anchorExists = pageIDsOf.get(linkTitle).includes(linkAnchor);
		link.classList.add(anchorExists ? "not-orange-link" : "orange-link");
	}
}

// Activate the gadget.
let 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>