-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcontent.js
82 lines (62 loc) · 2.19 KB
/
content.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const CLS = "__double-click-highlighter__";
chrome.runtime.onMessage.addListener(msg => {
if (msg.name !== "loaded") {
return;
}
run();
});
function run() {
document.addEventListener("dblclick", e => {
const text = window.getSelection().toString().trim();
const specialCharOrEmpty = /(?:\W|^$)/.test(text);
if (specialCharOrEmpty) {
return;
}
removeHighlight();
highlight();
selectTarget();
function highlight() {
// todo using cache improve performance
Array.from(document.getElementsByTagName("span")).forEach(span => {
for (const node of span.childNodes) {
const {nodeType, nodeValue} = node;
if (nodeType !== Node.TEXT_NODE ||
!new RegExp(`[^\\w\\s]*\\b${text}\\b[^\\w\\s]*`).test(nodeValue)) {
continue;
}
// todo what if it has many texts?
const idx = nodeValue.indexOf(text);
node.nodeValue = nodeValue.replace(text, "");
const restNode = node.splitText(idx);
span.insertBefore(createColored(), restNode);
}
});
}
function createColored() {
const colored = document.createElement("span");
colored.className = CLS;
colored.style.backgroundColor = "yellow";
colored.textContent = text;
return colored;
}
function selectTarget() {
const [node] = e.target.getElementsByClassName(CLS);
const range = document.createRange();
range.selectNode(node);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
});
document.addEventListener("keydown", e => {
if (e.key !== "Escape") {
return;
}
window.getSelection().removeAllRanges();
removeHighlight();
});
}
function removeHighlight() {
Array.from(document.getElementsByClassName(CLS)).forEach(el => {
el.outerHTML = el.textContent;
});
}