Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Странное поведение regexp (https://javascript.ru/forum/misc/23332-strannoe-povedenie-regexp.html)

ksevelyar 20.11.2011 16:36

Парсер содержимого textarea в html (regexp)
 
http://jsfiddle.net/ksevelyar/4x6Qf/10/
output = ('<p>'+input.replace(/\n\n+/g,'</p><p>').replace(/[^>]\n/g, "<br />")+'</p>');


upd:

В целом абзацы и переносы строк создаются нормально, но до того момента как парсер натыкается на блочный html, например h2. Он пытается засунуть заголовок внутрь p, после чего браузер звереет и берёт инициативу на себя.

Нужно задать список всех блочных элементов и вставлять </p> перед и <p> после.

Отпишу в топик как что-нибудь получится.

ksevelyar 20.11.2011 19:16

http://jsfiddle.net/ksevelyar/4x6Qf/13/

Я хочу получить:
</p>ac<p> </p>dc<p>


Пробовал exec:
output = output.replace(block,'</p>'+block.exec(output)+'<p>');


Возвращает:
</p>ac,ac<p> </p>ac,ac<p>


Где ошибка?

P.S.

Как экранировать html теги для regexp? Например <h2>ac</h2>?

trikadin 20.11.2011 19:26

Так. Во-первых, тестовые примеры здесь надо публиковать. Во-вторых, абсолютно непонятно, какое поведение вам надо получить. Такое?

str="Весной, когда растет трава,\nМои припомните слова.\n\n- Постараюсь, - сказала Алиса.\n\nА летом ночь короче дня,\nИ, может, ты поймешь меня.";
alert(str.replace(/^/gm, "<p>").replace(/$/gm, "</p>").replace(/(?:\<p\>\<\/p\>)|\n/g, ""));


P. S. Где регулярка block? Где её код?

ksevelyar 20.11.2011 19:57

Цитата:

Так. Во-первых, тестовые примеры здесь надо публиковать.
Это обязательно? Я не против, но примеры с jsfiddle более наглядны.

Цитата:

Во-вторых, абсолютно непонятно, какое поведение вам надо получить. Такое?
Я хочу выводить html, при этом переводы строки преобразовывать в <br />, а если переводов два и больше оборачивать абзац в <p></p>. Эту часть я сделал.

Теперь я хочу чтобы в абзацы не заворачивались блочные элементы. Но перед тем как составить регулярное выражение содержащие все блочные элементы «тренируюсь на кошках». В роли кошек: block = /(ac|dc)/gi;

Цитата:

P. S. Где регулярка block? Где её код?
str="ac dc";

block = /(ac|dc)/gi;
    
str = str.replace(block,'</p>'+block.exec(output)+'<p>'); 

//str = str.replace(/\n\n+/g,'</p><p>');
    
//str = str.replace(/\n/g, "<br />");  
    
//str = ('<p>'+str+'</p>') 

alert(str);


Хочу получить:

</p>ac<p> </p>dc<p>


upd

alert(str.replace(/^/gm, "<p>").replace(/$/gm, "</p>").replace(/(?:\<p\>\<\/p\>)|\n/g, ""));

Первые две замены вроде понял.

Нагуглил:

(?:...) 	Passive (non-capturing) group

(?:pattern) 	Соответствует строке pattern, но не запоминает найденное соответствие. Используется для группировки частей образца, например, /ко(?:т|шка)/ — это краткая запись выражения /кот|кошка/.


Не могли бы вы пояснить эту конструкцию?

trikadin 20.11.2011 20:45

Цитата:

Сообщение от ksevelyar
Это обязательно? Я не против, но примеры с jsfiddle более наглядны.

Почитайте о форматировании - здесь есть возможность делать запускаемые образцы, и это всем удобно.

А вообще вот, почитайте: "Регулярные выражения". А когда прочтёте (и поймёте) - почитайте про их особенности.

trikadin 20.11.2011 20:48

Если после этого останутся вопросы - прочтите ещё раз) И только в крайнем случае вам придётся обращаться на форум))

ksevelyar 20.11.2011 22:12

Вроде потихоньку въезжаю в регулярные выражения, продолжу утром :0

str = "<p><h1>Pestilence</h1>War<h2>Famine</h2><pre>Death</pre></p>"

block = /\<(h1|h2|h3|h4|h5|h6|pre|div|ul|)\>([\s\S]*)\<\/\1\>/gim;
        
str = str.replace(block, '</p>$&<p>'); 

alert(str);

trikadin 20.11.2011 22:19

ksevelyar, мне кажется, он не совсем правильно работает))

ksevelyar 21.11.2011 08:21

Цитата:

Сообщение от trikadin (Сообщение 137951)
ksevelyar, мне кажется, он не совсем правильно работает))

Знаю, но решаю проблемы парсера постепенно. Сейчас он корректно справляется с более сложным (но всё равно синтетическим) текстом:

// Формируем абзацы.  
str = ('<p>'+str.replace(/\n\n+/g,'</p><p>')+'</p>');
    
// Вытаскиваем из них блочные элементы.   
block = /\<(h1|h2|h3|h4|h5|h6|pre|div|ul|)\>(.*?)\<\/\1\>/gi;   
str = str.replace(block, '</p>$&<p>');   
  
// Формируем преводы строк (<br />).
str = str.replace(/\n/g, "<br />");   
 
// Чистка от <p><br />.    
str = str.replace(/\<p\>\<br \/\>/g, "<p>");
// Чистка от <p></p>.   
str = str.replace(/\<p\>\<\/p\>/g, "");


<textarea id="content"><h2>Шалтай</h2>
Весной, когда растет трава,
Мои припомните слова.

<h2>Болтай</h2>
- Постараюсь, - сказала Алиса.

А летом ночь короче дня,
И, может, ты поймешь меня.</textarea>


Выводит:

<h2>Шалтай</h2>

<p>Весной, когда растет трава,<br />
Мои припомните слова.</p>

<h2>Болтай</h2>

<p>- Постараюсь, - сказала Алиса.</p>

<p>А летом ночь короче дня,<br />
И, может, ты поймешь меня.</p>


Сейчас нужно будет добавить удаление пробелов между переводами строк.

Какие ещё нестандартные ситуации возможны?

ksevelyar 21.11.2011 10:20

// Удаляем строки состоящие из пробелов.
str = str.replace(/^\s+$/gm, "");  
 
// Формируем абзацы.  
str = ('<p>'+str.replace(/\n\n+/g,'</p><p>')+'</p>');
    
// Вытаскиваем из них блочные элементы.   
block = /\<(h1|h2|h3|h4|h5|h6|pre|div|ul|)\>(.*?)\<\/\1\>/gi;   
str = str.replace(block, '</p>$&<p>');   
  
// Формируем преводы строк (<br />).
str = str.replace(/\n/g, "<br />");   
 
// Чистка от "<p><br />".    
str = str.replace(/\<p\>\<br \/\>/gi, "<p>");
// Чистка от "<br /></p>".    
str = str.replace(/\<br \/\>\<\/p\>/gi, "</p>"); 

// Чистка от "<p></p>".   
str = str.replace(/\<p\>\<\/p\>/gi, "");


Теперь нужно исключить обработку содержимого списков и pre.

До сих пор я решал проблемы добавляя фильтры. Но с pre так не получится — внутри него уже могут быть <br /> и фильтр удалит и их.

В голову приходит мысль о получении всех оригинальных <pre>...</pre> в переменную и замена ими обработанных парсером вариантов. Но это как-то громоздко.

Как сделать проще?

upd:

Это можно сделать с помощью чего-то вроде (/(?!\<pre\>)\n(?!\1)/gi, "<br />"); отпишу как что-нибудь получится.


Часовой пояс GMT +3, время: 14:32.