lk-text-select-highlight 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.trae/rules/project_rules.md +2 -0
- package/dist/lk-text-select-highlight.cjs.js +35 -15
- package/dist/lk-text-select-highlight.cjs.js.map +1 -1
- package/dist/lk-text-select-highlight.esm.js +35 -15
- package/dist/lk-text-select-highlight.esm.js.map +1 -1
- package/dist/lk-text-select-highlight.min.js +1 -1
- package/dist/lk-text-select-highlight.min.js.map +1 -1
- package/dist/lk-text-select-highlight.umd.js +35 -15
- package/dist/lk-text-select-highlight.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/index.js +35 -15
|
@@ -22,6 +22,18 @@ class TextHighlighter {
|
|
|
22
22
|
this.highlights = [];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Generate a simple UUID
|
|
27
|
+
*/
|
|
28
|
+
generateUUID() {
|
|
29
|
+
return (
|
|
30
|
+
"highlight-" +
|
|
31
|
+
Date.now() +
|
|
32
|
+
"-" +
|
|
33
|
+
Math.random().toString(36).substring(2, 11)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
25
37
|
/**
|
|
26
38
|
* Highlight selected text
|
|
27
39
|
*/
|
|
@@ -56,10 +68,11 @@ class TextHighlighter {
|
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
try {
|
|
59
|
-
const
|
|
71
|
+
const uuid = this.generateUUID();
|
|
72
|
+
const highlightedElement = this.wrapRange(range, uuid);
|
|
60
73
|
|
|
61
74
|
this.highlights.push({
|
|
62
|
-
|
|
75
|
+
uuid: uuid,
|
|
63
76
|
text: selection.toString(),
|
|
64
77
|
});
|
|
65
78
|
|
|
@@ -116,14 +129,18 @@ class TextHighlighter {
|
|
|
116
129
|
/**
|
|
117
130
|
* Wrap a range with highlight element
|
|
118
131
|
* @param {Range} range - The range to wrap
|
|
132
|
+
* @param {string} uuid - Unique identifier for the highlight
|
|
119
133
|
*/
|
|
120
|
-
wrapRange(range) {
|
|
134
|
+
wrapRange(range, uuid) {
|
|
121
135
|
const highlightEl = document.createElement("span");
|
|
122
136
|
highlightEl.className = this.options.className;
|
|
123
137
|
highlightEl.style.backgroundColor = this.options.color;
|
|
124
138
|
highlightEl.style.padding = "0";
|
|
125
139
|
highlightEl.style.margin = "0";
|
|
126
140
|
|
|
141
|
+
// Add UUID as data attribute
|
|
142
|
+
highlightEl.setAttribute("data-uuid", uuid);
|
|
143
|
+
|
|
127
144
|
// Clone the range and insert the highlight element
|
|
128
145
|
range.surroundContents(highlightEl);
|
|
129
146
|
|
|
@@ -135,12 +152,12 @@ class TextHighlighter {
|
|
|
135
152
|
*/
|
|
136
153
|
removeAllHighlights() {
|
|
137
154
|
this.highlights.forEach((highlight) => {
|
|
138
|
-
|
|
155
|
+
const element = document.querySelector(
|
|
156
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
157
|
+
);
|
|
158
|
+
if (element && element.parentNode) {
|
|
139
159
|
const textNode = document.createTextNode(highlight.text);
|
|
140
|
-
|
|
141
|
-
textNode,
|
|
142
|
-
highlight.element,
|
|
143
|
-
);
|
|
160
|
+
element.parentNode.replaceChild(textNode, element);
|
|
144
161
|
}
|
|
145
162
|
});
|
|
146
163
|
|
|
@@ -151,23 +168,26 @@ class TextHighlighter {
|
|
|
151
168
|
* Get all highlighted elements
|
|
152
169
|
*/
|
|
153
170
|
getHighlights() {
|
|
171
|
+
// Return highlights with uuid and text
|
|
154
172
|
return [...this.highlights];
|
|
155
173
|
}
|
|
156
174
|
|
|
157
175
|
/**
|
|
158
176
|
* Remove a specific highlight
|
|
159
|
-
* @param {Object} highlight - The highlight object to remove
|
|
177
|
+
* @param {Object} highlight - The highlight object to remove (containing uuid)
|
|
160
178
|
*/
|
|
161
179
|
removeHighlight(highlight) {
|
|
162
|
-
const index = this.highlights.
|
|
180
|
+
const index = this.highlights.findIndex(
|
|
181
|
+
(h) => h.uuid === highlight.uuid,
|
|
182
|
+
);
|
|
163
183
|
if (index !== -1) {
|
|
164
184
|
// Restore the original text
|
|
165
|
-
|
|
185
|
+
const element = document.querySelector(
|
|
186
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
187
|
+
);
|
|
188
|
+
if (element && element.parentNode) {
|
|
166
189
|
const textNode = document.createTextNode(highlight.text);
|
|
167
|
-
|
|
168
|
-
textNode,
|
|
169
|
-
highlight.element,
|
|
170
|
-
);
|
|
190
|
+
element.parentNode.replaceChild(textNode, element);
|
|
171
191
|
}
|
|
172
192
|
|
|
173
193
|
// Remove from the highlights array
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lk-text-select-highlight.cjs.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst highlightedElement = this.wrapRange(range);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\telement: highlightedElement,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t */\r\n\twrapRange(range) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tif (highlight.element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\thighlight.element.parentNode.replaceChild(\r\n\t\t\t\t\ttextNode,\r\n\t\t\t\t\thighlight.element,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.indexOf(highlight);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tif (highlight.element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\thighlight.element.parentNode.replaceChild(\r\n\t\t\t\t\ttextNode,\r\n\t\t\t\t\thighlight.element,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lk-text-select-highlight.cjs.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Generate a simple UUID\r\n\t */\r\n\tgenerateUUID() {\r\n\t\treturn (\r\n\t\t\t\"highlight-\" +\r\n\t\t\tDate.now() +\r\n\t\t\t\"-\" +\r\n\t\t\tMath.random().toString(36).substring(2, 11)\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst uuid = this.generateUUID();\r\n\t\t\tconst highlightedElement = this.wrapRange(range, uuid);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\tuuid: uuid,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t * @param {string} uuid - Unique identifier for the highlight\r\n\t */\r\n\twrapRange(range, uuid) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Add UUID as data attribute\r\n\t\thighlightEl.setAttribute(\"data-uuid\", uuid);\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\t// Return highlights with uuid and text\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove (containing uuid)\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.findIndex(\r\n\t\t\t(h) => h.uuid === highlight.uuid,\r\n\t\t);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,18 @@ class TextHighlighter {
|
|
|
20
20
|
this.highlights = [];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Generate a simple UUID
|
|
25
|
+
*/
|
|
26
|
+
generateUUID() {
|
|
27
|
+
return (
|
|
28
|
+
"highlight-" +
|
|
29
|
+
Date.now() +
|
|
30
|
+
"-" +
|
|
31
|
+
Math.random().toString(36).substring(2, 11)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
/**
|
|
24
36
|
* Highlight selected text
|
|
25
37
|
*/
|
|
@@ -54,10 +66,11 @@ class TextHighlighter {
|
|
|
54
66
|
}
|
|
55
67
|
|
|
56
68
|
try {
|
|
57
|
-
const
|
|
69
|
+
const uuid = this.generateUUID();
|
|
70
|
+
const highlightedElement = this.wrapRange(range, uuid);
|
|
58
71
|
|
|
59
72
|
this.highlights.push({
|
|
60
|
-
|
|
73
|
+
uuid: uuid,
|
|
61
74
|
text: selection.toString(),
|
|
62
75
|
});
|
|
63
76
|
|
|
@@ -114,14 +127,18 @@ class TextHighlighter {
|
|
|
114
127
|
/**
|
|
115
128
|
* Wrap a range with highlight element
|
|
116
129
|
* @param {Range} range - The range to wrap
|
|
130
|
+
* @param {string} uuid - Unique identifier for the highlight
|
|
117
131
|
*/
|
|
118
|
-
wrapRange(range) {
|
|
132
|
+
wrapRange(range, uuid) {
|
|
119
133
|
const highlightEl = document.createElement("span");
|
|
120
134
|
highlightEl.className = this.options.className;
|
|
121
135
|
highlightEl.style.backgroundColor = this.options.color;
|
|
122
136
|
highlightEl.style.padding = "0";
|
|
123
137
|
highlightEl.style.margin = "0";
|
|
124
138
|
|
|
139
|
+
// Add UUID as data attribute
|
|
140
|
+
highlightEl.setAttribute("data-uuid", uuid);
|
|
141
|
+
|
|
125
142
|
// Clone the range and insert the highlight element
|
|
126
143
|
range.surroundContents(highlightEl);
|
|
127
144
|
|
|
@@ -133,12 +150,12 @@ class TextHighlighter {
|
|
|
133
150
|
*/
|
|
134
151
|
removeAllHighlights() {
|
|
135
152
|
this.highlights.forEach((highlight) => {
|
|
136
|
-
|
|
153
|
+
const element = document.querySelector(
|
|
154
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
155
|
+
);
|
|
156
|
+
if (element && element.parentNode) {
|
|
137
157
|
const textNode = document.createTextNode(highlight.text);
|
|
138
|
-
|
|
139
|
-
textNode,
|
|
140
|
-
highlight.element,
|
|
141
|
-
);
|
|
158
|
+
element.parentNode.replaceChild(textNode, element);
|
|
142
159
|
}
|
|
143
160
|
});
|
|
144
161
|
|
|
@@ -149,23 +166,26 @@ class TextHighlighter {
|
|
|
149
166
|
* Get all highlighted elements
|
|
150
167
|
*/
|
|
151
168
|
getHighlights() {
|
|
169
|
+
// Return highlights with uuid and text
|
|
152
170
|
return [...this.highlights];
|
|
153
171
|
}
|
|
154
172
|
|
|
155
173
|
/**
|
|
156
174
|
* Remove a specific highlight
|
|
157
|
-
* @param {Object} highlight - The highlight object to remove
|
|
175
|
+
* @param {Object} highlight - The highlight object to remove (containing uuid)
|
|
158
176
|
*/
|
|
159
177
|
removeHighlight(highlight) {
|
|
160
|
-
const index = this.highlights.
|
|
178
|
+
const index = this.highlights.findIndex(
|
|
179
|
+
(h) => h.uuid === highlight.uuid,
|
|
180
|
+
);
|
|
161
181
|
if (index !== -1) {
|
|
162
182
|
// Restore the original text
|
|
163
|
-
|
|
183
|
+
const element = document.querySelector(
|
|
184
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
185
|
+
);
|
|
186
|
+
if (element && element.parentNode) {
|
|
164
187
|
const textNode = document.createTextNode(highlight.text);
|
|
165
|
-
|
|
166
|
-
textNode,
|
|
167
|
-
highlight.element,
|
|
168
|
-
);
|
|
188
|
+
element.parentNode.replaceChild(textNode, element);
|
|
169
189
|
}
|
|
170
190
|
|
|
171
191
|
// Remove from the highlights array
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lk-text-select-highlight.esm.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst highlightedElement = this.wrapRange(range);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\telement: highlightedElement,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t */\r\n\twrapRange(range) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tif (highlight.element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\thighlight.element.parentNode.replaceChild(\r\n\t\t\t\t\ttextNode,\r\n\t\t\t\t\thighlight.element,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.indexOf(highlight);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tif (highlight.element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\thighlight.element.parentNode.replaceChild(\r\n\t\t\t\t\ttextNode,\r\n\t\t\t\t\thighlight.element,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lk-text-select-highlight.esm.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Generate a simple UUID\r\n\t */\r\n\tgenerateUUID() {\r\n\t\treturn (\r\n\t\t\t\"highlight-\" +\r\n\t\t\tDate.now() +\r\n\t\t\t\"-\" +\r\n\t\t\tMath.random().toString(36).substring(2, 11)\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst uuid = this.generateUUID();\r\n\t\t\tconst highlightedElement = this.wrapRange(range, uuid);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\tuuid: uuid,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t * @param {string} uuid - Unique identifier for the highlight\r\n\t */\r\n\twrapRange(range, uuid) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Add UUID as data attribute\r\n\t\thighlightEl.setAttribute(\"data-uuid\", uuid);\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\t// Return highlights with uuid and text\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove (containing uuid)\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.findIndex(\r\n\t\t\t(h) => h.uuid === highlight.uuid,\r\n\t\t);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).TextHighlighter=e()}(this,function(){"use strict";return class{constructor(t={}){this.options={className:t.className||"highlighted-text",color:t.color||"#ffff00",container:t.container||document.body,strictMode:t.strictMode||!1,caseSensitive:void 0===t.caseSensitive||t.caseSensitive,...t},this.highlights=[]}highlightSelection(){const t=window.getSelection();if(!t.toString().trim())return!1;const e=t.getRangeAt(0),n=this.options.container;if(!n.contains(e.startContainer)||!n.contains(e.endContainer))return!1;const i=e.commonAncestorContainer;if(!n.contains(i))return!1;if(this.options.strictMode&&this.hasTargetClassInSelection(e))return!1;try{const n=this.wrapRange(e);return this.highlights.push({
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).TextHighlighter=e()}(this,function(){"use strict";return class{constructor(t={}){this.options={className:t.className||"highlighted-text",color:t.color||"#ffff00",container:t.container||document.body,strictMode:t.strictMode||!1,caseSensitive:void 0===t.caseSensitive||t.caseSensitive,...t},this.highlights=[]}generateUUID(){return"highlight-"+Date.now()+"-"+Math.random().toString(36).substring(2,11)}highlightSelection(){const t=window.getSelection();if(!t.toString().trim())return!1;const e=t.getRangeAt(0),n=this.options.container;if(!n.contains(e.startContainer)||!n.contains(e.endContainer))return!1;const i=e.commonAncestorContainer;if(!n.contains(i))return!1;if(this.options.strictMode&&this.hasTargetClassInSelection(e))return!1;try{const n=this.generateUUID();this.wrapRange(e,n);return this.highlights.push({uuid:n,text:t.toString()}),!0}catch(t){return console.warn("Could not highlight selection:",t),!1}}hasTargetClassInSelection(t){const e=t.startContainer.nodeType===Node.ELEMENT_NODE?t.startContainer:t.startContainer.parentElement,n=t.endContainer.nodeType===Node.ELEMENT_NODE?t.endContainer:t.endContainer.parentElement;if(e&&e.classList&&e.classList.contains(this.options.className))return!0;if(n&&n.classList&&n.classList.contains(this.options.className))return!0;const i=document.createElement("div");i.appendChild(t.cloneContents());return i.querySelectorAll(`.${this.options.className}`).length>0}wrapRange(t,e){const n=document.createElement("span");return n.className=this.options.className,n.style.backgroundColor=this.options.color,n.style.padding="0",n.style.margin="0",n.setAttribute("data-uuid",e),t.surroundContents(n),n}removeAllHighlights(){this.highlights.forEach(t=>{const e=document.querySelector(`[data-uuid="${t.uuid}"]`);if(e&&e.parentNode){const n=document.createTextNode(t.text);e.parentNode.replaceChild(n,e)}}),this.highlights=[]}getHighlights(){return[...this.highlights]}removeHighlight(t){const e=this.highlights.findIndex(e=>e.uuid===t.uuid);if(-1!==e){const n=document.querySelector(`[data-uuid="${t.uuid}"]`);if(n&&n.parentNode){const e=document.createTextNode(t.text);n.parentNode.replaceChild(e,n)}return this.highlights.splice(e,1),!0}return!1}}});
|
|
2
2
|
//# sourceMappingURL=lk-text-select-highlight.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lk-text-select-highlight.min.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst highlightedElement = this.wrapRange(range);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\
|
|
1
|
+
{"version":3,"file":"lk-text-select-highlight.min.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Generate a simple UUID\r\n\t */\r\n\tgenerateUUID() {\r\n\t\treturn (\r\n\t\t\t\"highlight-\" +\r\n\t\t\tDate.now() +\r\n\t\t\t\"-\" +\r\n\t\t\tMath.random().toString(36).substring(2, 11)\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst uuid = this.generateUUID();\r\n\t\t\tconst highlightedElement = this.wrapRange(range, uuid);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\tuuid: uuid,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t * @param {string} uuid - Unique identifier for the highlight\r\n\t */\r\n\twrapRange(range, uuid) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Add UUID as data attribute\r\n\t\thighlightEl.setAttribute(\"data-uuid\", uuid);\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\t// Return highlights with uuid and text\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove (containing uuid)\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.findIndex(\r\n\t\t\t(h) => h.uuid === highlight.uuid,\r\n\t\t);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":["constructor","options","this","className","color","container","document","body","strictMode","caseSensitive","undefined","highlights","generateUUID","Date","now","Math","random","toString","substring","highlightSelection","selection","window","getSelection","trim","range","getRangeAt","contains","startContainer","endContainer","commonAncestor","commonAncestorContainer","hasTargetClassInSelection","uuid","wrapRange","push","text","error","console","warn","startElement","nodeType","Node","ELEMENT_NODE","parentElement","endElement","classList","tempDiv","createElement","appendChild","cloneContents","querySelectorAll","length","highlightEl","style","backgroundColor","padding","margin","setAttribute","surroundContents","removeAllHighlights","forEach","highlight","element","querySelector","parentNode","textNode","createTextNode","replaceChild","getHighlights","removeHighlight","index","findIndex","h","splice"],"mappings":"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"}
|
|
@@ -26,6 +26,18 @@
|
|
|
26
26
|
this.highlights = [];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Generate a simple UUID
|
|
31
|
+
*/
|
|
32
|
+
generateUUID() {
|
|
33
|
+
return (
|
|
34
|
+
"highlight-" +
|
|
35
|
+
Date.now() +
|
|
36
|
+
"-" +
|
|
37
|
+
Math.random().toString(36).substring(2, 11)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
29
41
|
/**
|
|
30
42
|
* Highlight selected text
|
|
31
43
|
*/
|
|
@@ -60,10 +72,11 @@
|
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
try {
|
|
63
|
-
const
|
|
75
|
+
const uuid = this.generateUUID();
|
|
76
|
+
const highlightedElement = this.wrapRange(range, uuid);
|
|
64
77
|
|
|
65
78
|
this.highlights.push({
|
|
66
|
-
|
|
79
|
+
uuid: uuid,
|
|
67
80
|
text: selection.toString(),
|
|
68
81
|
});
|
|
69
82
|
|
|
@@ -120,14 +133,18 @@
|
|
|
120
133
|
/**
|
|
121
134
|
* Wrap a range with highlight element
|
|
122
135
|
* @param {Range} range - The range to wrap
|
|
136
|
+
* @param {string} uuid - Unique identifier for the highlight
|
|
123
137
|
*/
|
|
124
|
-
wrapRange(range) {
|
|
138
|
+
wrapRange(range, uuid) {
|
|
125
139
|
const highlightEl = document.createElement("span");
|
|
126
140
|
highlightEl.className = this.options.className;
|
|
127
141
|
highlightEl.style.backgroundColor = this.options.color;
|
|
128
142
|
highlightEl.style.padding = "0";
|
|
129
143
|
highlightEl.style.margin = "0";
|
|
130
144
|
|
|
145
|
+
// Add UUID as data attribute
|
|
146
|
+
highlightEl.setAttribute("data-uuid", uuid);
|
|
147
|
+
|
|
131
148
|
// Clone the range and insert the highlight element
|
|
132
149
|
range.surroundContents(highlightEl);
|
|
133
150
|
|
|
@@ -139,12 +156,12 @@
|
|
|
139
156
|
*/
|
|
140
157
|
removeAllHighlights() {
|
|
141
158
|
this.highlights.forEach((highlight) => {
|
|
142
|
-
|
|
159
|
+
const element = document.querySelector(
|
|
160
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
161
|
+
);
|
|
162
|
+
if (element && element.parentNode) {
|
|
143
163
|
const textNode = document.createTextNode(highlight.text);
|
|
144
|
-
|
|
145
|
-
textNode,
|
|
146
|
-
highlight.element,
|
|
147
|
-
);
|
|
164
|
+
element.parentNode.replaceChild(textNode, element);
|
|
148
165
|
}
|
|
149
166
|
});
|
|
150
167
|
|
|
@@ -155,23 +172,26 @@
|
|
|
155
172
|
* Get all highlighted elements
|
|
156
173
|
*/
|
|
157
174
|
getHighlights() {
|
|
175
|
+
// Return highlights with uuid and text
|
|
158
176
|
return [...this.highlights];
|
|
159
177
|
}
|
|
160
178
|
|
|
161
179
|
/**
|
|
162
180
|
* Remove a specific highlight
|
|
163
|
-
* @param {Object} highlight - The highlight object to remove
|
|
181
|
+
* @param {Object} highlight - The highlight object to remove (containing uuid)
|
|
164
182
|
*/
|
|
165
183
|
removeHighlight(highlight) {
|
|
166
|
-
const index = this.highlights.
|
|
184
|
+
const index = this.highlights.findIndex(
|
|
185
|
+
(h) => h.uuid === highlight.uuid,
|
|
186
|
+
);
|
|
167
187
|
if (index !== -1) {
|
|
168
188
|
// Restore the original text
|
|
169
|
-
|
|
189
|
+
const element = document.querySelector(
|
|
190
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
191
|
+
);
|
|
192
|
+
if (element && element.parentNode) {
|
|
170
193
|
const textNode = document.createTextNode(highlight.text);
|
|
171
|
-
|
|
172
|
-
textNode,
|
|
173
|
-
highlight.element,
|
|
174
|
-
);
|
|
194
|
+
element.parentNode.replaceChild(textNode, element);
|
|
175
195
|
}
|
|
176
196
|
|
|
177
197
|
// Remove from the highlights array
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lk-text-select-highlight.umd.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst highlightedElement = this.wrapRange(range);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\telement: highlightedElement,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t */\r\n\twrapRange(range) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tif (highlight.element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\thighlight.element.parentNode.replaceChild(\r\n\t\t\t\t\ttextNode,\r\n\t\t\t\t\thighlight.element,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.indexOf(highlight);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tif (highlight.element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\thighlight.element.parentNode.replaceChild(\r\n\t\t\t\t\ttextNode,\r\n\t\t\t\t\thighlight.element,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lk-text-select-highlight.umd.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * lk-text-select-highlight - A lightweight text selection highlight library\r\n * @module lk-text-select-highlight\r\n */\r\n\r\nclass TextHighlighter {\r\n\tconstructor(options = {}) {\r\n\t\tthis.options = {\r\n\t\t\tclassName: options.className || \"highlighted-text\",\r\n\t\t\tcolor: options.color || \"#ffff00\",\r\n\t\t\tcontainer: options.container || document.body, // DOM容器,默认为整个body\r\n\t\t\tstrictMode: options.strictMode || false, // 严格模式,默认为false\r\n\t\t\tcaseSensitive:\r\n\t\t\t\toptions.caseSensitive !== undefined\r\n\t\t\t\t\t? options.caseSensitive\r\n\t\t\t\t\t: true,\r\n\t\t\t...options,\r\n\t\t};\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Generate a simple UUID\r\n\t */\r\n\tgenerateUUID() {\r\n\t\treturn (\r\n\t\t\t\"highlight-\" +\r\n\t\t\tDate.now() +\r\n\t\t\t\"-\" +\r\n\t\t\tMath.random().toString(36).substring(2, 11)\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Highlight selected text\r\n\t */\r\n\thighlightSelection() {\r\n\t\tconst selection = window.getSelection();\r\n\t\tif (!selection.toString().trim()) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst range = selection.getRangeAt(0);\r\n\r\n\t\t// 检查选择的范围是否在指定的容器内\r\n\t\tconst container = this.options.container;\r\n\t\tif (\r\n\t\t\t!container.contains(range.startContainer) ||\r\n\t\t\t!container.contains(range.endContainer)\r\n\t\t) {\r\n\t\t\treturn false; // 选择超出了指定容器范围\r\n\t\t}\r\n\r\n\t\t// 更全面地检查整个范围是否在容器内\r\n\t\tconst commonAncestor = range.commonAncestorContainer;\r\n\t\tif (!container.contains(commonAncestor)) {\r\n\t\t\treturn false; // 整个范围不在容器内\r\n\t\t}\r\n\r\n\t\t// 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素\r\n\t\tif (this.options.strictMode) {\r\n\t\t\tif (this.hasTargetClassInSelection(range)) {\r\n\t\t\t\treturn false; // 选择范围内包含目标className的元素,不允许高亮\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst uuid = this.generateUUID();\r\n\t\t\tconst highlightedElement = this.wrapRange(range, uuid);\r\n\r\n\t\t\tthis.highlights.push({\r\n\t\t\t\tuuid: uuid,\r\n\t\t\t\ttext: selection.toString(),\r\n\t\t\t});\r\n\r\n\t\t\treturn true;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.warn(\"Could not highlight selection:\", error);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if the selection range contains elements with the target class\r\n\t * @param {Range} range - The range to check\r\n\t */\r\n\thasTargetClassInSelection(range) {\r\n\t\t// Check if startContainer or endContainer themselves have the target class\r\n\t\tconst startElement =\r\n\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.startContainer\r\n\t\t\t\t: range.startContainer.parentElement;\r\n\r\n\t\tconst endElement =\r\n\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\r\n\t\t\t\t? range.endContainer\r\n\t\t\t\t: range.endContainer.parentElement;\r\n\r\n\t\tif (\r\n\t\t\tstartElement &&\r\n\t\t\tstartElement.classList &&\r\n\t\t\tstartElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\tendElement &&\r\n\t\t\tendElement.classList &&\r\n\t\t\tendElement.classList.contains(this.options.className)\r\n\t\t) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Create a temporary div to work with the range content\r\n\t\tconst tempDiv = document.createElement(\"div\");\r\n\t\ttempDiv.appendChild(range.cloneContents());\r\n\r\n\t\t// Check if any child elements have the target class\r\n\t\tconst elementsWithTargetClass = tempDiv.querySelectorAll(\r\n\t\t\t`.${this.options.className}`,\r\n\t\t);\r\n\t\treturn elementsWithTargetClass.length > 0;\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap a range with highlight element\r\n\t * @param {Range} range - The range to wrap\r\n\t * @param {string} uuid - Unique identifier for the highlight\r\n\t */\r\n\twrapRange(range, uuid) {\r\n\t\tconst highlightEl = document.createElement(\"span\");\r\n\t\thighlightEl.className = this.options.className;\r\n\t\thighlightEl.style.backgroundColor = this.options.color;\r\n\t\thighlightEl.style.padding = \"0\";\r\n\t\thighlightEl.style.margin = \"0\";\r\n\r\n\t\t// Add UUID as data attribute\r\n\t\thighlightEl.setAttribute(\"data-uuid\", uuid);\r\n\r\n\t\t// Clone the range and insert the highlight element\r\n\t\trange.surroundContents(highlightEl);\r\n\r\n\t\treturn highlightEl;\r\n\t}\r\n\r\n\t/**\r\n\t * Remove all highlights\r\n\t */\r\n\tremoveAllHighlights() {\r\n\t\tthis.highlights.forEach((highlight) => {\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.highlights = [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get all highlighted elements\r\n\t */\r\n\tgetHighlights() {\r\n\t\t// Return highlights with uuid and text\r\n\t\treturn [...this.highlights];\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a specific highlight\r\n\t * @param {Object} highlight - The highlight object to remove (containing uuid)\r\n\t */\r\n\tremoveHighlight(highlight) {\r\n\t\tconst index = this.highlights.findIndex(\r\n\t\t\t(h) => h.uuid === highlight.uuid,\r\n\t\t);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Restore the original text\r\n\t\t\tconst element = document.querySelector(\r\n\t\t\t\t`[data-uuid=\"${highlight.uuid}\"]`,\r\n\t\t\t);\r\n\t\t\tif (element && element.parentNode) {\r\n\t\t\t\tconst textNode = document.createTextNode(highlight.text);\r\n\t\t\t\telement.parentNode.replaceChild(textNode, element);\r\n\t\t\t}\r\n\r\n\t\t\t// Remove from the highlights array\r\n\t\t\tthis.highlights.splice(index, 1);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lk-text-select-highlight",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A lightweight JavaScript library for highlighting selected text on web pages",
|
|
5
5
|
"main": "dist/lk-text-select-highlight.cjs.js",
|
|
6
6
|
"module": "dist/lk-text-select-highlight.esm.js",
|
package/src/index.js
CHANGED
|
@@ -20,6 +20,18 @@ class TextHighlighter {
|
|
|
20
20
|
this.highlights = [];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Generate a simple UUID
|
|
25
|
+
*/
|
|
26
|
+
generateUUID() {
|
|
27
|
+
return (
|
|
28
|
+
"highlight-" +
|
|
29
|
+
Date.now() +
|
|
30
|
+
"-" +
|
|
31
|
+
Math.random().toString(36).substring(2, 11)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
/**
|
|
24
36
|
* Highlight selected text
|
|
25
37
|
*/
|
|
@@ -54,10 +66,11 @@ class TextHighlighter {
|
|
|
54
66
|
}
|
|
55
67
|
|
|
56
68
|
try {
|
|
57
|
-
const
|
|
69
|
+
const uuid = this.generateUUID();
|
|
70
|
+
const highlightedElement = this.wrapRange(range, uuid);
|
|
58
71
|
|
|
59
72
|
this.highlights.push({
|
|
60
|
-
|
|
73
|
+
uuid: uuid,
|
|
61
74
|
text: selection.toString(),
|
|
62
75
|
});
|
|
63
76
|
|
|
@@ -114,14 +127,18 @@ class TextHighlighter {
|
|
|
114
127
|
/**
|
|
115
128
|
* Wrap a range with highlight element
|
|
116
129
|
* @param {Range} range - The range to wrap
|
|
130
|
+
* @param {string} uuid - Unique identifier for the highlight
|
|
117
131
|
*/
|
|
118
|
-
wrapRange(range) {
|
|
132
|
+
wrapRange(range, uuid) {
|
|
119
133
|
const highlightEl = document.createElement("span");
|
|
120
134
|
highlightEl.className = this.options.className;
|
|
121
135
|
highlightEl.style.backgroundColor = this.options.color;
|
|
122
136
|
highlightEl.style.padding = "0";
|
|
123
137
|
highlightEl.style.margin = "0";
|
|
124
138
|
|
|
139
|
+
// Add UUID as data attribute
|
|
140
|
+
highlightEl.setAttribute("data-uuid", uuid);
|
|
141
|
+
|
|
125
142
|
// Clone the range and insert the highlight element
|
|
126
143
|
range.surroundContents(highlightEl);
|
|
127
144
|
|
|
@@ -133,12 +150,12 @@ class TextHighlighter {
|
|
|
133
150
|
*/
|
|
134
151
|
removeAllHighlights() {
|
|
135
152
|
this.highlights.forEach((highlight) => {
|
|
136
|
-
|
|
153
|
+
const element = document.querySelector(
|
|
154
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
155
|
+
);
|
|
156
|
+
if (element && element.parentNode) {
|
|
137
157
|
const textNode = document.createTextNode(highlight.text);
|
|
138
|
-
|
|
139
|
-
textNode,
|
|
140
|
-
highlight.element,
|
|
141
|
-
);
|
|
158
|
+
element.parentNode.replaceChild(textNode, element);
|
|
142
159
|
}
|
|
143
160
|
});
|
|
144
161
|
|
|
@@ -149,23 +166,26 @@ class TextHighlighter {
|
|
|
149
166
|
* Get all highlighted elements
|
|
150
167
|
*/
|
|
151
168
|
getHighlights() {
|
|
169
|
+
// Return highlights with uuid and text
|
|
152
170
|
return [...this.highlights];
|
|
153
171
|
}
|
|
154
172
|
|
|
155
173
|
/**
|
|
156
174
|
* Remove a specific highlight
|
|
157
|
-
* @param {Object} highlight - The highlight object to remove
|
|
175
|
+
* @param {Object} highlight - The highlight object to remove (containing uuid)
|
|
158
176
|
*/
|
|
159
177
|
removeHighlight(highlight) {
|
|
160
|
-
const index = this.highlights.
|
|
178
|
+
const index = this.highlights.findIndex(
|
|
179
|
+
(h) => h.uuid === highlight.uuid,
|
|
180
|
+
);
|
|
161
181
|
if (index !== -1) {
|
|
162
182
|
// Restore the original text
|
|
163
|
-
|
|
183
|
+
const element = document.querySelector(
|
|
184
|
+
`[data-uuid="${highlight.uuid}"]`,
|
|
185
|
+
);
|
|
186
|
+
if (element && element.parentNode) {
|
|
164
187
|
const textNode = document.createTextNode(highlight.text);
|
|
165
|
-
|
|
166
|
-
textNode,
|
|
167
|
-
highlight.element,
|
|
168
|
-
);
|
|
188
|
+
element.parentNode.replaceChild(textNode, element);
|
|
169
189
|
}
|
|
170
190
|
|
|
171
191
|
// Remove from the highlights array
|