MediaWiki:Wikificator.js: различия между версиями

Материал из Emuverse
(Источник: Википедия)
 
(актуальная версия)
Строка 1: Строка 1:
// ВНИМАНИЕ! Внося изменения в код, не забывайте обновлять справку на странице [[Википедия:Викификатор]]  
var wmCantWork = 'Викификатор не может работать в вашем браузере',
wmFullText = 'Викификатор обработает ВЕСЬ текст на этой странице. Продолжить?',
wmTalkPage = 'Викификатор не обрабатывает страницы обсуждения целиком.\n\nВыделите ваше сообщение — обработано будет только оно';
window.wfPlugins = window.wfPlugins || [];


/* <pre> */


var txt;
function Wikify() {
'use strict';
var wmFullText = 'Wikificator will process ALL text on this page. Continue?';
var txt = '',
var wmCantWork = 'Wikificator cannot work in your browser';
hidden = [],
var wmWontWork = 'Wikificator will not work in Netscape 4.x and less';
wpTextbox1 = document.editform.wpTextbox1,
winScroll = document.documentElement.scrollTop;




var wmCategoryNS = 'Категория';
// FUNCTIONS
        /* мешает
var wmTemplateNS = 'Шаблон';
var wmUserNS = 'Участник';
var wmImageNS = 'Изображение';
var wmMediaNS = 'Медиа';
        */


var wmLocaleNS = new Array ( wmCategoryNS /*, wmTemplateNS, wmUserNS, wmImageNS, wmMediaNS */ );
function r( r1, r2 ) {
var wmEnNS = new Array ( 'category' /*, 'template', 'user', 'image', 'media' */);
txt = txt.replace( r1, r2 );
}


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


if (window.event){
function hideTag ( tag ) {
  document.onkeypress = pressed;
hide( new RegExp( '<' + tag + '( [^>]+)?>[\\s\\S]+?<\\/' + tag + '>', 'gi' ) );
}
}


function pressed() //On Ctrl+Enter (MSIE)
function hideTemplates() {
{key = window.event.keyCode;if (key==10){Wikify();}}
var pos = 0,
//======================================
stack = [],
function Wikify()
tpl,
{
left,
check_regexp(); // Check whether regular expressions are supported
right;
 
while ( true ) {
// Только если пользователь указал в персональном скрипте auto_comment = 1;
left = txt.indexOf( '{{', pos );
 
right = txt.indexOf( '}}', pos );
// Раскоментировал, теперь не должно ругаться (добавил определение переменной в общий монобук)  
if ( left === -1 && right === -1 && !stack.length ) {
 
break;
if (auto_comment == 1) {
}
  var wpS = document.editform.wpSummary;
if ( left !== -1 && ( left < right || right === -1 ) ) {
  if (wpS.value != '' && wpS.value.charAt(wpS.value.length-2) != '/') {
stack.push( left );
    wpS.value += ', Викификатор'
pos = left + 2;
  } else {
} else {
    wpS.value += 'Викификатор'
left = stack.pop();
  }
if ( typeof left === 'undefined' ) {
}
if ( right === -1 ) {
 
pos += 2;
document.editform.wpTextbox1.focus();
continue;
var txtarea = document.editform.wpTextbox1;
} else {
if(document.selection  && !is_gecko)/* IE */ {
left = 0;
txt = " "+document.selection.createRange().text;
}
if (txt == " ") {all_text();} // If nothing was selected;
}
else{
if ( right === -1 ) {
Process();
right = txt.length;
txt = txt.substr (1, txt.length-1);
}
document.selection.createRange().text = txt;
right += 2;
tpl = txt.substring( left, right );
txt = txt.substring( 0, left ) +
'\x01' + hidden.push( tpl ) + '\x02' +
txt.substr( right );
pos = right - tpl.length;
}
}
}
}
}
else if((txtarea.selectionStart || txtarea.selectionStart == '0')&&(navigator.productSub>20031000)) /*Gecko-browsers older then 10.2003*/  {
 
var startPos = txtarea.selectionStart;
function processText() {
var endPos = txtarea.selectionEnd;
var i,
var scrollTop=txtarea.scrollTop;
u = '\u00A0'; // unbreakable space
txt = " "+(txtarea.value).substring(startPos, endPos);
if ( mw.config.get('wgNamespaceNumber') % 2 || mw.config.get('wgNamespaceNumber') === 4 ) { // is talk page
if (txt == " ") {all_text();} // If nothing was selected;
u = ' ';
else{
var sigs = txt.match( /\d\d:\d\d, \d\d? \S{3,8} 20\d\d \(UTC\)/g );
Process();
if ( sigs && sigs.length > 1 ) {
txt = txt.substr (1, txt.length-1);
alert( wmTalkPage );
txtarea.value = txtarea.value.substring(0, startPos) + txt + txtarea.value.substring(endPos, txtarea.value.length);
return;
txtarea.focus();
}
}
}
}
else{if (confirm(wmFullText)) {all_text();}} // Other browsers
}
//======================================
function all_text()// Process all text
{
txt = " "+document.editform.wpTextbox1.value;
Process();
txt = txt.substr (1, txt.length-1);
document.editform.wpTextbox1.value=txt;
}
//======================================
function check_regexp()// Check whether regular expressions are supported
{
var reg1 = "code";
reg1 = reg1.replace(/d/g, "r");
if (reg1 != "core"){alert(wmCantWork);exit;}
b_ver = navigator.appVersion.substr (0, 1);
if (navigator.appName=="Netscape"&&b_ver<5){alert(wmWontWork);exit;}
return ;
}
function Process()
// We have 2 more pairs of safe chars in \x1E — \x1F !
{
if (wgNamespaceNumber % 2 || wgNamespaceNumber==4) {
var sigs = txt.match(/\d\d:\d\d, \d\d? \S{3,9} 20\d\d \(UTC\)/g);
if (sigs && sigs.length > 1)
  if (!confirm('Пожалуйста, не обрабатывайте Викификатором реплики других участников. Вы уверены, что хотите продолжить?'))
    return;
}
//var nowiki = ReplaceElements( '\<math\>(.|\r|\n)+?\<\/math\>, "\x03", "\x04" );
//That variant will make ReplaceTags() function unnecessary, but it's so ugly...


var nowiki = ReplaceTags( 'nowiki', "\x03", "\x04" );
hideTag( 'nowiki' );
var pre = ReplaceTags( 'pre', "\x12", "\x13" );
hideTag( 'pre' );
var code = ReplaceTags( 'code', "\x1c", "\x1d" );
hideTag( 'source' );
var math = ReplaceTags( 'math', "\x05", "\x06" );
hideTag( 'syntaxhighlight' );
var gallery = ReplaceTags( 'gallery', "\x14", "\x15" );
hideTag( 'templatedata' );
var source = ReplaceTags( 'source', "\x1E", "\x1F" );


// Exclude lines starting with space
hideTag( 'code' );
f_space = txt.substr (0, 1)
hideTag( 'tt' );
txt = txt.substr (1, txt.length-1)
var sp_lines = ReplaceElements( "^( )(.+)$", "\x16", "\x17" );
txt = f_space + txt


ProcessNS( wmEnNS , wmLocaleNS );
hideTag( 'graph' );
CorrectRanges();
hideTag( 'hiero' );
hideTag( 'math' );
hideTag( 'timeline' );


// Exclude templates and internal links
r( /( |\n|\r)+\{\{(·||\*)\}\}/g, '{{$2}}' ); // before {{·/•/*}}, usually in templates
var templates = ReplaceElements( "\\{\\{(.|\\r|\\n)+?\\}\\}", "\x18", "\x19" );
r( /\{\{\s*[Шш]аблон:([\s\S]+?)\}\}/g, '{{$1}}' );
var links = ReplaceElements( "(\\[\\[)(.*?)(\\||\\]\\])", "\x10", "\x11" );
r( /(\{\{\s*)reflist(\s*[\|\}])/ig, '$1примечания$2' );
var ext_links = ReplaceElements( "\\[(http|https|ftp|tftp|news|nntp|telnet|irc|gopher)://(.*?)\\]", "\x1A", "\x1B");


HTML2Wiki();
hideTemplates();
hide( /^[ \t].*/mg );
hide( /(https?|ftp|news|nntp|telnet|irc|gopher):\/\/[^\s\[\]<>"]+ ?/gi );
hide( /^#(redirect|перенапр(авление)?)/i );
hideTag( 'gallery' );


// Exclude tags and tag attributes (all text in quotes after "=" sign)
var attrs = ReplaceElements( '(=)(\\s?)(\\' + '")(.*?)(\\")', "\x0E", "\x0F");
var tags = ReplaceElements( "<([^>]*?)>", "\x01", "\x02");


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


RestoreElements( tags, "\x01", "\x02");
RestoreElements( attrs, "\x0E", "\x0F");
RestoreElements( ext_links, "\x1A", "\x1B" );
RestoreElements( links, "\x10", "\x11" );
RestoreElements( templates, "\x18", "\x19" );
RestoreElements( sp_lines, "\x16", "\x17" );
RestoreElements( gallery, "\x14", "\x15" );
RestoreElements( math, "\x05", "\x06" );
RestoreElements( code, "\x1c", "\x1d" );
RestoreElements( pre, "\x12", "\x13" );
RestoreElements( nowiki, "\x03", "\x04" );
RestoreElements( source, "\x1E", "\x1F" );


}
// LINKS
r( /(\[\[:?)(category|категория):( *)/ig, '$1Категория:' );
r( /(\[\[:?)(module|модуль):( *)/ig, '$1Модуль:' );
r( /(\[\[:?)(template|шаблон):( *)/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' + u + '$2' );
r( /(\(|\s)(\[\[[IVX]{1,5}\]\])[\u00A0 ]?(-{1,3}|–|—) ?(\[\[[IVX]{1,5}\]\])(\W)/g, '$1$2—$4$5' );
r( /(\[\[[IVX]{1,5}\]\]) ?(вв?\.)/g, '$1' + u + '$2' );
r( /\[\[(\d+)\]\]\sгод/g, '[[$1' + u + 'год]]' );
r( /\[\[(\d+)\sгод\|\1\]\]\sгод/g, '[[$1' + u + 'год]]' );
r( /\[\[(\d+)\sгод\|\1\sгод([а-я]{0,3})\]\]/g, '[[$1' + u + 'год]]$2' );
r( /\[\[((\d+)(?: (?:год )?в [\wa-яёА-ЯЁ ]+\|\2)?)\]\][\u00A0 ](год[а-яё]*)/g, '[[$1' + u + '$3]]' );
r( /\[\[([XVI]+)\]\]\sвек/g, '[[$1' + u + 'век]]' );
r( /\[\[([XVI]+)\sвек\|\1\]\]\sвек/g, '[[$1' + u + 'век]]' );
r( /\[\[([XVI]+)\sвек\|\1\sвек([а-я]{0,3})\]\]/g, '[[$1' + u + 'век]]$2' );
r( /\[\[(([XVI]+) век\|\2)\]\][\u00A0 ]век/g, '[[$2' + u + 'век]]' );
// Nice links
r( /(\[\[[^|\[\]]*)[\u00AD\u200E\u200F]+([^\[\]]*\]\])/g, '$1$2' ); // Soft Hyphen & DirMark
r( /\[\[ *([^|\[\]]+) *\| *(\1)([a-zа-яё]*) *\]\]/g, '[[$2]]$3' );
r( /\[\[ *([^|\[\]]+)([^|\[\]()]+) *\| *\1 *\]\]\2/g, '[[$1$2]]' ); // text repetition after link
r( /\[\[ *(?!Файл:|Категория:)([a-zA-Zа-яёА-ЯЁ\u00A0-\u00FF %!\"$&'()*,\-—.\/0-9:;=?\\@\^_`’~]+) *\| *([^\|\[\]]+) *\]\]([a-zа-яё]+)/g, '[[$1|$2$3]]' ); // "
hide( /\[\[[^\]|]+/g); // only link part


function HTML2Wiki()
{


// TAGS
r( /<<(\S.+\S)>>/g, '"$1"' ); // << >>
r( /(su[pb]>)-(\d)/g, '$1−$2' ); // ->minus
r( /<(b|strong)>(.*?)<\/(b|strong)>/gi, "'''$2'''" );
r( /<(i|em)>(.*?)<\/(i|em)>/gi, "''$2''" );
r( /^<hr ?\/?>/gim, '----' );
r( /<[\/\\]?(hr|br)( [^\/\\>]+?)? ?[\/\\]?>/gi, '<$1$2 />' );
r( /[\u00A0 \t]*<ref(?:\s+name="")?(\s|>)/gi, '<ref$1' );
r( /(\n== *[a-zа-я\s\.:]+ *==\n+)<references *\/>/ig, '$1{' + '{примечания}}' );
hide( /<[a-z][^>]*?>/gi);


// Replace <b>, <strong> tags with ''' and <i>, <em> with ''
hide( /^(\{\||\|\-).*/mg); // table/row def
txt = txt.replace(/\<\/?(b|strong)\>/gim, "\'\'\'")
hide( /(^\||^!|!!|\|\|) *[a-z]+=[^|]+\|(?!\|)/mgi); // cell style
txt = txt.replace(/\<\/?(i|em)\>/gim, "\'\'")
hide( /\| +/g); // formatted cell


// Replace <hr> tag with ----, improve <hr> and <br> tags
r( /[ \t\u00A0]+/g, ' ' ); // double spaces
txt = txt.replace(/\<hr ?\/?\>/gi, "----")
txt = txt.replace(/\<hr ([^\>\/]+?) ?\/?\>/gi, "<hr $1 />")
txt = txt.replace(/\<br\/?\>/gi, "<br />")
txt = txt.replace(/\<br ([^\>\/]+?) ?\/?\>/gi, "<br $1 />")


// Replace small and big tags with inline styling
// Entities etc. → Unicode chars
if ( mw.config.get('wgNamespaceNumber') !== 10 ) {
r( /&(#x[0-9a-f]{2,4}|#[0-9]{3,4}|[0-9a-z]{2,8});/gi, function ( s ) {
var t = document.createElement( 'textarea' );
t.innerHTML = s;
var c = t.value;
if ( c.length === 1 && c.charCodeAt( 0 ) > 127 ) {
return c;
}
return s;
});
}
r( /\(tm\)/gi, '™' );
r( /\.\.\./g, '…' );
r( /(^|[^+])\+-(?!\+|-)/g, '$1±' );
r( /~=/g, '≈' );
r( /\^2(\D)/g, '²$1' );
r( /\^3(\D)/g, '³$1' );
r( /(\s)кв\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1' + u + '$2²$3' );
r( /(\s)куб\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1' + u + '$2³$3' );
r( /((?:^|[\s"])\d+(?:[\.,]\d+)?)\s*[xх]\s*(\d+(?:[\.,]\d+)?)\s*([мm]{1,2}(?:[\s"\.,;?!]|$))/g, '$1×$2' + u + '$3' );
r( /([\wа-яА-ЯёЁ])'([\wа-яА-ЯёЁ])/g, '$1’$2' ); //'
r( /№№/g, '№' );


/// txt = txt.replace(/(\<small\>)/g, "<span style=\"font-size\:smaller\;\">");
// Headings
/// txt = txt.replace(/(\<\/small\>)/g, "<\/span>");
r( /^(=+)[ \t\f\v]*(.*?)[ \t\f\v]*=+$/gm, '$1 $2 $1' ); //add spaces inside
/// txt = txt.replace(/(\<big\>)/g, "<span style=\"font-size\:1.25em\;\">");
r( /([^\r\n])(\r?\n==.*==\r?\n)/g, '$1\n$2' ); //add empty line before
/// txt = txt.replace(/(\<\/big\>)/g, "<\/span>");
r( /^== см(\.?|отри|отрите) ?также ==$/gmi, '== См. также ==' );
r( /^== сноски ==$/gmi, '== Примечания ==' );
r( /^== внешние\sссылки ==$/gmi, '== Ссылки ==' );
r( /^== (.+)[.:] ==$/gm, '== $1 ==' );
r( /^== '''(?!.*'''.*''')(.+)''' ==$/gm, '== $1 ==' );


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


// Process default namespaces
// Hyphens and en dashes to pretty dashes
r( /–/g, '-' ); // &ndash; -> hyphen
r( /(\s)-{1,3} /g, '$1— ' ); // hyphen -> &mdash;
r( /(\d)--(\d)/g, '$1—$2' ); // -> &mdash;
r( /(\s)-(\d)/g, '$1−$2' ); // hyphen -> minus


function ProcessNS( En_NS_List , Loc_NS_List )
// Year and century ranges
{
r( /(\(|\s)([12]?\d{3})[\u00A0 ]?(-{1,3}|—) ?([12]?\d{3})(?![\wА-ЯЁа-яё]|-[^ех]|-[ех][\wА-ЯЁа-яё])/g, '$1$2—$4' );
r( /([12]?\d{3}) ?(гг?\.)/g, '$1' + u + '$2' );
r( /(\(|\s)([IVX]{1,5})[\u00A0 ]?(-{1,3}|—) ?([IVX]{1,5})(?![\w\-])/g, '$1$2—$4' );
r( /([IVX]{1,5}) ?(вв?\.)/g, '$1' + u + '$2' );


for (i=0; i < En_NS_List.length; i++)
// Reductions
  {
r( /(Т|т)\.\s?е\./g, '$1о есть' );
  //alert("(\\[\\[)(:?)(" + En_NS_List[i] + "|" +
r( /(Т|т)\.\s?к\./g, '$1ак как' );
  //Loc_NS_List[i] + ")(:)( *)");
r( /(В|в)\sт\. ?ч\./g, '$1 том числе' );
 
r( /(И|и)\\.\s?д\./g, '$1' + u + 'т.' + u + 'д.' );
  txt = txt.replace( new RegExp( "(\\[\\[:?)(" + En_NS_List[i] + "|" +
r( /(И|и)\sт\.\s?п\./g, '$1' + u + 'т.' + u + 'п.' );
  Loc_NS_List[i] + "):( *)" , "gi" ), "$1" + Loc_NS_List[i] + ":");
r( /(Т|т)\.\s?н\./g, '$1.' + u + 'н.' );
r( /(И|и)\.\s?о\./g, '$1.' + u + 'о.' );
r( /н\.\s?э(\.|(?=\s))/g, 'н.' + u + 'э.' );
r( /(Д|д)(о|\.)\sн\.\s?э\./g, '$1о' + u + 'н.' + u + 'э.' );
r( /(\d)[\u00A0 ]?(млн|млрд|трлн|(?:м|с|д|к)?м|[км]г)\.?(?=[,;.]| "?[а-яё\-])/g, '$1' + u + '$2' );
r( /(\d)[\u00A0 ](тыс)([^\.А-Яа-яЁё])/g, '$1' + u + '$2.$3' );
r( /ISBN:\s?(?=[\d\-]{8,17})/, 'ISBN ' );


  }
// Insert/delete spaces
}
r( /^([#*:]+)[ \t\f\v]*(?!\{\|)([^ \t\f\v*#:;])/gm, '$1 $2' ); // space after #*: unless before table
r( /(\S)[\u00A0 \t](-{1,3}|—)[\u00A0 \t](\S)/g, '$1' + u + '— $3' );
r( /([А-ЯЁ]\.) ?([А-ЯЁ]\.) ?([А-ЯЁ][а-яё])/g, '$1' + u + '$2' + u + '$3' );
r( /([А-ЯЁ]\.)([А-ЯЁ]\.)/g, '$1 $2' );
r( /([а-яё]"?\)?[\.\?!:])((?:\x01\d+\x02\|)?[A-ZА-ЯЁ])/g, '$1 $2' ); // word. word
r( /([)"a-zа-яё\]²³])\s*([,:])([\[("a-zа-яё])/g, '$1$2 $3' ); // word, word
r( /([)"a-zа-яё\]²³])\s([,;])\s([\[("a-zа-яё])/g, '$1$2 $3' );
r( /([^%\/\wА-Яа-яЁё]\d+?(?:[\.,]\d+?)?) ?([%‰])(?!-[А-Яа-яЁё])/g, '$1' + u + '$2' ); //5 %
r( /(\d) ([%‰])(?=-[А-Яа-яЁё])/g, '$1$2' ); //5%-й
r( /([№§])(\s*)(\d)/g, '$1' + u + '$3' );
// inside ()
r( /\( +/g, '(' );
r( / +\)/g, ')' );


//======================================
// Temperature
// Replace '<replaced_tag> ... </replaced_tag>' (<nowiki> <br/> </nowiki>)
r( /([\s\d=≈≠≤≥<>—("'|])([+±−\-]?\d+?(?:[.,]\d+?)?)(([ °\^*]| [°\^*])(C|F))(?=[\s"').,;!?|\x01])/gm, '$1$2' + u + '°$5' ); //'
// with 'opepening_char + tag's counter + closing_char' ('\x03'+1'+'\x04')
//======================================


function ReplaceTags(replaced_tag, op_char, cl_char )
// Dot → comma in numbers
r( /(\s\d+)\.(\d+[\u00A0 ]*[%‰°×])/gi, '$1,$2' );


// @replaced_tag - tag to be replaced
// Plugins
// @op_char, @cl_char (opening & closing chars) - "Safe" pair of
for ( i in window.wfPlugins ) {
// unicode unprintable characters, that will be used in replacement
if ( window.wfPlugins.hasOwnProperty( i ) ) {
window.wfPlugins[i]( txt, r );
}
}


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


var counter = 0; //tags counter
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());
}
txt = txt.substr( 1, txt.length - 2 );
}


// RegExp pattern
function processAllText() {
var pattern = "\\<" + replaced_tag + "\\>(.|\r|\n)+?\<\\/" + replaced_tag + "\\>";
txt = wpTextbox1.value;
processText();
r( /^[\n\r]+/, '' );
wpTextbox1.value = txt;
txt = '';
if ( window.auto_comment &&
window.insertSummary &&
!document.editform.wpSection.value
) {
window.insertSummary( 'викификатор' );
}
}


// RegExp template to be replaced (multiline text between
// <replaced_tag> and </replaced_tag> case sensitive tags)
var replaced_regexp = new RegExp(pattern , "im")


// Buffer for replaced matches storage. It's array of matching substrings -
// Check regexp support
// multiline text between <replaced_tag> and </replaced_tag> case sensitive tags ()
try {
matches_buffer = txt.match( new RegExp(pattern , "gim") );
txt = 'ая'.replace( /а/g, 'б' ).replace( /б(?=я)/, 'в' );
} catch ( e ) {}
if ( txt !== 'вя' ) {
alert( wmCantWork );
return;
}


// while some substring of txt matches replaced_regexp...
wpTextbox1.focus();
while (replaced_regexp.test(txt))
  {
  txt = txt.replace(replaced_regexp, op_char + ++counter + cl_char );
  }
return matches_buffer;
}


//======================================
// Modern browsers
// Replace '<replaced_tag> ... </replaced_tag>' (<nowiki> <br/> </nowiki>)
if ( typeof wpTextbox1.selectionStart !== 'undefined' ) {
// with 'opepening_char + tag's counter + closing_char' ('\x03'+1'+'\x04')
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;


function ReplaceElements( req_exp, op_char, cl_char )
// 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();
}


// @req_exp - reqular expression to be replaced
// Other browsers
// @op_char, @cl_char (opening & closing chars) - "Safe" pair of
} else if ( confirm( wmFullText ) ) {
// unicode unprintable characters, that will be used in replacement
processAllText();
 
}
{
 
var counter = 0; //tags counter
 
// RegExp template to be replaced (multiline, case sensitive)
var replaced_regexp = new RegExp( req_exp , "m" )
 
// Buffer for replaced matches storage. It's array of matching substrings.
// (multiline, case sensitive, global)
matches_buffer = txt.match( new RegExp( req_exp , "gm" ) );


// while some substring of txt matches replaced_regexp...
document.documentElement.scrollTop = winScroll; // scroll back, for IE/Opera
while (replaced_regexp.test(txt))
  {
  //alert(txt.match(replaced_regexp));
  txt = txt.replace(replaced_regexp, op_char + ++counter + cl_char );
  }
return matches_buffer;
}
}


//======================================
// Restore text, that was damaged by replacing 3 chars with substring from array
//======================================


function RestoreElements( replaced_buffer, op_char, cl_char )
// Toolbar buttons


// @replaced_buffer - array of replaced substrings.
var addOldToolbarButton = function() {
// @op_char, @cl_char (opening & closing chars) - "Safe" pair
var $toolbar = $( '#gadget-toolbar' );
// to be replaced with <replaced_tag> and </replaced_tag> accordingly
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 addNewToolbarButton = function() {
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'main',
'group': 'gadgets',
'tools': {
'wikif': {
label: 'Викификатор — автоматический обработчик текста',
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/0/06/Wikify-toolbutton.png',
action: {
type: 'callback',
execute: function() {
Wikify();
}
}
}
}
} );
};


var counter = 0; //tags counter
if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
 
mw.loader.using( [ 'user.options', 'jquery.textSelection' ], function () {
// RegExp template to be replaced (3 chars: tag's counter
if ( mw.user.options.get( 'usebetatoolbar' ) === 1 ) {
// surrunded by "Safe" pair)
if ( mw.user.options.get( 'showtoolbar' ) === 1 ) {
var replaced_regexp = new RegExp("\\" +op_char+ "([0-9]*)\\" +cl_char );
$.when(
 
mw.loader.using( 'ext.wikiEditor.toolbar' ),
//replaced_regexp = /\x03([0-9]*)\x04/
$.ready
 
).then( addNewToolbarButton );
// while some substring of txt matches replaced_regexp...
}
while (replaced_regexp.test(txt))
} else {
{
mw.loader.using( 'mediawiki.toolbar', function() {
  txt = txt.replace(replaced_regexp, replaced_buffer[counter++]);
$( addOldToolbarButton );
}
});
return txt;
}
}
} );
 
// Corrects year and century ranges (as links) in text
function CorrectRanges() {
// Correct year ranges
txt = txt.replace(/(?!ISBN)(\(|\s)(\[\[[12]?\d{3}\]\])[\u00A0 ]?(-|--|–|—) ?(\[\[[12]?\d{3}\]\])(\W)/g, "$1$2—$4$5")
txt = txt.replace(/(\[\[[12]?\d{3}\]\]) ?(г\.|гг\.)/g, "$1\u00A0$2")
// Correct century ranges
txt = txt.replace(/(\(|\s)(\[\[[IVX]{1,5}\]\])[\u00A0 ]?(-|--|–|—) ?(\[\[[IVX]{1,5}\]\])(\W)/g, "$1$2—$4$5")
txt = txt.replace(/(\[\[[IVX]{1,5}\]\]) ?(в\.|вв\.)/g, "$1\u00A0$2")
}
 
/***************************************************
Typographical considerations
***************************************************/
function ProcessTypography() {
 
// Insert spaces in titles
txt = txt.replace(/^(=+)([ \t\f\v]*)(.*?)([ \t\f\v]*)(=+)$/gm, "$1 $3 $1")
//======================================
// Use 1 character to display squaring and cubing
txt = txt.replace(/(<sup>2<\/sup>|&sup2;)/g, "²");
txt = txt.replace(/(<sup>3<\/sup>|&sup3;)/g, "³");
txt = txt.replace(/(\^2)(\D)/g, "²$2");
txt = txt.replace(/(\^3)(\D)/g, "³$2");
//======================================
// Replace right HTML symbols with wrong ones in order to process everything
txt = txt.replace(/–/g, "-")
txt = txt.replace(/(«|»|“|”|„|\&((la|ra|bd|ld)quo|#132|#147|#148|quot);)/g, "\"")
//======================================
// Replace double hyphen with a dash
txt = txt.replace(/(--)(\[\[Участник|\~\~\~)/g, "—$2")
//======================================
// Replace set of 'less then' or 'greater then' symbols (<< or >>) with usual double quotes
txt = txt.replace(/(<<)(\S.+\S)(>>)/g, "\"$2\"")
//======================================
// Process degree sign "°", "+-" and "~="
txt = txt.replace(/(\+[--])|(&plusmn;)/g, "±")
txt = txt.replace(/(~=)/g, "≈")
txt = txt.replace(/\&deg;/g, "°")
txt = txt.replace(/([ =≈≠≤≥<>("'|]|^)([+±−\-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])[CС])(?=[ "').,;!?|]|$)/gm, "$1$2\u00A0°C")
txt = txt.replace(/([ =≈≠≤≥<>("'|]|^)([+±−\-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])F)(?=[ "').,;|!?]|$)/gm, "$1$2\u00A0°F")
//======================================
// Replace "...", "&hellip;" and "&#133;" with ellipsis
txt = txt.replace(/(\.{3}|\&(hellip|#133);)/g, '')
// Apostrophe handler
txt = txt.replace(/([\wа-яА-ЯёЁ])'([\wа-яА-ЯёЁ])/g, "$1’$2")
// Minus handler
txt = txt.replace(/(sup\>|sub\>|\s)-(\d)/g, "$1−$2")
//======================================
// Replace hyphens and en dashes with normal dashes
txt = txt.replace(/\&(#151|[nm]dash);/g, "—")
txt = txt.replace(/(&nbsp;|[\f\n\r\t\v\u00A0\u2028\u2029])(-|--|–) /g, "$1— ")
txt = txt.replace(/(\d)--(\d)/g, "$1—$2")
// Insert non-breaking space before dashes
txt = txt.replace(/(\S) (-|--|–|—) (\S)/g, "$1\u00A0— $3")
//======================================
// Special characters: ©, ®, ™, §, €, ¥ и £.
txt = txt.replace(/\&copy;/gi, "©")
txt = txt.replace(/\&reg;/gi, "®")
txt = txt.replace(/(\((tm|тм)\)|\&trade;)/gi, "™")
txt = txt.replace(/\&sect;/gi, "§")
txt = txt.replace (/\&euro;/gi, "€")
txt = txt.replace (/\&yen;/gi, "¥")
txt = txt.replace (/\&pound;/gi, "£")
//======================================
// Correct year ranges
txt = txt.replace(/(\(|\s)([12]?\d{3})[\u00A0 ]?(-|--|–|—) ?([12]?\d{3})(\W)/g, "$1$2—$4$5")
txt = txt.replace(/([12]?\d{3}) ?(г\.|гг\.)/g, "$1\u00A0$2")
// Correct century ranges
txt = txt.replace(/(\(|\s)([IVX]{1,5})[\u00A0 ]?(-|--|–|—) ?([IVX]{1,5})(\W)/g, "$1$2—$4$5")
txt = txt.replace(/([IVX]{1,5}) ?(в\.|вв\.)/g, "$1\u00A0$2")
// Correct the reductions
txt = txt.replace(/(Т|т)\. ?е\./g, "$1о есть")
txt = txt.replace(/(Т|т)\. ?к\./g, "$1ак как")
txt = txt.replace(/(В|в) т\. ?ч\./g, "$1 том числе")
txt = txt.replace(/и т\. ?д\./g, "и\u00A0т\.\u00A0д\.")
txt = txt.replace(/и т\. ?п\./g, "и\u00A0т\.\u00A0п\.")
txt = txt.replace(/(Т|т)\. ?н\./g, "$1\.\u00A0н\.")
txt = txt.replace(/н\. ?э\./g, "н\.\u00A0э\.")
txt = txt.replace(/(Д|д)(о|\.) н\. ?э\./g, "$1о\u00A0н\.\u00A0э\.")
txt = txt.replace(/(\d) ?(млн|млрд|трлн|(?:м|с|д|к)?м|[км]?г|с)\.?( ([^\.А-ЯЁ])|[,;.])(?!\[.*?\|[А-Я].*?\])/g, "$1\u00A0$2$3")
txt = txt.replace(/(\d) (тыс)([^\.А-Яа-яЁё])/g, "$1\u00A0$2.$3")
 
//txt = txt.replace(/(\d) (млн|млрд|трлн)([^А-Яа-яЁё])/g, "$1\u00A0$2$3")
// Insert missing and delete unnecessary spaces
txt = txt.replace(/([А-Я]\.) ?([А-Я]\.) ?([А-Я][а-я])/g, "$1\u00A0$2\u00A0$3")
txt = txt.replace(/([А-Я]\.)([А-Я]\.)/g, "$1 $2")
txt = txt.replace(/^([#\*:]+)([ \t\f\v]*)([^ \t\f\v\*#:])/gm, "$1 $3")
txt = txt.replace(/([а-я])(\.)([А-ЯA-Z])/g, "$1$2 $3")
txt = txt.replace(/([а-яa-z\)\»\“\"\]])(\s*)(\,)([а-яa-z\(\«\„\"\[])/g, "$1$3 $4")
txt = txt.replace(/([а-яa-z\)\»\“\"\]])(\s)([\,\;])(\s)([а-яa-z\(\«\„\"\[])/g, "$1$3 $5")
txt = txt.replace(/([^%\/\w]\d+?(?:[.,]\d+?)?) ?([%‰])(?!-[А-Яа-яЁё])/g, "$1\u00A0$2")
txt = txt.replace(/(\d) ([%‰])(?=-[А-Яа-яЁё])/g, "$1$2")
txt = txt.replace(/([№§])(\s*)(\d)/g, "$1\u00A0$3")
txt = txt.replace(/(^|[^ \t])([ \t]+)($|\n)/gm, "$1$3")
txt = txt.replace(/(\()( +)/g, "$1");
txt = txt.replace(/( +)(\))/g, "$2");
//======================================
// Avoid double spaces
txt = txt.substr (1, txt.length-1);
txt = txt.replace(/(\S)([ \t]{2,})([\S\r])/g, "$1 $3")
txt = " " + txt
//======================================
// Replace double quotes ("")  with double angle quotes («»)
txt = txt.replace(/([\x01-(\s\|\"]|\/|\+)(\")([^\"]{0,})([^\s\"(\|])(\")/g, "$1«\$3\$4»")
// Quotations in quotes
if (/"/.test(txt))
{
  txt = txt.replace(/([\x01(\s\"])(\")([^\"]{0,})([^\s\"(\|])(\")/g, "\$1«\$3\$4»")
  while (/(«)([^»]*)(«)/.test(txt))
    txt = txt.replace(/(«)([^»]*)(«)([^»]*)(»)/g, "\$1\$2„\$4“")
}
}
}
/* </pre> */

Версия от 18:09, 21 декабря 2015

var wmCantWork = 'Викификатор не может работать в вашем браузере',
	wmFullText = 'Викификатор обработает ВЕСЬ текст на этой странице. Продолжить?',
	wmTalkPage = 'Викификатор не обрабатывает страницы обсуждения целиком.\n\nВыделите ваше сообщение — обработано будет только оно';
window.wfPlugins = window.wfPlugins || [];


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


	// FUNCTIONS

	function r( r1, r2 ) {
		txt = txt.replace( r1, r2 );
	}

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

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

	function hideTemplates() {
		var pos = 0,
			stack = [],
			tpl,
			left,
			right;
		while ( true ) {
			left = txt.indexOf( '{{', pos );
			right = txt.indexOf( '}}', pos );
			if ( left === -1 && right === -1 && !stack.length ) {
				break;
			}
			if ( left !== -1 && ( left < right || right === -1 ) ) {
				stack.push( left );
				pos = left + 2;
			} else {
				left = stack.pop();
				if ( typeof left === 'undefined' ) {
					if ( right === -1 ) {
						pos += 2;
						continue;
					} else {
						left = 0;
					}
				}
				if ( right === -1 ) {
					right = txt.length;
				}
				right += 2;
				tpl = txt.substring( left, right );
				txt = txt.substring( 0, left ) +
					'\x01' + hidden.push( tpl ) + '\x02' +
					txt.substr( right );
				pos = right - tpl.length;
			}
		}
	}

	function processText() {
		var i,
			u = '\u00A0'; // unbreakable space
		if ( mw.config.get('wgNamespaceNumber') % 2 || mw.config.get('wgNamespaceNumber') === 4 ) { // is talk page
			u = ' ';
			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;
			}
		}

		hideTag( 'nowiki' );
		hideTag( 'pre' );
		hideTag( 'source' );
		hideTag( 'syntaxhighlight' );
		hideTag( 'templatedata' );

		hideTag( 'code' );
		hideTag( 'tt' );

		hideTag( 'graph' );
		hideTag( 'hiero' );
		hideTag( 'math' );
		hideTag( 'timeline' );

		r( /( |\n|\r)+\{\{(·|•|\*)\}\}/g, '{{$2}}' ); // before {{·/•/*}}, usually in templates
		r( /\{\{\s*[Шш]аблон:([\s\S]+?)\}\}/g, '{{$1}}' );
		r( /(\{\{\s*)reflist(\s*[\|\}])/ig, '$1примечания$2' );

		hideTemplates();
		hide( /^[ \t].*/mg );
		hide( /(https?|ftp|news|nntp|telnet|irc|gopher):\/\/[^\s\[\]<>"]+ ?/gi );
		hide( /^#(redirect|перенапр(авление)?)/i );
		hideTag( 'gallery' );


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


		// LINKS
		r( /(\[\[:?)(category|категория):( *)/ig, '$1Категория:' );
		r( /(\[\[:?)(module|модуль):( *)/ig, '$1Модуль:' );
		r( /(\[\[:?)(template|шаблон):( *)/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' + u + '$2' );
		r( /(\(|\s)(\[\[[IVX]{1,5}\]\])[\u00A0 ]?(-{1,3}|–|—) ?(\[\[[IVX]{1,5}\]\])(\W)/g, '$1$2—$4$5' );
		r( /(\[\[[IVX]{1,5}\]\]) ?(вв?\.)/g, '$1' + u + '$2' );
		r( /\[\[(\d+)\]\]\sгод/g, '[[$1' + u + 'год]]' );
		r( /\[\[(\d+)\sгод\|\1\]\]\sгод/g, '[[$1' + u + 'год]]' );
		r( /\[\[(\d+)\sгод\|\1\sгод([а-я]{0,3})\]\]/g, '[[$1' + u + 'год]]$2' );
		r( /\[\[((\d+)(?: (?:год )?в [\wa-яёА-ЯЁ ]+\|\2)?)\]\][\u00A0 ](год[а-яё]*)/g, '[[$1' + u + '$3]]' );
		r( /\[\[([XVI]+)\]\]\sвек/g, '[[$1' + u + 'век]]' );
		r( /\[\[([XVI]+)\sвек\|\1\]\]\sвек/g, '[[$1' + u + 'век]]' );
		r( /\[\[([XVI]+)\sвек\|\1\sвек([а-я]{0,3})\]\]/g, '[[$1' + u + 'век]]$2' );
		r( /\[\[(([XVI]+) век\|\2)\]\][\u00A0 ]век/g, '[[$2' + u + 'век]]' );
		// Nice links
		r( /(\[\[[^|\[\]]*)[\u00AD\u200E\u200F]+([^\[\]]*\]\])/g, '$1$2' ); // Soft Hyphen & DirMark
		r( /\[\[ *([^|\[\]]+) *\| *(\1)([a-zа-яё]*) *\]\]/g, '[[$2]]$3' );
		r( /\[\[ *([^|\[\]]+)([^|\[\]()]+) *\| *\1 *\]\]\2/g, '[[$1$2]]' ); // text repetition after link
		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( /(su[pb]>)-(\d)/g, '$1−$2' ); // ->minus
		r( /<(b|strong)>(.*?)<\/(b|strong)>/gi, "'''$2'''" );
		r( /<(i|em)>(.*?)<\/(i|em)>/gi, "''$2''" );
		r( /^<hr ?\/?>/gim, '----' );
		r( /<[\/\\]?(hr|br)( [^\/\\>]+?)? ?[\/\\]?>/gi, '<$1$2 />' );
		r( /[\u00A0 \t]*<ref(?:\s+name="")?(\s|>)/gi, '<ref$1' );
		r( /(\n== *[a-zа-я\s\.:]+ *==\n+)<references *\/>/ig, '$1{' + '{примечания}}' );
		hide( /<[a-z][^>]*?>/gi);

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

		r( /[ \t\u00A0]+/g, ' ' ); // double spaces

		// Entities etc. → Unicode chars
		if ( mw.config.get('wgNamespaceNumber') !== 10 ) {
			r( /&(#x[0-9a-f]{2,4}|#[0-9]{3,4}|[0-9a-z]{2,8});/gi, function ( s ) {
				var t = document.createElement( 'textarea' );
				t.innerHTML = s;
				var c = t.value;
				if ( c.length === 1 && c.charCodeAt( 0 ) > 127 ) {
					return c;
				}
				return s;
			});
		}
		r( /\(tm\)/gi, '™' );
		r( /\.\.\./g, '…' );
		r( /(^|[^+])\+-(?!\+|-)/g, '$1±' );
		r( /~=/g, '≈' );
		r( /\^2(\D)/g, '²$1' );
		r( /\^3(\D)/g, '³$1' );
		r( /(\s)кв\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1' + u + '$2²$3' );
		r( /(\s)куб\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1' + u + '$2³$3' );
		r( /((?:^|[\s"])\d+(?:[\.,]\d+)?)\s*[xх]\s*(\d+(?:[\.,]\d+)?)\s*([мm]{1,2}(?:[\s"\.,;?!]|$))/g, '$1×$2' + u + '$3' );
		r( /([\wа-яА-ЯёЁ])'([\wа-яА-ЯёЁ])/g, '$1’$2' ); //'
		r( /№№/g, '№' );

		// 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( /^== сноски ==$/gmi, '== Примечания ==' );
		r( /^== внешние\sссылки ==$/gmi, '== Ссылки ==' );
		r( /^== (.+)[.:] ==$/gm, '== $1 ==' );
		r( /^== '''(?!.*'''.*''')(.+)''' ==$/gm, '== $1 ==' );

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

		// Hyphens and en dashes to pretty dashes
		r( /–/g, '-' ); // &ndash; -> hyphen
		r( /(\s)-{1,3} /g, '$1— ' ); // hyphen -> &mdash;
		r( /(\d)--(\d)/g, '$1—$2' ); // -> &mdash;
		r( /(\s)-(\d)/g, '$1−$2' ); // hyphen -> minus

		// Year and century ranges
		r( /(\(|\s)([12]?\d{3})[\u00A0 ]?(-{1,3}|—) ?([12]?\d{3})(?![\wА-ЯЁа-яё]|-[^ех]|-[ех][\wА-ЯЁа-яё])/g, '$1$2—$4' );
		r( /([12]?\d{3}) ?(гг?\.)/g, '$1' + u + '$2' );
		r( /(\(|\s)([IVX]{1,5})[\u00A0 ]?(-{1,3}|—) ?([IVX]{1,5})(?![\w\-])/g, '$1$2—$4' );
		r( /([IVX]{1,5}) ?(вв?\.)/g, '$1' + u + '$2' );

		// Reductions
		r( /(Т|т)\.\s?е\./g, '$1о есть' );
		r( /(Т|т)\.\s?к\./g, '$1ак как' );
		r( /(В|в)\sт\. ?ч\./g, '$1 том числе' );
		r( /(И|и)\sт\.\s?д\./g, '$1' + u + 'т.' + u + 'д.' );
		r( /(И|и)\sт\.\s?п\./g, '$1' + u + 'т.' + u + 'п.' );
		r( /(Т|т)\.\s?н\./g, '$1.' + u + 'н.' );
		r( /(И|и)\.\s?о\./g, '$1.' + u + 'о.' );
		r( /н\.\s?э(\.|(?=\s))/g, 'н.' + u + 'э.' );
		r( /(Д|д)(о|\.)\sн\.\s?э\./g, '$1о' + u + 'н.' + u + 'э.' );
		r( /(\d)[\u00A0 ]?(млн|млрд|трлн|(?:м|с|д|к)?м|[км]г)\.?(?=[,;.]| "?[а-яё\-])/g, '$1' + u + '$2' );
		r( /(\d)[\u00A0 ](тыс)([^\.А-Яа-яЁё])/g, '$1' + u + '$2.$3' );
		r( /ISBN:\s?(?=[\d\-]{8,17})/, 'ISBN ' );

		// Insert/delete spaces
		r( /^([#*:]+)[ \t\f\v]*(?!\{\|)([^ \t\f\v*#:;])/gm, '$1 $2' ); // space after #*: unless before table
		r( /(\S)[\u00A0 \t](-{1,3}|—)[\u00A0 \t](\S)/g, '$1' + u + '— $3' );
		r( /([А-ЯЁ]\.) ?([А-ЯЁ]\.) ?([А-ЯЁ][а-яё])/g, '$1' + u + '$2' + u + '$3' );
		r( /([А-ЯЁ]\.)([А-ЯЁ]\.)/g, '$1 $2' );
		r( /([а-яё]"?\)?[\.\?!:])((?:\x01\d+\x02\|)?[A-ZА-ЯЁ])/g, '$1 $2' ); // word. word
		r( /([)"a-zа-яё\]²³])\s*([,:])([\[("a-zа-яё])/g, '$1$2 $3' ); // word, word
		r( /([)"a-zа-яё\]²³])\s([,;])\s([\[("a-zа-яё])/g, '$1$2 $3' );
		r( /([^%\/\wА-Яа-яЁё]\d+?(?:[\.,]\d+?)?) ?([%‰])(?!-[А-Яа-яЁё])/g, '$1' + u + '$2' ); //5 %
		r( /(\d) ([%‰])(?=-[А-Яа-яЁё])/g, '$1$2' ); //5%-й
		r( /([№§])(\s*)(\d)/g, '$1' + u + '$3' );
		// inside ()
		r( /\( +/g, '(' );
		r( / +\)/g, ')' );

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

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

		// Plugins
		for ( i in window.wfPlugins ) {
			if ( window.wfPlugins.hasOwnProperty( i ) ) {
				window.wfPlugins[i]( txt, r );
			}
		}

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

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


	// 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 addNewToolbarButton = function() {
	$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
		'section': 'main',
		'group': 'gadgets',
		'tools': {
			'wikif': {
				label: 'Викификатор — автоматический обработчик текста',
				type: 'button',
				icon: '//upload.wikimedia.org/wikipedia/commons/0/06/Wikify-toolbutton.png',
				action: {
					type: 'callback',
					execute: function() {
						Wikify();
					}
				}
			}
		}
	} );
};

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.toolbar' ),
					$.ready
				).then( addNewToolbarButton );
			}
		} else {
			mw.loader.using( 'mediawiki.toolbar', function() {
				$( addOldToolbarButton );
			});
		}
	} );
}