I have a chrome extension content script that attempts to match strings from an array of objects with textcontent
from html nodes. If there is a match, the extension will replace the the html that contains the match with new html.
I am having problems with the matching. The array that contains the strings is made up of 2367 objects, with each object containing a name property.
I implemented a TreeWalker to narrow down the nodes I am parsing to only those that contain text with words.
Basically, I am trying to find the intersection of nodes that contain string matches. However, every approach I have taken for this problem has results in execution times that take 5 minutes or longer and/or CPU bottlenecking. I am hoping you guys may be able to point out what I am doing wrong or send me in different direction. Thanks in advance!
So far, all my attempts at finding matches have included some implementation of RegEx. replace()
seems to be the most taxing, but test()
does not provide much improvement.
For looping through the array of nodes and the Array of string objects, I have tried for..of
loops, for
loops, forEach()
with a nested forEach()
, and a filter()
with a nested some()
.
Here is a simple version of the content script.
const test = (players) => {
let body = document.body;
let bodyCopy = body.cloneNode(true)
let treeWalker = document.createTreeWalker(
bodyCopy,
NodeFilter.SHOW_TEXT,
node => {
let regex = /\w+/gi
if (regex.test(node.textContent)) {
return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_SKIP;
}
}
);
let nodes = [];
while (treeWalker.nextNode()) {
nodes.push(treeWalker.currentNode);
}
const intersection = (_players, _nodes) => {
let matchedPlayers = [];
matchedPlayers = _players.filter(player => {
return _nodes.some((node) => {
let re = new RegExp(player.name.full, 'i')
return re.test(node.textContent)
})
})
console.log (matchedPlayers);
}
return intersection(players, nodes)
}
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.message === "test") {
console.log(request.players)
test(request.players)
sendResponse({ gotIt: "Got it!" })
}
}
)
Here is what an object from the request.players
array looks like
{
"name": {
"full": "Austin Adams",
"first": "Austin",
"last": "Adams",
"ascii_first": "Austin",
"ascii_last": "Adams",
},
"owned": false
}