【问题标题】:How should one handle newlines in bbcode?应该如何处理 bbcode 中的换行符?
【发布时间】:2015-04-30 23:35:41
【问题描述】:

我正在使用 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>

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

CSS 方式

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

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

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

我们可以通过定义一些来解决:

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

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

我该怎么做?方式

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

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

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

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

【问题讨论】:

    标签: css whitespace bbcode pecl nl2br


    【解决方案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] 之后和换行符之前键入一个空格,&lt;br /&gt; 不会被删除。我或许可以使用正则表达式来查找[tag][whitespace]&lt;br /&gt;,但我不认为这是一个大问题。


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

    【讨论】:

      【解决方案2】:

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

      偷偷摸摸(但无效的 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 规则的单个规则,但是因为我从未听说过这种选择器,然后我才可以通过使用我知道的选择器表示法(相当)安全地玩它尽可能跨浏览器兼容。

      我希望这对某人有帮助!

      【讨论】:

      • 拥有br 根本不显示不会使他们在列表或表格中创建的无效标记更好一点。这不是“偷偷摸摸”,它只是在对抗症状,而不是真正的问题。
      • 好点,我已经调整了标题。我仍然希望听到更好的方法,但在此之前我将采用这种方法。
      • 另一个注意事项:这不会从表格元素之间干净地删除换行符,因为浏览器(好吧,至少是 chrome)将通过移动 @987654327 来“修复”错误标记@标签在样式表之前的表格之前有机会隐藏它们。
      猜你喜欢
      • 2019-09-15
      • 1970-01-01
      • 2010-09-07
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 1970-01-01
      相关资源
      最近更新 更多