在内容运营中,我们经常会遇到这样的需求:在一篇文章列表页或者某个专题页上,需要展示文章的摘要内容。这些文章通常是通过Markdown编辑器撰写的,内容中可能包含图片、链接、加粗文本等丰富的HTML结构。如果只是简单地对Markdown渲染后的HTML字符串进行字符或单词截断,往往会破坏其原有的标签结构,导致页面布局混乱,甚至出现未闭合的标签,严重影响用户体验。
安企CMS作为一个高效、灵活的内容管理系统,充分考虑了这类内容展示的挑战。它通过其强大的模板引擎和内置的过滤器功能,提供了一套优雅的解决方案,让我们能够在截取Markdown渲染后的HTML内容时,确保标签结构完整无损。
理解安企CMS中的Markdown内容渲染
首先,我们需要了解安企CMS是如何处理Markdown内容的。当我们在后台使用Markdown编辑器撰写文章时,系统会将Markdown文本存储起来。在前端页面需要展示这些内容时,特别是像文档详情页这样的完整内容页面,通常会将Markdown文本渲染成HTML。
在安企CMS的模板中,我们可以通过archiveDetail标签来获取文章的各种字段,其中就包括Markdown编辑器的内容字段Content。这个Content字段在调用时有一个非常实用的render参数。当我们设置render=true时,系统会自动将存储的Markdown文本转换并渲染成标准的HTML内容。如果不需要渲染,则可以设置为render=false,或者在编辑器关闭时省略此参数,此时Content字段会输出原始的Markdown文本。
例如,要获取渲染后的文章内容,我们可以这样使用:
{% archiveDetail articleContent with name="Content" render=true %}
需要注意的是,渲染后的HTML内容,在模板中输出时为了避免被浏览器再次转义显示为纯文本,还需要配合|safe过滤器使用。这是Web开发中常见的安全实践,|safe告诉模板引擎这段内容是安全的HTML,可以直接输出。
核心策略:智能截取HTML内容
现在,我们已经获得了渲染后的HTML内容,但如果直接对这个HTML字符串进行字符或单词截断,问题就出现了。例如,一段HTML <p>这是一段<b>重要的</b>文字。</p>,如果我们在“重要”二字中间截断,那么<b>标签就无法闭合,浏览器会尝试修复,但结果往往不可预测,导致排版错乱。
为了解决这个问题,安企CMS内置了专门用于处理HTML内容的截断过滤器:truncatechars_html和truncatewords_html。
truncatechars_html:number:这个过滤器会根据指定的字符数量来截断HTML内容,同时智能地检查并闭合所有未闭合的HTML标签。它会确保截断后的HTML仍然是一个有效的、结构完整的片段,并且在截断位置添加省略号“…”。truncatewords_html:number:与truncatechars_html类似,但它是根据指定的单词数量来截断HTML内容。它同样会处理HTML标签的闭合问题,并添加省略号。
这两个过滤器是截取HTML内容而不破坏标签结构的关键。
实战演练:截取Markdown渲染后的HTML内容
假设我们正在构建一个文章列表页,每篇文章都需要显示一个150字符左右的摘要,并且希望摘要保留Markdown中原有的加粗、斜体等HTML样式。
在我们的模板文件中,可以这样来编写:
{# 假设我们正在遍历一个文章列表,item是当前文章对象 #}
{% for item in archives %}
<div class="article-summary">
<h3><a href="{{ item.Link }}">{{ item.Title }}</a></h3>
<div class="summary-content">
{# 先获取并渲染Markdown内容为HTML #}
{%- archiveDetail fullContent with name="Content" id=item.Id render=true %}
{# 对渲染后的HTML内容进行字符截断,并确保安全输出 #}
{{ fullContent|truncatechars_html:150|safe }}
</div>
<a href="{{ item.Link }}" class="read-more">阅读更多 ></a>
</div>
{% endfor %}
在上面的代码中:
- 我们首先通过
{% archiveDetail fullContent with name="Content" id=item.Id render=true %}获取了指定文章的Content字段内容,并将其强制渲染为HTML。渲染后的HTML内容被赋值给fullContent变量。 - 接着,我们对
fullContent变量使用了|truncatechars_html:150过滤器。这个过滤器会智能地截取HTML内容的前150个字符(包括HTML标签自身占用的字符),并且最重要的是,它会自动处理截断位置可能导致的未闭合标签,将其正确闭合。 - 最后,我们再次使用了
|safe过滤器,以确保截取并处理后的HTML摘要能够被浏览器正常解析和显示,而不是作为纯文本输出。
通过这种方式,我们可以在文章列表页上看到每篇文章的简短摘要,这些摘要既保留了原有的HTML格式,又避免了因截断而产生的标签结构破坏问题,使得页面布局保持整洁。
进一步的思考:何时选择哪种截取方式
- 按字符截取 (
truncatechars_html): 当你对摘要的长度有严格的字符数量限制时,例如要求所有摘要都控制在100个字符以内,不论其内容是中文、英文还是HTML标签,truncatechars_html会是更精确的选择。 - 按单词截取 (
truncatewords_html): 如果你的网站内容主要是英文,并且希望摘要在语义上更完整,避免在单词中间截断,那么truncatewords_html会更适合。它会尝试在单词边界处截断,使摘要更具可读性。 - 获取纯文本摘要 (
striptags): 有时候,我们可能完全不需要保留任何HTML样式,只想要纯文本的摘要。在这种情况下,可以使用|striptags过滤器,它会移除所有的HTML标签,然后你再对得到的纯文本进行|truncatechars或|truncatewords截断。例如:{{ fullContent|striptags|truncatechars:150 }}。
安企CMS的这些内置功能,为内容运营者提供了极大的便利。无需手动清理HTML,也无需担心复杂的正则匹配,只需简单地在模板中调用相应的标签和过滤器,就能轻松实现高质量的内容摘要展示。
常见问题 (FAQ)
1. 如何获取Markdown内容的原始文本,而不是渲染后的HTML?
如果你想在前端页面获取Markdown内容的原始文本,而不是经过渲染后的HTML,可以在archiveDetail标签中将render参数设置为false。例如:
{% archiveDetail rawMarkdown with name="Content" render=false %}
此时rawMarkdown变量中存储的就是未经转换的Markdown原文。
2. 如果我只想获取纯文本摘要,不保留任何HTML标签,该怎么做?
如果你希望摘要是纯文本,不保留任何HTML标签,可以先使用|striptags过滤器移除所有HTML标签,然后再进行字符或单词截断。例如,截取150个字符的纯文本摘要:
{% archiveDetail fullContent with name="Content" render=true %}
{{ fullContent|striptags|truncatechars:150 }}
这里先将Markdown渲染成HTML,再剥离HTML标签,最后截断纯文本。
3. 为什么在使用truncatechars_html或truncatewords_html之后,还需要加上|safe过滤器?
安企CMS的模板引擎(类似Django)默认会对所有输出内容进行HTML转义,以防止跨站脚本攻击(XSS)等安全问题。这意味着,即使truncatechars_html或truncatewords_html过滤器已经智能地处理了HTML标签闭合,生成了有效的HTML片段,如果缺少|safe过滤器,这些HTML标签(例如<p>、<b>)仍然会被转义成实体编码(例如<p>、<b>),导致浏览器无法正确解析和渲染。加上|safe是为了明确告知模板引擎,这段内容是经过验证的,可以直接作为HTML输出。