From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.

// <nowiki>

// This is a modified version of [[User:Sam Sailor/Scripts/Sagittarius+.js]] ([[Special:PermaLink/899463476]])

// Docs: [[User:Wugapodes/Capricorn]]



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

/*globals jQuery, mw, importStylesheet */



////////////////////////////////////////////////////////////////////////////////

// Helper function definitions

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();

	}

}



function normaliseAnchor(anchor) {

	// "." 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 = childi];

			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 ((attrkey === void(0)) || (attrkey === null))

			continue;

		node.setAttribute(key, String(attrkey]));

	}



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

		var handler = eventskey];

		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 = {

    "fromRelatedInfo": "Related information, From",

    "toRelatedInfo": "Related information, To",

    "fromPartOfSpeech": "Parts of speech, From",

    "fromEngVar": "English variant spelling, From",

    "fromOrthographicModification": "Orthographic difference, From",

    "toOrthographicModification": "Orthographic difference, To",

    "fromAlt": "Alternative names, From",

    "fromDisambiguation": "Ambiguity, From",

    //"toDisambiguation": "Ambiguity, To",

    //"fromSpecificity": "Specificity, From",

    "fromAnthroponym": "Anthroponym, From",

    "fromFiction": "Fiction, From",

    "fromWork": "Works of art and works generally, From",

    "toWork": "Works of art and works generally, To",

    "fromLocationOrInfrastructure": "Geographic location or infrastructure, From",

    "fromFormerName": "Former names, From",

    "toFormerName": "Former names, To",

    "fromSystematicName": "Systematic name, From",

    "toSystematicName": "Systematic name, To",

    "fromPostal": "From postal information",

    "fromOrganization": "From organization",

    "fromMath": "From mathematical topic",

    "fromComic": "Comics, From",

    "toComic": "Comics, To",

    "fromMiddleEarth": "Middle-earth topic, From",

    "toMiddleEarth": "Middle-earth topic, To",

    "fromMisc": "From miscellaneous information",

    "fromMeta": "Meta information, From",

    "toMeta": "Meta information, To",

    "fromProtected": "Protection level, From",

    "toNameSpace": "Namespaces, To",

    "fromPrintworthiness":"Printworthiness"

};



////////////////////////////////////////////////////////////////////////////////

// Callback functions



function mainCallback(aliasJSON, templateJSON) {

	var templateAliases = aliasJSON;

	var redirectTemplates = templateJSON;

	//console.log(templateAliases);

	//console.log(redirectTemplates);

	// <nowiki>

	'use strict';

	

	importStylesheet('User:Wugapodes/Capricorn.css');

	

	

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

	

	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;

	

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

		markup = markup.substr(m0].length);

		this.target = m1];

	

		this.rcatt = {};

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

			var alias = normaliseTitle(m1]);

			while (templateAliasesalias])

				alias = templateAliasesalias]; // hopefully there are no loops.

			

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

				var params = m2].split('|');

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

					if (!paramsj])

						continue;

					if (paramsj].indexOf('=') !== -1)

						break out;

					alias = normaliseTitle("R " + paramsj]);

					while (templateAliasesalias])

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

					if (alias in redirectTemplates)

						this.rcattalias = true;

					else

						break out;

				}

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

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

				while (mm = rr.exec(m2])) {

					alias = normaliseTitle(mm1]);

					while (templateAliasesalias])

						alias = templateAliasesalias];

					if (alias in redirectTemplates)

						this.rcattalias = true;

				}

			} else if (alias in redirectTemplates) {

				if (m2]) // TODO

					break;

				this.rcattalias = true;

			} else {

				break;	

			}

			markup = markup.substr(m0].length);

		}

	

		this.tail = markup;

	};

	

	MarkupBlob.prototype.toString = function () {

		var markup = '#REDIRECT [[' + this.target + ']]\n';

		var tail = '';

		var wrapped = [];

		for (var key in this.rcatt) {

			if (this.rcattkey])

				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) {

						rcattkey = this.checked;

					}

				}),

				' ',

				redirectTemplateskey].label

			], {

				"title": redirectTemplateskey].tooltip

			});

		}

		

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

		var group = {};

		for (var key in templateGroups) {

			list.appendChild(el('dt', templateGroupskey]));

			list.appendChild(el('dd', groupkey = el('ul')));

		}

		for (var key in redirectTemplates) {

			var label = makeCheckBox(key);

			groupredirectTemplateskey].group].appendChild(el('li', label));

		}

		

		var collapsibleContent = el('div', list, { 

			"class": "mw-collapsible-content",

			"id": "capricorn-toggle-content"

		})

		return collapsibleContent;

	}

	

	//

	//  Interface creation

	//

	function buildEditingUI(mblob, saveCallback) {

		var statusbar;

		var needsCheck = true;

		var doSave;

		var uiLink, uiTarget;

		mblob = mblob || new MarkupBlob();

		

		// Change text of status bar

		function setStatus(status) {

			while (statusbar.firstChild) // Remove previous statuses

				statusbar.removeChild(statusbar.firstChild);

			if (status) { // If status is a string, add it

				if (typeof status === 'string')

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

				else {  // Otherwise, loop through list and add statuses

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

						if (typeof statusj === 'string')

							statusbar.appendChild(document.createTextNode(statusj]));

						else

							statusbar.appendChild(statusj]);

					}

				}

			}

		}

		

		// Check if the target has changed??

		// Not actually sure what this does yet 21 Oct 2019

		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()) : '';

				if (uiLink) 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 patrolLine;

		var origTarget = mblob.target

		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' }),

				el('input', null, {

					"type": "button",

					"class":"capricorn-toggle",

					"id": "capricorn-toggle-button",

					"value": "Hide rcat list"

				}, {

					'click': function() {

						$( "#capricorn-toggle-content" ).toggle();

						var buttonText = $("#capricorn-toggle-button")[0].value;

						if (buttonText === "Hide rcat list") {

							$("#capricorn-toggle-button")[0].value = "Show rcat list"

						} else {

							$("#capricorn-toggle-button")[0].value = "Hide rcat list"

						};

					}

				})

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

			buildTagList(mblob.rcatt),

			uiStatusLine = el('p', 

				patrolLine = el('span', [], {}),

				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 Capricorn"], mw.util.getUrl("User:Wugapodes/Capricorn"))

				], {

					'style': 'float: right;'

				})

			])

		], {

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

			'class': 'kephir-sagittarius-editor'

		}, {

			'submit': function (ev) {

				ev.preventDefault();

				if (uiStatusLine.childNodes1].childNodes0]) {

					var patrolVal = uiStatusLine.childNodes1].childNodes0].childNodes0].checked;

					if (patrolVal) {

						api.get({

							"action": "query",

							"format": "json",

							"prop": "revisions",

							"meta": "tokens",

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

							"rvprop": "ids",

							"rvslots": "",

							"rvlimit": "1",

							"rvdir": "newer",

							"type": "patrol"

						}, {

							success: function (result) {

								//console.log(mw.config.get('wgPageName'))

								var patrolToken = result"query"]["tokens"]["patroltoken"];

								var revIDpart = result"query"]["pages"];

								var revID = null;

								for (var page in revIDpart) {

									revID = revIDpartpage]["revisions"][0]["revid"];

								}

								//console.log(revID)

								api.post({

									"action": 'patrol',

									"revid": revID,

									"token": patrolToken

								}, {

									success: function (result) {

										if (result.error) {

											console.log(result.error);

											setStatus([

												'API error: "',

												result.error.info,

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

											]);

											console.log(result.error)

											return;

										}

									}

								});

							}

						});

					}

				}

				ui.doCheck(saveCallback);

			}

		});

		ui.statusLine = uiStatusLine;

		ui.patrolLine = patrolLine;

		ui.origTarget = origTarget

	

		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 (sectCachetitle]) {

						var normSect = normaliseAnchor(sect);

						$uiTarget.suggestions('suggestions',

							sectCachetitle].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);

						sectCachetitle = 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',

							sectCachetitle].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.pagespgid];

						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 = this0];

					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 = $textbox0];

	

					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.redirects0]) {

							var newTarget = result.parse.redirects0].to + (result.parse.redirects0].tofragment ? "#" + result.parse.redirects0].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.redirects0].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 (sectlistj].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 a section called "',

									normTarget.fragment,

									'". Try again to proceed anyway.'

								]);

	

								return;

							}

						}

	

						callback(setStatus);

					}

				});

				

				return;

			}

	

			callback(setStatus);

		};

	

		return ui;

	}

	

	function setSummary(current,orig) {

	    var summary;

	    if (orig === current) {

	        summary= "Modifying [[WP:RCAT|redirect categories]] using [[User:Wugapodes/Capricorn|Capricorn ♑]]";

	    } else {

	        summary = 'Redirecting to [[' + current + ']] ([[User:Wugapodes/Capricorn|♑]])'

	    }

	    return summary

	}

	

	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...']);

					var summary = setSummary(mblob.target,ui.origTarget)

					api.post({

						action: 'edit',

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

						createonly: 1,

						summary: summary,

						text: mblob.toString(),

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

					}, {

						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 Capricorn'

		], {

			"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: 'revisions',

			rvprop: 'timestamp|content',

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

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

			rvlimit: 1,

			rvdir: 'older'

		}, {

			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.pagesmw.config.get('wgArticleId')];

				var mblob;

				var token = mw.user.tokens.get('csrfToken')

				try {

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

				} 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...']);

					var summary = setSummary(mblob.target,ui.origTarget)

					api.post({

						action: 'edit',

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

						basetimestamp: page.revisions0].timestamp,

						summary: summary,

						text: mblob.toString(),

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

					}, {

						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';

						}

					});				

				});

				var userName = mw.user.getName();

				api.get({

					"action": "query",

					"format": "json",

					"list": "users",

					"usprop": "groups",

					"ususers": userName

				}, { success: function(result) {

					var groups = result"query"]["users"][0]["groups"

					if (groups.includes("patroller")) {

						ui.patrolLine.insertBefore(el('label', 

									el('input', [], {

									'class': 'checkbox',

									'type': 'checkbox',

									'id': 'patrol',

									'value': 'patrol'

									}), 'Mark as patrolled?']),null);

						}

					}

				});

				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 || !editform.wpTextbox1 || 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;

			}

			

			currentTarget = mblob.target

	

			ui = buildEditingUI(mblob, function () {

				editform.wpSummary.value = 'Redirecting to [[' + mblob.target + ']] ([[User:Wugapodes/Capricorn|♑]])';

				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 Capricorn"

		}));

	

		var submitButton;

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

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

			inputsi].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...']);

					var summary = setSummary(currentTarget,ui.origTarget)

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

					editform.wpSummary.value = summary;

					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) {

			pagesListi].href += '?redirect=no';

		}

	}

}



function abortConditions() {

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

		throw 'Capricorn 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. Capricorn aborts.';

	}

}



function Capricorn() {

	$.getJSON("https://en.wikipedia.org/?title=User:Wugapodes/Capricorn/RedirectAliases.json&action=raw&ctype=application/json", function(aliasJSON) {

		$.getJSON("https://en.wikipedia.org/?title=User:Wugapodes/Capricorn/RedirectTemplates.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.pages0].redirect || (window.location.href.includes('&redlink=1'))) {

			Capricorn();

		} else {

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

			return;

		}

	}

});

/*</source>

 

[[Category:Wikipedia scripts]]

*/

// </nowiki>