You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在HTML/JavaScript中动态高亮GPT API返回的Markdown代码语法?

问题原因

highlight.js 只对 <pre><code> 标签包裹的代码生效,你页面里的三重反引号代码块只是普通文本,没有被转换成对应的HTML结构,所以自然不会触发高亮。

解决方法

核心是把流式返回的 Markdown 格式代码块,转换成 highlight.js 能识别的 HTML 标签,再触发高亮逻辑。

1. 手动正则替换(适合简单场景)

写一个函数识别文本中的 [语言]\n代码内容 结构,替换成对应的 <pre><code class="language-[语言]"> 标签,插入页面后调用 highlight.js 处理新内容。

模拟流式处理的测试代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Code Highlight Demo</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
</head>
<body>
  <div id="content" style="white-space: pre-wrap"></div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
  <script>
    // 模拟GPT流式返回的文本内容
    const streamText = `这是一段普通说明文本
\`\`\`javascript
var s = "JavaScript syntax highlighting";
window.alert(s);
var num = 42;
\`\`\`
这是另一段普通文本
\`\`\`python
print("Hello World")
\`\`\``;

    // 将Markdown代码块转换为HTML标签的函数
    function convertCodeBlock(text) {
      // 匹配三重反引号包裹的代码块,捕获语言类型和代码内容
      return text.replace(/```(\w+)\n([\s\S]*?)```/g, (match, lang, code) => {
        // 转义HTML特殊字符,避免格式错乱和XSS风险
        const escapedCode = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        return `<pre><code class="language-${lang}">${escapedCode}</code></pre>`;
      });
    }

    // 模拟流式追加内容的逻辑
    let currentIndex = 0;
    const contentEl = document.getElementById('content');
    const interval = setInterval(() => {
      if (currentIndex >= streamText.length) {
        clearInterval(interval);
        hljs.highlightAll();
        return;
      }
      // 每次追加一个字符,模拟流式返回效果
      const chunk = streamText[currentIndex];
      contentEl.textContent += chunk;
      currentIndex++;

      // 检查是否出现完整代码块标记,触发转换和高亮
      if (contentEl.textContent.includes('```')) {
        const htmlContent = convertCodeBlock(contentEl.textContent);
        contentEl.innerHTML = htmlContent;
        hljs.highlightAll();
      }
    }, 50);
  </script>
</body>
</html>

2. 使用Markdown解析库(更省心)

如果返回内容包含复杂Markdown格式(比如标题、列表),直接用成熟的解析库(如marked)把文本转成HTML,同时集成highlight.js高亮逻辑。

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Code Highlight Demo</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
</head>
<body>
  <div id="content"></div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
  <script>
    // 配置marked,让它生成带语言类的code标签并自动高亮
    marked.setOptions({
      highlight: function(code, lang) {
        const targetLang = hljs.getLanguage(lang) ? lang : 'plaintext';
        return hljs.highlight(code, { language: targetLang }).value;
      }
    });

    // 模拟流式返回的文本
    const streamText = `这是一段普通文本
\`\`\`javascript
var s = "JavaScript syntax highlighting";
window.alert(s);
var num = 42;
\`\`\`
### 这是一个标题
- 列表项1
- 列表项2
\`\`\`python
print("Hello World")
\`\``;

    let currentIndex = 0;
    const contentEl = document.getElementById('content');
    const interval = setInterval(() => {
      if (currentIndex >= streamText.length) {
        clearInterval(interval);
        return;
      }
      const chunk = streamText[currentIndex];
      contentEl.textContent += chunk;
      currentIndex++;

      // 实时解析Markdown并渲染
      contentEl.innerHTML = marked.parse(contentEl.textContent);
    }, 50);
  </script>
</body>
</html>
注意事项
  • 流式处理时尽量避免重复解析已处理内容,否则会导致性能问题或重复渲染高亮代码,可以记录已处理的位置,只处理新追加的片段。
  • 如果涉及用户生成内容,要做好XSS防护,比如转义特殊字符或使用支持安全解析的Markdown库。

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:12:46