simbiat / nl2tag
将换行符转换为不同HTML标签的类
Requires
- php: ^8.3
- ext-mbstring: *
This package is auto-updated.
Last update: 2024-09-22 05:31:46 UTC
README
将换行符转换为各种HTML标签(如 br
、p
和 li
)的类。它还可以帮助创建漂亮的变更日志(基于 li
包装)。
为什么?
最初的想法是创建一个 nl2br
的版本,但用于段落。如果你在 Google(或 Stackoverflow)中搜索它,可以找到几个简单的解决方案,但所有这些我都发现至少有一些缺陷。
- 它们不会检查是否已经有一个
p
标签在相应的段落周围。这可能会导致额外的段落。至少某些浏览器会将此显示为额外的段落,即 `<线1><p><线2>/p>线3</p>
` 将导致 3 个段落,这可能不是预期的。 - 实际上,有一些标签,按照 phrasing content 的规范,不应该放在
p
中。或者更确切地说,有一些标签,可以放在其中。 - 它们会更改标签内的换行符,而你可能希望保留换行符不变。例如,
pre
和textarea
是你通常希望保留换行符的标签。例如,code
、samp
、kbd
和var
是其他常见的值,但技术上可以是任何设置了white-space
CSS 属性为pre
、pre-wrap
、pre-line
或break-spaces
的标签。 - 它们通常只检查
\r\n
或只是\r
或\n
,而实际上还有更多表示换行的符号,以及相应的 HTML 实体,它们很容易出现在 HTML 字符串中。
当你处理 HTML 时,这些缺陷可能会成为问题,因此我想找到一种方法来规避这些问题,因此有了这个库。但在概念化初期,我意识到,对于 li
项目和甚至 br
,也很有意义去做类似的事情。
我还想能够创建可以很好地用 CSS 样式化的变更日志列表,并且由于这与我们为 nl2li
所拥有的逻辑相同,它是在同一个类中完成的。
限制
- 显然,由于处理过程试图变得“智能”,这里有各种各样的检查,它们确实会花费时间。它可能比其他解决方案慢,尽管你很可能不会注意到这一点。
- 没有递归。这意味着,如果你有类似
text <div>text2 text3</div> text4
的东西
<p>text</p><div>text2<br>text3</div><p>text4</p>
你会得到
<p>text</p><div><p>text2</p><p>text3</p></div><p>text4</p>
而不是
- 这是因为递归需要遍历 DOM 树,这意味着转换为
DOMDocument
,但转换字符串可能会在不可预测的位置添加额外的标签,因为它试图“修复”可能损坏的文档。这种修改可能会导致与预期截然不同的结果,并且无法预测。考虑到库的预期用途,使用单个级别应该足够。 - 我相信,由于这个类依赖于正则表达式,因此通过该类处理时,某些标签和/或换行符的组合可能会导致“损坏”的输出。另一种选择是依赖PHP的
DOMDocument
及其相关功能。
常量
类包含一些公共常量,以防您在其他代码类中需要类似的东西。
newLinesRegex
- 被视为“换行符”的实体列表。它是一个使用|
作为分隔符的字符串,可以直接用于正则表达式。voidElements
- 标准HTML5标签的数组,被视为“自闭合”,即不需要闭合标签。preserveSpacesIn
- 标准HTML5标签的数组,通常意味着在其中保留空白。phrasingContent
- 被视为“短语内容”的标准HTML5标签的数组,对此没有其他条件。flowContent
- 与phrasingContent
类似,但用于“流内容”,如规范中所述。
选项
该类有一些可以更改的选项(公共变量)。
$preserveSpacesIn
- 用于调整您想要在其中保留空白的标签列表。可以是一个空数组,这意味着所有标签内的换行符都可能被相应地替换。$phrasingContent
- 用于调整被视为短语内容的标签列表。不能从相应的常量中删除标签。最可能更新此列表的情况是您有自定义HTML元素。$flowContent
- 用于调整被视为流内容的标签列表。不能从相应的常量中删除标签。最可能更新此列表的情况是您有自定义HTML元素。$wrapperOnly
- 被视为仅作为包装器的标签列表,如table
等。它们可以在标签之间有换行符,除非排除在外,否则如果您启用了$situationalBR
,您可能会得到过多的<br>
标签。$insideWrappersOnly
- 仅在相应包装器内出现的标签列表,其中可以有有意义的换行符,如td
、th
。专门与$wrapperOnly
设置结合使用。$situationalBR
- 布尔标志(默认为true
),表示类是否可以在找到换行符时用<br>
替换内容中的换行符,并且它不是保留空白的位置。如果名称不够清晰,那是因为无法想出更合适的名称。$collapseNewLines
- 布尔标志(默认为true
),表示类是否尝试合并换行符。这意味着<br><br>
将替换为<br>
,<br>
标签将在<p>
标签之间被删除(即仅<p>1</p><br><p>2</p>
将更改为<p>1</p><p>2</p>
),并且仅由空白组成的段落也将被删除。我相信在大多数情况下,您会希望启用此功能,但可能存在您想避免它的情况,例如,当您可以在<textarea>
内部具有相应的组合时。$preserveNonBreakingSpace
- 布尔标志,表示类是否将保留带有非换行空格的空段落(即 
,在处理过程中转换为正确字符)。如果设置为true
(默认为false
),则即使$collapseNewLines
也设置为true
,则类似<p> </p>
的行也不会被删除。
用法
创建对象
$object = (new \Simbiat\nl2tag);
如有必要,调整设置。设置器可以链接使用。以下示例将添加custom-element
作为短语内容,并将只有textarea
需要保留空白。
$object->setPhrasingContent(['custom-element'])->setPreserveSpacesIn(['textarea']);
调用适当的函数,同时向其中发送字符串。
$result = $object->nl2p('string');
<div>asdasda</div> <a href="https://example.com">asdsada</a> test test2 <code class="test"> test3<div>afdas</div></code> <code>tgitjsglsjdgdsjglsd</code> <span>span</span> after_span <div class="test">test4</div> <p>test5</p> <div>test6 test7</div>
通过nl2p()
传递将提供此结果
<div>asdasda</div><p><a href="https://example.com">asdsada</a></p><p>test</p><p>test2</p><code class="test"> test3<div>afdas</div></code><p><code>tgitjsglsjdgdsjglsd</code></p><p><span>span</span> after_span</p><div class="test">test4</div><p>test5</p><div>test6<br>test7</div>
如果通过 nl2br()
处理,将提供以下结果:
<div>asdasda</div><br><a href="https://example.com">asdsada</a><br>test<br>test2<br><code class="test"> test3<div>afdas</div></code><br><code>tgitjsglsjdgdsjglsd</code><br><span>span</span> after_span<br><div class="test">test4</div><br><p>test5</p><br><div>test6<br>test7</div>
如果通过 nl2li()
处理,将提供以下结果:
<ul><li><div>asdasda</div></li><li><a href="">asdsada</a></li><li>test</li><li>test2</li><li><code class="test"> test3<div>afdas</div></code></li><li><code>tgitjsglsjdgdsjglsd</code></li><li><span>span</span> after_span</li><li><div class="test">test4</div></li><li><p>test5</p></li><li><div>test6<br>test7</div></li></ul>
nl2li()
默认将字符串包裹在 ul
中,但你可以传递一个可选的第二个字符串(menu
,ol
,ul
),这将允许你更改获取的列表类型。
还有 nl2li()
的一个变体,称为 changelog()
。逻辑非常相似,但它还会检查行文本值的第一字符,并为 <li>
添加适当的类。如果字符不是 *
、+
或 -
之一,则将开始一个子列表(即新的 <ul>
),直到遇到另一个类似行或字符串的末尾。
像这样的字符串
* Some general change in logic List of changes in a specific module: + Feature added - Feature removed List of changes in another module: * Some general change
将生成如下 HTML(在标签之间添加空白以提高可读性,实际字符串将不会包含它们):
<ul class="changelog_list"> <li class="changelog_change">Some general change in logic</li> <li class="changelog_sublist_name">List of changes in a specific module:</li> <ul class="changelog_sublist"> <li class="changelog_addition">Feature added</li> <li class="changelog_removal">Feature removed</li> </ul> <li class="changelog_sublist_name">List of changes in another module:</li> <ul class="changelog_sublist"> <li class="changelog_change">Some general change</li> </ul> </ul>
如果进行样式化,你可以得到一个看起来很不错的变更日志,例如,就像你在 这里 看到的那样。