Skip to content
This repository has been archived by the owner on Jun 13, 2024. It is now read-only.

Commit

Permalink
Ignore entire subtrees if needed.
Browse files Browse the repository at this point in the history
We already ignore the immediate children of script, form,
etc. elements, as well as spans that we've inserted ourselves.  This
change makes us skip the entire subtree of such an element.

One important effect is that if another extension changes one of our
spans using a similar algorithm to ours (inserting a new subtree) we
previously could end up reprocessing that node in a future
document_end event.  Now, we prevent that.
  • Loading branch information
piquan committed May 21, 2016
1 parent fbae362 commit 2f81f66
Showing 1 changed file with 56 additions and 14 deletions.
70 changes: 56 additions & 14 deletions substitutions/js/substitutions.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,45 +63,87 @@ chrome.runtime.sendMessage("config", function(response) {
"TEXTAREA": 0
};

// Set up the functions we'll need to perform the iteration.
var node;
var iter;

var filter = {
acceptNode: function(node) {
if (node.nodeType == Node.TEXT_NODE) {
// This is a text node that we should show to the
// filter.
return NodeFilter.FILTER_ACCEPT;
}
if (node.nodeType == Node.ELEMENT_NODE) {
// Fold to upper case before checking the tag name,
// since this may be XHTML etc.
if (node.tagName.toUpperCase() in ignore) {
// Ignore this element, and all its children.
return NodeFilter.FILTER_REJECT;
}
if (node.classList.contains("xkcdSubstitutionsExtensionSubbed")) {
// We've already changed this text. Note that some
// other extension or the page's own scripts may
// have made more changes to what we did, so don't
// fight back and forth, constantly changing the
// DOM. Instead, just skip this subtree entirely.
return NodeFilter.FILTER_REJECT;
}
}
// This is not a node we're interested in. Skip this node,
// but process its children.
return NodeFilter.FILTER_SKIP;
}
};

function substitute(node) {
"use strict";
var replacementIdx;
var splitIdx;
var parent = node.parentElement;
if (parent) {
if (parent.tagName in ignore) {
return;
}
var cls = parent.getAttribute("class");
if (cls && cls.indexOf("xkcdSubstitutionsExtensionSubbed") != -1) {
return;
}
}

// Before starting, make sure there's something to substitute.
// Otherwise, we end up doing a lot of expensive tree modification
// for no reason.
if (!node.nodeValue.match(originalsRegexp)) {
return;
}
var splits = node.nodeValue.split(originalsRegexp);

// Prepare a document fragment to hold the result.
var docFrag = document.createDocumentFragment();

// Split the string into substring, where each substring either contains
// something we'll substitute, or something that we won't. We do this
// by using the capturing parentheses in originalsRegexp.
var splits = node.nodeValue.split(originalsRegexp);
for (splitIdx = 0; splitIdx < splits.length; splitIdx++) {
var splitString = splits[splitIdx];
var splitStringLower = splitString.toLowerCase();
var newNode;
if (splitStringLower in replacementsMap) {
// This is something that needs to be changed.
newNode = document.createElement("span");
newNode.setAttribute("class", "xkcdSubstitutionsExtensionSubbed");
newNode.setAttribute("title", splitString);
newNode.textContent = matchCase(replacementsMap[splitStringLower],
splitString);
} else {
// This is a stretch between stuff that needs changing.
newNode = document.createTextNode(splitString);
}
docFrag.appendChild(newNode);
}

// Let the tree walker know that its place has changed: the old
// node it sent us is gone, and so we'll update its current place
// to refer to the last node we've processed.
iter.currentNode = docFrag.lastChild;
// Make the changes.
node.parentNode.replaceChild(docFrag, node);
}

var node, iter;
var iter = document.createNodeIterator(document.body, NodeFilter.SHOW_TEXT);
iter = document.createTreeWalker(document.body,
NodeFilter.SHOW_ELEMENT |
NodeFilter.SHOW_TEXT,
filter);
while ((node = iter.nextNode())) {
substitute(node);
}
Expand Down

0 comments on commit 2f81f66

Please sign in to comment.