5

我正在开发一个 Chrome 扩展程序,用于替换网页文本中的指定字符串或 RegEx。

它总体上运行良好,但有两个我想解决的问题:

(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]eplace\s[Ss]ome\s[Tt]ext/g, 'with other text');  
});

我在网上找到了一些部分答案,但无法让它们正常工作。

例如,一种建议的解决方案是更改"run_at": "document_end""run_at": "document_start". 这会在构建 DOM 之前运行内容脚本,因此理论上它应该在显示任何内容之前进行文本替换。但在我的情况下,它导致扩展完全停止替换文本。

4

1 回答 1

2

一个可行的替代方案是通过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后代的变化,以“捕捉”动态加载/更改的内容。)

清单.json:

...
"content_scripts": [
    {
        "matches": [...],
        "js":         ["content.js"],
        "run_at":     "document_start",
        "all_frames": true
    }
],
...

如果您决定采用MutationObserver方法,那么这个 JS 库应该可以让您的生活更轻松:mutation-summary


关于您的问题,为什么在“document_start”执行您的脚本没有任何效果:
发生这种情况,因为当时(“document_start”)您的脚本没有任何东西可以替换(即它在任何其他内容之前加载并运行添加到 DOM)。

于 2013-10-28T08:27:05.647 回答