User:Ahecht/Scripts/RedirectTagID.js
Appearance
< User:Ahecht | Scripts
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Ahecht/Scripts/RedirectTagID.
//RedirectTagID v0.4 by [[User:Ahecht]]
$(document).ready( mw.loader.using('mediawiki.api').then( async () => {
if (!['Recentchanges', 'Contributions', 'Newpages'].includes(mw.config.get('wgCanonicalSpecialPageName'))) return;
const tags = document.querySelectorAll('.mw-tag-marker-mw-new-redirect, .mw-tag-marker-mw-changed-redirect-target');
var api = new mw.Api( { userAgent: `RedirectTagID/0.4 (${mw.config.get('wgServerName').split('.')[1]}:${mw.config.get('wgServerName').split('.')[0]}, User:Ahecht)` } );
var titleMap = new Map();
var oldids = [];
var tagByOldidMap = new Map();
tags.forEach(tag => {
const container = tag.closest('td') || tag.closest('li');
if (!container) {console.warn("RedirectTagID: Parent li/tr not found for ", container); return;}
var title = container.getAttribute('data-target-page');
if (!title) {
var titleMatch = null;
var allLinks = Array.from(
container.querySelectorAll('a.mw-contributions-title, a.mw-changeslist-title, a.mw-newpages-pagename')
);
for (const titleLink of allLinks) {
if (
titleLink.compareDocumentPosition(tag) &
Node.DOCUMENT_POSITION_FOLLOWING
) {
titleMatch = titleLink;
} else {
break;
}
}
if (!titleMatch) {console.warn("RedirectTagID: Title link not found for ", container); return;}
title = titleMatch.textContent.trim();
}
if (!title) {
console.log("RedirectTagID: Title not found for ", container);
return;
}
var oldid = null;
if (mw.config.get('wgCanonicalSpecialPageName') == 'Recentchanges') {
let histContainer = container.querySelector('a.mw-changeslist-diff, a.mw-changeslist-diff-cur')?.href;
if (histContainer) {
oldid = histContainer.match(/diff=(\d+)/i)?.[1];
if (oldid == '0') {
oldid = histContainer.match(/oldid=(\d+)/i)?.[1];
}
} else {
histContainer = container.querySelector('span.mw-changeslist-links')?.querySelector('span');
if (histContainer && (histContainer.innerHTML == histContainer.innerText)) {
oldid = 1;
titleMap.set(tag, title);
} else {
console.log('RedirectTagID: Diff link not found for ', container);
return;
}
}
} else { // Contributions or Newpages
oldid = container.getAttribute('data-mw-revid');
}
if (!oldid) {
console.log('RedirectTagID: Diff ID not found for ', container);
return;
}
if (oldid != 1) {
oldids.push(oldid);
tagByOldidMap.set(oldid, tag)
}
} );
var contentMap = new Map();
var promises = [];
titleMap.forEach( (title, tag) => { // grab first revision of each page without an oldid
promises.push( api.get( {
"action": "query",
"format": "json",
"prop": "revisions",
"titles": title,
"formatversion": "2",
"rvprop": "content",
"rvdir": "newer",
"rvlimit": "1"
} ).fail(
(e, f) => console.warn("RedirectTagID: ", f.error.info)
).done( data => {
let page = data?.query?.pages?.[0];
if (typeof page !== 'object') {
console.warn("RedirectTagID: No page found in API data for ", title, data);
return;
}
if (typeof page?.revisions?.[0] !== 'object') {
if (page.missing === true) {
contentMap.set(tag, false);
} else {
console.warn("RedirectTagID: No revisions found for ", title, data);
}
return;
}
contentMap.set(tag, page?.revisions?.[0]?.content || '');
} ) );
} );
while (oldids.length) { // grab contents of oldids in batches of 50
let revids = oldids.splice(0, 50).join('|');
promises.push( api.get( {
"action": "query",
"format": "json",
"prop": "revisions",
"revids": revids,
"formatversion": "2",
"rvprop": "content|ids",
} ).fail(
(e, f) => console.warn("RedirectTagID: ", f.error.info)
).done( data => {
let pages = data?.query?.pages;
if (typeof pages !== 'object') {
console.warn("RedirectTagID: No pages found in API data for ", revids, data);
return;
}
pages.forEach( (page) => {
let content = null;
let revision = page?.revisions?.[0];
if (typeof revision === 'object') {
content = revision?.content || '';
} else {
if (page.missing === true) {
content = false;
} else {
console.warn("RedirectTagID: No revisions found for ", page.title, data);
return;
}
}
let tag = tagByOldidMap.get(String(revision?.revid));
if (tag) {
contentMap.set(tag, content);
} else {
console.warn("RedirectTagID: Invalid revid ", revision.revid, data, tagByOldidMap);
}
} );
} ) );
}
await Promise.allSettled(promises); // Wait for all API calls to finish
contentMap.forEach( (content, tag) => {
if (tag.dataset.redirectTargetAppended === '1') {
//console.warn("RedirectTagID: Redirect already appended to", tag);
return;
}
if (content === false) {
tag.append( ' (deleted)');
tag.dataset.redirectTargetAppended = '1';
return;
}
var target = content.match(/(?:#REDIRECT:?|return require *\(?) *(?:\[\[|") *(.*?) *(?:\]\]|")/i);
if (!target?.[1]) {
console.warn("RedirectTagID: No redirect found in ", content, tag);
return;
}
var toLink = mw.config.get('wgArticlePath').replace('$1', mw.util.rawurlencode(target[1]));
var toText = target[1].replace("#", " § ");
tag.append( ' to ', Object.assign(document.createElement('a'), {href: toLink, textContent: toText}));
tag.dataset.redirectTargetAppended = '1';
} );
} ) );