User:Erutuon/scripts/watchlistScriptTagging.js
< User:Erutuon | scripts
Note – after saving, you may have to bypass your browser’s cache to see the changes.
- Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
- Konqueror and Chrome: click Reload or press F5;
- Opera: clear the cache in Tools → Preferences;
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.
- The following documentation is located at User:Erutuon/scripts/watchlistScriptTagging.js/documentation. [edit]
- Useful links: root page • root page’s subpages • links • redirects • your own
- Extend to Special:WhatLinksHere, Special:Contributions.
/*
Script-tags links in your watchlist and the Recent Changes and Related Changes
pages, using [[User:Erutuon/scripts/scriptRecognition.js]] to detect the script.
Uses ES6, so will not work on some older browsers.
*/
// <nowiki>
/* jshint eqeqeq: true, undef: true, unused: true, loopfunc: true */
/* globals mw, $, isCombining */
"use strict";
$(() => {
const basePageName = mw.config.get("wgPageName").match(/^[^/]+|^\//)[0];
if (![
"Special:Watchlist",
"Special:RecentChanges",
"Special:RecentChangesLinked",
"Special:Contributions",
"Special:WhatLinksHere"
].includes(basePageName)) {
return;
}
// from https://api.jquery.com/jQuery.getScript
$.cachedScript = function (url, options) {
options = $.extend(options || {}, {
dataType: "script",
cache: true,
url: url
});
return $.ajax(options);
};
$.when($.cachedScript(
"//en.wiktionary.org/w/index.php?action=raw&title=User:Erutuon/scripts/scriptRecognition.js&ctype=text/javascript"),
$.cachedScript(
"//en.wiktionary.org/w/index.php?action=raw&title=User:Erutuon/scripts/combiningCharacters.js&ctype=text/javascript"),
mw.loader.using("mediawiki.Title"))
.done(() => {
function addTagger(toTagSelector, mutationObserverTarget) {
const getScriptCache = Object.create(null);
const cachedGetScript = function (str) {
if (str in getScriptCache) {
return getScriptCache[str];
} else {
const script = window.getScript(str);
getScriptCache[str] = script;
return script;
}
};
function addDottedCircle(str) {
if (isCombining(str.codePointAt(0)))
str = '\u25CC' + str;
return str;
}
function scriptTagLinks(parent, selector) {
if (!(!parent || parent instanceof window.Element
|| parent instanceof window.HTMLDocument)) {
throw new TypeError("Expected Element or HTMLDocument or falsy value");
}
parent = parent || document;
for (const titleElement of parent.querySelectorAll(selector)) {
const content = titleElement.textContent;
// Skip unless title is in "Rhymes" or "Rhymes talk" namespaces
// or contains characters above U+0370 (could contain non-Latin).
if (!/^Rhymes(?: talk)?:|[\u0370-\uFFFF]/.test(content))
continue;
const title = new mw.Title(content);
if (!title)
continue;
switch (title.getNamespaceId()) {
case 0: { // main
// Avoid tagging translations and derived terms subpage names.
titleElement.innerHTML = content.replace(/^(.+?)(\/(?:translations|derived terms))?$/,
(wholeMatch, base, postfix) => {
const script = cachedGetScript(base);
return script
? '<span class="' + script + '">'
+ addDottedCircle(base) + '</span>'
+ (postfix || '')
: wholeMatch;
});
break;
}
// Add script class to the last portion of Talk namespace links.
case 1: // Talk
titleElement.innerHTML = content.replace(/^(Talk:)(.+)$/,
(wholeMatch, namespace, unPrefixed) => {
const script = cachedGetScript(unPrefixed);
return script
? namespace + '<span class="' + script + '">'
+ addDottedCircle(unPrefixed) + '</span>'
: wholeMatch;
});
break;
case 106: case 107: // Rhymes, Rhymes talk
titleElement.innerHTML = content.replace(/^(Rhymes(?: talk)?:(.+?)\/)(.+)$/,
function (wholeMatch, rootPageName, languageName, rhyme) {
return rootPageName
+ (languageName === "Telugu"
? '<span class="Telu" lang="te">'
: '<span class="IPA">')
+ rhyme
+ '</span>';
});
break;
}
}
}
// Document loading and back and forward events.
$(() => scriptTagLinks(document, toTagSelector));
$(window).on("popstate", () => scriptTagLinks(document, toTagSelector));
// Use MutationObserver to script-tag links when
// "View newest changes" button is clicked.
const target = mutationObserverTarget;
if (!target)
return;
const observer = new MutationObserver((mutationList) => {
for (const mutation of mutationList) {
/*
* The div element containing watchlist entries should have a first
* element with the class mw-changeslist-line.
*/
for (const node of mutation.addedNodes) {
if (node.nodeType === 1
&& node.querySelector(toTagSelector)) {
scriptTagLinks(node, toTagSelector);
}
}
}
});
observer.observe(target, { childList: true });
return observer;
}
switch (basePageName) {
case "Special:Watchlist":
case "Special:RecentChanges":
case "Special:RecentChangesLinked":
addTagger(".mw-changeslist-title", document.getElementsByClassName("mw-changeslist")[0]);
break;
case "Special:Contributions":
addTagger(".mw-contributions-title", document.getElementsByClassName("mw-contributions-list")[0]);
break;
case "Special:WhatLinksHere":
addTagger("#mw-whatlinkshere-list li > a", document.getElementById("mw-whatlinkshere-list"));
break;
}
});
});
// </nowiki>