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

如何修复将</>替换为对应闭合标签的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;
    }
  });
};
测试验证
  1. 基础场景
    输入:
<button>I'm a button!</> I'm text!

输出:

<button>I'm a button!</button> I'm text!
  1. 嵌套标签场景
    输入:
<div><p>Hello</> World</>

输出:

<div><p>Hello</p> World</div>
  1. 带属性标签场景
    输入:
<div class="container"><a href="/home">Home</> Welcome</>

输出:

<div class="container"><a href="/home">Home</a> Welcome</div>
方案优势
  • 完全基于原始字符串解析,不受浏览器HTML修正逻辑干扰
  • 支持带任意属性的标签
  • 严格遵循「最近未闭合标签」规则处理嵌套</>
  • 自动识别自闭合标签(如<img/>、<input/>),不会错误压入栈

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:04:58