Увага: Після публікування слід очистити кеш браузера, щоб побачити зміни.

  • Firefox / Safari: тримайте Shift, коли натискаєте Оновити, або натисніть Ctrl-F5 чи Ctrl-Shift-R (⌘-R на Apple Mac)
  • Google Chrome: натисніть Ctrl-Shift-R (⌘-Shift-R на Apple Mac)
  • Internet Explorer / Edge: тримайте Ctrl, коли натискаєте Оновити, або натисніть Ctrl-F5
  • Opera: натисніть Ctrl-F5
//<!--
var wmVersion = '2017-02-15';
var wmCantWork = 'Вікіфікатор не працює з цією версію оглядача\n\nWikificator can not work in your browser';
var wmFullText = 'Вікіфікатор опрацює ВЕСЬ текст. Виконати?';
var wmTalkPage = 'Будь ласка, не обробляйте Вікіфікатором репліки інших користувачів. Виділіть текст, який треба опрацювати.';

function Wikify() {
	'use strict';
	var txt = '', 
		hidden = [], 
		wpTextbox1 = document.editform.wpTextbox1,
		winScroll = document.documentElement.scrollTop;
		
	// Functions:

	function r(regExp, replaceTo) {
		txt = txt.replace(regExp, replaceTo);
	}

	function hide(regExp) {
		r(regExp, function (value) {
			return '\x01' + hidden.push(value) + '\x02';
		});
	}

	function hideTag(tag) {
		hide(new RegExp('<' + tag + '( [^>]+)?>[\\s\\S]+?<\\/' + tag + '>', 'gi'));
	}

	function hideTags(tags) {
		for (var i = 0; i < tags.length; i++) {
			hideTag(tags[i]);
		}
	}
	
	function hideTemplate(template) {
		hide(new RegExp('\{\{' + template + '[^-A-Za-zА-Яа-я0-9][\\s\\S]*?\}\}', 'g'));
	}
	
	function hideTemplates(templates) {
		for (var i = 0; i < templates.length; i++) {
			hideTemplate(templates[i]);
		}
	}

	function findall(regExp, func) {
		var matches = txt.match(regExp);
		if (matches) {
			for (var i = 0; i < matches.length; i++) {
				func(matches[i]);
			}
		}
	}

	function endsWith(str, suffixes) {
		for (var i = 0; i < suffixes.length; i++) {
			var suffix = suffixes[i];
			if (str.indexOf(suffix, str.length - suffix.length) !== -1) {
				return true;
			}
		}
		return false;
	}

	function processAllText() {
		txt = wpTextbox1.value;
		if (txt == 'version') {
			alert('Вікіфікатор ' + wmVersion);
		}
		
		processText();
		r(/^[\n\r]+/, '');
		wpTextbox1.value = txt;
		txt = '';
		if (window.auto_comment && window.insertSummary && !document.editform.wpSection.value) {
			insertSummary('викификатор');
		}
	}

	function processText() {
		var pattern, matches; // служебные переменные
		var nbsp = '\u00A0'; // non-breaking space
		if (wgNamespaceNumber % 2 || wgNamespaceNumber == 4) { // is talk page
			nbsp = ' ';
			var sigs = txt.match(/\d\d:\d\d, \d\d? \S{3,8} 20\d\d \(UTC\)/g);
			if (sigs && sigs.length > 1) {
				alert(wmTalkPage);
				return;
			}
		}

		hideTags(['nowiki', 'pre', 'source', 'code', 'syntaxhighlight', 'tt', 'math', 'timeline', 'gallery']);

		// Скрываем шаблоны
		hideTemplates(['іл', 'бібліографія', 't', 'с']);

		hide(/^ .*/mg);
		hide(/(https?|ftp|news|nntp|telnet|irc|gopher):\/\/[^\s\[\]<>"]+ ?/gi);
		hide(/^#(redirect|перенапр(авлення)?)/i);
		hide(/<!\-\-.+?\-\->/mg); // -- убираем HTML комментарии

		r(/ +(\n|\r)/g, '$1'); // spaces at EOL
		txt = '\n' + txt + '\n';

		// Links
		r(/(\[\[:?)(category|категорія):( *)/ig, '$1Категорія:');
		r(/(\[\[:?)(image|зображення|file):( *)/ig, '$1Файл:');
		// Linked years, centuries and ranges
		r(/(\(|\s)(\[\[[12]?\d{3}\]\])[\u00A0 ]?(-{1,3}|—) ?(\[\[[12]?\d{3}\]\])(\W)/g, '$1$2–$4$5'); // короткое тире
		r(/(\[\[[12]?\d{3}\]\]) ?(рр?\.)/g, '$1' + nbsp + '$2');
		r(/(\(|\s)(\[\[[IVX]{1,5}\]\])[\u00A0 ]?(-{1,3}|—) ?(\[\[[IVX]{1,5}\]\])(\W)/g, '$1$2–$4$5'); // короткое тире
		r(/(\[\[[IVX]{1,5}\]\]) ?((вв?|ст)\.)/g, '$1' + nbsp + '$2');
		r(/\[\[(\d+)\]\][\u00A0 ]рік/g, '[[$1' + nbsp + 'рік]]');
		r(/\[\[([XVI]+)\]\]\s(століття|сторіччя)/g, '[[$1 століття|$1 $2]]');
		r(/\[\[([XVI]+)\sстоліття\|\1\sстоліття([а-яієїґ]{0,3})\]\]/g, '[[$1 століття]]$2');
		r(/\[\[(([XVI]+) століття\|\2)\]\][\u00A0 ]століття/g, '[[$2 століття]]');
		// Nice links
		r(/(\[\[[^|\[\]]*)[\u00AD\u200E\u200F]+([^\[\]]*\]\])/g, '$1$2'); // Soft Hyphen & DirMark
		r(/\[\[ *([a-zA-Zа-яёієїґА-ЯЁІЄЇҐ\u00A0-\u00FF %!\"$&'()*,\-.\/0-9:;=?\\@\^_`’~]+) *\| *(\1)([a-zа-яёієїґ]*) *\]\]/g, '[[$2]]$3'); // "
		r(/\[\[ *([a-zA-Zа-яёієїґА-ЯЁІЄЇҐ\u00A0-\u00FF %!\"$&'()*,\-.\/0-9:;=?\\@\^_`’~]+) *\| *([^|[\]]+) *\]\]([a-zа-яёієїґ]+)/g, '[[$1|$2$3]]'); // "
		
		hide(/\[\[[^\]|]+/g); // only link part

		// Tags
		r(/<<(\S.+\S)>>/g, '"$1"'); //<< >>
		r(/(sup>|sub>|\s)-(\d)/g, '$1−$2'); //minus
		r(/(<sup>2<\/sup>|&sup2;)/gi, '²');
		r(/(<sup>3<\/sup>|&sup3;)/gi, '³');
		r(/<(b|strong)>(.*)<\/(b|strong)>/gi, "'''$2'''");
		r(/<(i|em)>(.*?)<\/(i|em)>/gi, "''$2''");
		r(/^<hr ?\/?>/gim, '----');
		r(/<\/?(hr|br)( [^\/>]+?)? ?\/?>/gi, '<$1$2 />');
		r(/(\n== *[a-zа-яієїґ\s\.:]+ *==\n+)<references *\/>/ig,'$1{\{примітки}}');
		hide(/<[a-z][^>]*?>/gi);

		// Tables
		hide(/^({\||\|-).*/mg); // table/row def
		hide(/(^\||^!|!!|\|\|) *[a-z]+=[^|]+\|(?!\|)/mgi); // cell style
		hide(/\| +/g); // formatted cell

		// Spaces
		r(/[ \t]+/g, ' '); // double spaces
		r(/\n\n\n+/g, '\n\n'); // remove several empty lines

		// Headings
		r(/^(=+)[ \t\f\v]*(.*?)[ \t\f\v]*=+$/gm, '$1 $2 $1'); // add spaces inside
		r(/([^\r\n])(\r?\n==.*==\r?\n)/g, '$1\n$2'); // add empty line before
		r(/^== див(\.?|ись|іться) ?також ==$/gmi, '== Див. також ==');
		r(/^== зовнішні\sпосилання ==$/gmi, '== Посилання ==');
		r(/^== (.+)[.:] ==$/gm, '== $1 ==');

		r(/«|»|“|”|„/g, '"'); // temp

		// Hyphens and en dashes to pretty dashes
		//r(/–/g, '-'); // &ndash; ->  hyphen
		r(/&(#151|mdash);/g, '—'); // -> &mdash;
		r(/(&nbsp;|\s)[-—]{1,3} /g, '$1— '); // hyphen -> &mdash;
		r(/(\d)--(\d)/g, '$1–$2'); // -> &ndash;
		r(/^# ?-$/mg, '# —'); // это нужно в списках синонимов/антонимов

		// Entities etc. -> Unicode chars
		r(/&#x([0-9a-f]{1,4});/gi, function (n, a) {
			return String.fromCharCode(eval('0x' + a.substr(-4)));
		}); // &#x301;
		r(/&copy;/gi, '©');
		r(/&reg;/gi, '®');
		r(/&sect;/gi, '§');
		r(/&euro;/gi, '€');
		r(/&yen;/gi, '¥');
		r(/&pound;/gi, '£');
		r(/&deg;/g, '°');
		r(/\(tm\)|\(тм\)|&trade;/gi, '™');
		r(/\.\.\.|&hellip;/g, '…');
		r(/\+-|&plusmn;/g, '±');
		r(/~=/g, '≈');
		r(/\^2(\D)/g, '²$1');
		r(/\^3(\D)/g, '³$1');
		r(/(\s)кв\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1$2²$3');
		r(/(\s)куб\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1$2³$3');
		r(/((?:^|[\s"])\d+(?:[\.,]\d+)?)\s*[xх]\s*(\d+(?:[\.,]\d+)?)\s*([мm]{1,2}(?:[\s"\.,;?!]|$))/g, '$1×$2'+ nbsp +'$3');
		r(/&((la|ra|bd|ld)quo|quot);/g, '"');
		r(/№№/g, '№');

		// Year and century ranges
		r(/(\(|\b)([12]?\d{3})[\u00A0 ]?(-{1,3}|—) ?([12]?\d{3})(?![\w-°])/g, '$1$2–$4'); // короткое тире
		r(/([12]?\d{3}) ?(гг?\.)/g, '$1' + nbsp + '$2');
		r(/(\(|\s)([IVX]{1,5})[\u00A0 ]?(-{1,3}|—) ?([IVX]{1,5})(?![\w-°])/g, '$1$2–$4'); // короткое тире
		r(/([IVX]{1,5}) ?((вв?|ст)\.)/g, '$1' + nbsp + '$2');

		// Reductions
		r(/н\.\s?е\./g, 'н\.' + nbsp + 'е\.');
		r(/(Д|д)(о|\.)\sн\.\s?е\./g, '$1о' + nbsp + 'н\.' + nbsp + 'е\.');
		r(/(\d)[\u00A0 ]?(млн|млрд|трлн|(?:м|с|д|к)?м|[км]г)\.?(?=[,;.]| "?[а-яёієїґ-])/g, '$1' + nbsp + '$2');
		r(/(\d)[\u00A0 ](тис)([^\.А-Яа-яЁёієїґІЄЇҐ])/g, '$1' + nbsp + '$2.$3');		
		r(/ISBN:\s?(?=[\d\-]{8,17})/, 'ISBN ');

		// Insert/delete spaces
		r(/&#32;/g, ' '); // html-code of space
		r(/^([#*:]+)[ \t\f\v]*([^ \t\f\v*#:;])/gm, '$1 $2'); // space after #*:
		r(/(\S) (-{1,3}|—) (\S)/g, '$1' + nbsp + '— $3');
		r(/([А-ЯЁІЄЇҐ]\.) ?([А-ЯЁІЄЇҐ]\.) ?([А-ЯЁІЄЇҐ][а-яёієїґ])/g, '$1' + nbsp + '$2' + nbsp + '$3');
		r(/([А-ЯЁІЄЇҐ]\.)([А-ЯЁІЄЇҐ]\.)/g, '$1 $2');
		r(/([а-яёієїґ]"?\)?[\.\?!:])((?:\x01\d+\x02\|)?[А-ЯЁІЄЇҐ])/g, '$1 $2'); // word. word
		r(/([)"a-zа-яёієїґ\]])\s*([,:])\s*([\[("a-zа-яёієїґ])/gi, '$1$2 $3'); // word, word
		r(/([^%=\/\"\:\wА-Яа-яЁёієїґІЄЇҐ]\d+?(?:[\.,]\d+?)?)\s?([%‰])(?!-[А-Яа-яЁёієїґІЄЇҐ])/g, '$1' + nbsp + '$2'); // 5 %
		r(/(\d) ([%‰])(?=-[А-Яа-яЁёієїґІЄЇҐ])/g, '$1$2'); //5%-й
		r(/([№§])(\s*)(\d)/g, '$1' + nbsp + '$3');
		r(/\( +/g, '(');
		r(/ +\)/g, ')'); // inside ()

		// Temperature
		r(/([\s\d=≈≠≤≥<>("'|])([+±−-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])[CС])(?=[\s"').,;!?|])/gm, '$1$2' + nbsp + '°C'); //'
		r(/([\s\d=≈≠≤≥<>("'|])([+±−-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])F)(?=[\s"').,;|!?])/gm, '$1$2' + nbsp + '°F'); //'

		// Dot -> comma in numbers
		r(/(\s\d+)\.(\d+[\u00A0 ]*[%‰°])/gi, '$1,$2');

		// "" -> «»
		for (var i = 1; i <= 2; i++) {
			r(/([\s\x02!|#'"\/(;+-])"([^"]*)([^\s"(|])"([^a-zа-яё])/ig, '$1«$2$3»$4'); //"
		}
		while (/«[^»]*«/.test(txt)) {
			r(/«([^»]*)«([^»]*)»/g, '«$1„$2“');
		}

		// Заполнение слогов
		matches = txt.match(/(\|склади=([^{|}]+))(}|\||$})/m); // Если разбиение приведено без шаблона, обернуть его в шаблон
		if (matches) {
			r(matches[1], '|склади={{склади|' + matches[2].replace("\r", "").replace("\n", "").replace("-", "|").replace("·", "|.|") + '}}' );
		}
		r(/\|склади=$/m, '|склади={{склади|' + wgTitle + '}}');
		var words = wgTitle.split(/[ .,;:!?—]+/);
		r(/\|слово([1-9])=({{склади\|}})?\r?\n\|лема[1-9]=\r?\n(\|знак[1-9]=\r?\n)*/gm, function (str, num) {
			var w = words[parseInt(num)-1];
			var nextch = wgTitle.match(new RegExp(w + '([ .,;:!?—]+)') );
			var z = (nextch && nextch[1] != ' ' ) ? '|знак' + num + '=' + nextch[1] + '\r\n' : '';
			return (w) ? '|слово' + num + '={{склади|' + w + '}}\r\n|лема' + num + '=' + w + '\r\n' + z : '';
		});
		r(/\{\{склади\|\}\}/g, '{{склади|' + wgTitle + '}}'); // Заполнить пустой шаблон-болванку
		
		// Добавление шаблона {{приклад|}} если его нет
		findall(/^====\s*Значення\s*====(\n.*)*?\n(?=\=)/gm, function (value) {
			r(value, value.replace(/^#([^#\n](?!\{\{приклад\s*\|\s*[^\}]*?\s*\}\}))+$/gm, '$& {{приклад|}}'));
		});
		r(/([а-яёієїґ\]]{2})\.\s*{{приклад/gi, '$1 {{приклад'); // Убрать точки в конце толкований
		
		// Замена списка шаблоном
		findall(/^===\s*Споріднені слова\s*===(\n.*)*?\n(?=\=)/gm, function (value) {
			var section = value;
			var list = {}, list_size = 0;
			section = section.replace(/^\*\s*([^:]+)\s*:\s*([^\*\n]*)\n/gm, function (str, param, value) {
				if (param === 'зменш.-пестливі форми' ) {
					param = 'змп';
				}
				list[param] = value; 
				list_size++;
				return '';
			});
			if (list_size > 0) {
				var templ = '{{спорідн';
				for (var param in list) {
					templ = templ + '\n|' + param + '=' + list[param];
				}
				templ = templ + '\n}}\n';
				r(value, section.replace(/^(===\s*Споріднені слова\s*===)\n/m, '$1\n'+ templ));
			}
		});
		
		// Возвращение всех ранее скрытых элементов (через hide и hideTag)
		txt = txt.substr(1, txt.length - 2);
		if ('0'.replace('0', '$$') == '$') { ////$ in replacing string is special, except in IE
			for (i = 0; i < hidden.length; i++) {
				hidden[i] = hidden[i].replace(/\$/g, '$$$$');
			}
		}
		while (hidden.length > 0) {
			r('\x01' + hidden.length + '\x02', hidden.pop());
		}
		
		r(/\[\[Категорія:\]\]/g, '{{categ|lang=}}'); // Замена на шаблон
	}

	// Check regexp support
	try {
		txt = 'ая'.replace(/а/g, 'б').replace(/б(?=я)/, 'в');
	}
	catch (e) {
	}
	if (txt !== 'вя') {
		alert(wmCantWork);
		return;
	}

	wpTextbox1.focus();

	// Modern browsers
	if (typeof wpTextbox1.selectionStart !== 'undefined') {
		var textScroll = wpTextbox1.scrollTop,
			startPos = wpTextbox1.selectionStart,
			endPos = wpTextbox1.selectionEnd;
		txt = wpTextbox1.value.substring(startPos, endPos);
		if (txt === '') {
			processAllText();
		}
		else {
			processText();
			wpTextbox1.value = wpTextbox1.value.substring(0, startPos) + txt + wpTextbox1.value.substring(endPos);
		}
		wpTextbox1.selectionStart = startPos;
		wpTextbox1.selectionEnd = startPos + txt.length;
		wpTextbox1.scrollTop = textScroll;
	}
	// IE
	else if (document.selection && document.selection.createRange) {
		var range = document.selection.createRange();
		txt = range.text;
		if (txt === '') {
			processAllText();
		}
		else {
			processText();
			range.text = txt;
			if (range.moveStart) {
				range.moveStart('character', -txt.length);
			}
			range.select();
		}
	}
	// Other browsers
	else if (confirm(wmFullText)) {
		processAllText();
	}

	document.documentElement.scrollTop = winScroll; // scroll back, for IE/Opera
}

// Toolbar buttons

var addOldToolbarButton = function() {
	var $toolbar = $( '#gadget-toolbar' );
	if ( !$toolbar.length ) {
		$toolbar = $( '#toolbar' );
	}
	$( '<div>' )
		.addClass( 'mw-toolbar-editbutton' )
		.attr( 'alt', 'Вікіфікатор' )
		.attr( 'title', 'Вікіфікатор' )
		.css( {
			'width': '69px',
			'backgroundImage': 'url(//upload.wikimedia.org/wikipedia/commons/3/38/Button_wikify.png)'
		} )
		.appendTo( $toolbar )
		.on( 'click', Wikify );
};

var customizeToolbar = function () {
	$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
		'section': 'main',
		'groups': {
			'extra': {
				'tools': {
					'wikif': {
						label: 'Вікіфікатор',
							type: 'button',
						icon: '//upload.wikimedia.org/wikipedia/commons/0/06/Wikify-toolbutton.png',
						action: {
							type: 'callback',
							execute: function() {
								Wikify();
							}
						}
					}
				}
			}
		}
	} );
	// Prepend wikificator button
  	$('#wikiEditor-ui-toolbar .section-main').prepend($('#wikiEditor-ui-toolbar .group-extra'));
	
	// Скрываем кнопку викификатора из панели инструментов редактора кода
	mw.util.addCSS('.codeEditor-ui-toolbar .group-extra { display:none; }');
};

if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
	mw.loader.using( [ 'user.options', 'jquery.textSelection' ], function () {
		if ( mw.user.options.get( 'usebetatoolbar' ) === 1 ) {
			if ( mw.user.options.get( 'showtoolbar' ) === 1 ) {
				$.when(
					mw.loader.using( ['ext.wikiEditor', 'schema.Edit'] ),
					$.ready
				).then( customizeToolbar );
			}
		} else {
			mw.loader.using( 'mediawiki.toolbar', function() {
				$(document).ready( addOldToolbarButton );
			});
		}
	} );
}
//-->