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

Материал из Ролевая энциклопедии
Перейти к: навигация, поиск
(начало установки)
 
(обновление?)
 
(не показано 5 промежуточных версий 2 участников)
Строка 1: Строка 1:
// Копия [[Wikipedia:ru:MediaWiki:Wikificator.js]] согласно [[Wikipedia:ru:ВП:ВФ-ИУ]].
+
var wmCantWork = 'Викификатор не может работать в вашем браузере',
 +
  wmFullText = 'Викификатор обработает ВЕСЬ текст на этой странице. Продолжить?',
 +
  wmTalkPage = 'Викификатор не обрабатывает страницы обсуждения целиком.\n\nВыделите ваше сообщение — обработано будет только оно';
 +
window.wfPlugins = window.wfPlugins || [];
  
/* <pre> */
+
function Wikify() {
 +
  'use strict';
 +
  var txt = '',
 +
    hidden = [],
 +
    wpTextbox1 = document.editform.wpTextbox1,
 +
    winScroll = document.documentElement.scrollTop;
  
var txt;
 
 
var wmFullText = 'Wikificator will process ALL text on this page. Continue?';
 
var wmCantWork = 'Wikificator cannot work in your browser';
 
var wmWontWork = 'Wikificator will not work in Netscape 4.x and less';
 
  
 +
  // FUNCTIONS
  
var wmCategoryNS = 'Категория';
+
  function r(r1, r2) {
var wmTemplateNS = 'Шаблон';
+
    txt = txt.replace(r1, r2);
var wmUserNS = 'Участник';
+
  }
var wmImageNS = 'Изображение';
 
var wmMediaNS = 'Медиа';
 
  
var wmLocaleNS = new Array ( wmCategoryNS, wmTemplateNS, wmUserNS, wmImageNS, wmMediaNS );
+
  function hide(re) {
var wmEnNS = new Array ( 'category', 'template', 'user', 'image', 'media');
+
    r(re, function (s) {
 +
      return '\x01' + hidden.push(s) + '\x02';
 +
    });
 +
  }
  
 +
  function hideTag(tag) {
 +
    hide(new RegExp('<' + tag + '( [^>]+)?>[\\s\\S]+?<\\/' + tag + '>', 'gi'));
 +
  }
  
if (window.event){
+
  function hideTemplates() {
  document.onkeypress = pressed;
+
    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 pressed() //On Ctrl+Enter (MSIE)
+
  function processText() {
{key = window.event.keyCode;if (key==10){Wikify();}}
+
    var i,
//======================================
+
      u = '\u00A0'; // unbreakable space
function Wikify()
+
    if (window.wgNamespaceNumber % 2 || window.wgNamespaceNumber === 4) { // is talk page
{
+
      u = ' ';
check_regexp(); // Check whether regular expressions are supported
+
      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;
 +
      }
 +
    }
  
// Только если пользователь указал в персональном скрипте auto_comment = 1;
+
    hideTag('nowiki');
 +
    hideTag('pre');
 +
    hideTag('source');
 +
    hideTag('syntaxhighlight');
 +
    hideTag('code');
 +
    hideTag('tt');
 +
    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');
  
if (auto_comment == 1) {
+
    hideTemplates();
  var wpS = document.editform.wpSummary;
+
    hide(/^ .*/mg);
  if (wpS.value != '' && wpS.value.charAt(wpS.value.length-2) != '/') {
+
    hide(/(https?|ftp|news|nntp|telnet|irc|gopher):\/\/[^\s\[\]<>"]+ ?/gi);
    wpS.value += ', Викификатор'
+
    hide(/^#(redirect|перенапр(авление)?)/i);
  } else {
+
    hideTag('gallery');
    wpS.value += 'Викификатор'
 
  }
 
}
 
  
document.editform.wpTextbox1.focus();
 
var txtarea = document.editform.wpTextbox1;
 
if(document.selection  && !is_gecko)/* IE */ {
 
txt = " "+document.selection.createRange().text;
 
if (txt == " ") {all_text();} // If nothing was selected;
 
else{
 
Process();
 
txt = txt.substr (1, txt.length-1);
 
document.selection.createRange().text = txt;
 
}
 
}
 
else if((txtarea.selectionStart || txtarea.selectionStart == '0')&&(navigator.productSub>20031000)) /*Gecko-browsers older then 10.2003*/  {
 
var startPos = txtarea.selectionStart;
 
var endPos = txtarea.selectionEnd;
 
var scrollTop=txtarea.scrollTop;
 
txt = " "+(txtarea.value).substring(startPos, endPos);
 
if (txt == " ") {all_text();} // If nothing was selected;
 
else{
 
Process();
 
txt = txt.substr (1, txt.length-1);
 
txtarea.value = txtarea.value.substring(0, startPos) + txt + txtarea.value.substring(endPos, txtarea.value.length);
 
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" );
 
var pre = ReplaceTags( 'pre', "\x12", "\x13" );
 
var code = ReplaceTags( 'code', "\x1c", "\x1d" );
 
var math = ReplaceTags( 'math', "\x05", "\x06" );
 
var gallery = ReplaceTags( 'gallery', "\x14", "\x15" );
 
  
// Exclude lines starting with space
+
    r(/ +(\n|\r)/g, '$1'); // spaces at EOL
f_space = txt.substr (0, 1)
+
    txt = '\n' + txt + '\n';
txt = txt.substr (1, txt.length-1)
 
var sp_lines = ReplaceElements( "^( )(.+)$", "\x16", "\x17" );
 
txt = f_space + txt
 
  
ProcessNS( wmEnNS , wmLocaleNS );
 
CorrectRanges();
 
  
// Exclude templates and internal links
+
    // LINKS
var templates = ReplaceElements( "\\{\\{(.|\\r|\\n)+?\\}\\}", "\x18", "\x19" );
+
    r(/(\[\[:?)(category|категория):( *)/ig, '$1Категория:');
var links = ReplaceElements( "(\\[\\[)(.*?)(\\||\\]\\])", "\x10", "\x11" );
+
    r(/(\[\[:?)(image|изображение|file):( *)/ig, '$1Файл:');
var ext_links = ReplaceElements( "\\[(http|https|ftp|tftp|news|nntp|telnet|irc|gopher)://(.*?)\\]", "\x1A", "\x1B");
+
    // 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
  
HTML2Wiki();
 
  
// Exclude tags and tag attributes (all text in quotes after "=" sign)
+
    // TAGS
var attrs = ReplaceElements( '(=)(\\s?)(\\' + '")(.*?)(\\")', "\x0E", "\x0F");
+
    r(/<<(\S.+\S)>>/g, '"$1"'); // << >>
var tags = ReplaceElements( "<([^>]*?)>", "\x01", "\x02");
+
    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);
  
ProcessTypography();
+
    hide(/^(\{\||\|\-).*/mg); // table/row def
ProcessTypography(); // Second call
+
    hide(/(^\||^!|!!|\|\|) *[a-z]+=[^|]+\|(?!\|)/mgi); // cell style
 +
    hide(/\| +/g); // formatted cell
  
//alert(txt);
+
    r(/[ \t\u00A0]+/g, ' '); // double spaces
  
RestoreElements( tags, "\x01", "\x02");
+
    // Entities etc. → Unicode chars
RestoreElements( attrs, "\x0E", "\x0F");
+
    if (window.wgNamespaceNumber !== 10) {
RestoreElements( ext_links, "\x1A", "\x1B" );
+
      r(/&(#x[0-9a-f]{2,4}|#[0-9]{3,4}|[0-9a-z]{2,8});/gi, function (s) {
RestoreElements( links, "\x10", "\x11" );
+
        var t = document.createElement('textarea');
RestoreElements( templates, "\x18", "\x19" );
+
        t.innerHTML = s;
RestoreElements( sp_lines, "\x16", "\x17" );
+
        var c = t.value;
RestoreElements( gallery, "\x14", "\x15" );
+
        if (c.length === 1 && c.charCodeAt(0) > 127) {
RestoreElements( math, "\x05", "\x06" );
+
          return c;
RestoreElements( code, "\x1c", "\x1d" );
+
        }
RestoreElements( pre, "\x12", "\x13" );
+
        return s;
RestoreElements( nowiki, "\x03", "\x04" );
+
      });
 +
    }
 +
    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 ==');
  
function HTML2Wiki()
+
    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
  
// Replace <b>, <strong> tags with ''' and <i>, <em> with ''
+
    // Year and century ranges
txt = txt.replace(/\<\/?(b|strong)\>/gim, "\'\'\'")
+
    r(/(\(|\s)([12]?\d{3})[\u00A0 ]?(-{1,3}|—) ?([12]?\d{3})(?![\wА-ЯЁа-яё]|-[^ех]|-[ех][\wА-ЯЁа-яё])/g, '$1$2—$4');
txt = txt.replace(/\<\/?(i|em)\>/gim, "\'\'")
+
    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');
  
// Replace <hr> tag with ----, improve <hr> and <br> tags
+
    // Reductions
txt = txt.replace(/\<hr ?\/?\>/gi, "----")
+
    r(/(Т|т)\.\s?е\./g, '$1о есть');
txt = txt.replace(/\<hr ([^\>\/]+?) ?\/?\>/gi, "<hr $1 />")
+
    r(/(Т|т)\.\s?к\./g, '$1ак как');
txt = txt.replace(/\<br\/?\>/gi, "<br />")
+
    r(/(В|в)\sт\. ?ч\./g, '$1 том числе');
txt = txt.replace(/\<br ([^\>\/]+?) ?\/?\>/gi, "<br $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 ');
  
// Replace small and big tags with inline styling
+
    // 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, ')');
  
/// txt = txt.replace(/(\<small\>)/g, "<span style=\"font-size\:smaller\;\">");
+
    // Temperature
/// txt = txt.replace(/(\<\/small\>)/g, "<\/span>");
+
    r(/([\s\d=≈≠≤≥<>—("'|])([+±−\-]?\d+?(?:[.,]\d+?)?)(([ °\^*]| [°\^*])(C|F))(?=[\s"').,;!?|\x01])/gm, '$1$2' + u + '°$5'); //'
/// txt = txt.replace(/(\<big\>)/g, "<span style=\"font-size\:1.25em\;\">");
 
/// txt = txt.replace(/(\<\/big\>)/g, "<\/span>");
 
  
}
+
    // Dot → comma in numbers
 +
    r(/(\s\d+)\.(\d+[\u00A0 ]*[%‰°×])/gi, '$1,$2');
  
// Process default namespaces
+
    // Plugins
 +
    for (i in window.wfPlugins) {
 +
      if (window.wfPlugins.hasOwnProperty(i)) {
 +
        window.wfPlugins[i](txt, r);
 +
      }
 +
    }
  
function ProcessNS( En_NS_List , Loc_NS_List )
+
    // "" → «»
{
+
    for (i = 1; i <= 2; i++) {
 +
      r(/([\s\x02!|#'"\/(;+\-])"([^"]*)([^\s"(|])"([^a-zа-яё])/ig, '$1«$2$3»$4'); //"
 +
    }
 +
    while (/«[^»]*«/.test(txt)) {
 +
      r(/«([^»]*)«([^»]*)»/g, '«$1„$2“');
 +
    }
  
for (i=0; i < En_NS_List.length; i++)
+
    if ('0'.replace('0', '$$') === '$') { ////$ in replacing string is special, except in IE
  {
+
      for (i = 0; i < hidden.length; i++) {
  //alert("(\\[\\[)(:?)(" + En_NS_List[i] + "|" +
+
        hidden[i] = hidden[i].replace(/\$/g, '$$$$');
  //Loc_NS_List[i] + ")(:)( *)");
+
      }
 
+
    }
  txt = txt.replace( new RegExp( "(\\[\\[:?)(" + En_NS_List[i] + "|" +
+
    while (hidden.length > 0) {
   Loc_NS_List[i] + "):( *)" , "gi" ), "$1" + Loc_NS_List[i] + ":");
+
      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('викификатор');
 +
    }
 
   }
 
   }
}
 
  
//======================================
 
// Replace '<replaced_tag> ... </replaced_tag>' (<nowiki> <br/> </nowiki>)
 
// with 'opepening_char + tag's counter + closing_char' ('\x03'+1'+'\x04')
 
//======================================
 
  
function ReplaceTags(replaced_tag, op_char, cl_char )
+
  // Check regexp support
 +
  try {
 +
    txt = 'ая'.replace(/а/g, 'б').replace(/б(?=я)/, 'в');
 +
  }
 +
  catch (e) {}
 +
  if (txt !== 'вя') {
 +
    alert(wmCantWork);
 +
    return;
 +
  }
  
// @replaced_tag - tag to be replaced
+
  wpTextbox1.focus();
// @op_char, @cl_char (opening & closing chars) - "Safe" pair of
 
// unicode unprintable characters, that will be used in replacement
 
  
{
+
  // Modern browsers
 
+
  if (typeof wpTextbox1.selectionStart !== 'undefined') {
var counter = 0; //tags counter
+
    var textScroll = wpTextbox1.scrollTop,
 
+
      startPos = wpTextbox1.selectionStart,
// RegExp pattern
+
      endPos = wpTextbox1.selectionEnd;
var pattern = "\\<" + replaced_tag + "\\>(.|\r|\n)+?\<\\/" + replaced_tag + "\\>";
+
    txt = wpTextbox1.value.substring(startPos, endPos);
 
+
    if (txt === '') {
// RegExp template to be replaced (multiline text between
+
      processAllText();
// <replaced_tag> and </replaced_tag> case sensitive tags)
+
    }
var replaced_regexp = new RegExp(pattern , "im")
+
    else {
 
+
      processText();
// Buffer for replaced matches storage. It's array of matching substrings -
+
      wpTextbox1.value = wpTextbox1.value.substring(0, startPos) + txt + wpTextbox1.value.substring(endPos);
// multiline text between <replaced_tag> and </replaced_tag> case sensitive tags ()
+
    }
matches_buffer = txt.match( new RegExp(pattern , "gim") );
+
    wpTextbox1.selectionStart = startPos;
 
+
    wpTextbox1.selectionEnd = startPos + txt.length;
// while some substring of txt matches replaced_regexp...
+
    wpTextbox1.scrollTop = textScroll;
while (replaced_regexp.test(txt))
+
  }
  {
+
  // IE
  txt = txt.replace(replaced_regexp, op_char + ++counter + cl_char );
+
  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();
 +
    }
 
   }
 
   }
return matches_buffer;
+
  // Other browsers
}
+
  else if (confirm(wmFullText)) {
 
+
    processAllText();
//======================================
 
// Replace '<replaced_tag> ... </replaced_tag>' (<nowiki> <br/> </nowiki>)
 
// with 'opepening_char + tag's counter + closing_char' ('\x03'+1'+'\x04')
 
//======================================
 
 
 
function ReplaceElements( req_exp, op_char, cl_char )
 
 
 
// @req_exp - reqular expression to be replaced
 
// @op_char, @cl_char (opening & closing chars) - "Safe" pair of
 
// unicode unprintable characters, that will be used in replacement
 
 
 
{
 
 
 
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...
 
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 )
 
 
// @replaced_buffer - array of replaced substrings.
 
// @op_char, @cl_char (opening & closing chars) - "Safe" pair
 
// to be replaced with <replaced_tag> and </replaced_tag> accordingly
 
 
{
 
 
var counter = 0; //tags counter
 
 
// RegExp template to be replaced (3 chars: tag's counter
 
// surrunded by "Safe" pair)
 
var replaced_regexp = new RegExp("\\" +op_char+ "([0-9]*)\\" +cl_char );
 
 
//replaced_regexp = /\x03([0-9]*)\x04/
 
 
// while some substring of txt matches replaced_regexp...
 
while (replaced_regexp.test(txt))
 
{
 
  txt = txt.replace(replaced_regexp, replaced_buffer[counter++]);
 
}
 
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“")
 
}
 
  
 +
  document.documentElement.scrollTop = winScroll; // scroll back, for IE/Opera
 
}
 
}
 
/* </pre> */
 

Текущая версия на 10:33, 30 января 2024

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 (window.wgNamespaceNumber % 2 || window.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('code');
    hideTag('tt');
    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(/^ .*/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(/(\[\[:?)(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 (window.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
}