lk-text-select-highlight 1.0.3 → 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.
@@ -0,0 +1,2 @@
1
+ git提交的描述都用中文
2
+ 代码备注使用中文
@@ -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 highlightedElement = this.wrapRange(range);
71
+ const uuid = this.generateUUID();
72
+ const highlightedElement = this.wrapRange(range, uuid);
60
73
 
61
74
  this.highlights.push({
62
- element: highlightedElement,
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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.indexOf(highlight);
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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 highlightedElement = this.wrapRange(range);
69
+ const uuid = this.generateUUID();
70
+ const highlightedElement = this.wrapRange(range, uuid);
58
71
 
59
72
  this.highlights.push({
60
- element: highlightedElement,
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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.indexOf(highlight);
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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({element: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){const e=document.createElement("span");return e.className=this.options.className,e.style.backgroundColor=this.options.color,e.style.padding="0",e.style.margin="0",t.surroundContents(e),e}removeAllHighlights(){this.highlights.forEach(t=>{if(t.element.parentNode){const e=document.createTextNode(t.text);t.element.parentNode.replaceChild(e,t.element)}}),this.highlights=[]}getHighlights(){return[...this.highlights]}removeHighlight(t){const e=this.highlights.indexOf(t);if(-1!==e){if(t.element.parentNode){const e=document.createTextNode(t.text);t.element.parentNode.replaceChild(e,t.element)}return this.highlights.splice(e,1),!0}return!1}}});
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\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":["constructor","options","this","className","color","container","document","body","strictMode","caseSensitive","undefined","highlights","highlightSelection","selection","window","getSelection","toString","trim","range","getRangeAt","contains","startContainer","endContainer","commonAncestor","commonAncestorContainer","hasTargetClassInSelection","highlightedElement","wrapRange","push","element","text","error","console","warn","startElement","nodeType","Node","ELEMENT_NODE","parentElement","endElement","classList","tempDiv","createElement","appendChild","cloneContents","querySelectorAll","length","highlightEl","style","backgroundColor","padding","margin","surroundContents","removeAllHighlights","forEach","highlight","parentNode","textNode","createTextNode","replaceChild","getHighlights","removeHighlight","index","indexOf","splice"],"mappings":"sPAKA,MACC,WAAAA,CAAYC,EAAU,IACrBC,KAAKD,QAAU,CACdE,UAAWF,EAAQE,WAAa,mBAChCC,MAAOH,EAAQG,OAAS,UACxBC,UAAWJ,EAAQI,WAAaC,SAASC,KACzCC,WAAYP,EAAQO,aAAc,EAClCC,mBAC2BC,IAA1BT,EAAQQ,eACLR,EAAQQ,iBAETR,GAGJC,KAAKS,WAAa,EACnB,CAKA,kBAAAC,GACC,MAAMC,EAAYC,OAAOC,eACzB,IAAKF,EAAUG,WAAWC,OACzB,OAAO,EAGR,MAAMC,EAAQL,EAAUM,WAAW,GAG7Bd,EAAYH,KAAKD,QAAQI,UAC/B,IACEA,EAAUe,SAASF,EAAMG,kBACzBhB,EAAUe,SAASF,EAAMI,cAE1B,OAAO,EAIR,MAAMC,EAAiBL,EAAMM,wBAC7B,IAAKnB,EAAUe,SAASG,GACvB,OAAO,EAIR,GAAIrB,KAAKD,QAAQO,YACZN,KAAKuB,0BAA0BP,GAClC,OAAO,EAIT,IACC,MAAMQ,EAAqBxB,KAAKyB,UAAUT,GAO1C,OALAhB,KAAKS,WAAWiB,KAAK,CACpBC,QAASH,EACTI,KAAMjB,EAAUG,cAGV,CACR,CAAE,MAAOe,GAER,OADAC,QAAQC,KAAK,iCAAkCF,IACxC,CACR,CACD,CAMA,yBAAAN,CAA0BP,GAEzB,MAAMgB,EACLhB,EAAMG,eAAec,WAAaC,KAAKC,aACpCnB,EAAMG,eACNH,EAAMG,eAAeiB,cAEnBC,EACLrB,EAAMI,aAAaa,WAAaC,KAAKC,aAClCnB,EAAMI,aACNJ,EAAMI,aAAagB,cAEvB,GACCJ,GACAA,EAAaM,WACbN,EAAaM,UAAUpB,SAASlB,KAAKD,QAAQE,WAE7C,OAAO,EAGR,GACCoC,GACAA,EAAWC,WACXD,EAAWC,UAAUpB,SAASlB,KAAKD,QAAQE,WAE3C,OAAO,EAIR,MAAMsC,EAAUnC,SAASoC,cAAc,OACvCD,EAAQE,YAAYzB,EAAM0B,iBAM1B,OAHgCH,EAAQI,iBACvC,IAAI3C,KAAKD,QAAQE,aAEa2C,OAAS,CACzC,CAMA,SAAAnB,CAAUT,GACT,MAAM6B,EAAczC,SAASoC,cAAc,QAS3C,OARAK,EAAY5C,UAAYD,KAAKD,QAAQE,UACrC4C,EAAYC,MAAMC,gBAAkB/C,KAAKD,QAAQG,MACjD2C,EAAYC,MAAME,QAAU,IAC5BH,EAAYC,MAAMG,OAAS,IAG3BjC,EAAMkC,iBAAiBL,GAEhBA,CACR,CAKA,mBAAAM,GACCnD,KAAKS,WAAW2C,QAASC,IACxB,GAAIA,EAAU1B,QAAQ2B,WAAY,CACjC,MAAMC,EAAWnD,SAASoD,eAAeH,EAAUzB,MACnDyB,EAAU1B,QAAQ2B,WAAWG,aAC5BF,EACAF,EAAU1B,QAEZ,IAGD3B,KAAKS,WAAa,EACnB,CAKA,aAAAiD,GACC,MAAO,IAAI1D,KAAKS,WACjB,CAMA,eAAAkD,CAAgBN,GACf,MAAMO,EAAQ5D,KAAKS,WAAWoD,QAAQR,GACtC,IAAc,IAAVO,EAAc,CAEjB,GAAIP,EAAU1B,QAAQ2B,WAAY,CACjC,MAAMC,EAAWnD,SAASoD,eAAeH,EAAUzB,MACnDyB,EAAU1B,QAAQ2B,WAAWG,aAC5BF,EACAF,EAAU1B,QAEZ,CAIA,OADA3B,KAAKS,WAAWqD,OAAOF,EAAO,IACvB,CACR,CACA,OAAO,CACR"}
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 highlightedElement = this.wrapRange(range);
75
+ const uuid = this.generateUUID();
76
+ const highlightedElement = this.wrapRange(range, uuid);
64
77
 
65
78
  this.highlights.push({
66
- element: highlightedElement,
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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.indexOf(highlight);
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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",
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 highlightedElement = this.wrapRange(range);
69
+ const uuid = this.generateUUID();
70
+ const highlightedElement = this.wrapRange(range, uuid);
58
71
 
59
72
  this.highlights.push({
60
- element: highlightedElement,
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
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.indexOf(highlight);
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
- if (highlight.element.parentNode) {
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
- highlight.element.parentNode.replaceChild(
166
- textNode,
167
- highlight.element,
168
- );
188
+ element.parentNode.replaceChild(textNode, element);
169
189
  }
170
190
 
171
191
  // Remove from the highlights array
package/test_server.cjs DELETED
@@ -1,43 +0,0 @@
1
- const http = require("http");
2
- const fs = require("fs");
3
- const path = require("path");
4
-
5
- const port = 8080;
6
- const server = http.createServer((req, res) => {
7
- let filePath = "." + req.url;
8
-
9
- if (filePath === "./") {
10
- filePath = "./test_uuid_attr.html";
11
- }
12
-
13
- const extname = path.extname(filePath).toLowerCase();
14
- let contentType = "text/html";
15
-
16
- const mimeTypes = {
17
- ".js": "application/javascript",
18
- ".css": "text/css",
19
- ".html": "text/html",
20
- ".json": "application/json",
21
- };
22
-
23
- contentType = mimeTypes[extname] || "text/html";
24
-
25
- fs.readFile(filePath, (err, content) => {
26
- if (err) {
27
- if (err.code === "ENOENT") {
28
- res.writeHead(404);
29
- res.end("404 Not Found");
30
- } else {
31
- res.writeHead(500);
32
- res.end(`Server Error: ${err.code}`);
33
- }
34
- } else {
35
- res.writeHead(200, { "Content-Type": contentType });
36
- res.end(content, "utf-8");
37
- }
38
- });
39
- });
40
-
41
- server.listen(port, () => {
42
- console.log(`Server running at http://localhost:${port}/`);
43
- });
@@ -1,138 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>UUID Attribute Test</title>
7
- <style>
8
- body {
9
- font-family: Arial, sans-serif;
10
- max-width: 800px;
11
- margin: 0 auto;
12
- padding: 20px;
13
- line-height: 1.6;
14
- }
15
-
16
- .demo-text {
17
- background-color: #f9f9f9;
18
- padding: 20px;
19
- border-radius: 5px;
20
- margin: 20px 0;
21
- }
22
-
23
- .controls {
24
- margin: 20px 0;
25
- }
26
-
27
- button {
28
- background-color: #4caf50;
29
- color: white;
30
- padding: 10px 15px;
31
- border: none;
32
- border-radius: 4px;
33
- cursor: pointer;
34
- margin-right: 10px;
35
- margin-bottom: 10px;
36
- }
37
-
38
- button:hover {
39
- background-color: #45a049;
40
- }
41
-
42
- .highlighted-text {
43
- background-color: #ffff00;
44
- padding: 0;
45
- margin: 0;
46
- }
47
-
48
- .inspect-btn {
49
- background-color: #2196f3;
50
- }
51
-
52
- .inspect-btn:hover {
53
- background-color: #0b7dda;
54
- }
55
- </style>
56
- </head>
57
- <body>
58
- <h1>UUID Attribute Test</h1>
59
-
60
- <div class="controls">
61
- <button id="highlightBtn">高亮选中文本</button>
62
- <button id="inspectBtn" class="inspect-btn">
63
- 检查高亮元素属性
64
- </button>
65
- <button id="clearBtn">清除所有高亮</button>
66
- </div>
67
-
68
- <div class="demo-text" id="demo-content">
69
- <p>
70
- 请选择这段文字的一部分,然后点击"高亮选中文本"按钮。
71
- 高亮后点击"检查高亮元素属性"按钮查看data-uuid属性是否存在。
72
- </p>
73
- <p>
74
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
75
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
76
- enim ad minim veniam, quis nostrud exercitation ullamco laboris
77
- nisi ut aliquip ex ea commodo consequat.
78
- </p>
79
- </div>
80
-
81
- <div id="output"></div>
82
-
83
- <script src="./dist/lk-text-select-highlight.umd.js"></script>
84
- <script>
85
- // 初始化文本高亮器
86
- const highlighter = new TextHighlighter({
87
- className: "highlighted-text",
88
- color: "#ffff00",
89
- });
90
-
91
- // 高亮按钮事件
92
- document
93
- .getElementById("highlightBtn")
94
- .addEventListener("click", () => {
95
- const success = highlighter.highlightSelection();
96
- console.log("高亮操作结果:", success);
97
- });
98
-
99
- // 检查属性按钮事件
100
- document
101
- .getElementById("inspectBtn")
102
- .addEventListener("click", () => {
103
- const allHighlights =
104
- document.querySelectorAll(".highlighted-text");
105
- let outputHtml = "<h3>高亮元素属性检查:</h3>";
106
-
107
- allHighlights.forEach((el, index) => {
108
- const uuid = el.getAttribute("data-uuid");
109
- outputHtml += `<p>元素 ${index + 1}: data-uuid = ${uuid || "NOT FOUND"}</p>`;
110
-
111
- // 输出所有属性
112
- const attrs = Array.from(el.attributes);
113
- attrs.forEach((attr) => {
114
- console.log(
115
- `Attribute: ${attr.name} = ${attr.value}`,
116
- );
117
- });
118
- });
119
-
120
- if (allHighlights.length === 0) {
121
- outputHtml = "<h3>没有发现高亮元素</h3>";
122
- }
123
-
124
- document.getElementById("output").innerHTML = outputHtml;
125
- });
126
-
127
- // 清除高亮按钮
128
- document
129
- .getElementById("clearBtn")
130
- .addEventListener("click", () => {
131
- highlighter.removeAllHighlights();
132
- document.getElementById("output").innerHTML =
133
- "<h3>已清除所有高亮</h3>";
134
- console.log("已清除所有高亮");
135
- });
136
- </script>
137
- </body>
138
- </html>