When using the AanQi CMS to manage website content, we often 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, but instead displayed as<p>/<a>This format is displayed directly. This is usually not the desired effect; it makes the page layout chaotic and loses the convenience advantages of the Markdown editor.
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 the form of raw Markdown text.# 标题Converted to<h1>标题</h1>The issue lies in the fact that the generated HTML tags are processed again by the automatic escaping mechanism of the template engine before being output to the page.<h1>becomes<h1>This resulted in HTML tags being doubly escaped, and ultimately displayed as plain text in the browser.
After understanding this mechanism, the solution becomes clear.The core is to inform the template engine: this content is already in HTML format, it is safe, and there is no need for further escaping.
Utilize|safeThe filter ensures the content is rendered correctly.
The template engine of Anqi CMS provides a name calledsafeThe filter, its role is to mark the content in the variable as "safe HTML", preventing the template engine from escaping it again.This is the most direct and commonly used method to solve the problem of Markdown content being escaped twice after rendering.
Suppose you are on the article detail page (or any content display page) and througharchiveDetailget the document content using tags, and assign the content toarticleContentVariable:
{%- archiveDetail articleContent with name="Content" %}
By default,articleContentThe Markdown content will be rendered into HTML, but its HTML tags may be escaped again. To avoid this second escaping, you only need to outputarticleContentA variable is, add it|safeFilter:
{{ articleContent|safe }}
In this way, when the template engine receives the rendered HTML string,|safeThe filter will output it directly as HTML code, and the browser can correctly parse and display the proper formatting and styles.
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 includes malicious scripts (XSS attack code), using|safe[en] Also output them as is, which may introduce security risks. Therefore, we strongly recommend that only content sources you trust (such as content inputted by backend editors) be used|safe.
Fine-tune Markdown rendering behavior in specific scenarios
In some cases, you may want to have more fine-grained control over the rendering process of Markdown content. For example, document contentContentThe field will automatically convert Markdown to HTML when the Markdown editor is enabled. However, you can also manually specify whether to perform this conversion, throughrenderControl the parameters.
If you set it when fetching content.render=trueThe system will force Markdown to be converted to HTML on the server side. At this point, you still need to combine|safeA filter to prevent these generated HTML tags from being doubly escaped:
{# 强制在服务器端将Markdown转为HTML,并使用 |safe 阻止二次转义 #}
{% archiveDetail articleContent with name="Content" render=true %}
{{ articleContent|safe }}
On the other hand, if you setrender=falseIf so, 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 handle the original Markdown through a JavaScript library (such as a library that supports rendering mathematical formulas or flowcharts).|safeThe filter is no longer about double escaping for HTML tags, but to ensure that the original Markdown text (if it contains special characters like HTML) itself is not escaped by the template engine. However, more commonly, if you use a frontend renderer, the responsibility of HTML parsing is handed over to the browser and frontend scripts.|safeThe use cases may vary slightly, mainly depending on how the frontend renderer receives and processes the content.
In summary, to avoid the HTML tags rendered from Markdown content being escaped again, the most critical step is to always remember to add when outputting variables containing HTML content in the template.|safeFilter. This ensures that your content is displayed as expected while reminding us to pay attention to the safety of the content source.
Common Questions (FAQ)
1. Why does my Markdown content display HTML tags instead of rendering effects?
It is usually because the template engine of AnQi CMS defaults to HTML-escape all output variable content for security reasons. When Markdown content is rendered to HTML, these HTML tags (such as<p>)Would be doubly escaped<p>,which would cause it to be displayed as text in the browser. The solution is to use|safea filter to inform the template engine that no escaping is needed.
2. Use|safeIs the filter safe? Will it introduce XSS risks?
|safeThe filter does indeed disable HTML escaping, which means that if malicious JavaScript code (XSS) is present in the content, it will be output and executed as-is. Therefore, it is essential to use|safeBe cautious at all times.Suggest using this filter only for content sources you trust (such as strictly reviewed backend editing content).|safe.
3. Besides|safeFilter, are there any 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 %}Place 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 more refined scope of action, is the preferred choice for handling specific variable content, as it only affects the marked variables and not the entire code block.