在运营网站时,我们有时会遇到这样的需求:后台录入的纯文本内容,希望在前端展示时能够自动显示行号,这对于展示代码、诗歌、配置脚本或任何需要逐行阅读的文本内容都非常有帮助。虽然AnQiCMS后台录入内容非常方便,但如何让这些纯文本内容在前端显示时,自动加上美观的行号呢?安企CMS灵活的模板引擎可以帮助我们轻松实现这一点。

理解内容来源与处理基础

首先,我们需要明确这些纯文本内容的来源。在AnQiCMS中,您通常会在“文档管理”或“页面管理”中,通过文档或单页的“内容”字段录入这些文本。这些内容在前端模板中,通常会通过archiveDetailpageDetail这样的标签来获取。例如,如果您要获取文章的详情内容,可能会这样写:

{% archiveDetail articleContent with name="Content" %}
{{ articleContent }}

这里的articleContent变量就包含了您从后台录入的文本。

AnQiCMS的模板引擎支持类似Django模板和Blade模板的语法,其中包含丰富的过滤器(filters),可以对变量进行各种处理。要为内容添加行号,我们主要会用到一个名为linenumbers的过滤器。这个过滤器会将文本内容按行进行处理,并在每一行前自动添加“1. ”、“2. ”这样的行号前缀。

处理可能含HTML标签的内容

很多时候,我们从AnQiCMS后台输入的内容并非纯粹的文本,即使看起来是纯文本,后台的富文本编辑器或Markdown编辑器也可能会在其中添加一些HTML标签,例如<div><p><span>等。如果您直接将含有这些HTML标签的内容应用linenumbers过滤器,它会将HTML标签也作为一行进行编号,这通常不是我们想要的结果,会使行号显示变得混乱。

为了解决这个问题,我们需要在应用linenumbers过滤器之前,先将内容中的所有HTML标签剥离掉,使其成为真正的纯文本。安企CMS提供了一个非常实用的striptags过滤器,它能够有效地剥离字符串中的所有HTML标签。

所以,处理流程变为:内容 -> 剥离HTML标签 -> 添加行号

在模板中,这会体现为过滤器的链式使用:

{{ articleContent | striptags | linenumbers }}

确保正确渲染:safe过滤器

当您应用了linenumbers过滤器后,输出的内容会是像 1. 这是第一行 这样的格式。AnQiCMS的模板引擎出于安全考虑,默认会对输出内容中的特殊字符(如<>)进行转义,以防止跨站脚本攻击(XSS)。这意味着,如果您不加处理,浏览器可能会把“1. ”这些内容当作普通的字符串显示,而不是将其作为HTML渲染。

此时,我们需要使用safe过滤器来告诉模板引擎,这段内容是安全的,可以直接作为HTML输出,让浏览器按照HTML规范进行解析和显示。safe过滤器通常放在所有其他过滤器的最后,以确保最终输出的内容被正确处理。

所以,完整的处理流程是:内容 -> 剥离HTML标签 -> 添加行号 -> 标记为安全HTML

最终的过滤器链看起来是这样的:

{{ articleContent | striptags | linenumbers | safe }}

整合方案示例

让我们来看一个完整的例子,假设您在后台发布了一篇文章,内容是多行的纯文本或包含简单HTML的文本,您希望在文章详情页 (archive/detail.html 或自定义文章模板) 中显示带有行号的内容。

在您的模板文件中(例如template/default/archive/detail.html),找到显示文章内容的部分,并进行修改:

<article class="article-detail">
    <h1>{% archiveDetail with name="Title" %}</h1>
    <div class="article-meta">
        <span>发布日期:{% archiveDetail with name="CreatedTime" format="2006-01-02" %}</span>
        <span>浏览量:{% archiveDetail with name="Views" %}</span>
        <!-- 其他文章元信息 -->
    </div>

    <div class="article-content-with-line-numbers">
        {%- archiveDetail articleContent with name="Content" %}
        <pre class="line-numbers-pre"><code>{{ articleContent | striptags | linenumbers | safe }}</code></pre>
    </div>

    <!-- 上一篇/下一篇、相关文章等其他内容 -->
</article>

在上面的代码中,我们首先通过{%- archiveDetail articleContent with name="Content" %}将文章内容获取到一个名为articleContent的变量中。{%-的使用是为了避免在这一行引入不必要的空白。

接着,在<pre><code>...</code></pre>标签内部,我们对articleContent变量依次使用了striptagslinenumberssafe三个过滤器。

  • striptags确保内容是纯文本。
  • linenumbers为每一行添加编号。
  • safe让浏览器将带有行号的文本作为HTML正确渲染。

使用<pre>标签是为了保留内容的原始格式,特别是空格和换行符,而<code>标签则表明这是代码内容,有助于语义化。

一些样式美化建议

linenumbers过滤器默认生成的行号样式可能比较简单,例如1.。如果您希望行号显示得更美观,可以通过CSS进行一些定制。例如,您可以为行号和内容分别设置不同的颜色、字体或对齐方式。

/* 在您的 style.css 文件中添加 */
.line-numbers-pre {
    background-color: #f8f8f8;
    border: 1px solid #ddd;
    padding: 15px;
    margin-bottom: 20px;
    overflow-x: auto; /* 确保长行可以滚动 */
    white-space: pre-wrap; /* 保留空白符和换行符 */
}

.line-numbers-pre code {
    display: block; /* 确保每行独立显示 */
    font-family: monospace;
    line-height: 1.6;
    color: #333;
}

.line-numbers-pre code span.line-number { /* 假设linenumbers会给行号一个span */
    color: #999;
    margin-right: 10px;
    text-align: right;
    display: inline-block; /* 让行号保持独立 */
    min-width: 30px; /* 确保行号有足够的宽度 */
}

请注意,linenumbers过滤器本身并没有直接为行号包裹<span>标签,它只是在每行文本前添加了1.这样的前缀。因此,如果您需要对行号进行更精细的CSS控制,可能需要考虑使用JavaScript在前端动态处理,或者接受其默认的输出格式,并通过precode标签的样式来间接影响整体呈现。

通过以上步骤,您就可以让AnQiCMS后台输入的纯文本内容,在前端模板中自动以带有行号的清晰格式呈现了。


常见问题解答 (FAQ)

Q1:如果我的内容已经是纯文本,还需要使用 striptags 过滤器吗?

A1:理论上来说,如果内容确定是完全没有HTML标签的纯文本,striptags过滤器并不是必需的。但为了确保兼容性,尤其是当您不确定后台内容是否会被富文本编辑器“污染”时,加上striptags是一个更稳妥的选择,它不会对纯文本产生负面影响,只会剥离可能存在的任何HTML标签,确保linenumbers过滤器只处理纯文本内容。

Q2:linenumbers 过滤器输出的行号样式可以自定义吗?例如,我想要[1]而不是1.

A2:linenumbers过滤器目前默认以“1.”、“2.”这样的格式添加行号,并且不直接提供修改行号格式的参数。如果您需要更高级的行号格式(如[1]),可能需要结合自定义JavaScript或更复杂的模板逻辑来实现。在CSS层面,您可以通过调整precode标签的样式,例如设置文本颜色、行高、内边距等,来间接美化行号的显示效果。

Q3:我只想给文章内容中的某个特定段落添加行号,而不是整个内容,可以实现吗?

A3:可以的。linenumbers过滤器是作用于整个字符串