我正在开发一个Chrome扩展程序,该扩展程序可以替换网页文本中的指定字符串或正则表达式。
它总体上运行良好,但我想解决两个问题:
(1) 在文本替换发生之前显示原始的、未更改的网页文本。
(2) 文本替换不会影响滚动到页面底部后动态加载的 Facebook 帖子。
这是代码,改编自 https://stackoverflow.com/a/6012345#6012345,略有改动。
// manifest.json
{
"manifest_version": 2,
"name": "Replace Text",
"version": "1.0",
"content_scripts": [ {
"js": [ "jquery.min.js", "replace.js" ],
"matches": [ "<all_urls>" ],
"run_at": "document_end"
} ]
}
// replace.js
jQuery.fn.textWalk = function( fn ) {
this.contents().each( jwalk );
function jwalk() {
var nn = this.nodeName.toLowerCase();
if( nn === '#text') {
fn.call( this );
} else if( this.nodeType === 1 && this.childNodes && this.childNodes[0] && nn !== 'script' && nn !== 'textarea' ) {
$(this).contents().each( jwalk );
}
}
return this;
};
$('body').textWalk(function() {
this.data = this.data.replace('This Text', 'That Text');
this.data = this.data.replace(/[Rr]eplaces[Ss]omes[Tt]ext/g, 'with other text');
});
我在网上找到了一些部分答案,但无法让它们正常工作。
例如,一个建议的解决方案是将"run_at": "document_end"
更改为"run_at": "document_start"
。这会在构造 DOM 之前运行内容脚本,因此理论上它应该在显示任何内容之前执行文本替换。但就我而言,它导致扩展完全停止替换文本。
一个可行的替代方案是通过 MutationObserver 监听 DOM 更改,并动态更改 TextNodes(或其他任何内容)的内容。从技术上讲,这不会在渲染任何内容之前发生,但它应该足够接近用户不会注意到(除非您所做的更改是巨大的)。
另请参阅我对类似问题的回答。
示例代码
(这仍然需要twicking,例如处理动态节点更新。
内容.js:
// Modify the content somehow...
var doFilter = function(textNode) {
textNode.data = textNode.data + "<br />" + textNode.data;
}
// Create a MutationObserver to handle events
// (e.g. filtering TextNode elements)
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
[].slice.call(mutation.addedNodes).forEach(function(node) {
if (node.nodeName.toLowerCase() == "#text") {
doFilter(node);
}
});
}
});
});
// Start observing "childList" events in document and its descendants
observer.observe(document, {
childList: true,
subtree: true
});
(上面的代码用于侦听添加的节点。您可能希望观察者侦听正文及其后代中的characterData
和childList
变化,以"捕获"动态加载/更改的内容。
manifest.json:
...
"content_scripts": [
{
"matches": [...],
"js": ["content.js"],
"run_at": "document_start",
"all_frames": true
}
],
...
如果你决定采用MutationObserver方法,那么这个JS库应该让你的生活更轻松:突变摘要
关于您的问题,为什么在"document_start"处执行脚本没有任何效果:
发生这种情况是因为此时("document_start")您的脚本没有要替换的内容(即,在将任何其他内容添加到 DOM 之前加载并运行它)。