用于查找未关闭的HTML标记的JavaScript库/函数

用于查找未关闭的HTML标记的JavaScript库/函数,javascript,html,tags,Javascript,Html,Tags,我目前正在寻找一种解决方案,从原始HTML的任意片段中查找并列出任何未关闭的HTML标记。我不觉得这应该是一个可怕的问题,但我似乎无法在JS中找到这样做的东西。不幸的是,这需要客户端,因为它用于将注释呈现到HTML页面。显然,注释有点麻烦,因为它们选择或应用的格式可能只适用于HTML元素的一部分(即,覆盖在现有HTML标记上的标记) 一个简单的用例是,您可能只希望呈现HTML页面的一部分,但稍后再注入其余部分。例如,想象一个假设的片段: <p>This is my text <

我目前正在寻找一种解决方案,从原始HTML的任意片段中查找并列出任何未关闭的HTML标记。我不觉得这应该是一个可怕的问题,但我似乎无法在JS中找到这样做的东西。不幸的是,这需要客户端,因为它用于将注释呈现到HTML页面。显然,注释有点麻烦,因为它们选择或应用的格式可能只适用于HTML元素的一部分(即,覆盖在现有HTML标记上的标记)

一个简单的用例是,您可能只希望呈现HTML页面的一部分,但稍后再注入其余部分。例如,想象一个假设的片段:

<p>This is my text <StartDelayedInject/> with a comment I added. </p>
<p> But it doesn't exist until now. </p> <StopDelayedInject/>
这是我添加了注释的文本

但它直到现在才存在

我将做一些预处理来重建HTML,以便将部分元素包装到应用适当格式的span类型元素中。最初,这将以以下形式进行分析:

<p><span>This is my text</span></p>
这是我的文本

在一些用户操作之后,它将被修改为一个表单,例如:

<p><span>This is my text</span><span>with a comment I added.</span></p>
<p>But it doesn't exist until now.</p>
这是我添加了注释的文本

但它直到现在才存在

这是一个非常简单的例子(很明显,像ul元素和表这样的东西会变得更复杂),但给出了一般原则。然而,为了有效地做到这一点,我需要能够检查一段HTML,并找出有哪些标记已经打开(但没有关闭)。如果我知道这些信息,我可以将最后一个未终止的文本数据包装到一个范围中,关闭未关闭的标记,并知道在需要时返回到该点以注入剩余的内容。但是,我需要知道仍然打开的标签,这样当我注入或修改另一段内容时,我可以确保将其放在正确的位置(例如,在第一段中获得“添加了注释”)


根据我对上下文无关语法的理解,这应该是一项相对简单的任务。每次打开/输入或关闭/退出标记时,您可以保持一堆标记处于打开状态,但尚未关闭。话虽如此,我还是更愿意使用一个更成熟的解决方案库,而不是为此制作一个朴素的解析器。我假设有一些JSHTML解析器可以做到这一点,对吗?很多人都知道如何关闭标记,因此在某些时候他们计算得非常清楚。

问题是JavaScript只能通过两种方式访问html:

  • 从某种意义上说,每个元素都是一个对象,具有浏览器在页面加载时创建的属性和方法
  • 从某种意义上说,它是一个文本字符串
  • 使用与html接口的第一种方法,无法检测未关闭的标记,因为您只能访问浏览器解析html后为您创建的对象

    使用第二种方法,您必须通过html解析器运行整个html字符串。有些人可能认为您可以简单地使用regexp来实现,但是,这是不可行的。我指给你看这个奇妙的故事

    即使您找到了一个非常健壮的html解析器来使用,您仍然会遇到这样一个问题,即在您的JavaScript还没有触及它之前,浏览器就已经尝试解析可能被破坏的html,并且可能到处都有错误

    编辑:


    如果您喜欢解析器的想法,John Resig创建了您可能想要引用的解析器。

    不完美,但下面是我检查打开/关闭标记之间不匹配的快速方法:

    function find_unclosed_tags(str) {
        str = str.toLowerCase();
        var tags = ["a", "span", "div", "ul", "li", "h1", "h2", "h3", "h4", "h5", "h6", "p", "table", "tr", "td", "b", "i", "u"];
        var mismatches = [];
        tags.forEach(function(tag) { 
            var pattern_open = '<'+tag+'( |>)'; 
            var pattern_close = '</'+tag+'>'; 
    
            var diff_count = (str.match(new RegExp(pattern_open,'g')) || []).length - (str.match(new RegExp(pattern_close,'g')) || []).length;
    
            if(diff_count != 0) {
                mismatches.push("Open/close mismatch for tag " + tag + ".");
            }
        });
    
        return mismatches;
    }
    
    函数查找未关闭的标签(str){
    str=str.toLowerCase();
    var标签=[“a”、“span”、“div”、“ul”、“li”、“h1”、“h2”、“h3”、“h4”、“h5”、“h6”、“p”、“table”、“tr”、“td”、“b”、“i”、“u”];
    var不匹配=[];
    tags.forEach(函数(tag){
    变量模式_open=');
    var模式_close='';
    var diff_count=(str.match(新RegExp(pattern_open,'g'))| |[]).length-(str.match(新RegExp(pattern_close,'g'))| |[])length;
    如果(差异计数!=0){
    不匹配。推送(“标记“+标记+”的打开/关闭不匹配”);
    }
    });
    返回不匹配;
    }
    
    我应该澄清一下,我有能力获取原始字符串(如果您有一个shell页面加载真实内容,这相当简单),因此我希望在允许浏览器将其添加到DOM之前使用HTML类型解析器。因此,浏览器无法“解析损坏的HTML”(除非我自己的代码无法正确附加终止符,或者如果原始HTML一开始就不好)。我也非常清楚正则表达式是一个糟糕的解决方案,因此我问了这个问题,并特别询问了“JS HTML解析器”。像Tidy/jTidy这样的库检测未终止的标记。问题是:是否存在一个JS库可以检测未终止的标记并报告丢失的标记?除非最近有一些我不知道的魔法,否则我不相信你可以用JavaScript对呈现的页面做你想做的事。我的意思是,理论上,您可以在页面加载时对整个HTML字符串运行HTML解析器。问题是,在这种情况发生之前,您的html已经加载,很可能在JS访问它之前显示渲染错误。这基本上是一个相当笨拙的解决方案。我还不知道有任何为JavaScript预先创建的客户端html解析器。是的,这也是我今天在搜索中找到的最好的一个。在此基础上构建可能是目前最好的选择。我还应该强调,让解析器添加结束标记是不够的,我还需要知道需要添加哪些结束标记,以跟踪下一个内容应该插入的位置。可能还值得注意的是,我已经用bison/yacc和lex之类的东西构建了解析器。我只是认为,在已经存在这么多HTML解析器的情况下,为这个目的构建和测试另一个HTML解析器是荒谬的。