MediaWiki:Gadget-OrangeLinks.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary Tag: Manual revert |
No edit summary |
||
| Line 1: | Line 1: | ||
/* eslint-env es6, browser, jquery */ | |||
/* eslint semi: "error" */ | |||
/* jshint esversion: 6, eqeqeq: true */ | |||
/* globals $, mw */ | |||
/* requires mw.cookie, mw.storage */ | |||
// <nowiki> | // <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) { | function getTitleAndAnchor(link) { | ||
let linkTitle = decodeURIComponent(link.pathname.split("/wiki/")[1]); | |||
let linkAnchor = decodeURIComponent(link.hash.slice(1) || ""); | |||
return [linkTitle, linkAnchor]; | return [linkTitle, linkAnchor]; | ||
} | } | ||
mw.util.addCSS( | 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); | |||
} | |||
`); | |||
// | // Maps each page to a list of IDs. | ||
let pageIDsOf = new Map(); | |||
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 = []; | |||
let linksToProcess = []; | |||
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. | 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; | if (link.matches(".orange-link, .not-orange-link, .new, .external")) continue; | ||
let [linkTitle, linkAnchor] = getTitleAndAnchor(link); | |||
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 45: | Line 48: | ||
// Filter out duplicates. | // Filter out duplicates. | ||
pagesToProcess = Array.from(new Set(pagesToProcess)); | |||
// Process the array in chunks. | // Process the array in chunks. | ||
let queries = []; | |||
for ( | 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 wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}"; | |||
let params = { | |||
action: "expandtemplates", | |||
format: "json", | |||
prop: "wikitext", | |||
text: wikitext | |||
}; | |||
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(" ")); | |||
} | |||
} | })); | ||
} | |||
} | } | ||
// 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(() => { | ||
for ( | for (let link of linksToProcess) { | ||
let [linkTitle, linkAnchor] = getTitleAndAnchor(link); | |||
if (pageIDsOf.get(linkTitle).includes(linkAnchor)) { | |||
if (pageIDsOf | |||
link.classList.add("not-orange-link"); | link.classList.add("not-orange-link"); | ||
} else { | } else { | ||
| Line 94: | Line 87: | ||
// Activate the gadget. | // Activate the gadget. | ||
let 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:53, 16 September 2025
/* eslint-env es6, browser, jquery */
/* eslint semi: "error" */
/* jshint esversion: 6, eqeqeq: true */
/* globals $, mw */
/* requires mw.cookie, mw.storage */
// <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.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);
}
`);
// Maps each page to a list of IDs.
let pageIDsOf = new Map();
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/") && !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);
if (!linkAnchor || /^[a-z]/.test(linkAnchor) || (new mw.Title(linkTitle)).namespace !== 0) continue;
pagesToProcess.push(linkTitle);
linksToProcess.push(link);
}
// Filter out duplicates.
pagesToProcess = Array.from(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 wikitext = "{{#invoke:get IDs|show|" + chunk.join("|") + "}}";
let params = {
action: "expandtemplates",
format: "json",
prop: "wikitext",
text: wikitext
};
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(" "));
}
}));
}
// After all the queries have returned, determine whether each link needs to be orange.
Promise.all(queries).then(() => {
for (let link of linksToProcess) {
let [linkTitle, linkAnchor] = getTitleAndAnchor(link);
if (pageIDsOf.get(linkTitle).includes(linkAnchor)) {
link.classList.add("not-orange-link");
} else {
link.classList.add("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>