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

MDX中使用正则提取带任意数量Props的React组件的问题

用正则提取MDX中React组件的Props信息

先解决你当前的两个核心问题:

  1. 避免捕获自闭合标签的/:你的原正则(.*)是贪婪匹配,会把/>里的/也吞进去。可以把结尾的匹配拆成两种情况——要么是>(起始标签),要么是\s*/>(自闭合标签),同时用非贪婪匹配限制Props的范围。
  2. 单独提取每个Props到数组:直接用单个正则分组捕获所有Props后,再用专门匹配单个Props的正则拆分,这比一次性用正则分组捕获N个Props更现实(因为Props数量不固定,正则没法预定义分组数)。

第一步:匹配完整的组件标签(提取组件名和所有Props字符串)

先写一个能准确匹配两种组件标签的正则,把组件名和Props整体提取出来,同时避开自闭合的/:

<([A-Z][A-Za-z0-9]*)(?:\s+([\s\S]*?))?(?:\s*\/?>|>)

正则说明:

  • ([A-Z][A-Za-z0-9]*):捕获组件名(首字母大写,后续字母数字,符合React组件命名规范)
  • (?:\s+([\s\S]*?))?:非捕获组,匹配Props部分——\s+匹配Props前的空格,([\s\S]*?)非贪婪捕获所有Props内容([\s\S]匹配换行,兼容多行Props),末尾的?表示Props可选(比如<Component />这种无Props的情况)
  • (?:\s*\/?>|>):匹配标签结尾——要么是\s*\/>(自闭合标签,允许空格后加/),要么是>(起始标签)

用这个正则匹配你的例子:

  • <Component prop="1" />:捕获组1是Component,捕获组2是prop="1"(不会包含/)
  • <Component test="something" something='here'>:捕获组1是Component,捕获组2是test="something" something='here'

第二步:拆分Props字符串为单个Props数组

拿到Props的整体字符串后,用下面的正则匹配单个Props,再通过matchAll提取所有结果:

(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|({[\s\S]*?})))?

正则说明:

  • (\w+):捕获Prop名(字母数字下划线)
  • (?:\s*=\s*(?:"([^"]*)"|'([^']*)'|({[\s\S]*?})))?:匹配Prop值的三种情况,可选(支持布尔属性,比如<Component disabled>):
    • "([^"]*)":捕获双引号包裹的字符串值
    • '([^']*)':捕获单引号包裹的字符串值
    • ({[\s\S]*?}):捕获花括号包裹的表达式值(比如{2}、{user.name})

代码示例(JavaScript):

const mdxContent = `
<Button variant="primary" onClick={() => handleClick()} disabled />
<Card title='Hello' style={{ padding: 16 }} />
`;

// 匹配组件标签的正则
const componentRegex = /<([A-Z][A-Za-z0-9]*)(?:\s+([\s\S]*?))?(?:\s*\/?>|>)/g;
// 匹配单个Props的正则
const propRegex = /(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|({[\s\S]*?})))?/g;

let match;
while ((match = componentRegex.exec(mdxContent)) !== null) {
  const componentName = match[1];
  const propsStr = match[2] || '';
  const props = [];

  let propMatch;
  while ((propMatch = propRegex.exec(propsStr)) !== null) {
    const propName = propMatch[1];
    // 取第一个非空的匹配值(双引号/单引号/表达式)
    const propValue = propMatch[2] || propMatch[3] || propMatch[4] || true;
    props.push({ name: propName, value: propValue });
  }

  console.log(`组件:${componentName}`);
  console.log('Props数组:', props);
}

运行后输出:

组件:Button
Props数组: [
  { name: 'variant', value: 'primary' },
  { name: 'onClick', value: '() => handleClick()' },
  { name: 'disabled', value: true }
]
组件:Card
Props数组: [
  { name: 'title', value: 'Hello' },
  { name: 'style', value: '{ padding: 16 }' }
]

注意事项

  • 这个方案能覆盖绝大多数常见Props场景,但如果Props里有嵌套的引号或花括号(比如prop="He said 'hello'"),正则可能会失效——这种复杂场景建议用专门的MDX解析器,正则毕竟不是语法解析器,处理嵌套结构有局限性。
  • 如果你的MDX里有HTML标签(首字母小写),这个正则会自动忽略,因为我们限制了组件名首字母大写,符合React组件和HTML标签的区分规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:45:41