使用 Javascript 创建节点树删除某些不需要的元素

Recreating a node tree removing certain, uneeded elements with Javascript

我正在使用 WYSIWYG 编辑器,并尝试清理从中返回的内容。这里有两个转换的例子

<div>                       <div>
  <p>                         <blockquote>
    <blockquote>                <span>
      <p>                         <b>
        <span>      --->            <i>
          <b>       --->              <u>
            <u>               <p>
              <i>               Text
    <p>                       <p>
      Text                      Text
    Text

<div>                       <div>
  <p>                         <blockquote>
    <blockquote>                <h1>
      <h1>                        Text
        Text                      <ul>
        <ul>                    Text
      Text          --->      <p>
    Text            --->        Text
    <h3>                      <h3>
  <p>                         <p>
    Text                        Text
    <b>                         <b>
      <i>                         <i>
  <h2>                        <h2>

所以,这里发生了什么:

<p><blockquote><h*> 不允许在彼此内部。 <p><blockquote><h*><ul><ol> 仅允许是 <div> 的直系后代。其他任何东西都应该在其中之一内。

所以我需要做的是有效地遍历树,并将它们放在正确的层次结构中。

从第一个示例中可以看出,<blockquote><p> 中拉出,<p><p> 中拉出,然后,创建了一个新的 <p> 来容纳剩余的 Text,并删除了第一个 <p> (至少我是这样看的,它也可能是最后一个 Text放在未使用的<p>).

里面

第二个,<blockquote>被拉出<p>,剩下的Text放在新的<p>里面,或者不用的[=14] =],不管你怎么看,<h3> 被从 <p> 中拉出来了,其他一切都很好,所以不用管它。

我真的很难将此逻辑正确地放置到正确放置元素和创建新元素的位置。请记住,这是一个非常肤浅的示例,但我可能需要说将某些内容拉出几个级别,或者删除一个不执行任何操作的节点(<p> inside a <blockquote>)。

这是我想出的最好的伪装,但它仍然有问题。

if not p and not BQ and not h*
    create p
    fragment.appendChild(node)
else if (p && hasParent(p || BQ || H*)) or 
        (h* && hasParent(p || h*)) or
        (BQ && hasParent(p || h*)
            fragment.appendChild(node)
else
    fragment.lastChild.appendChild(node)

虽然它不起作用,因为第一个 if 会不断地在子节点上创建 <p>,例如 <blockquote> 内部的 Text .还有一些其他错误,但重要的是它的逻辑有缺陷。

有人能帮我把这个逻辑弄对吗?伪代码显然很好,但我真的很难理解这个层次结构。我突然想到递归函数可能会有用,但我什至还没有想出半途而废的东西。

感谢所有帮助,谢谢。

这是我最后得到的。基本上,如果我发现一个不符合标准的节点,它以及它之后的所有内容都将移动到父节点下方,会发生什么情况。这个过程只是重复,直到一切都有效。

isValidTree 的代码未显示。所做的只是根据我正在寻找的规则验证子树。它 returns 一个 node 如果树无效,告诉我从哪里开始删除,或者是真的那棵树里面的一切都很好。

function rebuildTree(doc, node){
    // Keep track the original tree
    var original = node.parentNode;

    // As long as node is valid
    while(node){
        // Remember who the next sibling is, that way we can keep inserting before it
        var sibling = node.nextSibling;

        // Check if node is valid
        var badNode = isValidTree(node);

        // If we didn't get true back, then we need to move badNode, and all next-siblings to after the parent
        if(badNode !== true){
            // Get the next sibling, so we don't lose track of it
            var nextNode = badNode.nextSibling;

            // While we have a badNode
            while(badNode){
                // If we have a text node
                if(badNode.nodeName.toLowerCase() === "#text"){
                    // Create a paragraph
                    var p = doc.createElement("p");
                    // And place the textNode into the paragraph
                    p.appendChild(badNode);

                    // Then insert the node before the sibling
                    node.parentNode.insertBefore(p, sibling);

                    // And remove the original
                    badNode.parentNode.removeChild(badNode);
                }
                // Otherwise, we can just insert the badNode before the sibling
                else{
                    node.parentNode.insertBefore(badNode, sibling);
                }

                // Then assign badNode to be the nextNode
                badNode = nextNode;
                // And get the nextNode (If it's not null yet)
                if(nextNode){
                    nextNode = badNode.nextSibling;
                }
            }
        }
        // Now go to the next sibling of node, which at this point may be one of it's once-was children
        node = node.nextSibling;
    }
    // Return the node's parent (i.e. the entire tree)
    return original;
}