如何为react-markdown添加自定义语法,使{{}}内文本变蓝且兼容原有语法?
为react-markdown添加{{ }}自定义蓝色文本语法
你的现有实现存在几个问题:
- 拆分文本后生成了多个
<h2>或<p>标签,这不符合HTML规范(每个标题/段落应该是单个元素) - 依赖
text.children[0]获取文本内容的方式很脆弱,当Markdown元素包含多个子节点时会失效 - 只能处理
<h2>和<p>元素,其他Markdown元素(比如列表项、链接文本等)中的{{ }}无法被识别
更可靠的方案是通过remark插件解析{{ }}语法,将其转换为自定义AST节点,再统一渲染为蓝色文本。这样能确保所有Markdown元素中的{{ }}都能生效,同时保持原有Markdown结构的正确性。
修正后的实现代码
import React from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; // 自定义remark插件:解析{{ }}语法 const remarkCustomBlueText = () => { return (tree) => { // 遍历AST节点 const visitNode = (node) => { if (node.type === "text" && node.value.includes("{{")) { // 拆分文本为普通文本和{{ }}包裹的部分 const parts = node.value.split(/({{(.*?)}})/); const newChildren = []; parts.forEach(part => { if (part.startsWith("{{") && part.endsWith("}}")) { // 创建自定义节点 newChildren.push({ type: "blueText", value: part.slice(2, -2).trim(), // 去掉{{ }}并去除首尾空格 data: { hName: "span" } }); } else if (part) { // 保留普通文本节点 newChildren.push({ type: "text", value: part }); } }); // 替换原文本节点为新的子节点数组 node.type = "textParent"; node.children = newChildren; } // 递归处理子节点 if (node.children) { node.children.forEach(visitNode); } }; visitNode(tree); }; }; const CustomMarkdown = ({ children }) => { return ( <ReactMarkdown remarkPlugins={[remarkGfm, remarkCustomBlueText]} components={{ // 渲染自定义blueText节点 blueText: ({ value }) => ( <span style={{ color: "blue" }}>{value}</span> ) }} > {children} </ReactMarkdown> ); }; export default CustomMarkdown;
方案说明
- remark插件解析语法:通过遍历AST树,识别包含{{ }}的文本节点,将其拆分为普通文本和自定义
blueText节点,确保所有Markdown元素中的{{ }}都能被处理。 - 统一渲染自定义节点:在
components中添加blueText的渲染逻辑,将其转换为蓝色的<span>标签。 - 兼容性保障:该方案不会破坏原有Markdown语法,无论是在标题、段落、列表还是其他元素中的{{ }}都能正常显示为蓝色。
内容的提问来源于stack exchange,提问作者Шэйд
相关产品推荐
相关产品推荐

