Ble*_*oul 0 html javascript regex
我正在尝试使用Javascript来修改现有的HTML文档,以便我可以span使用带有计数器的标记包围网页中的每个文本单词.这是一个非常具体的问题,所以我将提供一个示例案例:
<body><p>hello, <br>
change this</p>
<img src="lorempixel.com/200/200> <br></body></html>
Run Code Online (Sandbox Code Playgroud)
这应该改为:
<body><p><span id="1">hello,</span>
<br> <span id="2"> change</span><span id="3"> this</span> </p>
<br> <img src="lorempixel.com/200/200> <br></body></html>
Run Code Online (Sandbox Code Playgroud)
我在思考或regex解决方案,但他们变得非常复杂,我不知道如何忽略标签和更改文本而不完全破坏页面.
任何想法赞赏!
不要在原始HTML上使用正则表达式.仅在文本上使用它.这是因为正则表达式是一个无上下文解析器,但HTML是一种递归语言.您需要一个递归下降解析器来正确处理HTML.
首先是DOM的一些有用功能:
document.body 是DOM的根childNodes数组(甚至是注释,文本和属性)<span>或<h>不包含文本,而是包含包含文本的文本节点.nodeType属性,文本节点是类型3.nodeValue属性,它根据节点的类型保存不同的东西.对于文本节点nodeValue包含实际文本.因此,使用上面的信息,我们可以用跨度包围所有单词.
首先是一个简单的实用函数,它允许我们处理DOM:
// First a simple implementation of recursive descent,
// visit all nodes in the DOM and process it with a callback:
function walkDOM (node,callback) {
if (node.nodeName != 'SCRIPT') { // ignore javascript
callback(node);
for (var i=0; i<node.childNodes.length; i++) {
walkDOM(node.childNodes[i],callback);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以遍历DOM并找到文本节点:
var textNodes = [];
walkDOM(document.body,function(n){
if (n.nodeType == 3) {
textNodes.push(n);
}
});
Run Code Online (Sandbox Code Playgroud)
请注意,我这两步都是为了避免包含两次单词.
现在我们可以处理文本节点:
// simple utility functions to avoid a lot of typing:
function insertBefore (new_element, element) {
element.parentNode.insertBefore(new_element,element);
}
function removeElement (element) {
element.parentNode.removeChild(element);
}
function makeSpan (txt, attrs) {
var s = document.createElement('span');
for (var i in attrs) {
if (attrs.hasOwnProperty(i)) s[i] = attrs[i];
}
s.appendChild(makeText(txt));
return s;
}
function makeText (txt) {return document.createTextNode(txt)}
var id_count = 1;
for (var i=0; i<textNodes.length; i++) {
var n = textNodes[i];
var txt = n.nodeValue;
var words = txt.split(' ');
// Insert span surrounded words:
insertBefore(makeSpan(words[0],{id:id_count++}),n);
for (var j=1; j<words.length; j++) {
insertBefore(makeText(' '),n); // join the words with spaces
insertBefore(makeSpan(words[j],{id:id_count++}),n);
}
// Now remove the original text node:
removeElement(n);
}
Run Code Online (Sandbox Code Playgroud)
你有它.它很麻烦但是100%安全 - 它永远不会破坏你网页中其他javascript标签.我上面的很多实用功能都可以用你选择的库替换.但是,不要把整个文档视为一个巨大的innerHTML字符串.除非您愿意在纯JavaScript中编写HTML解析器.