Вопрос по php, nl2br, regex, line-breaks, html – PHP: Как сохранить разрывы строк, используя nl2br () с очистителем HTML?

4

Выпуск: Когда используешьОчиститель HTML для обработки введенного пользователем содержимого разрывы строк не переводятся в<br> теги.

Рассмотрим следующий вводимый пользователем контент:

Lorem ipsum dolor sit amet.
This is another line.

<pre>.my-css-class {
    color: blue;
}
</pre>

Lorem ipsum:


Lorem
Ipsum
Dolor


Dolor sit amet,
MyName

При обработке с использованием HTML-очистителя вышеприведенное изменяется следующим образом:

Лорем ипсум долор сит амет. Это еще одна строка.

.my-css-class {
    color: blue;  
} 

Lorem ipsum:

LoremIpsumбольДолор сижу амет, MyName

Как вы видете, "Мое имя" который должен был находиться на отдельной строке пользователем, отображается вместе с предыдущей строкой.

Как исправить?

Использование PHPnl2br() функция, конечно. Однако возникают новые проблемы, независимо от того, используем ли мы его до или послеочищающий содержимое.

Вот пример использования nl2br () перед очистителем HTML:

Лорем ипсум долор сит амет.

Это еще одна строка.

.my-css-class {

    color: blue; 

} 

Lorem ipsum:

LoremIpsumболь

Долор сижу амет,

Мое имя

Что происходит, что nl2br () добавляет<br> для каждого переноса строки, поэтому даже те, в

 блок обрабатывается, а также разрывы строк после каждого тег.

Что я пробовал

Я попробовалпользовательская функция nl2br () который заменяет разрывы строк на<br> теги, а затем удаляет все<br> теги от

 блоки. Это прекрасно работает, однако проблема остается для Предметы.

Попытка того же подхода для блоки также удалят все<br> теги из дети, если мы не будем использовать более сложное регулярное выражение для удаления<br> теги внутри элементы, но снаружи элементы. Но тогда как насчет вложенных в пределах вещь? Чтобы справиться со всеми этими ситуациями, мыЯ должен иметь еще более сложное регулярное выражение!

Если это правильный подход, не могли бы вы помочь мне с регулярным выражением?Если оно'Не правильный подход, как я могу решить эту проблему? Я также открыт к альтернативам HTML-очистителю.

Другие ресурсы, которые ямы уже смотрели на:

HTMLPurifier: авто бр

http://htmlpurifier.org/phorum/read.php?2,3034
Вы'действительно нужно разобрать HTML и применитьnl2br только на определенных текстовых узлах, исключая
 элементы «.: Тот'Это именно то, что я хочу, есть идеи, как мне добиться этого с помощью HTML Purifier (или другого)? Ваша помощь очень ценится;)
Community
Re "Тот'с ума: Да, это. И ТАК используетРазметка разрывов строк! SO просто не удаляет некоторые теги HTML, но имеет Markdown для базового форматирования текста, включая разрывы строк. Тот'Моя точка зрения: если вы требуете от своих пользователей писать только HTML и HTML, тогдаЭто обмен. deceze
@ deceze я понимаю, что этоэто не легкая задача, однако яищу техническую помощь, а не советую о первоначальном выборепозволяющий (невнушительный) некоторые теги HTML. Если ты'Если вы заинтересованы в таком аргументе, посмотрите соответствующий вопрос о правильной разметке:stackoverflow.com/questions/342961/... Ура! Community
@deceze контент поступает из простой текстовой области, где допускаются некоторые теги HTML. Разрешение некоторых тегов HTML, таких как,<strong></strong>
 или же это новая тенденция, которая стремится заменитьBB-кода,уценка, а такжетекстильный например.
Community

Ваш Ответ

2   ответа
0

возможно это поможет.

function custom_nl2br($html) {
    $pattern = "/(.*?)/s";
    preg_match($pattern, $html, $matches);

    $html = nl2br(str_replace($matches[0], '[placeholder]', $html));
    $html = str_replace('[placeholder]',$matches[0], $html);

    return $html;
}
4

Эта проблема может быть решена частично (если не полностью) с помощью пользовательскихnl2br() функция:

function nl2br_special($string){

    // Step 1: Add <br> tags for each line-break
    $string = nl2br($string); 

    // Step 2: Remove the actual line-breaks
    $string = str_replace("\n", "", $string);
    $string = str_replace("\r", "", $string);

    // Step 3: Restore the line-breaks that are inside <pre></pre> tags
    if(preg_match_all('/\(.*?)\/', $string, $match)){
        foreach($match as $a){
            foreach($a as $b){
            $string = str_replace('<pre>'.$b.'</pre>', "<pre>".str_replace("<br>", PHP_EOL, $b)."</pre>", $string);
            }
        }
    }

    // Step 4: Removes extra <br> tags

    // Before <pre> tags
    $string = str_replace("<br><br><br><pre>", '<br><br><pre>', $string);
    // After </pre> tags
    $string = str_replace("</pre><br><br>", '</pre><br>', $string);

    // Arround  tags
    $string = str_replace("<br><br>", '<br>', $string);
    $string = str_replace("<br><br>", '<br>', $string);
    // Inside   tags
    $string = str_replace("<br>", '', $string);
    $string = str_replace("<br>", '', $string);

    // Arround  tags
    $string = str_replace("<br><br>", '<br>', $string);
    $string = str_replace("<br><br>", '<br>', $string);
    // Inside   tags
    $string = str_replace("<br>", '', $string);
    $string = str_replace("<br>", '', $string);

    // Arround  tags
    $string = str_replace("<br>", '', $string);
    $string = str_replace("<br>", '', $string);

    return $string;
}

Это должно быть применено к содержаниюдо это очищенный HTML. Никогда не перерабатывайте очищенный контент, если вы не знаете, что выделаешь

Обратите внимание, что, поскольку каждый разрыв строки и двойной разрыв строки уже сохранены, вы не должны использоватьAutoFormat.AutoParagraph Особенность HTML Purifier:

// Process line-breaks
$string = nl2br_special($string);

// Initiate HTML Purifier config
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('HTML.Allowed', 'p,ul,ol,li,strong,b,em,i,u,a[href],code,pre,blockquote,cite,img[src|alt],br,hr,h3,h4');
//$purifier_config->set('AutoFormat.AutoParagraph', true); // Make sure to NOT use this

// Initiate HTML Purifier
$purifier = new HTMLPurifier($purifier_config);

// Purify the content!
$string = $purifier->purify($string);

Тот'сидеть!

Кроме того, поскольку изначально допускались базовые теги HTML,улучшить пользовательский опыт, не добавляя другой синтаксис разметкиВы можете разрешить пользователям публиковать код, особенно HTML-код, который не будет интерпретироваться / удаляться HTML-очистителем.

HTML Purifier в настоящее время позволяет размещать код, но требует сложных маркеров CDATA:


Трудно запомнить и написать. Чтобы максимально упростить взаимодействие с пользователем, я считаю, что лучше всего разрешить пользователям добавлять код, встраивая его с помощью простого кода.<code></code> (для встроенного кода) и<code></code>

 (для блоков кода) теги. Вот как это сделать:<p></p><pre><code>function custom_code_tag_callback($code) {

    return '<code>'.trim(htmlspecialchars($code[1])).'</code>';
}
function custom_pre_tag_callback($code) {

    return '<pre><code>'.trim(htmlspecialchars($code[1])).'</code></pre>';
}

// Don't require HTMLPurifier's CDATA enclosing, instead allow simple <code> or </code><pre><code> tags
$string = preg_replace_callback("/\(.*?)\/is", 'custom_code_tag_callback', $string);
$string = preg_replace_callback("/\(.*?)\/is", 'custom_pre_tag_callback', $string);
</code></pre><p>Обратите внимание, что, как и обработка nl2br, она должна быть выполнена до того, как содержимое будет очищено HTML. Кроме того, имейте в виду, что если пользователь ставит<code><code></code> или же<code></code></code></p><pre><code> теги в своем собственном размещенном коде, тогда он закроет родительский<code><code></code> или же<code></code><pre><code></code> тег, содержащий его код. Это не может быть решено, а также применимо к исходным маркерам CDATA или к любой разметке, даже той, которая используется в StackOverflow (например, использование символа `в образце кода закроет тег кода).<p></p><p>Наконец, для удобства пользователей есть и другие вещи, которые мы могли бы автоматизировать, например, ссылки, которые мы хотим сделать кликабельными. К счастью, это можно сделать с помощью HTML Purifier.<code>AutoFormat.Linkify</code> особенность.</p><p>Вот окончательный код, который включает в себя все для окончательной настройки:</p><pre><code>// === Declare functions ===

function nl2br_special($string){

    // Step 1: Add <br> tags for each line-break
    $string = nl2br($string); 

    // Step 2: Remove the actual line-breaks
    $string = str_replace("\n", "", $string);
    $string = str_replace("\r", "", $string);

    // Step 3: Restore the line-breaks that are inside <pre></pre> tags
    if(preg_match_all('/\(.*?)\/', $string, $match)){
        foreach($match as $a){
            foreach($a as $b){
            $string = str_replace('<pre>'.$b.'</pre>', "<pre>".str_replace("<br>", PHP_EOL, $b)."</pre>", $string);
            }
        }
    }

    // Step 4: Removes extra <br> tags

    // Before <pre> tags
    $string = str_replace("<br><br><br><pre>", '<br><br><pre>', $string);
    // After </pre> tags
    $string = str_replace("</pre><br><br>", '</pre><br>', $string);

    // Arround  tags
    $string = str_replace("<br><br>", '<br>', $string);
    $string = str_replace("<br><br>", '<br>', $string);
    // Inside   tags
    $string = str_replace("<br>", '', $string);
    $string = str_replace("<br>", '', $string);

    // Arround  tags
    $string = str_replace("<br><br>", '<br>', $string);
    $string = str_replace("<br><br>", '<br>', $string);
    // Inside   tags
    $string = str_replace("<br>", '', $string);
    $string = str_replace("<br>", '', $string);

    // Arround  tags
    $string = str_replace("<br>", '', $string);
    $string = str_replace("<br>", '', $string);

    return $string;
}


function custom_code_tag_callback($code) {

    return '<code>'.trim(htmlspecialchars($code[1])).'</code>';
}

function custom_pre_tag_callback($code) {

    return '<pre><code>'.trim(htmlspecialchars($code[1])).'</code></pre>';
}



// === Process user's input ===

// Process line-breaks
$string = nl2br_special($string);

// Allow simple <code> or </code><pre><code> tags for posting code
$string = preg_replace_callback("/\(.*?)\/is", 'custom_code_tag_callback', $string);
$string = preg_replace_callback("/\(.*?)\/is", 'custom_pre_tag_callback', $string);


// Initiate HTML Purifier config
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('HTML.Allowed', 'p,ul,ol,li,strong,b,em,i,u,a[href],code,pre,blockquote,cite,img[src|alt],br,hr,h3,h4');
$purifier_config->set('AutoFormat.Linkify', true); // Make links clickable
//$purifier_config->set('HTML.TargetBlank', true); // Uncomment if you want links to open new tabs
//$purifier_config->set('AutoFormat.AutoParagraph', true); // Leave this commented as it conflicts with nl2br


// Initiate HTML Purifier
$purifier = new HTMLPurifier($purifier_config);

// Purify the content!
$string = $purifier->purify($string);
</code></pre><p>Ура!</p></code></pre></pre></code></code></pre></code></pre>

Похожие вопросы