
本文介绍如何使用 Highlight.js 对通过流式响应(如 SSE 或 GPT API)动态插入的 Markdown 代码块(language\n...\n)进行实时语法高亮,解决 hljs.highlightAll() 仅处理静态 元素的问题。
本文介绍如何使用 highlight.js 对通过流式响应(如 sse 或 gpt api)动态插入的 markdown 代码块(```language\n...\n```)进行实时语法高亮,解决 `hljs.highlightall()` 仅处理静态 `
` 元素的问题。<p>在实际开发中,尤其是集成大模型流式输出(如 OpenAI 的 SSE 响应)时,服务端常以 Markdown 格式返回包含代码片段的文本(例如用三重反引号包裹的 javascript ...)。但 Highlight.js 默认只识别已渲染为 </p><pre class="brush:php;toolbar:false;"><code class="javascript">...</code>的 DOM 结构,而不会解析纯文本中的 Markdown 代码标记——这正是你遇到“手动写的
能高亮,但 <p> 内的 ... 不生效”的根本原因。</p>
<p>要实现<strong>动态高亮</strong>,核心思路是:<strong>将 Markdown 风格的代码块转换为 Highlight.js 可识别的标准 HTML 结构,并在插入后主动调用高亮方法</strong>。以下是完整、健壮的解决方案:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/shouce/1862" title="使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件"><img
src="https://img.php.cn/upload/manual/000/000/010/170901721079108.gif" alt="使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/shouce/1862" title="使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件" class="overflowclass">使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件</a>
<p class="overflowclass">如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Andr​​oid友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Andr​​oid应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更</p>
</div>
<a rel="nofollow" href="/xiazai/shouce/1862" title="使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<h3>✅ 步骤一:用正则提取并转换 Markdown 代码块</h3>
<pre class="brush:php;toolbar:false;">function convertMarkdownCodeBlocks(htmlString) {
// 匹配 ```lang\n...content...\n```(支持空语言标签和多行内容)
const regex = /```(\w+)?\n([\s\S]*?)\n```/g;
return htmlString.replace(regex, (match, lang, code) => {
const language = lang || 'plaintext';
const escapedCode = code
.replace(/&/g, '&')
.replace(/, '<')
.replace(/>/g, '>')
.replace(/"/g, '"');
return `<pre class="brush:php;toolbar:false;"><code class="language-${language}">${escapedCode}</code></pre>`;
});
}</pre>
<blockquote><p>⚠️ 注意:必须对代码内容做 HTML 实体转义(, &, "),否则可能破坏 DOM 结构或引发 XSS 风险。</p></blockquote>
<h3>✅ 步骤二:动态渲染后立即高亮</h3>
<p>假设你通过 EventSource 或 fetch + ReadableStream 接收流式文本,并追加到容器中(如 </p>
<div id="output"></div>):<pre class="brush:php;toolbar:false;"><div id="output" style="font-family: -apple-system, system-ui, sans-serif;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css"><script>
hljs.configure({ ignoreUnescapedHTML: true }); // 安全选项:跳过未转义HTML的高亮(推荐开启)
function renderAndHighlight(markdownText) {
const container = document.getElementById('output');
const htmlWithPreCode = convertMarkdownCodeBlocks(markdownText);
container.innerHTML += htmlWithPreCode;
// 仅高亮新插入的 <code> 元素,避免重复处理全页面
hljs.highlightElement(container.lastElementChild.querySelector('code'));
}
// 示例:模拟流式响应
const mockStream = [
"这是普通文本。\n\n```javascript\nconsole.log('Hello');\n```\n\n再一段说明。",
"\n```python\ndef greet():\n return 'Hi!'\n```"
];
mockStream.forEach(text => setTimeout(() => renderAndHighlight(text), 500));
</script></pre>
<h3>✅ 关键要点总结</h3>
<ul>
<li>
<strong>不要依赖 hljs.highlightAll() 一次性扫描全页</strong>:它只在初始加载时运行,无法响应后续 DOM 变更;</li>
<li>
<strong>必须手动调用 hljs.highlightElement(el) 或 hljs.highlightBlock(el)</strong>(新版推荐前者)对新插入的 <code> 元素单独高亮;
通过以上方法,你即可无缝支持从 GPT API 等流式接口返回的 Markdown 代码块,并实现毫秒级、安全、可维护的动态语法高亮。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










