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.
/*

disFixer v. 2.3
by Matma Rex and ToSter
CC-BY SA 3.0

*/
/*global mw, $, gConfig, prompt, escape, unescape */
/*jshint laxbreak:true */

if(mw.config.get('wgUserLanguage') === 'pl') {
	mw.messages.set({
		'gadget-disfixer-name': 'disFixer',
		'gadget-disfixer-description-page': 'WP:Narzędzia/disFixer',

		'gadget-disfixer-and': ' i ', //used in summary
		'gadget-disfixer-autosummary-begin': 'poprawa linków do',
		'gadget-disfixer-dabs-short': 'ujedn.',
		'gadget-disfixer-redirs-short': 'przek.',

		'gadget-disfixer-fix-links': 'Popraw linki do ujednoznacznień i przekierowań', //main button
		'gadget-disfixer-fix-links-disam': 'Popraw linki do ujednoznacznień',
		'gadget-disfixer-fix-links-redir': 'Popraw linki do przekierowań',
		'gadget-disfixer-wait': 'Czekaj…', //main button after click

		'gadget-disfixer-no-redir-links': 'Brak linków do przekierowań.',
		'gadget-disfixer-fixing-in-progress': 'Rozwiązywanie przekierowań: trwa…',

		'gadget-disfixer-fix-redirs-only': 'Popraw przekierowania (Wykonaj także inne zmiany! Sama poprawa przekierowań nie ma sensu!)', //fix button if no dabs
		'gadget-disfixer-fix-button': 'Popraw', //fix button

		'gadget-disfixer-fix-dabs': 'Popraw ujednoznacznienia:', //before list of dabs
		'gadget-disfixer-view-dab-page': 'Zobacz stronę ujedn.', //title
		'gadget-disfixer-scroll-to-link': 'Przewiń do pozycji linku w tekście', //title
		'gadget-disfixer-unlink': 'odlinkuj', //last element in every list

		'gadget-disfixer-fix-redirs-checkbox': 'popraw przekierowania',

		'gadget-disfixer-other-target': 'inny cel…',
		'gadget-disfixer-set-new-link-target': 'Dokąd ma prowadzić link?'
	});
} else {
	mw.messages.set({
		'gadget-disfixer-name': 'disFixer',
		'gadget-disfixer-description-page': 'User:Matma Rex/disFixer',

		'gadget-disfixer-and': ' and ', //used in summary
		'gadget-disfixer-autosummary-begin': 'fixed links to',
		'gadget-disfixer-dabs-short': 'dabs',
		'gadget-disfixer-redirs-short': 'redirs',

		'gadget-disfixer-fix-links': 'Fix links to disambigs and/or redirects', //main button
		'gadget-disfixer-fix-links-disam': 'Fix links to disambigs',
		'gadget-disfixer-fix-links-redir': 'Fix links to redirects',
		'gadget-disfixer-wait': 'Wait…', //main button after click

		'gadget-disfixer-no-redir-links': 'No links to redirects.',
		'gadget-disfixer-fixing-in-progress': 'Fixing redirects in progress…',

		'gadget-disfixer-fix-redirs-only': 'Fix redirects (Make some additional changes! Fixing only redirects makes no sense!)', //fix button if no dabs
		'gadget-disfixer-fix-button': 'Fix them!', //fix button

		'gadget-disfixer-fix-dabs': 'Fix disambigs:', //before list of dabs
		'gadget-disfixer-view-dab-page': 'View dab page', //title
		'gadget-disfixer-scroll-to-link': 'Scroll to link position on page', //title
		'gadget-disfixer-unlink': 'unlink', //last element in every list

		'gadget-disfixer-fix-redirs-checkbox': 'fix redirects',

		'gadget-disfixer-other-target': 'other target…',
		'gadget-disfixer-set-new-link-target': 'Set the new link target:'
	});
}

if(mw.loader.getState('ext.gadget.gConfig')) {
	mw.loader.using('ext.gadget.gConfig', function() {
		// ustawienia
		gConfig.register('disFixer', { name: disStr('name'), descriptionPage: disStr('description-page') }, [
			{
				name: 'fixIfRedirsOnly',
				desc: 'Wyświetl przycisk także wtedy, gdy do poprawy są same przekierowania.',
				type: 'boolean',
				deflt: false,
				legacy: [window, 'disFixIfRedirsOnly']
			},
			{
				name: 'markAsMinor',
				desc: 'Oznacz zmiany jako małe.',
				type: 'boolean',
				deflt: false,
				legacy: [window, 'disMarkAsMinor']
			},
			{
				name: 'codeCleanup',
				desc: 'Automatycznie uruchom WP:SK po każdej zmianie.',
				type: 'boolean',
				deflt: false,
				legacy: [window, 'disCodeCleanup']
			}
		]);
	});
} else {
	window.disFixIfRedirsOnly = false;
	window.disMarkAsMinor = false;
	window.disCodeCleanup = false;
}

function disStr(name) {
	return mw.message('gadget-disfixer-'+name).plain();
}

function disGetConfig(option) {
	if(mw.loader.getState('ext.gadget.gConfig')) {
		return gConfig.get('disFixer', option);
	} else {
		var map = {
			fixIfRedirsOnly: 'disFixIfRedirsOnly',
			markAsMinor: 'disMarkAsMinor',
			codeCleanup: 'disCodeCleanup'
		};
		return window[ map[option] ];
	}
}

function disCallApi( request, callback ) {
	request.format = 'json';
	$.post( mw.util.wikiScript( 'api' ), request, callback, 'json' );
}

window.disScrollToLink = function(target)
{
	if (window.disHighlightedLinkTimeout !== undefined && window.disHighlightedLink !== undefined) {
		clearTimeout(window.disHighlightedLinkTimeout);
		window.disHighlightedLink.css('background', '');
	}

	window.disHighlightedLink = $(window.dis).filter('[title="' + target.replace('"', '\\"') + '"]').first();
	window.disHighlightedLink.css('background', 'red');

	window.disHighlightedLinkTimeout = setTimeout(function() {
		window.disHighlightedLink.css('background', '');
	}, 3000);
	window.disHighlightedLink.get(0).scrollIntoView();
};

function disLoadFixer()
{
	var dis = window.dis = $('#mw-content-text a.mw-disambig').get();
	var disRedirs = window.disRedirs = $('#mw-content-text a.mw-redirect').get();

	//nie ma disambigów, na pewno - nic do roboty
	if (dis.length === 0) {
		if (!disGetConfig('fixIfRedirsOnly') || disRedirs.length === 0) {
			return; //możliwość wymuszenia sprawdzania mimo braku disambigów, ale tylko, gdy są rediry
		}
	}

	var txt = disStr('fix-links');
	if (dis.length === 0) {
		txt = disStr('fix-links-redir');
	}
	else if (disRedirs.length === 0) {
		txt = disStr('fix-links-disam');
	}
	var el = '<input id="disBeginButton" type="submit" class="disFixerButton" value="' + txt + '" />';

	$('h1:first').before(el);
	$('#disBeginButton').click(function() {
		try {
			$('#disBeginButton').val(disStr('wait'));
		} catch(er){}
		disBegin();
	});
}

function disBegin()
{
	var el = '<div id="disRedirsStatus"></div>';
	$('h1:first').before(el);

	$('#disRedirsStatus').append('<input type="checkbox" id="disFixRedirsCheckbox" style="display:none" />');
	if (window.disRedirs.length === 0) {
		$('#disRedirsStatus').append(disStr('no-redir-links'));
	}
	else {
		$('#disRedirsStatus').append(disStr('fixing-in-progress'));
	}

	var titles = [];
	for (var i = 0; i < window.dis.length; i++) {
		titles.push(window.dis[i].title);
	}

	disCallApi( {
		action: 'query',
		prop: 'links',
		titles: titles.join( '|' ),
		plnamespace: 0,
		pllimit: 'max'
	}, function( data ) {
		disCallback( data );
	} );

	if (window.disRedirs.length > 0) {
		var titles2 = [];
		for (var j = 0; j < window.disRedirs.length; j++) {
			titles2.push(window.disRedirs[j].title);
		}

		disCallApi( {
			action: 'query',
			prop: 'revisions',
			rvprop: 'content',
			titles: titles2.join( '|' )
		}, function( data ) {
			disRedirCallback2( data );
		} );
	}
}

function disCallback(res)
{
	var el;
	if (res.query === undefined && disGetConfig('fixIfRedirsOnly')) {
		el = '<div id="disContainer"><input type="submit" class="disFixerButton" value="' + disStr('fix-redirs-only')
			+ '" style="font-weight:bold;color:red" /></div>';

		$('#disBeginButton').replaceWith(el);
		$('#disContainer input').click(disSend);
	}
	else {
		var addScrollToLink = $('#content').get(0).scrollIntoView;
		var pages = res.query.pages;

		var str = disStr('fix-dabs') + '<br />';
		for (var i in pages) {
			if (isNaN(+i)) continue; //prototypes, damn
			var page = pages[i];

			str +=
				'<label>' + page.title + ' '
				+ '<a href="/w/index.php?title=' +encodeURIComponent(page.title) + '" title="' + disStr('view-dab-page')
				+ '" target="_new">&#8663;</a>'
				+ (addScrollToLink ? '<a href="javascript:disScrollToLink(' + '\'' + page.title
					+ '\'' + ')" title="' + disStr('scroll-to-link') + '">&#8659;</a>'
					: '')
				+ ': <select id="input-dislink' + page.title + '">';
			str += '<option>' + page.title + '</option>';

			if (page.links === undefined) {
				page.links = [];
			}
			for (var j = 0; j < page.links.length; j++) {
				str += '<option>' + page.links[j].title + '</option>';
			}

			str += '<option style="color:grey">[' + disStr('unlink') + ']</option>';
			str += '</select> <input type="submit" class="disFixerButton" onclick="disSetLinkTarget(this,'
				+ '\'' + page.title + '\'' + ')" value="' + disStr('other-target') + '" /></label><br />';
		}

		el = '<div id="disContainer">' + str
			+ '<input type="submit" class="disFixerButton" value="' + disStr('fix-button') + '" /></div>';
		$('#disBeginButton').replaceWith(el);
		$('#disContainer input:last').click(disSend);
	}
}

function disRedirCallback2(res)
{
	var pages = res.query.pages;
	window.disResolvedRedirs = [];

	for (var i in pages) {
		if (isNaN(i)) continue;

		var f = pages[i].title;
		var t = pages[i].revisions[0]['*'].replace(/^#(?:REDIRECT|TAM|PATRZ|PRZEKIERUJ)\s*\[\[([^\]]+)\]\][\s\S]*$/i, '$1');

		if (t.match(/[<>\[\]|{}\r\n]/)) {
			//coś się pomieszało - tych znaków nie powinno być w tytule strony
			continue;
		}

		window.disResolvedRedirs.push({from:f, to:t});
	}

	var el = '<input type="checkbox" id="disFixRedirsCheckbox" checked="checked" /> '
		+ '<label for="disFixRedirsCheckbox">' + disStr('fix-redirs-checkbox')
		+ ' (' + window.disResolvedRedirs.length + ')</label>';
	$('#disRedirsStatus').html(el);
	$('#disRedirsStatus').css('color', 'green');
}

function disSend()
{
	var inputs = $('#disContainer select');
	var toFix = [];
	for (var i = 0; i < inputs.length; i++) {
		var from = inputs[i].options[0].value;
		var to = inputs[i].value;
		if (from == to) continue;
		toFix.push(from + '~' + to);
	}
	createCookie('disFixDis' + mw.config.get('wgPageName'), toFix.join('|'), 0);

	if (window.disResolvedRedirs !== undefined && $('#disFixRedirsCheckbox').attr('checked')) {
		var toFixRedirs = [];
		for (var j = 0; j < window.disResolvedRedirs.length; j++) {
			var fromRedir = window.disResolvedRedirs[j].from;
			var toRedir = window.disResolvedRedirs[j].to;
			toFixRedirs.push(fromRedir + '~' + toRedir);
		}
		createCookie('disFixRedirs' + mw.config.get('wgPageName'), toFixRedirs.join('|'), 0);
	}

	var edittab = document.getElementById('ca-editsource') || document.getElementById('ca-edit');
	window.location = $(edittab).find('a:first').attr('href');
}

function disOnloadEdit()
{
	var whatIsFixed = [];
	var str = $('#wpTextbox1').textSelection('getContents');

	str = str.replace(/\r\n/g,'\n').replace(/\s*$/, '');

	if (disGetConfig('codeCleanup') && window.wp_sk !== undefined) {
		str = window.wp_sk.cleaner(str);
	}
	else {
		str = disCleanLinks(str);
	}

	var linksDisam = readCookie('disFixDis' + mw.config.get('wgPageName'));
	var linksRedir = readCookie('disFixRedirs' + mw.config.get('wgPageName'));

	var links = [];
	if (linksDisam && linksDisam !== 'undefined') {
		links = linksDisam.split('|');
		whatIsFixed.push(disStr('dabs-short'));
	}
	if (linksRedir && linksRedir !== 'undefined') {
		links = $.merge(links, linksRedir.split('|'));
		whatIsFixed.push(disStr('redirs-short'));
	}

	if (links.length > 0) {
		for (var i = 0; i < links.length; i++) {
			var l = links[i].split('~');
			var from = l[0].replace(/([\/\.\*\+\?\|\(\)\[\]\{\}\\])/g, '\\$1'); //regex escape
			var to = l[1];
			var safe_from = '['+from.substring(0,1).toLowerCase()+from.substring(0,1).toUpperCase()+']'+from.substring(1);

			if (to == '[' + disStr('unlink') + ']') {
				str = str.replace(new RegExp('\\[\\[(' + safe_from + ')(?:#[^\\]\\|]+|)\\]\\]', 'g'), '$1');
				str = str.replace(new RegExp('\\[\\[' + safe_from + '(?:#[^\\]\\|]+|)\\|([^\\]]+)\\]\\]', 'g'), '$1');
				continue;
			}
			var sh = to.indexOf('#') != -1;
			str = str.replace(new RegExp('\\[\\[(' + safe_from + ')(#[^\\]\\|]+|)\\]\\]', 'g'), '[[' + (sh ? to : to + '$2') + '|$1]]');
			str = str.replace(new RegExp('\\[\\[' + safe_from + '(#[^\\]\\|]+|)\\|([^\\]]+)\\]\\]', 'g'), '[[' + (sh ? to : to + '$1') + '|$2]]');
		}
	}
	str = disCleanLinks(str);

	eraseCookie('disFixDis' + mw.config.get('wgPageName'));
	eraseCookie('disFixRedirs' + mw.config.get('wgPageName'));

	if (whatIsFixed.length === 0) {
		return;
	}

	$('#wpTextbox1').textSelection('setContents', str);
	var newval = $('#wpSummary').val() + '[[' + disStr('description-page') + '|' + disStr('autosummary-begin')
		+ ' ' + whatIsFixed.join(disStr('and')) + ']]' + (disGetConfig('codeCleanup') ? ', [[WP:SK]]' : '');
	$('#wpSummary').val(newval);
	if (disGetConfig('markAsMinor')) {
		$('#wpMinoredit').attr('checked', 'checked');
	}
	$('#wpDiff').click();
}

window.disSetLinkTarget = function(el, disName) //helper - for buttons
{
	el = $(el);
	var target = prompt(disStr('set-new-link-target'), disName);
	if (!target) {
		return;
	}

	var opt = '<option value="' + target + '">' + target + '</option>';
	var sel = el.parent().find('select:first');
	sel.append(opt);
	sel.find('option:last').attr('selected', 'selected');
};

// based on Nux's code cleanup
// http://pl.wikipedia.org/wiki/Wikipedysta:Nux/wp_sk.js
function disCleanLinks(str)
{
	//najprostszy cleanup, głównie po to, żeby regeksy do poprawy linków mogły być prostsze

	// [[Kto%C5%9B_jaki%C5%9B#co.C5.9B|...]]›[[Ktoś jakiś#coś|...]]
	str = str.replace(/\[\[([^|#\]]*)([^|\]]*)(\||\]\])/g, function(a, name, anchor, end)
	{
		try {
			name = decodeURIComponent(name);
			anchor = decodeURIComponent(anchor.replace(/\.([0-9A-F]{2})\.([0-9A-F]{2})/g, '%$1%$2'));
			a = '[[' + name + anchor + end;
		} catch(err){} // błąd na linkach typu [[%]]

		return a.replace(/_/g, ' ');
	});

	// [[Link|link]] > [[link]]
	str = str.replace(/\[\[([^|\]])([^|\]]*)\|([^\]])\2\]\]/g, function (a, w1_1, w_rest, w2_1)
	{
		return (w1_1.toUpperCase() == w2_1.toUpperCase()) ? '[[' + w2_1 + w_rest + ']]' : a;
	});

	// (ro)zwijanie wikilinków
	str = str.replace(/\[\[([^|\]]*)\|\1([a-zA-ZżółćęśąźńŻÓŁĆĘŚĄŹŃ]*)\]\]/g, '[[$1]]$2');
	str = str.replace(/\[\[([^|\]]+)\|([^|\]]+)\]\]([a-zA-ZżółćęśąźńŻÓŁĆĘŚĄŹŃ]+)/g, '[[$1|$2$3]]');

	// usuwanie spacji w wikilinkach
	str = str.replace(/\[\[ *([^\]\|:]*[^\]\| ]) *\|/g, '[[$1|');
	str = str.replace(/([^ \t\n])\[\[ +/g, '$1 [[');
	str = str.replace(/\[\[ +/g, '[[');
	str = str.replace(/([^ \t\n])\[\[([^\]\|:]+)\| +/g, '$1 [[$2|');
	str = str.replace(/\[\[([^\]\|:]+)\| +/g, '[[$1|');
	str = str.replace(/([^ \|]) +\]\]([^ \t\na-zA-ZżółćęśąźńŻÓŁĆĘŚĄŹŃ])/g, '$1]] $2');
	str = str.replace(/([^ \|]) +\]\]([^a-zA-ZżółćęśąźńŻÓŁĆĘŚĄŹŃ])/g, '$1]]$2');

	return str;
}


// http://www.quirksmode.org/js/cookies.html
// modified to use sessionStorage when available
function createCookie(name, value, days)
{
	if(window.sessionStorage)
	{
		if (days < 0) sessionStorage.removeItem(name);
		else sessionStorage[name] = value;
	}
	else
	{
		// fall back to cookies
		var expires = '';
		if (days) {
			var date = new Date();
			date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
			expires = "; expires=" + date.toGMTString();
		}
		document.cookie = escape(name) + "=" + escape(value) + expires + "; path=/";
	}
}

function readCookie(name)
{
	if(window.sessionStorage)
	{
		return (sessionStorage[name]) + ''; //weird Firefox fix / FIXME: is this still needed for anything?
	}
	else
	{
		var nameEQ = escape(name) + "=";
		var ca = document.cookie.split(';');
		for (var i = 0; i < ca.length; i++) {
			var c = ca[i];
			while (c.charAt(0) == ' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) === 0) return unescape(c.substring(nameEQ.length,c.length));
		}
		return null;
	}
}

function eraseCookie(name)
{
	createCookie(name, "", -1);
}

/*
AND FINALLY ONLOAD
*/

mw.loader.using(
	( mw.loader.getState('ext.gadget.gConfig') ? ['ext.gadget.gConfig'] : [] ).concat( 'jquery.textSelection' ),
	function() {
		if ( mw.config.get( 'wgAction' ) == 'edit' ) {
			$( document ).ready( function() {
				if ( disGetConfig('codeCleanup') && window.wp_sk !== undefined ) {
					// Wait for RL to load WP:SK
					mw.loader.using( 'ext.gadget.wp_sk', function() {
						disOnloadEdit();
					} );
				} else {
					disOnloadEdit();
				}
			} );
		}

		// Do not show interface, when previewing the page or on talk pages
		if ( mw.config.get( 'wgAction' ) !== 'submit' && mw.config.get( 'wgNamespaceNumber' ) % 2 === 0 ) {
			$( document ).ready( function() {
				disLoadFixer();
			} );
		}
	}
);