javascript - 从 DOM 中提取和替换文本的通用方法

标签 javascript html google-chrome-extension rangy

<分区>

我有两个包装器:

function wrapSentences(str, tmpl) {
    return str.replace(/[^\.!\?]+[\.!\?]+/g, tmpl || "<sentence>$&</sentence>")
}

function wrapWords(str, tmpl) {
return str.replace(/\w+/g, tmpl || "<word>$&</word>");
}

我在我们的扩展中使用这些来包装用户出于 TTS 和设置目的访问的任何网页上的每个单词和句子。

document.body 是每个网站上最原子化的元素,但是执行 body.innerHTML = wrapWords(body.innerText) 将(显然)替换不同文本节点之间的任何元素,从而破坏网站(的视觉部分)。我正在寻找一种方法来找到任何文本周围最接近的元素,而无需了解该元素的任何具体信息,因此我可以用包装等效项替换它,而无需以任何方式更改网站。

我发现了几个指向最深子节点的示例,但它们都依赖于传递一些扩展无法知道的内容(节点或 ID)。我们将使用 rangy 来突出显示,但有同样的问题......我总是最终不得不传递一个节点或 ID,而扩展程序在访问随机站点时无法意识到这一点。

需要传递节点的示例之一:

    function replaceTextNodes(node, newText) {
    if (node.nodeType === 3) {
        //Filter out text nodes that contain only whitespace
        if (!/^\s*$/.test(node.data)) {
            node.data = newText;
        }
    } else if (node.hasChildNodes()) {
        for (let i = 0, len = node.childNodes.length; i < len; ++i) {
            replaceTextNodes(node.childNodes[i], newText);
        }
    }
}

如果需要,我很乐意更好地解释它。我担心我的措辞可能并不总是最好的,我知道这一点。

最佳答案

看起来你想要的是页面上的所有文本节点... This question可能有你的答案。
使用第一个答案中的函数:

编辑:现在在 <word> 中换行文本节点,而不仅仅是它们的 textContent

function textNodesUnder(el){
  var n, a=[], walk=document.createTreeWalker(el,NodeFilter.SHOW_TEXT,null,false);
  while(n=walk.nextNode()) a.push(n);
  return a;
}

exp = /(?:(\W+)|(\w+))/g

textNodesUnder(document.body)
    .filter(t => !/^\s*$/.test(t.textContent))
    .forEach(t => {
        let s = t.textContent, match
        while(match = exp.exec(s)) {
            let el
            if(match[1] !== undefined) {
                el = document.createTextNode(match[1])
            }
            else {
                el = document.createElement("word")
                el.textContent = match[2]
            }
            t.parentNode.insertBefore(el, t)
        }
        t.parentElement.removeChild(t)
    })

关于javascript - 从 DOM 中提取和替换文本的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46669577/

相关文章:

javascript - 无法让 Backbone 关系与 AMD 一起使用 (RequireJS)

javascript - jQuery DataTable + sAjaxSource + Spring(服务端处理)处理

javascript - 在 html Canvas 中绘制具有特定 Angular 线

javascript - Chrome 扩展 : identify web requests of background-page iframe?

javascript - Stylus (CSS) 的客户端使用

javascript - 使用服务器端事件动态发送消息到浏览器

html - 将 Material-UI 文本字段与段落对齐

javascript - 仅在按键后颜色变化

html - 具有固定宽度和灵活宽度的 3 列的行

javascript - 自定义事件细节 "tainted"?