Строка 12: |
Строка 12: |
| // Функция викифицирует переданный текст и возвращает викифицированный: | | // Функция викифицирует переданный текст и возвращает викифицированный: |
| function wikifyText (s) { | | function wikifyText (s) { |
− | var txt='', hidden = [];
| |
| | | |
− | var u = '\u00A0'; // -- unbreakable space.
| + | if (isDiscussion) { |
− | if (isDiscussion) {
| + | // -- это обсуждение. |
− | // -- это обсуждение.
| + | // Несколько дат, вероятно, чужие подписи:: |
− | u = ' ';
| + | var sigs = s.match (/\d\d:\d\d, \d\d? \S{3,8} 20\d\d \(UTC\)/g); |
− | // Несколько дат, вероятно, чужие подписи::
| + | if (sigs && sigs.length > 1) { |
− | var sigs = s.match (/\d\d:\d\d, \d\d? \S{3,8} 20\d\d \(UTC\)/g);
| + | window.alert (wmTalkPage); |
− | if (sigs && sigs.length > 1) {
| + | return s; |
− | window.alert (wmTalkPage);
| + | } |
− | return s;
| + | } |
− | }
| + | |
− | } | + | // Собственно, викификация: |
| + | var hidden = []; |
| + | |
| + | // Скрытие преформатированных тегов и прочих тегов, не подлежащих викификации: |
| + | s = hideTags (s, hidden, 'nowiki', 'templatedata', |
| + | 'pre', 'source', 'syntaxhighlight', 'code', 'kbd', 'tt', 'gallery', |
| + | 'graph', 'svgcode', 'graphviz', 'mscgen', 'score', 'math', 'hiero', 'timeline', |
| + | 'chem', 'mapframe', 'maplink' |
| + | ); |
| + | |
| + | s = r (s, /(IS[BS]N):?\s*([\s\d‒−—-]{8,17}[X\d])/ig, '{{$1|$2}}'); // -- ISBN/ISSN теперь в шаблон. |
| + | |
| + | s = hide (s, /\{\{[\s\S]+?}}/g, hidden);// — шаблоны. |
| + | s = hide (s, /^ .*/mg, hidden); // — преформатированный текст. |
| + | |
| + | s = r (s, /<\s*a\s+href\s*=\s*(["'])\s*https?:\/\/traditio(?:\.ru|-ru\.org|\.wiki)(?:\/wiki)?\/(\S+?)\s*\1\s*>(.+?)<\s*\/a\s*>/gi, wikifyInternalLinks); // -- внутренние <a> → [[]); |
| + | s = r (s, /<\s*a\s+href\s*=\s*(["'])(\S+?)\1\s*>(.+?)<\s*\/a\s*>/gi, '[$2 $3]'); // -- <a> → [); |
| + | |
| + | s = hide (s, /(?:https?|ftp|news|nntp|telnet|irc|gopher|magnet):\/\/[^\s\[\]<>"]+ ?/gi, hidden); // — гиперссылки. |
| + | s = hide (s, /^#(?:redirect|перенапр(авление)?)/i, hidden); // — перенаправления. |
| + | |
| + | s = r (s, / +(\n|\r)/g, '$1'); // -- пробелы в конце строки. |
| | | |
− | // Скрытие преформатированных тегов и прочих тегов, не подлежащих викификации:
| + | // Окружить текст переводами строки, чтобы гарантировать правильную работу |
− | s = hideTag (s, ['nowiki', 'pre', 'source', 'syntaxhighlight', 'code', 'tt', 'svgcode', 'graphviz', 'mscgen', 'score', 'math', 'gallery']);
| + | // регулярных выражений в первой и последней строке: |
− |
| + | // s = r (s, /^/, '\n'); |
− | s = runReplacements (s, [[/(IS[BS]N):?\s*([\s\d‒−—-]{8,17}[X\d])/ig, '{{$1|$2}}']]); // -- ISBN/ISSN теперь в шаблон.
| + | // s = r (s, /$/, '\n'); |
− |
| + | |
− | s = hide (s, /{\{[\s\S]+?}}/g); // — шаблоны.
| + | // Русификация пространств имён: |
− | s = hide (s, /^ .*/mg); // — преформатированный текст.
| + | s = r (s, /(\[\[:?)(category|категория):( *)/ig, '$1Категория:'); |
− |
| + | s = r (s, /(\[\[:?)(image|изображение|file):( *)/ig, '$1Файл:'); |
− | s = runReplacements (s, [ | + | |
− | [/<\s*a\s+href\s*=\s*(["'])\s*https?:\/\/traditio(?:\.ru|-ru\.org|\.wiki)(?:\/wiki)?\/(\S+?)\s*\1\s*>(.+?)<\s*\/a\s*>/gi, function (_, __, p2, p3) {
| + | // Оформление дат: |
− | return '[[' + decodeURIComponent (p2) + '|' + p3 + ']]';
| + | s = r (s, /(\(|\s)(\[\[[12]?\d{3}\]\])[\u00A0 ]?(-{1,3}|–|—) ?(\[\[[12]?\d{3}\]\])(\W)/g, '$1$2—$4$5'); |
− | }] // -- внутренние <a> → [[]]
| + | s = r (s, /(\[\[[12]?\d{3}\]\]) ?(гг?\.)/g, '$1\xa0$2'); |
− | , [/<\s*a\s+href\s*=\s*(["'])(\S+?)\1\s*>(.+?)<\s*\/a\s*>/gi, '[$2 $3]'] // -- <a> → []
| + | s = r (s, /(\(|\s)(\[\[[IVX]{1,5}\]\])[\u00A0 ]?(-{1,3}|–|—) ?(\[\[[IVX]{1,5}\]\])(\W)/g, '$1$2—$4$5'); |
− | ]); | + | s = r (s, /(\[\[[IVX]{1,5}\]\]) ?(вв?\.)/g, '$1\xa0$2'); |
− |
| + | s = r (s, /\[\[(\d+)\]\][\u00A0 ]год/g, '[[$1\xa0год]]'); |
− | s = hide (s, /(https?|ftp|news|nntp|telnet|irc|gopher):\/\/[^\s\[\]<>"]+ ?/gi); // — гиперссылки.
| + | s = r (s, /\[\[((\d+)(?: (?:год )?в [\wa-яёА-ЯЁ ]+\|\2)?)\]\][\u00A0 ](год[а-яё]*)/g, '[[$1\xa0$3]]'); |
− | s = hide (s, /^#(redirect|перенапр(авление)?)/i); // — перенаправления.
| + | s = r (s, /\[\[([XVI]+)\]\][\u00A0 ]век/g, '[[$1\xa0век]]'); |
| + | s = r (s, /\[\[(([XVI]+) век\|\2)\]\][\u00A0 ]век/g, '[[$2\xa0век]]'); |
| + | |
| + | // Удаление недопустимых символов из викиссылок: |
| + | s = r (s, /(\[\[[^|\[\]]*)[\u00AD\u200E\u200F]+([^\[\]]*\]\])/g, '$1$2'); // -- Soft Hyphen & DirMark. |
| + | s = r (s, /\[\[ *([a-zA-Zа-яёА-ЯЁ\u00A0-\u00FF %!\"$&'()*,\-.\/0-9:;=?\\@\^_`’~]+) *\| *(\1)([a-zа-яё]*) *\]\]/g, '[[$2]]$3'); // -- ". |
| + | s = r (s, /\[\[ *([a-zA-Zа-яёА-ЯЁ\u00A0-\u00FF %!\"$&'()*,\-.\/0-9:;=?\\@\^_`’~]+) *\| *([^|[\]]+) *\]\]([a-zа-яё]+)/g, '[[$1|$2$3]]'); // -- ". |
| + | |
| + | s = hide (s, /\[\[[^\]|]+/g, hidden); // -- скрытие викиссылок. |
| + | |
| + | // Все теги в <> надо обработать здесь: |
| | | |
− | s = s.replace (/ +(\n|\r)/g, '$1'); // -- пробелы в конце строки.
| + | // HTML -> викитекст: |
− | s = '\n' + s + '\n';
| + | s = r (s, /<<(\S.+\S)>>/g, '"$1"'); // -- угловые псевдокавычки в обычные. Или лучше в «»? |
| + | s = r (s, /(sup>|sub>|\s)-(\d)/g, '$1−$2'); // -- minus в индексах. |
| + | s = r (s, /(<sup>2<\/sup>|²)/gi, '²'); // -- символы квадрата |
| + | s = r (s, /(<sup>3<\/sup>|³)/gi, '³'); // и куба. |
| + | s = r (s, /<(b|strong)>([\s\S]+?)<\/(b|strong)>/gi,"'''$2'''"); // -- вики-полужирный. |
| + | s = r (s, /<(i|em)>([\s\S]+?)<\/(i|em)>/gi,"''$2''"); // -- вики-курсив. |
| + | s = r (s, /^<hr ?\/?>/gim, '----'); // -- вики-гор. разделитель. |
| + | s = r (s, /<\/?(hr|br)( [^\/>]+?)? ?\/?>/gi, '<$1$2 />'); // оформление hr/br по стандарту XML. |
| + | s = r (s, /\n*<p(?:\s+align\s*=\s*(["']?)(?:left|justify)\1\s*)?>([\s\S]*?)(<\/p>|(?=\n*<(p|h|pre)))/gi, '\n\n$2'); |
| + | // -- remove <p>. |
| + | // Заголовки: |
| + | s = r (s, /\n*<h1(?:[^>]*)>(.+?)<\/h1>\n*/gi, '\n\n= $1 =\n'); |
| + | s = r (s, /\n*<h2(?:[^>]*)>(.+?)<\/h2>\n*/gi, '\n\n== $1 ==\n'); |
| + | s = r (s, /\n*<h3(?:[^>]*)>(.+?)<\/h3>\n*/gi, '\n\n=== $1 ===\n'); |
| + | s = r (s, /\n*<h4(?:[^>]*)>(.+?)<\/h4>\n*/gi, '\n\n==== $1 ====\n'); |
| + | s = r (s, /\n*<h5(?:[^>]*)>(.+?)<\/h5>\n*/gi, '\n\n===== $1 =====\n'); |
| + | s = r (s, /\n*<h6(?:[^>]*)>(.+?)<\/h6>\n*/gi, '\n\n====== $1 ======\n'); |
| + | s = r (s, /(\n==\s*Примечания\s*==\n)<references *\/>/,'$1{{примечания}}'); |
| | | |
− | s = runReplacements (s, [ | + | // Создание сносок: |
− | // Русификация пространств имён:
| + | s = r (s, /(?!\n)([^\[])\[(\d+)\](?!\s*с\.)/g, '$1<ref name="ref$2" />'); // -- сноска вида [1]. |
− | [/(\[\[:?)(category|категория):( *)/ig, '$1Категория:']
| + | s = r (s, /\n\[(\d+)\]\s*([\s\S]+?)(?=\n\[\d+\]|$)/g, '\n<ref name="ref$1">$2</ref>');// -- текст сноски вида [1]. |
− | , [/(\[\[:?)(image|изображение|file):( *)/ig, '$1Файл:']
| |
− | // Оформление дат:
| |
− | , [/(\(|\s)(\[\[[12]?\d{3}\]\])[\u00A0 ]?(-{1,3}|–|—) ?(\[\[[12]?\d{3}\]\])(\W)/g, '$1$2—$4$5']
| |
− | , [/(\[\[[12]?\d{3}\]\]) ?(гг?\.)/g, '$1' + u + '$2']
| |
− | , [/(\(|\s)(\[\[[IVX]{1,5}\]\])[\u00A0 ]?(-{1,3}|–|—) ?(\[\[[IVX]{1,5}\]\])(\W)/g, '$1$2—$4$5']
| |
− | , [/(\[\[[IVX]{1,5}\]\]) ?(вв?\.)/g, '$1' + u + '$2']
| |
− | , [/\[\[(\d+)\]\][\u00A0 ]год/g, '[[$1' + u + 'год]]']
| |
− | , [/\[\[((\d+)(?: (?:год )?в [\wa-яёА-ЯЁ ]+\|\2)?)\]\][\u00A0 ](год[а-яё]*)/g, '[[$1' + u + '$3]]']
| |
− | , [/\[\[([XVI]+)\]\][\u00A0 ]век/g, '[[$1' + u + 'век]]']
| |
− | , [/\[\[(([XVI]+) век\|\2)\]\][\u00A0 ]век/g, '[[$2' + u + 'век]]']
| |
− | // Удаление недопустимых символов из викиссылок:
| |
− | , [/(\[\[[^|\[\]]*)[\u00AD\u200E\u200F]+([^\[\]]*\]\])/g, '$1$2'] // -- Soft Hyphen & DirMark.
| |
− | , [/\[\[ *([a-zA-Zа-яёА-ЯЁ\u00A0-\u00FF %!\"$&'()*,\-.\/0-9:;=?\\@\^_`’~]+) *\| *(\1)([a-zа-яё]*) *\]\]/g, '[[$2]]$3'] // -- ".
| |
− | , [/\[\[ *([a-zA-Zа-яёА-ЯЁ\u00A0-\u00FF %!\"$&'()*,\-.\/0-9:;=?\\@\^_`’~]+) *\| *([^|[\]]+) *\]\]([a-zа-яё]+)/g, '[[$1|$2$3]]'] // -- ".
| |
− | ]);
| |
− | s = hide (s, /\[\[[^\]|]+/g); // -- скрытие викиссылок.
| |
| | | |
− | // Все теги в <> надо обработать здесь:
| + | // .,… до сносок -- сдвиг сносок: |
− | s = runReplacements (s, [ | + | s = r (s, /\s*,\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi , '{{,}}$1'); // -- запятая до; |
− | // HTML -> викитекст:
| + | s = r (s, /\s*(…)\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi , '{{,|$1}}$2'); // -- др. знак до; |
− | [/<<(\S.+\S)>>/g, '"$1"'] // -- угловые кавычки в обычные. Или лучше в «»?
| + | s = r (s, /\s*\.\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi, '{{тчк}}$1'); // -- точка до; |
− | , [/(sup>|sub>|\s)-(\d)/g, '$1−$2'] // -- minus в индексах.
| |
− | , [/(<sup>2<\/sup>|²)/gi, '²'] // -- символы квадрата
| |
− | , [/(<sup>3<\/sup>|³)/gi, '³'] // и куба.
| |
− | , [/<(b|strong)>([\s\S]+?)<\/(b|strong)>/gi,"'''$2'''"] // -- вики-полужирный.
| |
− | , [/<(i|em)>([\s\S]+?)<\/(i|em)>/gi,"''$2''"] // -- вики-курсив.
| |
− | , [/^<hr ?\/?>/gim, '----'] // -- вики-гор. разделитель.
| |
− | , [/<\/?(hr|br)( [^\/>]+?)? ?\/?>/gi, '<$1$2 />'] // оформление hr/br по стандарту XML.
| |
− | , [/\n*<p(?:\s+align\s*=\s*(["']?)(?:left|justify)\1\s*)?>([\s\S]*?)<\/p>/gi, '\n\n$2']
| |
− | // -- remove <p>.
| |
− | , [/(\n==\s*Примечания\s*==\n)<references *\/>/,'$1{{примечания}}']
| |
| | | |
− | // Создание сносок:
| + | // .,… после сносок -- перенос до и сдвиг сносок: |
− | , [/(?!^)([^\[])\[(\d+)\](?!\s*с\.)/gm, '$1<ref name="ref$2" />'] // -- сноска.
| + | s = r (s, /\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)\s*(?:,|\{\{(?:,|зпт)\}\})/gi , '{{,}}$1'); // -- запятая после; |
− | , [/\n\[(\d+)\]\s*([\s\S]+?)(?=\n\[\d+\]|$)/g, '\n<ref name="ref$1">$2</ref>']// -- текст сноски.
| + | s = r (s, /\s*((?:<ref[^<\/>]*?(?:>[^<]+?<\/ref|\/)>)+)\s*([…])/gi , '{{,|$2}}$1'); // -- др. знак после; |
| + | s = r (s, /\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)\s*(?:\.|\{\{(?:,\|\.|тчк)\}\})/gi, '{{тчк}}$1'); // -- точка после; |
| | | |
− | // .,… до сносок -- сдвиг сносок:
| + | // !? после сносок -- перенос до: |
− | , [/\s*,\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi , '{{,}}$1'] // -- запятая до;
| + | s = r (s, /\s*((?:<ref[^<\/>]*?(?:>[^<]+?<\/ref|\/)>)+)([!?;:“])/gi , '$2$1'); // -- !? после; |
− | , [/\s*(…)\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi , '{{,|$1}}$2'] // -- др. знак до;
| |
− | , [/\s*\.\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi, '{{тчк}}$1'] // -- точка до;
| |
| | | |
− | // .,… после сносок -- перенос до и сдвиг сносок:
| + | // !?;:“» до сносок -- удаление лишних пробелов: |
− | , [/\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)\s*(?:,|\{\{(?:,|зпт)\}\})/gi , '{{,}}$1'] // -- запятая после;
| + | s = r (s, /\s*([!?;:“»])\s+((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi , '$1$2'); // -- др. знак до; |
− | , [/\s*((?:<ref[^<\/>]*?(?:>[^<]+?<\/ref|\/)>)+)\s*([…])/gi , '{{,|$2}}$1'] // -- др. знак после;
| + | |
− | , [/\s*((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)\s*(?:\.|\{\{(?:,\|\.|тчк)\}\})/gi, '{{тчк}}$1'] // -- точка после;
| + | // Удаление лишних пробелов и переводов строки внутри сносок: |
| + | s = r (s, /(<ref[^\/>]*>)\s+/gi, '$1'); |
| + | s = r (s, /\s+<\/ref>/gi, '</ref>'); |
| | | |
− | // !? после сносок -- перенос до:
| + | // Создание раздела сносок: |
− | , [/\s*((?:<ref[^<\/>]*?(?:>[^<]+?<\/ref|\/)>)+)([!?;:“])/gi , '$2$1'] // -- !? после;
| + | s = r (s, /((?:<ref\sname=".+?">[\s\S]+?<\/ref>)+)\s*$/, '<references>$1</references>\n'); // -- раздел сносок. |
| | | |
− | // !?;:“» до сносок -- удаление лишних пробелов:
| + | s = hide(s, /<[a-z][^>]*?>/gi, hidden); // -- hide all HTML tags. |
− | , [/\s*([!?;:“»])\s+((<ref[^<\/>]*?(>[^<]+?<\/ref|\/)>)+)/gi , '$1$2'] // -- др. знак до;
| |
| | | |
− | ]);
| + | s = hide(s, /^(?:{\||\|-).*/mg, hidden); // -- таблицы и ряды. |
− |
| + | s = hide(s, /(?:^\||^!|!!|\|\|) *[a-z]+=[^|]+\|(?!\|)/mgi, hidden); // -- стили ячеек. |
− | // Создание раздела сносок:
| + | s = hide(s, /\| +/g, hidden); // -- форматированные ячейки. |
− | if (s.indexOf ('<references>') === -1) {
| |
− | s = runReplacements (s, [
| |
− | [/((?:<ref\sname=".+?">[\s\S]+?<\/ref>)+)$/, '<references>$1</references>\n'] // -- раздел сносок.
| |
− | ]);
| |
− | } | |
− |
| |
− | s = hide(s, /<[a-z][^>]*?>/gi); // -- hide all HTML tags.
| |
| | | |
− | s = hide(s, /^({\||\|-).*/mg); // -- таблицы и ряды.
| + | // Двойные пробелы: |
− | s = hide(s, /(^\||^!|!!|\|\|) *[a-z]+=[^|]+\|(?!\|)/mgi); // -- стили ячеек.
| + | s = r (s, /[ \t]+/g, ' '); |
− | s = hide(s, /\| +/g); // -- форматированные ячейки.
| |
| | | |
− | s = s.replace (/[ \t]+/g, ' '); // -- двойные пробелы.
| + | // Заголовки: |
| + | s = r (s, /^(=+)[ \t\f\v]*(.*?)[ \t\f\v]*=+$/gm, '$1 $2 $1'); // -- окружить пробелами. |
| + | s = r (s, /([^\r\n])(\r?\n==.*==\r?\n)/g, '$1\n$2'); // -- пустую строку впереди. |
| + | s = r (s, /^== см(\.?|отрите) ?так\s*же ==$/gmi, '== См. также =='); // -- «См. также». |
| + | s = r (s, /^== сноски ==$/gmi, '== Примечания =='); |
| + | s = r (s, /^== L ==$/gmi, '== Ссылки =='); |
| + | s = r (s, /^== (.*[^.])[.:] ==$/gm, '== $1 =='); // -- точка или двоеточие в конце. |
| | | |
− | s = runReplacements (s, [
| + | // Любые кавычки → в простые, которые потом будут перерасставлены: |
− | // Заголовки:
| + | s = r (s, /&((la|ra|bd|ld)quo|quot);/g,'"'); |
− | [/^(=+)[ \t\f\v]*(.*?)[ \t\f\v]*=+$/gm, '$1 $2 $1'] // -- окружить пробелами.
| + | s = r (s, /«|»|“|”|„/g, '"'); // -- временное скрытие нормальных кавычек. Нужно ли? |
− | , [/([^\r\n])(\r?\n==.*==\r?\n)/g, '$1\n$2'] // -- пустую строку впереди.
| |
− | , [/^== см(\.?|отрите) ?так\s*же ==$/gmi, '== См. также =='] // -- «См. также».
| |
− | , [/^== сноски ==$/gmi, '== Примечания ==']
| |
− | , [/^== L ==$/gmi, '== Ссылки ==']
| |
− | , [/^== (.*[^.])[.:] ==$/gm, '== $1 =='] // -- точка или двоеточие в конце.
| |
| | | |
− | , [/«|»|“|”|„/g, '"'] // -- временное скрытие нормальных кавычек. Нужно ли?
| + | // Программный код как в github: |
| + | // ``` … ``` → <pre>…</pre>: |
| + | s = r (s, /\n```((.|\n)+?)\n```/g, '\n<pre>$1</pre>\n'); |
| + | s = r (s, /`(.+?)`/g, '<code>$1</code>'); // `…` → <code>…</code> |
| + | |
| + | // Тире и дефисы: |
| + | s = r (s, /–/g, '-'); // -- – → - |
| + | s = r (s, /&(#151|[nm]dash);/g, '—'); // -- мнемоника тире → — |
| + | s = r (s, /( |\s)-{1,3} /g, '$1— '); // -- отбитые - → — |
| + | s = r (s, /(\d)-{1,2}(\d)/g, '$1‒$2'); // -- -/-- между цифрами → ‒ (ߜ) |
| + | s = r (s, /([IVXLCDM]+)-{1,2}([IVXLCDM]+)/g, '$1‒$2'); // -- -/-- между римскими цифрами → ‒ (ߜ) |
| + | s = r (s, /(\s)-(\d)/g, '$1−$2'); // -- отбитый - перед цифрой → − |
| | | |
− | // Программыный код как в github:
| + | // Мнемоники HTML -> символы: |
− | // ``` … ``` → indented … → <pre>…</pre>:
| + | s = r (s, /&#x([0-9a-f]{1,4});/gi, char); //́ |
− | , [/\n```((.|\n)+?)\n```/g, function (_, s) {return s.replace (/^/gm, ' '); }]
| + | s = r (s, /©/gi,'©'); |
− | , [/`(.+?)`/g, '<code>$1</code>'] // `…` → <code>…</code>
| + | s = r (s, /®/gi,'®'); |
| + | s = r (s, /§/gi,'§'); |
| + | s = r (s, /€/gi,'€'); |
| + | s = r (s, /¥/gi,'¥'); |
| + | s = r (s, /£/gi,'£'); |
| + | s = r (s, /°/g,'°'); |
| + | s = r (s, /\(tm\)|\(тм\)|™/gi,'™'); |
| | | |
− | // Тире и дефисы:
| + | // Символы, которых нет на клавиатуре: |
− | , [/–/g, '-'] // -- – → -
| + | s = r (s, /\.\.\.|…/g,'…'); |
− | , [/&(#151|[nm]dash);/g, '—'] // -- мнемоника тире → —
| + | s = r (s, /\+-|±/g,'±'); |
− | , [/( |\s)-{1,3} /g, '$1— '] // -- отбитые - → —
| + | s = r (s, /~=/g,'≈'); |
− | , [/(\d)-{1,2}(\d)/g, '$1‒$2'] // -- -/-- между цифрами → ‒ (ߜ)
| + | s = r (s, /\^2(\D)/g,'²$1'); |
− | , [/([IVXLCDM]+)-{1,2}([IVXLCDM]+)/g, '$1‒$2'] // -- -/-- между римскими цифрами → ‒ (ߜ)
| + | s = r (s, /\^3(\D)/g,'³$1'); |
− | , [/(\s)-(\d)/g, '$1−$2'] // -- отбитый - перед цифрой → −
| + | s = r (s, /\([cс]\)/gi,'©'); |
| + | s = r (s, /([\wа-яА-ЯёЁ])'([\wа-яА-ЯёЁ])/g,'$1’$2'); //' → типографский апостроф. |
| + | s = r (s, /№№/g,'№'); // знаки номера. |
| + | |
| + | // Годы и века |
| + | s = r (s, /(\(|\s)([12]?\d{3})[\u00A0 ]?(-{1,3}|—) ?([12]?\d{3})(?![\w-°])/g, '$1$2—$4'); |
| + | s = r (s, /([12]?\d{3}) ?(гг?\.)/g, '$1\xa0$2'); |
| + | s = r (s, /(\(|\s)([IVX]{1,5})[\u00A0 ]?(-{1,3}|—) ?([IVX]{1,5})(?![\w-°])/g, '$1$2—$4'); |
| + | s = r (s, /([IVX]{1,5}) ?(вв?\.)/g, '$1\xa0$2'); |
| + | |
| + | // Сокращения: |
| + | s = r (s, /(Т|т)\.\s?е\./g, '$1о есть'); |
| + | s = r (s, /(Т|т)\.\s?к\./g, '$1ак как'); |
| + | s = r (s, /(В|в)\sт\. ?ч\./g, '$1 том числе'); |
| + | s = r (s, /и\sт\.\s?д\./g, 'и\xa0т\.\xa0д\.'); |
| + | s = r (s, /и\sт\.\s?п\./g, 'и\xa0т\.\xa0п\.'); |
| + | s = r (s, /(Т|т)\.\s?н\./g, '$1\.\xa0н\.'); |
| + | s = r (s, /н\.\s?э\./g, 'н\.\xa0э\.'); |
| + | s = r (s, /(Д|д)(о|\.)\sн\.\s?э\./g, '$1о\xa0н\.\xa0э\.'); |
| + | s = r (s, /(\d)[\u00A0 ]?(тыс\.|млн|млрд|трлн|(?:м|с|д|к)?м|[км]г)\.?(?=[,;.]| "?[а-яё-])/g, '$1\xa0$2'); |
| + | s = r (s, /(\d)[\u00A0 ](тыс)([^\.А-Яа-яЁё])/g, '$1\xa0$2.$3'); |
| + | s = r (s, /(\s)кв\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1\xA0$2²$3'); // -- квадратные единицы измерения. |
| + | s = r (s, /(\s)куб\.\s*(дм|см|мм|мкм|нм|км|м)(\s)/g, '$1\xA0$2³$3'); // -- кубические единицы измерения. |
| + | |
| + | // Пробелы: |
| + | s = r (s, /^([#*:]+)[ \t\f\v]*([^ \t\f\v*#:;])/gm, '$1 $2'); // -- в списках. |
| + | s = r (s, /(\S) (-{1,3}|—) (\S)/g, '$1\xa0— $3'); // тире. |
| + | s = r (s, /([А-Я]\.) ?([А-Я]\.) ?([А-Я][а-я])/g, '$1\xa0$2\xa0$3'); // -- инициалы. |
| + | s = r (s, /([А-Я]\.)([А-Я]\.)/g, '$1 $2'); // инициалы. |
| + | s = r (s, /([а-я]\.)([А-ЯA-Z])/g, '$1 $2'); // -- после точки. |
| + | s = r (s, /([)"а-яa-z\]])\s*,([\[("а-яa-z])/g, '$1, $2'); // -- после точки. |
| + | s = r (s, /([)"а-яa-z\]])\s([,;])\s([\[("а-яa-z])/g, '$1$2 $3'); // -- после запятой. |
| + | s = r (s, /([^%\/\w]\d+?(?:[.,]\d+?)?) ?([%‰])(?!-[А-Яа-яЁё])/g, '$1\xa0$2'); // -- проценты. |
| + | s = r (s, /(\d) ([%‰])(?=-[А-Яа-яЁё])/g, '$1$2'); // -- 5%-й |
| + | s = r (s, /([№§])(\s*)(\d)/g, '$1\xa0$3'); // -- номер и параграф. |
| + | s = r (s, /\( +/g, '('); |
| + | s = r (s, / +\)/g, ')'); // -- убрать пробелы у внутренних сторон скобок. |
| | | |
− | // Мнемоники HTML -> символы:
| + | // Температура: |
− | , [/&#x([0-9a-f]{1,4});/gi, function (n, a) {return String.fromCharCode (eval ('0x' + a.substr (-4)))}] //́
| + | s = r (s, /([\s\d=≈≠≤≥<>("'|])([+±−-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])[CС])(?=[\s"').,;!?|])/gm, '$1$2\xa0°C'); |
− | , [/©/gi,'©']
| + | s = r (s, /([\s\d=≈≠≤≥<>("'|])([+±−-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])F)(?=[\s"').,;|!?])/gm, '$1$2\xa0°F'); |
− | , [/®/gi,'®']
| |
− | , [/§/gi,'§']
| |
− | , [/€/gi,'€']
| |
− | , [/¥/gi,'¥']
| |
− | , [/£/gi,'£']
| |
− | , [/°/g,'°']
| |
− | , [/\(tm\)|\(тм\)|™/gi,'™']
| |
− |
| |
− | // Символы, которых нет на клавиатуре:
| |
− | , [/\.\.\.|…/g,'…']
| |
− | , [/\+-|±/g,'±']
| |
− | , [/~=/g,'≈']
| |
− | , [/\^2(\D)/g,'²$1']
| |
− | , [/\^3(\D)/g,'³$1']
| |
− | , [/\([cс]\)/gi,'©']
| |
− |
| |
− | // Любые кавычки → в простые, которые потом будут перерасставлены:
| |
− | , [/&((la|ra|bd|ld)quo|quot);/g,'"']
| |
− |
| |
− | , [/([\wа-яА-ЯёЁ])'([\wа-яА-ЯёЁ])/g,'$1’$2'] //' → типографский апостроф.
| |
− |
| |
− | , [/№№/g,'№'] // знаки номера.
| |
| | | |
− | // Годы и века
| + | // Десятичная точка → запятая: |
− | , [/(\(|\s)([12]?\d{3})[\u00A0 ]?(-{1,3}|—) ?([12]?\d{3})(?![\w-°])/g, '$1$2—$4']
| + | s = r (s, /(\s\d+)\.(\d+[\u00A0 ]*[%‰°])/gi, '$1,$2'); |
− | , [/([12]?\d{3}) ?(гг?\.)/g, '$1' + u + '$2']
| |
− | , [/(\(|\s)([IVX]{1,5})[\u00A0 ]?(-{1,3}|—) ?([IVX]{1,5})(?![\w-°])/g, '$1$2—$4']
| |
− | , [/([IVX]{1,5}) ?(вв?\.)/g, '$1' + u + '$2']
| |
| | | |
− | // Сокращения:
| + | // Союзы, предлоги, частицы: |
− | , [/(Т|т)\.\s?е\./g, '$1о есть']
| + | s = r (s, /(^|\s|\()(а|в|во|да|для|до|за|и|ибо|из|из-за|из-под|или|к|ко|на|над|не|ни|но|о|об|обо|от|перед|по|под|при|с|со|у)\s+/gi, '$1$2\xA0'); // -- проклитики |
− | , [/(Т|т)\.\s?к\./g, '$1ак как']
| + | s = r (s, /\s+(б|бы|ж|же|ли|ль)(?=$|\s|[,;:.!?)])/gi, '\xA0$1'); // -- энклитики. |
− | , [/(В|в)\sт\. ?ч\./g, '$1 том числе']
| |
− | , [/и\sт\.\s?д\./g, 'и' + u + 'т\.' + u + 'д\.']
| |
− | , [/и\sт\.\s?п\./g, 'и' + u + 'т\.' + u + 'п\.']
| |
− | , [/(Т|т)\.\s?н\./g, '$1\.' + u + 'н\.']
| |
− | , [/н\.\s?э\./g, 'н\.' + u + 'э\.']
| |
− | , [/(Д|д)(о|\.)\sн\.\s?э\./g, '$1о' + u + 'н\.' + u + 'э\.']
| |
− | , [/(\d)[\u00A0 ]?(тыс\.|млн|млрд|трлн|(?:м|с|д|к)?м|[км]г)\.?(?=[,;.]| "?[а-яё-])/g, '$1' + u + '$2']
| |
− | , [/(\d)[\u00A0 ](тыс)([^\.А-Яа-яЁё])/g, '$1' + u + '$2.$3']
| |
| | | |
− | // Пробелы:
| + | // Интерфейс для дополнений к викификатору: |
− | , [/^([#*:]+)[ \t\f\v]*([^ \t\f\v*#:;])/gm, '$1 $2'] // -- в списках.
| + | var pairs = window.wfPlugins; |
− | , [/(\S) (-{1,3}|—) (\S)/g, '$1' + u + '— $3'] // тире.
| + | if (pairs && pairs.length) { |
− | , [/([А-Я]\.) ?([А-Я]\.) ?([А-Я][а-я])/g, '$1' + u + '$2' + u + '$3'] // -- инициалы.
| + | pairs.forEach (function (pair) { |
− | , [/([А-Я]\.)([А-Я]\.)/g, '$1 $2'] // инициалы.
| + | s = r (s, pair [0], pair [1]); |
− | , [/([а-я]\.)([А-ЯA-Z])/g, '$1 $2'] // -- после точки.
| + | }); |
− | , [/([)"а-яa-z\]])\s*,([\[("а-яa-z])/g, '$1, $2'] // -- после точки.
| + | } |
− | , [/([)"а-яa-z\]])\s([,;])\s([\[("а-яa-z])/g, '$1$2 $3'] // -- после запятой.
| |
− | , [/([^%\/\w]\d+?(?:[.,]\d+?)?) ?([%‰])(?!-[А-Яа-яЁё])/g, '$1' + u + '$2'] // -- проценты.
| |
− | , [/(\d) ([%‰])(?=-[А-Яа-яЁё])/g, '$1$2'] // -- 5%-й
| |
− | , [/([№§])(\s*)(\d)/g, '$1' + u + '$3'] // -- номер и параграф.
| |
− | , [/\( +/g, '(']
| |
− | , [/ +\)/g, ')'] // -- убрать пробелы у внутренних сторон скобок.
| |
| | | |
− | // Температура:
| + | // Восстановление кавычек: "" → «»: |
− | , [/([\s\d=≈≠≤≥<>("'|])([+±−-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])[CС])(?=[\s"').,;!?|])/gm, '$1$2' + u + '°C']
| + | // s = restoreQuotes (s); |
− | , [/([\s\d=≈≠≤≥<>("'|])([+±−-]?\d+?(?:[.,]\d+?)?)(([ °^*]| [°^*])F)(?=[\s"').,;|!?])/gm, '$1$2' + u + '°F']
| + | s = r (s, /([\s\u00A0·\x02!|#'"\/(;+-])"([^"]*)([^\s"(|])"([^a-zа-яё])/ig, '$1<q>$2$3</q>$4'); // -- кавычки, внутри которых нет кавычек. |
| + | s = r (s, /([\s\u00A0·\x02!|#'"\/(;+-])"([^"]*)([^\s"(|])"([^a-zа-яё])/ig, '$1<q>$2$3</q>$4'); // -- и ещё раз. |
| | | |
− | // Десятичная точка → запятая:
| + | // Удаление начального и конечного пробелов: |
− | , [/(\s\d+)\.(\d+[\u00A0 ]*[%‰°])/gi, '$1,$2']
| + | s = r (s, /^\n/, ''); |
| + | s = r (s, /\n$/, ''); |
| | | |
− | // Союзы, предлоги, частицы, единицы измерения:
| + | // Восстановление скрытого: |
− | , [/(^|\s|\()(а|в|во|да|для|до|за|и|ибо|из|из-за|из-под|или|к|ко|на|не|ни|но|о|об|обо|от|перед|при|с|со|у)\s+/gi, '$1$2' + u] // -- проклитики
| + | s = restore (s, hidden); |
− | , [/\s+(б|бы|ж|же|ли|ль)(?=$|\s|[,;:.!?)])/gi, u + '$1'] // -- энклитики.
| |
− | ]);
| |
| | | |
− | // Интерфейс для дополнений к викификатору:
| + | return s; |
− | s = runReplacements (s, window.wfPlugins);
| |
| | | |
− | // Подумать о простых <q></q>:
| + | // Вспомогательные функции: |
− | // Восстановление кавычек: "" → «»:
| |
− | for (var i=1; i<=2; i++) {
| |
− | s = s.replace (/([\s\u00A0·\x02!|#'"\/(;+-])"([^"]*)([^\s"(|])"([^a-zа-яё])/ig, '$1«$2$3»$4'); //"
| |
− | }
| |
− | while (/«[^»]*«/.test(s)) {
| |
− | s = s.replace (/«([^»]*)«([^»]*)»/g, '«$1„$2“');
| |
− | }
| |
| | | |
− | s = s.substr (1, s.length - 2); // -- удаление начального и конечного пробелов.
| + | // Одна замена: |
− | if ('0'.replace('0', '$$') === '$') { // -- $ в регэксах, как всегда, IE особенный.
| + | function r (string, pattern, replacement) { |
− | for (i = 0; i < hidden.length; i++) {
| + | console.log ('Replacing ' + pattern + ' with ' + replacement); |
− | hidden [i] = hidden [i].replace (/\$/g, '$$$$');
| + | return string.replace (pattern, replacement); |
− | }
| + | } |
− | }
| + | |
− | // Раскрытие скрытого в hide ():
| + | // Скрытие фрагментов путём окружения \x01 и \x02: |
− | while (hidden.length > 0) {
| + | function hide (txt, re, hidden) { |
− | s = s.replace ('\x01' + hidden.length + '\x02', hidden.pop ());
| + | console.log ('Hiding ' + re); |
− | }
| + | return txt.replace (re, function (s) {return '\x01' + hidden.push (s) + '\x02'}); |
− |
| + | } |
− | return s;
| + | |
− |
| + | // Скрытие тегов: |
− | // Вспомогательные функции:
| + | function hideTags (/* variadic; no ES6 spread syntax txt, hidden, ... */) { |
− | // Выполнение массива замен:
| + | var args = Array.prototype.slice.call (arguments); |
− | function runReplacements (s, pairs, log) {
| + | var txt = args.shift () |
− | if (pairs && pairs.length) {
| + | var hidden = args.shift () |
− | pairs.forEach (function (pair) {
| + | var tags = args.join ('|'); |
− | if (log) console.log (pair [0] + ': Before: ' + s);
| + | return hide (txt, RegExp ('<(' + tags + ')( [^>]+)?>[\\s\\S]+?<\\/\\1>', 'gi')); |
− | s = s.replace (pair [0], pair [1]);
| + | } // -- function hideTags (txt, tags, hidden) |
− | if (log) console.log ('After: ' + s + '\n');
| + | |
− | });
| + | // Восстановление скрытого: |
− | }
| + | function restore (/* String */ s, /* Array */ hidden) { |
− | return s;
| + | if ('0'.replace('0', '$$') === '$') { // -- $ в регэксах, как всегда, IE особенный. |
− | }
| + | for (i = 0; i < hidden.length; i++) { |
− | // Скрытие фрагментов путём окружения \x01 и \x02:
| + | hidden [i] = hidden [i].replace (/\$/g, '$$$$'); |
− | function hide (txt, re) {
| + | } |
− | return txt.replace (re, function (s) {return '\x01' + hidden.push (s) + '\x02'});
| + | } |
− | }
| + | // Раскрытие скрытого в hide (): |
− | function hideTag (txt, tag) {
| + | while (hidden.length > 0) { |
− | if (tag.join) {
| + | s = s.replace ('\x01' + hidden.length + '\x02', hidden.pop ()); |
− | tag = tag.join ('|');
| + | } |
− | }
| + | return s; |
− | return hide (txt, RegExp ('<(' + tag + ')( [^>]+)?>[\\s\\S]+?<\\/\\1>', 'gi'));
| + | } // -- function restore (/* String */ s, /* Array */ hidden) |
− | }
| + | |
| + | // Превращение ссылок HTML на «Традицию» в викиссылки: |
| + | function wikifyInternalLinks (_, __, page, alias) { |
| + | return '[[' + decodeURIComponent (page) + '|' + alias + ']]'; |
| + | } |
| + | |
| + | // Создание символа из кода: |
| + | function char (_, a) { |
| + | return String.fromCharCode (eval ('0x' + a.substr (-4))) |
| + | } |
| + | |
| } // -- function wikifyText (s) | | } // -- function wikifyText (s) |
| | | |
Строка 273: |
Строка 303: |
| ); | | ); |
| }); | | }); |
− | }
| |
− |
| |
− | if (module) {
| |
− | module.exports = wikifyText;
| |
| } | | } |