我想知道是否有一种轻量级的方法可以使用 JavaScript 或 jQuery 来嗅探文档中的特定文本字符;说€并找到这个字符的所有实例。接着!编写一个用$替换所有实例的能力。
我为初学者找到了这个片段:
var str = 'test: '';
str = str.replace(/'/g, "'");
本质上; 我想要一个单页文档的解决方案。获取 X 的所有实例并将其设为 XY。只有文字字符。
我想知道是否有一种轻量级的方法可以使用 JavaScript 或 jQuery 来嗅探文档中的特定文本字符;说€并找到这个字符的所有实例。接着!编写一个用$替换所有实例的能力。
我为初学者找到了这个片段:
var str = 'test: '';
str = str.replace(/'/g, "'");
本质上; 我想要一个单页文档的解决方案。获取 X 的所有实例并将其设为 XY。只有文字字符。
这个怎么样,替换@
为$
:
$("body").children().each(function () {
$(this).html( $(this).html().replace(/@/g,"$") );
});
我自己的建议如下:
function nativeSelector() {
var elements = document.querySelectorAll("body, body *");
var results = [];
var child;
for(var i = 0; i < elements.length; i++) {
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3) {
results.push(child);
}
}
return results;
}
var textnodes = nativeSelector(),
_nv;
for (var i = 0, len = textnodes.length; i<len; i++){
_nv = textnodes[i].nodeValue;
textnodes[i].nodeValue = _nv.replace(/£/g,'€');
}
该nativeSelector()
函数来自这个问题的答案(由Anurag发布):getElementsByTagName() 等效于 textNodes。
这似乎是一项简单的任务,但您必须注意以下几点:
<script>
或<style>
内容,或者HTML标签或属性,这是不期望的总title
和alt
(以受控方式)之类的属性防备 xss使用以下方法通常无法解决攻击。例如,如果fetch
调用从页面上的某处读取 URL,然后向该 URL 发送请求,下面的函数将不会停止,因为这种情况本质上是不安全的。
这基本上选择包含普通文本的所有元素,通过它们的子节点——其中也是文本节点——,寻找这些文本节点并替换它们的内容。
您可以选择指定不同的根target
,例如replaceOnDocument(/€/g, "$", { target: someElement });
;默认情况下,<body>
选择了。
const replaceOnDocument = (pattern, string, {target = document.body} = {}) => {
// Handle `string` — see the last section
[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].forEach(({childNodes: [...nodes]}) => nodes
.filter(({nodeType}) => nodeType === document.TEXT_NODE)
.forEach((textNode) => textNode.textContent = textNode.textContent.replace(pattern, string)));
};
replaceOnDocument(/€/g, "$");
现在,这有点复杂:您需要检查三种情况:节点是否为文本节点,是否为元素及其属性应被替换,或者是否为元素及其属性应被替换。甲replacer
对象提供用于文本节点和元件的方法。
在替换属性和属性之前,替换者需要检查元素是否有匹配的属性;否则会创建新的属性,这是不受欢迎的。它还需要检查目标属性是否是字符串,因为只能替换字符串,或者目标属性的匹配属性是否不是函数,因为这可能导致xss 攻击。
在下面的示例中,您可以看到如何使用扩展功能:在可选的第三个参数中,您可以添加一个attrs
属性和一个props
属性,每个属性都是一个可迭代的(例如一个数组),用于要替换的属性和属性分别更换。
您还会注意到此代码段使用flatMap
. 如果不支持,请使用 polyfill 或将其替换为reduce
–concat
或map
– reduce
–concat
构造,如链接文档中所示。
const replaceOnDocument = (() => {
const replacer = {
[document.TEXT_NODE](node, pattern, string){
node.textContent = node.textContent.replace(pattern, string);
},
[document.ELEMENT_NODE](node, pattern, string, {attrs, props} = {}){
attrs.forEach((attr) => {
if(typeof node[attr] !== "function" && node.hasAttribute(attr)){
node.setAttribute(attr, node.getAttribute(attr).replace(pattern, string));
}
});
props.forEach((prop) => {
if(typeof node[prop] === "string" && node.hasAttribute(prop)){
node[prop] = node[prop].replace(pattern, string);
}
});
}
};
return (pattern, string, {target = document.body, attrs: [...attrs] = [], props: [...props] = []} = {}) => {
// Handle `string` — see the last section
[
target,
...[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].flatMap(({childNodes: [...nodes]}) => nodes)
].filter(({nodeType}) => replacer.hasOwnProperty(nodeType))
.forEach((node) => replacer[node.nodeType](node, pattern, string, {
attrs,
props
}));
};
})();
replaceOnDocument(/€/g, "$", {
attrs: [
"title",
"alt",
"onerror" // This will be ignored
],
props: [
"value" // Changing an `<input>`’s `value` attribute won’t change its current value, so the property needs to be accessed here
]
});
如果您需要使其与 HTML 实体一起使用,例如­
,上述方法将直接生成 string ­
,因为这是一个HTML实体,并且仅在分配.innerHTML
或使用相关方法时才有效。
因此,让我们通过将输入字符串传递给接受 HTML 字符串的对象来解决它:一个新的临时HTMLDocument
. 这是由DOMParser
的parseFromString
方法创建的;最后我们读了它documentElement
的textContent
:
string = new DOMParser().parseFromString(string, "text/html").documentElement.textContent;
如果你想使用这个,选择上面的一种方法,这取决于你是否要替换文本之外的 HTML 属性和 DOM 属性;然后简单地用// Handle `string` — see the last section
上面的行替换注释。
现在您可以使用replaceOnDocument(/Güterzug/g, "Güter­zug");
.
注意:如果您不使用字符串处理代码,您也可以删除{
}
围绕箭头函数体。
请注意,这会解析 HTML 实体,但仍然不允许插入实际的 HTML 标签,因为我们只读取textContent
. 这对于大多数情况也是安全的xss:由于我们正在使用parseFromString
并且页面document
不受影响,因此不会<script>
下载也不会onerror
执行处理程序。
如果结果更简单,您还应该考虑在 JavaScript 字符串\xAD
中­
直接使用而不是。
我想你可能想多了。
我的方法很简单。
用 div 标签将您的页面括起来:
<div id="mydiv">
<!-- you page here -->
</div>
在你的 javascript 中:
var html=document.getElementById('mydiv').innerHTML;
html = html.replace(/this/g,"that");
document.getElementById('mydiv').innerHTML=html;
与@max-malik 的回答类似,但不使用 jQuery,您也可以使用document.createTreeWalker执行此操作:
button.addEventListener('click', e => {
const treeWalker = document.createTreeWalker(document.body);
while (treeWalker.nextNode()) {
const node = treeWalker.currentNode;
node.textContent = node.textContent.replace(/@/g, '$');
}
})
<div>This is an @ that we are @ replacing.</div>
<div>This is another @ that we are replacing.</div>
<div>
<span>This is an @ in a span in @ div.</span>
</div>
<br>
<input id="button" type="button" value="Replace @ with $" />