|
10 | 10 | }, []); |
11 | 11 | }; |
12 | 12 |
|
| 13 | + const matchAll = function(regexp, str, fn) { |
| 14 | + let matches; |
| 15 | + while ((matches = regexp.exec(str)) !== null) { |
| 16 | + fn(matches); |
| 17 | + } |
| 18 | + } |
| 19 | + |
13 | 20 | const rootSearchNode = function() { |
14 | 21 | return document.querySelector('main[role="main"]'); |
15 | 22 | }; |
|
20 | 27 | return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string |
21 | 28 | } |
22 | 29 |
|
| 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 | + |
23 | 37 | const mutateDOM = function(mutations) { |
24 | 38 | return new Promise(function(resolve, _reject) { |
25 | 39 | requestAnimationFrame(function() { |
|
41 | 55 | // Make backup of original textContent. |
42 | 56 | node.setAttribute(DATA_TEXTCONTENT, content); |
43 | 57 | } |
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); |
49 | 80 | return Array.from(node.querySelectorAll('mark')); |
50 | 81 | }; |
51 | 82 | }; |
|
0 commit comments