Skip to content

Commit b38f6a6

Browse files
committed
Safer DOM insertion
1 parent 2e85dc3 commit b38f6a6

File tree

1 file changed

+36
-5
lines changed

1 file changed

+36
-5
lines changed

devdocs-macos/user-scripts/page-search.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
}, []);
1111
};
1212

13+
const matchAll = function(regexp, str, fn) {
14+
let matches;
15+
while ((matches = regexp.exec(str)) !== null) {
16+
fn(matches);
17+
}
18+
}
19+
1320
const rootSearchNode = function() {
1421
return document.querySelector('main[role="main"]');
1522
};
@@ -20,6 +27,13 @@
2027
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
2128
}
2229

30+
const separate = function(string, substr) {
31+
const startIdx = string.indexOf(substr);
32+
const before = string.slice(0, startIdx);
33+
const after = string.slice(startIdx + substr.length, string.length);
34+
return [before, after];
35+
}
36+
2337
const mutateDOM = function(mutations) {
2438
return new Promise(function(resolve, _reject) {
2539
requestAnimationFrame(function() {
@@ -41,11 +55,28 @@
4155
// Make backup of original textContent.
4256
node.setAttribute(DATA_TEXTCONTENT, content);
4357
}
44-
const newContent = content.replace(
45-
new RegExp(escapeRegExp(term), 'gi'),
46-
(match) => `<mark>${match}</mark>`
47-
);
48-
node.innerHTML = newContent;
58+
59+
const fragment = document.createDocumentFragment();
60+
61+
let text = content;
62+
matchAll(new RegExp(escapeRegExp(term), 'gi'), text, (match) => {
63+
const [before, after] = separate(text, match[0]);
64+
if (before.length > 0) {
65+
fragment.appendChild(document.createTextNode(before));
66+
}
67+
68+
const mark = document.createElement('mark');
69+
mark.textContent = match[0];
70+
fragment.appendChild(mark);
71+
72+
text = after;
73+
});
74+
if (text.length > 0) {
75+
fragment.appendChild(document.createTextNode(text));
76+
}
77+
78+
node.innerHTML = '';
79+
node.appendChild(fragment);
4980
return Array.from(node.querySelectorAll('mark'));
5081
};
5182
};

0 commit comments

Comments
 (0)