When using Anqi CMS to manage website content, we sometimes find that the carefully written Markdown content, when displayed on the front-end page, generates HTML tags (such as<p>/<a>) was not correctly parsed by the browser, instead it was interpreted as&lt;p&gt;/&lt;a&gt;This format is displayed directly. This is usually not the effect we want, as it makes the page layout messy and loses the convenience of Markdown editors.

The reason for this phenomenon is that content management systems and template engines usually enable automatic escaping by default for the security of the website.When you edit and save Markdown content in the background, the system may store it in its original Markdown text form.When calling and displaying this content on the front-end page, the Anqi CMS template engine (similar to Django template syntax) will first render the Markdown text into HTML, for example, by transforming# 标题to<h1>标题</h1>The issue is that the generated HTML tags are automatically escaped by the template engine again before being output to the page, which will<h1>becomes&lt;h1&gt;This resulted in HTML tags being escaped twice, ultimately displaying as plain text in the browser.

After understanding this mechanism, the solution becomes clear.The core is to inform the template engine that this content is already in HTML format, it is safe, and does not need to be escaped.

Utilize|safeThe filter ensures that the content is rendered correctly.

The Anqi CMS template engine provides a namedsafeThe filter's role is to mark the content of the variable as 'safe HTML', preventing the template engine from escaping it twice.This is the most direct and commonly used method to solve the problem of Markdown content rendering where tags are escaped twice.

Assuming you are on the article detail page (or other content display page) througharchiveDetailtag to obtain the document content, and assign the content toarticleContentVariable:

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

by default,articleContentThe Markdown content is rendered into HTML, but its HTML tags may be escaped again. To avoid this second escaping, you just need to outputarticleContentWhen a variable is|safeFilter:

{{ articleContent|safe }}

Then the template engine sees when it receives the rendered HTML string,|safeThe filter will directly output it as HTML code, and the browser can correctly parse and display the proper formatting and style.

Important reminder: |safeThe filter acts like a "key of trust", telling the template engine that you fully trust the safety of this content. This means that if the Markdown content contains malicious scripts (XSS attack code), using|safeIt will be output as is, which may introduce security risks. Therefore, we strongly recommend only using content sources you trust (such as content entered by backend editors)|safe.

Fine-tune Markdown rendering behavior in specific scenarios

In some cases, you may want to control the rendering process of Markdown content more finely. For example, document contentContentThe field will automatically convert Markdown to HTML when the Markdown editor is turned on. However, you can also manually specify whether to perform this conversion, byrenderParameters are controlled.

If you set it when fetching contentrender=true, the system will forcibly convert Markdown to HTML on the server side. At this point, you still need to combine|safeA filter to prevent these generated HTML tags from being escaped twice:

{# 强制在服务器端将Markdown转为HTML,并使用 |safe 阻止二次转义 #}
{% archiveDetail articleContent with name="Content" render=true %}
{{ articleContent|safe }}

On the contrary, if you setrender=falseThen the system will not convert Markdown to HTML on the server side, but will output the original Markdown text directly.In this case, you usually need to process the original Markdown on the frontend through JavaScript libraries (such as libraries that support mathematical formulae or flowchart rendering). At this time,|safeThe filter is no longer a double-escape for HTML tags, but to ensure that the original Markdown text (if it contains similar HTML special characters) itself is not escaped by the template engine. However, it is more common that if you use a frontend renderer, the responsibility of HTML parsing is handed over to the browser and frontend scripts.|safeThe use case will be somewhat different, mainly depending on how the front-end renderer receives and processes the content.

In summary, to avoid the HTML tags generated by Markdown rendering from being escaped twice, the most critical step is always to remember to add when outputting variables containing HTML content in the template|safeFilter. This ensures that your content is displayed in the expected manner while reminding us to pay attention to the safety of the content source.


Frequently Asked Questions (FAQ)

1. Why does my Markdown content show HTML tags instead of rendering effects?

It is usually because the template engine of AnQi CMS, for security reasons, defaults to escaping all output variable content. When Markdown content is rendered into HTML, these HTML tags (such as<p>It will be escaped twice&lt;p&gt;It will result in displaying it as text in the browser. The solution is to use a filter in the template to inform the template engine that it should not be escaped.|safeThe filter informs the template engine that it should not be escaped.

2. Use|safeIs the filter safe? Will it introduce XSS risks?

|safeThe filter does indeed disable HTML escaping, which means that if there is malicious JavaScript code (XSS) in the content, it will also be output as is and executed. Therefore, it is necessary to use|safeBe cautious. It is recommended to only use this filter on content sources you trust (such as content edited by strictly reviewed back-end editors).For content generated by users, you may need to consider more complex filtering and purification measures, or completely avoid using|safe.

3. Besides|safeFilter, are there other methods to prevent automatic escaping?

except|safeFilter, the template engine also provides{% autoescape off %}and{% autoescape on %}tags to control the automatic escaping behavior of specific code blocks. The{% autoescape off %}Put at the beginning of a content block,{% autoescape on %}At the end, it can close the automatic escaping of all variables within the block. But usually,|safeThe filter, due to its finer scope of action, is the preferred choice for handling specific variable content because it only affects the marked variables and not the entire code block.