Участник:AntonChupin/Wikificator.js
< Участник:AntonChupin
Перейти к навигации
Перейти к поиску
Версия от 13:41, 8 июля 2016; AntonChupin (обсуждение | вклад) (автоматическая правка орфографии и пр.)
Замечание. Возможно, после сохранения вам придётся очистить кэш своего браузера, чтобы увидеть изменения.
- Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl-F5 или Ctrl-R (⌘-R на Mac)
- Google Chrome: Нажмите Ctrl-Shift-R (⌘-Shift-R на Mac)
- Internet Explorer: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl-F5
- Opera: Перейдите в Menu → Настройки (Opera → Настройки на Mac), а затем Безопасность → Очистить историю посещений → Кэшированные изображения и файлы
//<!--
var wmVersion = '2016-06-18';
var wmCantWork = 'Викификатор не может работать в вашем браузере\n\nWikificator can not work in your browser';
var wmFullText = 'Викификатор обработает ВЕСЬ текст на этой странице. Продолжить?';
var wmTalkPage = 'Викификатор не обрабатывает страницы обсуждения целиком.\n\nВыделите ваше сообщение — обработано будет только оно';
function Wikify() {
var txt = '', hidden = [], wpTextbox1 = document.editform.wpTextbox1;
var winScroll = document.documentElement.scrollTop;
// 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
// Functions:
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', 'tt', 'math', 'gallery']);
//hide(/{\{[\s\S]+?}}/g); // templates
hide(/\{\{илл[\s\S]+?\}\}/g); // Скрываем шаблон "илл", чтобы не заменялись тире в именах файлов
hide(/\{\{Слайдер[\s\S]+?\}\}/g); // Скрываем шаблон "Слайдер", чтобы не заменялись тире в именах файлов
hide(/^ .*/mg);
hide(/(https?|ftp|news|nntp|telnet|irc|gopher):\/\/[^\s\[\]<>"]+ ?/gi);
hide(/^#(redirect|перенапр(авление)?)/i);
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(/\[\[((\d+)(?: (?:год )?в [\wa-яёА-ЯЁ ]+\|\2)?)\]\][\u00A0 ](год[а-яё]*)/g, '[[$1' + nbsp + '$3]]');
r(/\[\[([XVI]+)\]\][\u00A0 ]век/g, '[[$1' + nbsp + 'век]]');
r(/\[\[(([XVI]+) век\|\2)\]\][\u00A0 ]век/g, '[[$2' + nbsp + 'век]]');
// 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]]'); // "
// удаление ссылок в шаблоне {{родств-блок}}
findall(/{{родств-блок[^{}|]*[^{}]+}}/gm, function (value) {
r(value, value.replace(/\[\[([^\[\]\|]*?)\]\]/g, '$1'));
});
hide(/\[\[[^\]|]+/g); // only link part
// Tags
r(/<<(\S.+\S)>>/g, '"$1"'); //<< >>
r(/(sup>|sub>|\s)-(\d)/g, '$1−$2'); //minus
r(/(<sup>2<\/sup>|²)/gi, '²');
r(/(<sup>3<\/sup>|³)/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== *Примечания *==\n)<references *\/>/, '$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(/^== сноски ==$/gmi, '== Примечания ==');
r(/^== (.+)[.:] ==$/gm, '== $1 ==');
r(/«|»|“|”|„/g, '"'); // temp
// Hyphens and en dashes to pretty dashes
//r(/–/g, '-'); // – -> hyphen
r(/&(#151|mdash);/g, '—'); // -> —
r(/( |\s)[-—]{1,3} /g, '$1— '); // hyphen -> —
r(/(\d)--(\d)/g, '$1–$2'); // -> –
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)));
}); // ́
r(/©/gi, '©');
r(/®/gi, '®');
r(/§/gi, '§');
r(/€/gi, '€');
r(/¥/gi, '¥');
r(/£/gi, '£');
r(/°/g, '°');
r(/\(tm\)|\(тм\)|™/gi, '™');
r(/\.\.\.|…/g, '…');
r(/\+-|±/g, '±');
r(/~=/g, '≈');
r(/\^2(\D)/g, '²$1');
r(/\^3(\D)/g, '³$1');
r(/&((la|ra|bd|ld)quo|quot);/g, '"');
r(/([\wа-яА-ЯёЁ])'([\wа-яА-ЯёЁ])/g, '$1’$2'); //'
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, '$1о есть');
//r(/(Т|т)\.\s?к\./g, '$1ак как');
//r(/(В|в)\sт\. ?ч\./g, '$1 том числе');
r(/и\sт\.\s?д\./g, 'и' + nbsp + 'т.' + nbsp + 'д.');
r(/и\sт\.\s?п\./g, 'и' + nbsp + 'т.' + nbsp + 'п.');
r(/(Т|т)\.\s?н\./g, '$1.' + nbsp + 'н.');
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(/ /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(/([а-я]\.)([А-ЯA-Z])/g, '$1 $2'); // word. word
r(/([)"а-яa-z\]])\s*,([\[("а-яa-z])/g, '$1, $2'); // word, word
r(/([)"а-яa-z\]])\s([,;])\s([\[("а-яa-z])/g, '$1$2 $3');
r(/([^%\/\w]\d+?(?:[.,]\d+?)?) ?([%‰])(?!-[А-Яа-яЁё])/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“');
}
// Специфичные для Викисловаря вещи
r(/([а-я\]]{2})\.\s*{{пример/gi, '$1 {{пример'); // Убрать точки в конце толкований
// Заполнение слогов
r(/{{по-слогам\|}}/g, ''); // Выбросить пустой шаблон-болванку
matches = txt.match(/(\|слоги=([^{|}]+))(}|\||$})/m); // Если разбиение приведено без шаблона, обернуть его в шаблон
if (matches) {
r(matches[1], '|слоги={{по-слогам|' + matches[2].replace("\r", "").replace("\n", "").replace("-", "|").replace("·", "|.|") + '}}\n' );
}
r(/\|слоги=$/m, '|слоги={{по-слогам|' + wgTitle + '}}');
r(/{{adv ru\|([а-я]+)}}/, '{{adv ru|{{по-слогам|$1}}}}');
// Удаление устаревших параметров
findall(/{{(гл|сущ) ru((.|\s)*?)==/gm, function (value) {
r(value, value.replace("|show-text=1\r\n", '').replace("|show-text=1\n", '').replace("|show-text=1", ''));
});
// Добавление значения для параметра "основа="
r(/\|основа=$/m, '|основа=' + wgTitle);
// Удаление "-а", "-я", "-ь", "-о" и "-й" из основы для изменяемых существительных
findall(/{{сущ ru [fmn] (ina|a) [1-9][^{}|]*\|основа=([^{}|\n\r]+)/gm, function (value) {
var word = value.match(/\|основа=([^{}|\n\r]+)/)[1];
if (endsWith(word, ["ь", "а", "я", "о", "й"])) {
r(value, value.replace("|основа=" + word, "|основа=" + word.slice(0, -1)));
}
});
// Удаление "-ий", "-ый" и "-ой" в основе для прилагательных
findall(/{{прил ru[^{}|]*\|основа=([^{}|\n\r]+)/gm, function (value) {
var word = value.match(/\|основа=([^{}|\n\r]+)/)[1];
if (endsWith(word, ["ый", "ий", "ой"])) {
r(value, value.replace("|основа=" + word, "|основа=" + word.slice(0, -2)));
}
});
// Удаление лишнего параметра "основа1="
pattern =
"{{" +
// подходящий заголовок шаблона:
"(" +
"сущ ru f ina (0|1a|2a|3a|4a|5a|6a|7a|8a)|" +
"сущ ru f a (0|1a|2a|3a|4a|5a|7a|8a)|" +
"сущ ru n ina (0|1a|4a|7a)|" +
"сущ ru m a (0|1a|2a|3a|4a|6a)|" +
"сущ ru m ina (0|1a|2a|3a|4a|6a)" +
")" +
// оставшаясь часть шаблона:
"([^{}]*({{([^{}]*({{[^{}]+}})?[^{}]*)+}})?[^{}]*)+" +
"}}";
findall(new RegExp(pattern, 'gm'), function (value) {
r(value, value.replace(/\|основа1=[^|{}]*/g, ''));
});
// Возвращение всех ранее скрытых элементов (через 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());
}
}
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 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;
}
}
//-->