5

Web ページのテキストで指定された文字列または正規表現を置き換える Chrome 拡張機能に取り組んでいます。

全体的にはうまく機能しますが、解決したい2つの問題があります。

(1) テキスト置換が行われる前に、変更されていない元の Web ページ テキストが表示されます。

(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');  
});

オンラインで部分的な回答をいくつか見つけましたが、正しく機能させることができませんでした。

たとえば、提案された解決策の 1 つは、に変更"run_at": "document_end"することでした"run_at": "document_start"。これにより、DOM が構築される前にコンテンツ スクリプトが実行されるため、理論的には、何かが表示される前にテキストの置換を行う必要があります。しかし、私の場合、拡張機能がテキストの置き換えを完全に停止する原因となりました。

4

1 に答える 1

2

実行可能な代替手段は、MutationObserverを使用して DOM の変更をリッスンし、その場で TextNodes (またはその他のもの) のコンテンツを変更することです。技術的には、これは何かがレンダリングされる前に発生することはありませんが、ユーザーが気付かないほど十分に近いはずです (変更が大規模でない限り)。

同様の質問に対する私の回答も参照してください。

サンプルコード

(これには、動的なノードの更新を処理するなどの微調整が必​​要です。)

content.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
});

(上記のコードは、追加されたノードをリッスンするためのものです。動的にロード/変更されたコンテンツを「キャッチ」するために、オブザーバーにボディとその子孫の変更をリッスンさせたい場合があります。characterDatachildList

マニフェスト.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 に答える