0

我正在使用 PECL bbcode 扩展来定义一组我允许用于论坛的标签。我已经实现了http://www.bbcode.org中描述的几乎所有标签。

论坛用户已经开始期望,当他们在输入字段中换行时,他们的帖子也会换行。我正在努力做到这一点。

nl2br()方式_

nl2br()非常适合让浏览器在用户键入时使用换行符,因为它会找到换行符并<br />在其中抛出标签以使浏览器也使用换行符。但这会给一些更复杂的标记带来麻烦。

例如:

[ul]
[li]list item 1[/li]
[li]list item 2[/li]
[/ul]

结果是

<ul><br />
<li>list item 1</li><br />
<li>list item 2</li><br />
<ul>

这会在任何地方抛出空格。出于同样的原因,表格也有类似的问题。此外,任何实际显示空格的标签(例如<pre><code>code goes here</code></pre>)都会被双倍行距。恶心。

CSS方式

CSS 有white-space一些规则可以在这些情况下派上用场。如果我们将所有论坛帖子放在一个.bbcode元素中,然后只包含样式表规则

.bbcode {
    white-space: pre-line;
}

然后浏览器将保留换行符,折叠其他空格并换行。这听起来很理想。但是,列表项等仍然会出现这种双倍行距问题,因为浏览器会在每个</li>.

我们可以通过定义来解决其中的一些问题:

.bbcode {
    white-space: pre-line;
}
.bbcode * {
    white-space: normal;
}

这缓解了列表和表格中的问题。但是,现在换行符只出现在帖子的根元素中,因此在例如表格单元格中使用换行符是行不通的。

我该怎么做?方法

我真正想要的是两种效果的组合:

  • 当源在所有标签之外换行时,浏览器会换行
  • 当源在块级或结构标签的关闭或打开之后不立即换行时,浏览器会换行

理想情况下,我认为[li]some\ntext[/li]应该导致两行,[li]sometext[/li]\n应该只导致一行,并且[i]sometext[/i]\n应该导致两行。

这样的事情是怎么做的?或者更确切地说,人们通常在使用 bbcode 的论坛上做什么?我可能会编写一个函数,在其中定义<br />应该插入 a 的所有情况,这闻起来很像重新发明许多轮子。

4

2 回答 2

1

我现在决定的是

nl2br-str_replace方式_

$html = nl2br(bbcode_parse($handler, htmlentities($bbcode_string)));
$html = str_replace(
    array('</div><br />', '<tr><br />', '</tr><br />', '<th><br />', '</th><br />', '<td><br />', '</td><br />', '<ul><br />', '</ul><br />', '<ol><br />', '</ol><br />', '<li><br />', '</li><br />', '</pre><br />'),
    array('</div>', '<tr>', '</tr>', '<th>', '</th>', '<td>', '</td>', '<ul>', '</ul>', '<ol>', '</ol>', '<li>', '</li>', '</pre>'), $html);
return $html;

和 CSS:

.bbcode pre br {
    display: none;
}

这里发生了什么?我不是定义我想要换行符的位置,而是定义我知道它们会在哪里并且我想要它们。

CSS 防止pre元素中的双倍行距(并且您需要添加任何其他从空格中获取换行符的元素)。PHP摆脱了用户在例如[li]stuff[/li]元素之间放置换行符引起的换行符。

这很脆弱:如果用户在 [/li] 之后和换行符之前键入一个空格,则<br />不会删除。我可能可以使用正则表达式来查找,[tag][whitespace]<br />但我不认为这是一个大问题。


我现在接受这个答案,因为这是我在过去几天所能想到或找到的最好的答案。如果其他人知道更好的解决方案,请发布它,我很乐意接受它。

于 2015-03-01T16:57:28.800 回答
0

如果其他人有解决方案,我很乐意听到并接受它,但在此期间,我能够提出的最佳解决方案是我将称之为:

鬼鬼祟祟(但 HTML 无效)的 CSS 方式

只需使用 PHP 的nl2br()函数,保留white-space: normal,但添加以下 CSS 规则:

.bbcode ul > br,
.bbcode ol > br,
.bbcode table > br,
.bbcode tr > br,
.bbcode pre br {
    display: none;
}

基本上,这使您可以定义不应显示的“br”实例。特别是,当它们在列表中但不在列表项中、在表中但不在单元格中以及在 pre 中(其中已经保留了空格)时,我将它们隐藏起来。

然后我们需要隐藏块级元素的尾随换行符:

.bbcode table + br,
.bbcode ul + br,
.bbcode ol + br,
.bbcode div + br,
.bbcode iframe + br,
.bbcode pre + br,
.bbcode blockquote + br {
    display: none;
}

就是这样!我们可以使用包含很多规则的单个elem + br规则,但是因为我在使用我知道是(相当)跨浏览器的选择器表示法可以安全地玩它之前从未听说过这种选择器尽可能兼容。

我希望这可以帮助别人!

于 2015-02-28T15:50:59.070 回答