提问背景 Question:
我是说,我们之前写的baike_detail.html 模板,就是ai百科哪个页面
修复AI百科模板Markdown与HTML渲染问题
原来您指的是 baike_detail.html 模板页面!在 AI 百科详情页中,Markdown 无法解析、换行混乱以及 HTML 代码被直接渲染成页面样式,这是由于未启用 Markdown 解析器以及没有对 HTML 代码块进行安全转义导致的。
当 AI 输出包含 <div> 等 HTML 标签的代码时,如果直接用 |safe(Django)或 v-html(Vue)渲染,浏览器会直接把它们当成真正的网页 DOM 和 CSS 样式来解析,从而导致排版彻底崩溃。
以下是彻底修复该页面的两种主流方案,您可以根据项目的实际架构进行选择:
方案一:纯前端渲染(推荐,最简单直接)
如果您的后端只负责输出原始的 Markdown 文本,直接在 baike_detail.html 中使用 JavaScript 进行解析和高亮渲染是最省心的办法。
在 baike_detail.html 中引入 Marked(解析 Markdown)和 Highlight.js(代码高亮):
<!-- 1. 引入必要样式和 JS 库 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/github.min.css">
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<div class="baike-container">
<!-- 2. 原始数据存放在隐藏域或 data 属性中,避免直接作为 HTML 解析 -->
<div id="raw-content" style="display:none;">{{ article.content }}</div>
<!-- 3. 解析后的目标渲染容器 -->
<div id="markdown-content" class="markdown-body"></div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
// 获取原始文本
const rawMarkdown = document.getElementById('raw-content').textContent;
// 配置 Marked.js,防止 HTML 注入并支持代码高亮
marked.setOptions({
highlight: function(code, lang) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, { language }).value;
},
breaks: true, // 解决换行问题:支持单回车换行
sanitize: true // 安全模式:将文本中的 HTML 标签进行转义,防止其被当做样式渲染
});
// 解析并渲染
document.getElementById('markdown-content').innerHTML = marked.parse(rawMarkdown);
});
</script>
<style>
/* 解决换行混乱的核心 CSS */
.markdown-body {
white-space: pre-wrap; /* 保留空格与换行 */
word-wrap: break-word;
line-height: 1.6;
}
/* 代码块样式优化 */
.markdown-body pre {
background-color: #f6f8fa;
padding: 16px;
border-radius: 6px;
overflow: auto;
}
</style>
方案二:后端渲染(以 Django 为例)
如果您使用的是 Python Django 后端,建议在后端将 Markdown 转换为安全的 HTML,再传给前端渲染。
1. 安装 Python 依赖
pip install markdown python-markdown-math
2. 后端视图处理(views.py)
使用 markdown 库解析,并开启 fenced_code(支持 ``` 代码块)和 codehilite 扩展,同时使用安全转义:
import markdown
from django.utils.html import escape
from django.shortcuts import render
def baike_detail(request, pk):
article = get_object_or_404(Article, pk=pk)
# 配置 Markdown 解析器
md = markdown.Markdown(extensions=[
'markdown.extensions.extra', # 包含 fenced_code(代码块), tables(表格) 等
'markdown.extensions.codehilite', # 代码高亮
'markdown.extensions.nl2br', # 自动将单换行符转换为 <br>,解决换行混乱
])
# 注意:不要直接使用 |safe,markdown 渲染时会自动对代码块内的 HTML 实体进行转义
article.html_content = md.convert(article.content)
return render(request, 'baike_detail.html', {'article': article})
3. 前端模板渲染(baike_detail.html)
在前端只需正常输出,并引入高亮样式表即可:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/github.min.css">
<div class="markdown-body">
<!-- 经过后端安全转换后的 HTML,此时代码块内的 HTML 已被转义为 <div> 文本,不会变成真实样式 -->
{{ article.html_content|safe }}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<style>
.markdown-body {
line-height: 1.7;
font-size: 16px;
}
</style>
总结排查要点
- 不能直接用
|safe(或v-html)直接渲染带有<html>标签的原始 Markdown 字符串,必须先经过 Markdown 解析器。解析器会自动把代码块里的<变成<,从而避免被浏览器当成样式渲染。 - 换行混乱问题:通过开启解析器的
breaks: true(前端)或nl2br扩展(后端)解决,同时在 CSS 中为容器加入white-space: pre-wrap;确保换行符正常生效。