MDX中使用正则提取带任意数量Props的React组件的问题
用正则提取MDX中React组件的Props信息
先解决你当前的两个核心问题:
- 避免捕获自闭合标签的
/:你的原正则(.*)是贪婪匹配,会把/>里的/也吞进去。可以把结尾的匹配拆成两种情况——要么是>(起始标签),要么是\s*/>(自闭合标签),同时用非贪婪匹配限制Props的范围。 - 单独提取每个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
相关产品推荐
相关产品推荐

