revel模板不解析markdown,必须在控制器中用goldmark等库转为html并赋值为template.html类型后,模板通过{{.rawcontent}}安全输出;直接{{.content}}会转义显示源码。

Revel模板本身不解析Markdown,必须在控制器里用第三方库(如blackfriday或goldmark)转成HTML,再以template.HTML类型传入模板;直接{{.content}}会转义输出原始字符串,而{{.RawContent}}需提前赋值为template.HTML类型才安全。
为什么不能在模板里直接用Markdown语法
Revel用的是Go标准库html/template,它只认Go类型,不认识# 标题或* 列表这类标记。你若把原始Markdown字符串(如"# Hello\n- item1")直接塞进c.Render("content", mdStr),模板里写{{.content}}只会输出转义后的纯文本,浏览器看到的是<h1>Hello</h1>
<ul><li>item1</li></ul>这种源码,而不是渲染后的标题和列表。
正确做法:控制器里预转换 + 类型强转
必须在Action中完成解析,并把结果包装成template.HTML——这是Go模板唯一信任的“已信任HTML”类型:
- 安装解析库:
go get github.com/yuin/goldmark(推荐,比blackfriday更现代) - 在控制器中解析并转类型:
func (c App) Show() revel.Result { mdContent := "# 用户说明\n\n- 支持**加粗**\n- 支持[链接](/help)" var buf bytes.Buffer if err := goldmark.Convert([]byte(mdContent), &buf); err != nil { return c.RenderError("md parse failed: " + err.Error()) } // 关键:转成 template.HTML 才能绕过自动转义 c.RenderArgs["RawContent"] = template.HTML(buf.String()) return c.Render() } - 模板中必须用
{{.RawContent}},不能用{{.content}}——前者是已转义的HTML片段,后者会被二次转义
常见踩坑点
这几个地方出错会导致页面空白或显示源码:
MarkItDown 托管 Markdown 生成器:可将文件转换为 Markdown。支持 PDF、Word (.docx)、Excel (.xlsx/.xls)、PowerPoint (.pptx)、HTML、CSV、JSON、XML、图片等。
- 忘记导入
"html/template"包,导致template.HTML类型无法识别 - 变量名不匹配:
c.RenderArgs["RawContent"]传了,但模板里写{{.rawContent}}(大小写敏感,静默为空) - 没加
template.HTML()包装,直接传buf.String(),结果被{{.RawContent}}自动转义 - Goldmark默认不启用扩展(如表格、脚注),要支持
## 二级标题需显式配置解析器:md := goldmark.New( goldmark.WithExtensions(extension.GFM), )
更安全的方案:封装成模板函数
如果多处要用Markdown渲染,别重复写解析逻辑。在app/init.go里注册一个全局模板函数:
- 先定义函数:
func mdRender(input string) template.HTML { var buf bytes.Buffer goldmark.Convert([]byte(input), &buf) return template.HTML(buf.String()) } - 注册到Revel:
revel.AddTemplateFunc("md", mdRender) - 模板中直接用:
{{md .markdownText}},前提是.markdownText是普通字符串,不是template.HTML
注意:这个md函数不能处理含XSS风险的HTML片段(比如用户提交的<script></script>),生产环境建议加一层bluemonday过滤,否则mdRender会原样透出。










