如何使用JavaScript将文本的一部分包装在一个节点中

11 浏览
0 Comments

如何使用JavaScript将文本的一部分包装在一个节点中

我有一个具有挑战性的问题要解决。我正在编写一个脚本,该脚本以正则表达式作为输入。然后,该脚本在文档中找到与该正则表达式匹配的所有内容,并将每个匹配项包裹在自己的元素中。困难的部分是,文本是一个格式化的HTML文档,因此我的脚本需要在DOM中进行导航,并同时应用正则表达式于多个文本节点,同时确定如果需要的话在哪里分割文本节点。

例如,使用一个捕获以大写字母开头、以句号结尾的完整句子的正则表达式,该文档:

  HTML is a language used to make websites.
  It was developed by CERN employees in the early 90s.

理想情况下将变为:

  HTML is a language used to make websites.
  It was developed by CERN employees in the early 90s.

然后,该脚本应返回所有创建的元素的列表。

我已经有一些代码,可以找到所有文本节点,并将它们与整个文档中的位置和深度一起存储在列表中。你不需要真正理解那段代码来帮助我,它的递归结构可能有点令人困惑。但我不确定如何确定哪些元素应该包含在元素内。

function findTextNodes(node, depth = -1, start = 0) {
  let list = [];
  if (node.nodeType === Node.TEXT_NODE) {
    list.push({ node, depth, start });
  } else {
    for (let i = 0; i < node.childNodes.length; ++i) {
      list = list.concat(findTextNodes(node.childNodes[i], depth+1, start));
      if (list.length) {
        start += list[list.length-1].node.nodeValue.length;
      }
    }
  }
  return list;
}

我想将所有文档变为一个字符串,通过它运行正则表达式,并使用列表找出哪些节点对应于哪些正则表达式匹配项,然后相应地分割文本节点。

但是,当我有一个像这样的文档时,就出现了一个问题:

  This program is not stable yet. Do not use this in production yet.

有一个句子从标签外开始,但在标签内结束。现在,我不希望脚本将该链接分割为两个标签。在一个更复杂的文档中,这样做可能会破坏页面。代码可以将两个句子一起包装起来:

  This program is not stable yet. Do not use this in production yet.

或者只是将每个部分分别包装在自己的元素中:

  This program is 
  
    not stable yet.
    Do not use this in production yet.
  

可以有一个参数来指定它应该做什么。我只是不确定如何判断何时将发生不可能的分割,并且如何从中恢复。

当我在子元素内部有空格时,另一个问题出现了:

This is a sentence. 

从技术上讲,正则表达式匹配项会在句号后面、在标签的结束之前结束。然而,将空格视为匹配项的一部分并将其包装起来会更好:

This is a sentence. 

而不是这样:

This is a sentence. 

但这只是一个小问题。毕竟,我可以允许正则表达式包含额外的空格。

我知道这可能听起来像一个“帮我做”的问题,而不是我们每天在SO上看到的那种快速问题,但我已经被困在这个问题上一段时间了,这是我正在开发的一个开源库的最后障碍。如果你认为其他SE网站更适合这个问题,请引导我。

0