如何修复将</>替换为对应闭合标签的TypeScript/JavaScript函数?
问题分析
你用DOMParser的思路根本行不通——浏览器内置的HTML解析器会自动修正不规范代码:它会把</>当成无效内容直接忽略,还会把后续文本强行合并到前面的元素里,导致你维护的标签栈和原始字符串里的实际标签状态完全不匹配,替换结果自然出错。
解决方案
必须直接解析原始HTML字符串,手动维护标签栈,精准匹配每个</>对应的未闭合标签。以下是修复后的TypeScript函数:
const parse = (html: string): string => { // 存储未闭合的标签名(统一转小写避免大小写问题) const tagStack: string[] = []; // 正则匹配所有关键标签:开始标签、正常结束标签、自闭合标签、自定义闭合标签</> const tagRegex = /<(\/?)([a-zA-Z0-9]+)\b[^>]*>|(<\/>)/gi; return html.replace(tagRegex, (match, slash, tagName, selfClosePlaceholder) => { if (selfClosePlaceholder) { // 匹配到</>,替换为对应闭合标签 if (tagStack.length === 0) { // 无未闭合标签时保留原内容 return match; } const lastOpenTag = tagStack.pop()!; return `</${lastOpenTag}>`; } else if (slash) { // 处理正常结束标签,若栈顶匹配则弹出 const lowerTagName = tagName.toLowerCase(); if (tagStack.length > 0 && tagStack.at(-1) === lowerTagName) { tagStack.pop(); } // 保留原结束标签 return match; } else { // 处理开始标签,判断是否为自闭合标签 const isSelfClosing = match.endsWith('/>'); const lowerTagName = tagName.toLowerCase(); if (!isSelfClosing) { tagStack.push(lowerTagName); } // 保留原开始标签(包括属性) return match; } }); };
测试验证
- 基础场景
输入:
<button>I'm a button!</> I'm text!
输出:
<button>I'm a button!</button> I'm text!
- 嵌套标签场景
输入:
<div><p>Hello</> World</>
输出:
<div><p>Hello</p> World</div>
- 带属性标签场景
输入:
<div class="container"><a href="/home">Home</> Welcome</>
输出:
<div class="container"><a href="/home">Home</a> Welcome</div>
方案优势
- 完全基于原始字符串解析,不受浏览器HTML修正逻辑干扰
- 支持带任意属性的标签
- 严格遵循「最近未闭合标签」规则处理嵌套
</> - 自动识别自闭合标签(如
<img/>、<input/>),不会错误压入栈
内容的提问来源于stack exchange,提问作者Fighter178
相关产品推荐
相关产品推荐

