User:MJL/Archer.js

// This is a modified version of User:Sam Sailor/Scripts/Sagittarius+.js (Special:Diff/899155791)

// Such script itself was a modified version of User:Kephir/gadgets/sagittarius.js (Special:PermaLink/785248045)

// Some code was also stolen from User:Wugapodes/Capricorn.js (Special:Permalink/1043412413)

// Docs: User:MJL/Archer

//

/*jshint undef:true, latedef:true, shadow:true, loopfunc:true, scripturl:true, undef:true */

/*globals jQuery, mw, importStylesheet */

mw.loader.using(['jquery.suggestions', 'mediawiki.api', 'mediawiki.Title', 'mediawiki.action.view.redirectPage'], function () { //

'use strict';

if (mw.config.get('wgNamespaceNumber') < 0)

return;

function normaliseAnchor(anchor) {

function encodeCodePoint(c) {

if (c === 0x20)

return '_';

if (c < 0x80) {

return '.' + c.toString(16).toUpperCase();

} else if (c < 0x800) {

return '.' + (0xc0 | (c >>> 6) ).toString(16).toUpperCase() +

'.' + (0x80 | ( c & 0x3f)).toString(16).toUpperCase();

} else if (c < 0x10000) {

return '.' + (0xe0 | (c >>> 12) ).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 6) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ( c & 0x3f)).toString(16).toUpperCase();

} else if (c < 0x200000) {

return '.' + (0xf0 | (c >>> 18) ).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 12) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 6) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ( c & 0x3f)).toString(16).toUpperCase();

} else if (c < 0x4000000) {

return '.' + (0xf8 | (c >>> 24) ).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 18) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 12) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 6) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ( c & 0x3f)).toString(16).toUpperCase();

} else if (c < 0x80000000) {

return '.' + (0xfc | (c >>> 30) ).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 24) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 18) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 12) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ((c >>> 6) & 0x3f)).toString(16).toUpperCase() +

'.' + (0x80 | ( c & 0x3f)).toString(16).toUpperCase();

}

}

// "." is not escaped!

return anchor.replace(/[^0-9A-Za-z_:\.]/g, function (m) { /* [\ud800-\udbff][\udc00-\dfff]| */

if (m.length === 2) { // surrogate pair

return encodeCodePoint((m.charCodeAt(0) & 0x3ff) << 10 | m.charCodeAt(1) & 0x3ff);

} else {

return encodeCodePoint(m.charCodeAt(0));

}

});

}

function normaliseTitle(title) {

try {

var t = new mw.Title(title);

return t.getPrefixedText();

} catch (e) {

return null;

}

}

function el(tag, child, attr, events) {

var node = document.createElement(tag);

if (child) {

if ((typeof child === 'string') || (typeof child.length !== 'number'))

child = [child];

for (var i = 0; i < child.length; ++i) {

var ch = child[i];

if ((ch === void(null)) || (ch === null))

continue;

else if (typeof ch !== 'object')

ch = document.createTextNode(String(ch));

node.appendChild(ch);

}

}

if (attr) for (var key in attr) {

if ((attr[key] === void(0)) || (attr[key] === null))

continue;

node.setAttribute(key, String(attr[key]));

}

if (events) for (var key in events) {

var handler = events[key];

if ((key === 'input') && (window.oninput === void(0))) {

key = 'change';

}

node.addEventListener(key, handler, false);

}

return node;

}

function link(child, href, attr, ev) {

attr = attr || {};

ev = ev || {};

if (typeof attr === 'string') {

attr = { "title": attr };

}

if (typeof href === 'string')

attr.href = href;

else {

attr.href = 'javascript:void(null);';

ev.click = href;

}

return el('a', child, attr, ev);

}

var templateGroups = {

"fromabbreviationcapitalisationandgrammar": "From – abbreviation, capitalisation, and grammar",

"frompartsofspeach": "From parts of speach",

"fromspelling": "From – spelling",

"fromalternativenamesgeneral": "From alternative names, general",

"fromalternativenamesgeography": "From alternative names, geography",

"fromalternativenamespeople": "From alternative names, people",

"fromalternativenamesscientific": "From alternative names, scientific",

"fromalternativenamestechnical": "From alternative names, technical",

"frompostalinfo": "From postal information",

"fromcomics": "From comics",

"fromdisambiguations": "From disambiguations",

"fromfiction": "From fiction",

"frommiddleearth": "From Middle Earth",

"fromisocodes": "From ISO codes",

"fromrelatedinfo": "From related info",

"frommusic": "From music",

"fromsocialmedia": "From social media",

"fromrelatedpeople": "From related people",

"fromtransportation": "From – transportation",

"frommergersduplicatesandmoves": "From mergers, duplicates, and moves",

"fromnavigation": "From – navigation",

"togrammarpunctuationandspelling": "To – grammar, punctuation, and spelling",

"toalternativenames": "To alternative names",

"tonavigationanddisambiguation": "To – navigation and disambiguation",

"tonamespaces": "To namespaces",

"tocomics": "To comics",

"tomiddleearth": "To Middle Earth",

"totime": "To time articles",

"totemplates": "To Wikipedia templates",

"tomiscellaneous": "To miscellaneous",

"misc": "Miscellaneous"

};

function mainCallback(aliasJSON, templateJSON) {

var templateAliases = aliasJSON;

var redirectTemplates = templateJSON;

//console.log(templateAliases);

//console.log(redirectTemplates);

//

'use strict';

importStylesheet('User:MJL/Archer/Kephir.css');

var wgNamespaceIds = mw.config.get('wgNamespaceIds');

var api = new mw.Api();

var contentText = document.getElementById('mw-content-text');

var firstHeading = document.getElementById('firstHeading');

var redirMsg = contentText.getElementsByClassName('redirectMsg')[0];

var uiWrapper = el('div');

var edittoken = null;

function MarkupBlob(markup) {

if (!markup) {

this.target = '';

this.rcatt = {};

this.tail = '';

} else

this.parse(markup);

}

MarkupBlob.prototype.parse = function (markup) {

var rdrx = /^#REDIRECT\s*\[\[\s*([^\|{}[\]]+?)\s*]]\s*/i;

var tprx = /^\s*{{([A-Za-z ]+)((?:\|(?:[^|{}]*|{{[^|}]*}})+)*)}}\s*/i;

var m;

if (!(m = rdrx.exec(markup.trim())))

throw new Error('Not a redirect');

markup = markup.substr(m[0].length);

this.target = m[1];

this.rcatt = {};

out: while ((m = tprx.exec(markup))) {

var alias = normaliseTitle(m[1]);

while (templateAliases[alias])

alias = templateAliases[alias]; // hopefully there are no loops.

if (alias === "This is a redirect") {

var params = m[2].split('|');

for (var j = 0; j < params.length; ++j) {

if (!params[j])

continue;

if (params[j].indexOf('=') !== -1)

break out;

alias = normaliseTitle("R " + params[j]);

while (templateAliases[alias])

alias = templateAliases[alias]; // hopefully there are still no loops.

if (alias in redirectTemplates)

this.rcatt[alias] = true;

else

break out;

}

} else if (alias === "Redirect category shell") {

var mm, rr = /{{(.*?)}}/g;

while (mm = rr.exec(m[2])) {

alias = normaliseTitle(mm[1]);

while (templateAliases[alias])

alias = templateAliases[alias];

if (alias in redirectTemplates)

this.rcatt[alias] = true;

}

} else if (alias in redirectTemplates) {

if (m[2]) // TODO

break;

this.rcatt[alias] = true;

} else {

break;

}

markup = markup.substr(m[0].length);

}

this.tail = markup;

};

MarkupBlob.prototype.toString = function () {

var markup = '#REDIRECT ' + this.target + '';

var tail = '';

var wrapped = [];

for (var key in this.rcatt) {

if (this.rcatt[key])

if ((wrapped.length < 6) && /^R\s+/.test(key))

wrapped.push('{{' + key + '}}\n');

else

tail += '{{' + key + '}}\n';

}

if (wrapped.length)

markup += "\n{{Redirect category shell|\n" + wrapped.join("") + "}}\n";

markup += tail + '\n';

markup += this.tail;

return markup;

};

function buildTagList(rcatt) {

function makeCheckBox(key) {

return el('label', [

el('input', null, {

type: "checkbox",

checked: (key in rcatt) ? "checked" : null,

}, {

change: function (ev) {

rcatt[key] = this.checked;

}

}),

' ',

redirectTemplates[key].label

], {

"title": redirectTemplates[key].tooltip

});

}

var list = el('dl', null, { "class": "tag-list" });

var group = {};

for (var key in templateGroups) {

list.appendChild(el('dt', templateGroups[key]));

list.appendChild(el('dd', group[key] = el('ul')));

}

for (var key in redirectTemplates) {

var label = makeCheckBox(key);

group[redirectTemplates[key].group].appendChild(el('li', label));

}

return list;

}

function buildEditingUI(mblob, saveCallback) {

var statusbar;

var needsCheck = true;

var doSave;

var uiLink, uiTarget;

mblob = mblob || new MarkupBlob();

function setStatus(status) {

while (statusbar.firstChild)

statusbar.removeChild(statusbar.firstChild);

if (status) {

if (typeof status === 'string')

statusbar.appendChild(document.createTextNode(status));

else {

for (var j = 0; j < status.length; ++j) {

if (typeof status[j] === 'string')

statusbar.appendChild(document.createTextNode(status[j]));

else

statusbar.appendChild(status[j]);

}

}

}

}

function inputChanged(ev) {

/*jshint validthis:true */

try {

mblob.target = this.value;

var t = new mw.Title(this.value);

var frag = t.getFragment() ? '#' + normaliseAnchor(t.getFragment()) : '';

uiLink.href = mw.util.getUrl(t.getPrefixedDb(), { redirect: "no" }) + frag;

setStatus();

} catch (e) {

setStatus('Invalid title.');

if(uiLink) uiLink.href = 'javascript:void(0);';

}

needsCheck = true;

}

var uiStatusLine;

var ui = el('form', [

el('div', [

el('ul', [

el('li', [

uiTarget = el('input', null, {

'type': 'text',

'class': 'redirectText',

'value': mblob.target

}, {

'input': inputChanged,

'change': inputChanged,

'blur': function (ev) { // i would not have to write this, if it were not for jQuery. seriously.

if (mblob.target === this.value)

return;

inputChanged.call(this, ev);

}

})

])

], { 'class': 'redirectText' })

], { 'class': 'redirectMsg' }),

buildTagList(mblob.rcatt),

uiStatusLine = el('p', [

statusbar = el('span', [], {

'class': 'status-line'

}),

el('span', [

link(["Statistics for this page"], 'https://tools.wmflabs.org/pageviews?project=en.wikipedia.org&pages=' + encodeURIComponent(mw.config.get('wgPageName'))),

' • ',

link(["WP:TMR"], mw.util.getUrl("Wikipedia:Template messages/Redirect pages")),

' • ',

link(["About Archer"], mw.util.getUrl("User:MJL/Archer"))

], {

'style': 'float: right;'

})

])

], {

'action': 'javascript:void(0)',

'class': 'kephir-sagittarius-editor'

}, {

'submit': function (ev) {

ev.preventDefault();

ui.doCheck(saveCallback);

}

});

ui.statusLine = uiStatusLine;

var sectCache = {};

var $uiTarget = jQuery(uiTarget);

$uiTarget.suggestions({

submitOnClick: false,

delay: 500,

fetch: function (query) {

$uiTarget.suggestions('suggestions', []);

if (query.indexOf('#') !== -1) {

var title = query.substr(0, query.indexOf('#'));

var sect = query.substr(query.indexOf('#') + 1);

if (sectCache[title]) {

var normSect = normaliseAnchor(sect);

$uiTarget.suggestions('suggestions',

sectCache[title].filter(function (item) {

var norm = normaliseAnchor(item.anchor);

return norm.substr(0, normSect.length) === normSect;

})

);

return;

}

api.get({

action: 'parse',

page: title,

prop: 'sections|properties',

redirects: '1'

}).then(function (result) {

if (result.parse.redirects && result.parse.redirects.length) {

// XXX

return;

}

var disambig = false; // XXX

var normSect = normaliseAnchor(sect);

sectCache[title] = result.parse.sections.map(function (item) {

return {

anchor: item.anchor,

title: title + '#' + decodeURIComponent(item.anchor.replace(/_/g, ' ').replace(/\.([0-9A-Fa-f][0-9A-Fa-f])/g, '%')), // XXX: hack

disambig: disambig,

toString: function () {

return this.title;

}

};

});

$uiTarget.suggestions('suggestions',

sectCache[title].filter(function (item) {

var norm = normaliseAnchor(item.anchor);

return norm.substr(0, normSect.length) === normSect;

})

);

});

return;

}

api.get({

action: 'query',

generator: 'allpages',

gapprefix: query,

gaplimit: 16,

prop: 'info|pageprops',

}).then(function (result) {

var pglist = [];

for (var pgid in result.query.pages) {

var page = result.query.pages[pgid];

pglist.push({

title: page.title,

pageid: page.pageid,

disambig: page.pageprops && ('disambiguation' in page.pageprops),

redirect: 'redirect' in page,

toString: function () {

return this.title;

}

});

}

$uiTarget.suggestions('suggestions', pglist);

});

},

result: {

render: function (item, content) {

var elm = this[0];

elm.appendChild(el('span', [item.title], {

style: item.redirect ? 'font-style: italic' : ''

}));

if (item.disambig)

elm.appendChild(el('small', [' (disambiguation page)']));

if (item.redirect)

elm.appendChild(el('small', [' (redirect)']));

},

select: function ($textbox) {

var item = this.data('text');

var textbox = $textbox[0];

textbox.value = item.title;

if (item.redirect) {

api.get({

action: 'query',

pageids: item.pageid,

redirects: '1'

}).then(function (result) {

var redir = result.query.redirects.pop();

textbox.value = redir.to + (redir.tofragment ? '#' + redir.tofragment : '');

});

}

return true;

}

}

});

ui.doCheck = function (callback) {

var that = this;

if (!/^\s*[^\|{}[\]]+\s*$/.test(mblob.target)) {

setStatus(['Error: the target page name is invalid.']);

return;

}

if (needsCheck) {

var oldTarget = mblob.target;

var normTarget;

try {

normTarget = new mw.Title(oldTarget);

} catch (e) {

setStatus(['"', oldTarget, '" is not a valid page name. Try again to proceed anyway.']);

return;

}

setStatus(['Checking target validity...']);

needsCheck = false;

api.get({

action: 'parse',

page: oldTarget = mblob.target,

prop: 'sections',

redirects: '1'

}, {

success: function (result) {

var m;

if (result.error) {

if (result.error.code === 'missingtitle') {

setStatus([

'Error: The target page "',

link([normTarget.getPrefixedText()], mw.util.getUrl(normTarget.getPrefixedText(), { "class": "new" })),

'" does not exist. Try again to proceed anyway.'

]);

} else {

setStatus([

'API error: "',

result.error.info,

'" [code: ', el('code', [result.error.code]), ']'

]);

}

return;

}

if (result.parse.redirects && result.parse.redirects[0]) {

var newTarget = result.parse.redirects[0].to + (result.parse.redirects[0].tofragment ? "#" + result.parse.redirects[0].tofragment : "");

setStatus([

'Error: The target page "',

link([normTarget.getPrefixedText()], mw.util.getUrl(normTarget.getPrefixedText(), { redirect: "no" })),

'" is already a redirect to "',

link([newTarget], mw.util.getUrl(newTarget, { redirect: "no" })),

'". Try again to proceed anyway, or ',

link(['retarget this redirect to point there directly'], function () {

uiTarget.value = mblob.target = newTarget +

((!result.parse.redirects[0].tofragment && normTarget.fragment) ? '#' + normTarget.fragment : '');

needsCheck = true;

}),

'.'

]);

return;

}

if (normTarget.fragment) { // we have a section link

var sect = normaliseAnchor(normTarget.fragment);

var isValidSect = false;

var sectlist = result.parse.sections;

for (var j = 0; j < sectlist.length; ++j) {

if (sectlist[j].anchor === sect)

isValidSect = true;

}

if (!isValidSect) {

setStatus([

'Error: The target page "',

link([normTarget.getPrefixedText()], mw.util.getUrl(normTarget.getPrefixedText(), { redirect: "no" })),

'" does not have a section called "',

normTarget.fragment,

'". Try again to proceed anyway.'

]);

return;

}

}

callback(setStatus);

}

});

return;

}

callback(setStatus);

};

return ui;

}

if ((mw.config.get('wgAction') === 'view') && (mw.config.get('wgArticleId') === 0)) { // nonexistent page.

uiWrapper.appendChild(el('div', [

link(['Create a redirect'], function () {

while (uiWrapper.hasChildNodes())

uiWrapper.removeChild(uiWrapper.firstChild);

var mblob = new MarkupBlob();

var ui = buildEditingUI(mblob, function (setStatus) {

setStatus(['Saving...']);

api.post({

action: 'edit',

title: mw.config.get('wgPageName'),

token: mw.user.tokens.get('csrfToken'),

createonly: 1,

summary: 'Redirecting to ' + mblob.target + ' (Archer)',

text: mblob.toString()

}, {

success: function (result) {

if (result.error) {

setStatus([

'API error: "',

result.error.info,

'" [code: ', el('code', [result.error.code]), ']'

]);

return;

}

setStatus(['Saved. Reloading page...']);

if (/redirect=no/.test(location.href)) // XXX

location.reload();

else

location.search = location.search ? location.search + '&redirect=no' : '?redirect=no';

}

});

});

ui.statusLine.insertBefore(el('input', null, {

type: 'submit',

value: 'Save'

}), ui.statusLine.firstChild);

uiWrapper.appendChild(ui);

}), ' from this page with Archer'

], {

"class": "kephir-sagittarius-invite"

}));

contentText.parentNode.insertBefore(uiWrapper, contentText);

} else if ((mw.config.get('wgAction') === 'view') && mw.config.get('wgIsRedirect') && redirMsg) {

// start editor immediately

uiWrapper.appendChild(el('div', ['Loading page source…'], {

"class": "kephir-sagittarius-loading"

}));

contentText.insertBefore(uiWrapper, contentText.firstChild);

api.get({

action: 'query',

prop: 'info|revisions',

rvprop: 'timestamp|content',

pageids: mw.config.get('wgArticleId'),

rvstartid: mw.config.get('wgRevisionId'),

rvlimit: 1,

rvdir: 'older',

intoken: 'edit',

}, {

success: function (result) {

if (result.error) {

uiWrapper.appendChild(el('div', [

'API error: "',

result.error.info,

'" [code: ', el('code', [result.error.code]), ']. Reload to try again.'

], {

"class": "kephir-sagittarius-error"

}));

return;

}

while (uiWrapper.hasChildNodes())

uiWrapper.removeChild(uiWrapper.firstChild);

var page = result.query.pages[mw.config.get('wgArticleId')];

var mblob;

var token = page.edittoken;

try {

mblob = new MarkupBlob(page.revisions[0]['*']);

} catch(e) {

uiWrapper.appendChild(el('div', ['Error: unable to parse page. Edit the source manually.'], {

"class": "kephir-sagittarius-error"

}));

return;

}

redirMsg.parentNode.removeChild(redirMsg);

var ui = buildEditingUI(mblob, function (setStatus) {

setStatus(['Saving...']);

api.post({

action: 'edit',

title: mw.config.get('wgPageName'),

basetimestamp: page.revisions[0].timestamp,

token: mw.user.tokens.get('csrfToken'),

summary: 'Redirecting to ' + mblob.target + ' (Archer)',

text: mblob.toString()

}, {

success: function (result) {

if (result.error) {

setStatus([

'API error: "',

result.error.info,

'" [code: ', el('code', [result.error.code]), ']'

]);

return;

}

setStatus(['Saved. Reloading page...']);

if (/redirect=no/.test(location.href)) // XXX

location.reload();

else

location.search = location.search ? location.search + '&redirect=no' : '?redirect=no';

}

});

});

ui.statusLine.insertBefore(el('input', null, {

type: 'submit',

value: 'Save'

}), ui.statusLine.firstChild);

uiWrapper.appendChild(ui);

}

});

} else if ((mw.config.get('wgPageContentModel') === 'wikitext') && ((mw.config.get('wgAction') === 'edit') || (mw.config.get('wgAction') === 'submit'))) {

if (mw.util.getParamValue('section'))

return;

var editform = document.getElementById('editform');

if (editform.wpTextbox1.readOnly)

return;

var uiPivot = document.getElementsByClassName('wikiEditor-ui')[0];

var ui, mblob;

firstHeading.appendChild(document.createTextNode(' '));

firstHeading.appendChild(link(['♐'], function () {

if (ui && ui.parentNode)

ui.parentNode.removeChild(ui);

try {

mblob = new MarkupBlob(editform.wpTextbox1.value);

} catch (e) {

alert("Error: unable to parse page. This page is probably not a redirect.");

return;

}

ui = buildEditingUI(mblob, function () {

editform.wpSummary.value = 'Redirecting to ' + mblob.target + ' (Archer)';

editform.wpTextbox1.value = mblob.toString();

mblob = null;

ui.style.display = 'none';

uiPivot.style.display = '';

});

ui.style.display = 'none';

ui.statusLine.insertBefore(el('input', null, {

type: "button",

value: "Cancel",

}, {

click: function () {

mblob = null;

ui.style.display = 'none';

uiPivot.style.display = '';

}

}), ui.statusLine.firstChild);

ui.statusLine.insertBefore(el('input', null, {

type: "submit",

value: "Check"

}), ui.statusLine.firstChild);

uiPivot.parentNode.insertBefore(ui, uiPivot);

uiPivot.style.display = 'none';

ui.style.display = '';

}, {

"class": "kephir-sagittarius-editlink",

"title": "Edit this redirect with Archer"

}));

var submitButton;

var inputs = editform.getElementsByTagName('input');

for (var i = 0; i < inputs.length; ++i) {

inputs[i].addEventListener('click', function (ev) {

submitButton = this;

}, false);

}

editform.addEventListener('submit', function (ev) {

if (submitButton !== editform.wpSave)

return;

if (mblob) {

ev.preventDefault();

ev.stopImmediatePropagation();

ui.doCheck(function (setStatus) {

setStatus(['Proceeding with saving...']);

editform.wpTextbox1.value = mblob.toString();

editform.wpSummary.value = 'Redirecting to ' + mblob.target + ' (Archer)';

mblob = null;

editform.submit();

});

}

}, false);

}

if (!window.kephirSagittariusFollowCategoryRedirects)

if ((mw.config.get('wgAction') === 'view') && (mw.config.get('wgNamespaceNumber') === wgNamespaceIds.category)) {

var pagesList = document.getElementById('mw-pages').getElementsByClassName('mw-redirect');

for (var i = 0; i < pagesList.length; ++i) {

pagesList[i].href += '?redirect=no';

}

}

}

function abortConditions() {

if (window.location.href.includes('&diff=')) {

throw 'Archer does not run when viewing page diffs. Please revert before editing redirect.';

}

if (mw.config.get('wgNamespaceNumber') < 0) {

throw 'Page is in a virtual namespace. Archer aborts.';

}

}

function ArcherMain() {

$.getJSON("https://en.wikipedia.org/w/index.php?title=User:MJL/Archer/Aliases.json&action=raw&ctype=application/json", function(aliasJSON) {

$.getJSON("https://en.wikipedia.org/w/index.php?title=User:MJL/Archer/Templates.json&action=raw&ctype=application/json",function(templateJSON) {

mw.loader.using(['jquery.suggestions', 'mediawiki.api', 'mediawiki.Title', 'mediawiki.action.view.redirectPage'], function () {

mainCallback(aliasJSON,templateJSON);

});

});

});

}

var api = new mw.Api();

api.get({

action: "query",

format: "json",

prop: "info",

formatversion: 2,

titles: mw.config.get('wgPageName')

}, {

success: function (result) {

try {

abortConditions();

} catch(abortMessage) {

console.info(abortMessage)

return;

}

if (result.query.pages[0].redirect || (window.location.href.includes('&redlink=1'))) {

ArcherMain();

} else {

console.debug('Page is not a redirect.')

return;

}

}

});

});

//

/*

Category:Wikipedia scripts

  • /