必须用 template.HTML 包装 Markdown 解析结果才能在 Gin 模板中正确渲染 HTML,因为 html/template 默认转义所有字符串以防止 XSS;若传入普通 string,即使内容是 HTML 标签也会被显示为源码。

直接用 html/template 渲染 Markdown 原文会原样输出标签字符,浏览器看到的是 <p>Hello</p> 而不是渲染后的段落——必须显式解除 HTML 转义,且前提是 Markdown 解析器输出的是已转义的安全 HTML。
为什么 c.HTML() 默认不渲染 Markdown 内容
Gin 的 c.HTML() 底层使用 Go 标准库 html/template,它对所有 .xxx 插值默认执行 HTML 转义(如 → <code><),这是安全机制,防止 XSS。而 Markdown 解析器(如 goldmark、blackfriday)返回的是纯 HTML 字符串,若不经处理直接传入模板,就会被二次转义。
- 错误现象:
{{.Content}}在模板中显示为一堆带<的乱码,而不是正常排版 - 根本原因:不是 Gin 限制,而是
html/template的安全策略在起作用 - 关键前提:你必须自己完成 Markdown → HTML 的解析,Gin 不提供内置 Markdown 支持
如何安全地把 Markdown 渲染成 HTML 并插入模板
分两步:先用第三方库(如 github.com/yuin/goldmark)把 Markdown 字符串转成 HTML 字符串;再用 template.HTML 类型包装结果,告诉模板引擎“这段 HTML 是可信的,别转义”。
WiseOCR — 将 PDF 或图片文件转换为高质量 Markdown 文本,支持表格完整识别、多栏版式还原、中英文混排。适用场景:扫描件文字提取、纸质文档数字化、合同/报告/论文转文本、图片中文字提取。支持格式:PDF、JPG、JPEG、PNG、WEBP、GIF、BMP、TIFF。触发:用户上传文件并要求"帮我识别这个文件的文字"、"PDF转文字"、"图片转文本"、"帮我提取这个表格"——会调用本技能。说"用Wi
- 安装解析器:
go get github.com/yuin/goldmark - 在 handler 中解析并转换类型:
import "github.com/yuin/goldmark" <p>md := goldmark.New() var buf bytes.Buffer md.Convert([]byte("# Hello World\n\nThis is <em>italic</em>."), &buf) contentHTML := template.HTML(buf.String()) // 关键:转成 template.HTML</p><p>c.HTML(http.StatusOK, "post.html", gin.H{ "Title": "My Post", "Content": contentHTML, // 直接传入,模板里 {{.Content}} 就能渲染 }) </p> - 切勿用
strings.ReplaceAll或正则手写解析——既不安全也不完整
模板里怎么写才不会被转义
在 post.html 模板中,直接用 {{.Content}} 即可,但前提是传入的数据类型是 template.HTML。如果误传 string,哪怕内容是 <h1>Hi</h1>,也会被转义成可见标签。
- ✅ 正确:
{{.Content}}(当.Content是template.HTML类型) - ❌ 错误:
{{.Content | safeHTML}}——safeHTML是旧版text/template的函数,html/template不识别,会报错function "safeHTML" not defined - ⚠️ 注意:
{{.Content}}不等于{{printf "%s" .Content}},后者仍触发转义
常见踩坑点:样式丢失和 XSS 风险
Goldmark 默认不渲染 HTML 标签(如 <script></script>),但允许配置开启。如果你启用了 WithRendererOptions(goldmark.WithUnsafe()),又把用户输入直接喂给解析器,就可能引入 XSS。
- 生产环境务必禁用
WithUnsafe(),除非你完全信任原始 Markdown 来源 - CSS 样式不生效?Markdown 解析后只有语义标签(
<h2></h2>、<pre class="brush:php;toolbar:false;"><code></code>),没带 class,需自己加 CSS 或用扩展(如 <code>goldmark-meta</code>)注入 class 属性</pre> - 想支持代码高亮?得配
goldmark-highlighting扩展,并在模板中引入对应 JS/CSS
最易被忽略的是类型转换这一步:template.HTML(...) 必须在 Go 代码里做,不能靠模板函数补救。传错类型,页面就只能看源码。










