去提问»
提问背景 Question:
它是用go模板,直接将内容渲染过去的,但是我又不想在后台解析md,为了节约服务器资源,我想解析md的事情交给js,但是直接渲染内容的情况下,js又如何去渲染内容呢

Go模板结合JS前端渲染Markdown方案

发布时间:2026-08-17 22:35 👁️ 阅读:0

在不想消耗 Go 后端服务器 CPU 资源的前提下,将 Markdown 解析和代码高亮完全交给前端 JS 处理是一个非常明智的架构选择。

要解决**“直接渲染时 Go 自动转义”、“换行混乱”以及“HTML 代码被误渲染或破坏”**的问题,业界最经典的解决方案是:使用一个隐藏的 <textarea> 标签作为中介来存放原始 Markdown 数据

为什么使用 <textarea>

  1. 防止 HTML 被提前解析<textarea> 内部的内容会被浏览器视为纯文本,不会执行其中的 HTML 标签。
  2. Go 模板安全转义后可自动还原:Go 的 html/template 在向 <textarea> 输出内容时会安全地将 < 转义为 &lt;,但当 JavaScript 通过 .value 读取该 DOM 节点时,浏览器会自动将其还原为原始字符(如 <),不会导致 Markdown 语法变形。
  3. 完美保留换行符<textarea> 会原封不动地保留所有原始换行和空格。

💡 完整实现方案

1. 修改 baike_detail.html 模板结构

在 HTML 模板中,我们准备两个容器:一个隐藏的 textarea 用来装载 Go 传过来的原始数据,另一个 div 用来展示 JS 解析后的精美网页。

<!-- 1. 隐藏的容器:用于安全接收 Go 传递的原始 Markdown -->
<textarea id="markdown-raw" style="display: none;">{{ .Content }}</textarea>

<!-- 2. 实际展示的容器(引入 GitHub 风格的 Markdown 样式) -->
<div id="markdown-rendered" class="markdown-body" style="padding: 20px;">
    内容加载中...
</div>

<!-- 3. 引入前端必要的 CSS 样式(GitHub 皮肤 + 代码高亮皮肤) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github-dark.min.css">

<!-- 4. 引入前端解析 JS 库(Marked 负责解析 MD,Highlight 负责代码高亮) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.2/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>

2. 编写前端渲染 JavaScript 脚本

在页面底部添加以下 JS 代码,负责读取、解析、渲染并执行代码高亮:

<script>
    document.addEventListener("DOMContentLoaded", function () {
        // 1. 从 textarea 中读取原始的、未经浏览器二次污染的 Markdown 文本
        const rawMarkdown = document.getElementById("markdown-raw").value;

        // 2. 配置 marked.js 参数
        marked.setOptions({
            breaks: true,   // 解决“换行混乱”:支持单换行符转换为 <br>
            gfm: true,      // 启用 GitHub 风格的 Markdown (GFM)
            pedantic: false
        });

        // 3. 将 Markdown 转换为 HTML 并塞入展示容器
        const renderedHtml = marked.parse(rawMarkdown);
        const outputDiv = document.getElementById("markdown-rendered");
        outputDiv.innerHTML = renderedHtml;

        // 4. 解决“代码没有支持”:使所有代码块支持语法高亮
        outputDiv.querySelectorAll('pre code').forEach((block) => {
            hljs.highlightElement(block);
        });
    });
</script>

🛠️ 细节优化:处理可能存在的“空白占位”问题

因为 Go 的模板引擎会严格保留你写在 {{ .Content }} 左右的空格,为了防止模板本身的换行影响内容,建议在 HTML 模板中将 <textarea> 紧贴着模板标签写在一行:

<textarea id="markdown-raw" style="display: none;">{{.Content}}</textarea>

🌟 总结

通过这种方式:

  1. Go 后端:只做最简单的文本填充,消耗 0 额外 CPU 资源。
  2. 换行问题marked.setOptions({ breaks: true }) 强制将 Markdown 里的单回车当做换行解析,排版不再混乱。
  3. 代码与样式问题marked.js + highlight.js 完美重现 GitHub 级别的代码高亮渲染,HTML 代码标签也会在代码块中作为纯文本高亮,而不会破坏你的页面样式。