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

ReactMarkdown白名单HTML标签放行方案咨询及轻量实现代码求助

方案选择与代码示例

如果你想保留原Markdown里的<kbd>CTRL</kbd>写法,优先选rehype插件,不用修改原内容,直接在HTML处理阶段还原被转义的标签;要是愿意用更简洁的自定义Markdown语法(比如[kbd CTRL]),可以选remark插件,在解析阶段直接生成对应节点。

方案一:Rehype插件(保留原生标签写法)

ReactMarkdown会把<kbd>转义成&lt;kbd&gt;,这个插件会遍历AST,把转义后的文本替换成真实的<kbd>节点:

import ReactMarkdown from 'react-markdown';
import { visit } from 'unist-util-visit';

// 自定义rehype插件:还原<kbd>标签
const rehypeAllowKbd = () => {
  return (tree) => {
    visit(tree, 'text', (node, index, parent) => {
      const text = node.value;
      const kbdRegex = /&lt;kbd&gt;([^&]+)&lt;\/kbd&gt;/g;
      if (!kbdRegex.test(text)) return;

      const nodes = [];
      let lastIndex = 0;
      let match;

      while ((match = kbdRegex.exec(text)) !== null) {
        if (match.index > lastIndex) {
          nodes.push({ type: 'text', value: text.slice(lastIndex, match.index) });
        }
        nodes.push({
          type: 'element',
          tagName: 'kbd',
          properties: {},
          children: [{ type: 'text', value: match[1] }]
        });
        lastIndex = match.index + match[0].length;
      }

      if (lastIndex < text.length) {
        nodes.push({ type: 'text', value: text.slice(lastIndex) });
      }

      parent.children.splice(index, 1, ...nodes);
    });
  };
};

// 使用示例
const App = () => {
  const markdown = `Please press key <kbd>CTRL</kbd>`;
  return (
    <ReactMarkdown rehypePlugins={[rehypeAllowKbd]}>
      {markdown}
    </ReactMarkdown>
  );
};

export default App;

方案二:Remark插件(自定义Markdown语法)

自定义[CTRL](kbd)这样的语法(也可以改成[kbd CTRL],调整插件逻辑即可),在Markdown解析阶段直接生成<kbd>节点:

import ReactMarkdown from 'react-markdown';
import { visit } from 'unist-util-visit';

// 自定义remark插件:解析[内容](kbd)语法
const remarkKbd = () => {
  return (tree) => {
    visit(tree, 'link', (node, index, parent) => {
      if (node.url === 'kbd') {
        const kbdNode = {
          type: 'element',
          tagName: 'kbd',
          properties: {},
          children: node.children
        };
        parent.children.splice(index, 1, kbdNode);
      }
    });
  };
};

// 使用示例
const App = () => {
  const markdown = `Please press key [CTRL](kbd)`;
  return (
    <ReactMarkdown remarkPlugins={[remarkKbd]}>
      {markdown}
    </ReactMarkdown>
  );
};

export default App;

如果要改成[kbd CTRL]的写法,把插件里的visit目标改成text,用正则匹配拆分文本即可,逻辑和rehype方案类似。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:18:12