lk-text-select-highlight 1.0.4 → 1.0.6
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/README-cn.md +14 -0
- package/README.md +10 -0
- package/demo-full.html +246 -0
- package/dist/lk-text-select-highlight.cjs.js +65 -15
- package/dist/lk-text-select-highlight.cjs.js.map +1 -1
- package/dist/lk-text-select-highlight.esm.js +65 -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 +65 -15
- package/dist/lk-text-select-highlight.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/index.js +65 -15
- package/test-full.cjs +102 -0
- package/types/index.d.ts +6 -0
- package/validate-full-process.cjs +141 -0
package/README-cn.md
CHANGED
|
@@ -125,6 +125,20 @@ if (highlights.length > 0) {
|
|
|
125
125
|
|
|
126
126
|
支持所有现代浏览器 (Chrome, Firefox, Safari, Edge)。
|
|
127
127
|
|
|
128
|
+
## 测试
|
|
129
|
+
|
|
130
|
+
运行测试:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npm test
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
该库包含全面的单元测试,覆盖所有主要功能,包括初始化、自定义选项、严格模式处理和高亮管理。
|
|
137
|
+
|
|
138
|
+
## 浏览器兼容性
|
|
139
|
+
|
|
140
|
+
支持所有现代浏览器 (Chrome, Firefox, Safari, Edge)。
|
|
141
|
+
|
|
128
142
|
## 许可证
|
|
129
143
|
|
|
130
144
|
MIT
|
package/README.md
CHANGED
|
@@ -75,6 +75,16 @@ Removes a specific highlight object. The highlight object can be obtained from t
|
|
|
75
75
|
|
|
76
76
|
Removes all existing highlights.
|
|
77
77
|
|
|
78
|
+
## Testing
|
|
79
|
+
|
|
80
|
+
To run the tests:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The library includes comprehensive unit tests covering all major functionality including initialization, custom options, strict mode handling, and highlight management.
|
|
87
|
+
|
|
78
88
|
## License
|
|
79
89
|
|
|
80
90
|
MIT
|
package/demo-full.html
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
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>lk-text-select-highlight 完整功能演示</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
|
+
.container {
|
|
17
|
+
border: 2px solid #ddd;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
margin: 20px 0;
|
|
20
|
+
background-color: #f9f9f9;
|
|
21
|
+
border-radius: 5px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.controls {
|
|
25
|
+
margin: 20px 0;
|
|
26
|
+
padding: 15px;
|
|
27
|
+
background-color: #eef;
|
|
28
|
+
border-radius: 5px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
button {
|
|
32
|
+
margin: 5px;
|
|
33
|
+
padding: 8px 15px;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
background-color: #007bff;
|
|
36
|
+
color: white;
|
|
37
|
+
border: none;
|
|
38
|
+
border-radius: 3px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
button:hover {
|
|
42
|
+
background-color: #0056b3;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.highlighted-text {
|
|
46
|
+
background-color: yellow;
|
|
47
|
+
padding: 0;
|
|
48
|
+
margin: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.status {
|
|
52
|
+
margin: 10px 0;
|
|
53
|
+
padding: 10px;
|
|
54
|
+
background-color: #eee;
|
|
55
|
+
border-left: 4px solid #007bff;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#output {
|
|
59
|
+
background-color: #f0f0f0;
|
|
60
|
+
padding: 10px;
|
|
61
|
+
border-radius: 3px;
|
|
62
|
+
font-family: monospace;
|
|
63
|
+
white-space: pre-wrap;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
66
|
+
</head>
|
|
67
|
+
<body>
|
|
68
|
+
<h1>lk-text-select-highlight 完整功能演示</h1>
|
|
69
|
+
|
|
70
|
+
<div class="controls">
|
|
71
|
+
<button onclick="highlightText()">高亮选中文本</button>
|
|
72
|
+
<button onclick="removeAllHighlights()">清除所有高亮</button>
|
|
73
|
+
<button onclick="getHighlights()">获取高亮数据</button>
|
|
74
|
+
<button onclick="setHighlightsData()">设置预设高亮数据</button>
|
|
75
|
+
<button onclick="removeSpecificHighlight()">移除特定高亮</button>
|
|
76
|
+
<br /><br />
|
|
77
|
+
<label>
|
|
78
|
+
<input
|
|
79
|
+
type="checkbox"
|
|
80
|
+
id="strictMode"
|
|
81
|
+
onchange="toggleStrictMode()"
|
|
82
|
+
/>
|
|
83
|
+
严格模式
|
|
84
|
+
</label>
|
|
85
|
+
<label>
|
|
86
|
+
<input
|
|
87
|
+
type="checkbox"
|
|
88
|
+
id="limitedContainer"
|
|
89
|
+
onchange="toggleContainer()"
|
|
90
|
+
/>
|
|
91
|
+
限制容器内高亮
|
|
92
|
+
</label>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<div class="status">
|
|
96
|
+
<strong>状态信息:</strong>
|
|
97
|
+
<div id="output">点击按钮开始测试功能...</div>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div class="container" id="container1">
|
|
101
|
+
<h2>容器1 - 可高亮区域</h2>
|
|
102
|
+
<p>
|
|
103
|
+
这里是第一个容器的内容。您可以选择这段文字进行高亮。这是用于测试容器限制功能的文本。
|
|
104
|
+
</p>
|
|
105
|
+
<p>
|
|
106
|
+
尝试选择这部分文字:<strong>这段文字可以被高亮</strong>,因为它在容器内。
|
|
107
|
+
</p>
|
|
108
|
+
<p>还可以选择其他内容,比如:<em>斜体文字也可以被高亮</em>。</p>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="container" id="container2">
|
|
112
|
+
<h2>容器2 - 另一个可高亮区域</h2>
|
|
113
|
+
<p>这里是第二个容器的内容。这里也有一些可以高亮的文本。</p>
|
|
114
|
+
<p>
|
|
115
|
+
您可以试试选择
|
|
116
|
+
<span class="highlighted-text" data-uuid="demo-123"
|
|
117
|
+
>这个预先高亮的文本</span
|
|
118
|
+
>,看看在严格模式下的表现。
|
|
119
|
+
</p>
|
|
120
|
+
<p>这段文字也是可以被高亮的普通文本。</p>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<div>
|
|
124
|
+
<h2>非容器区域 - 默认也可高亮</h2>
|
|
125
|
+
<p>
|
|
126
|
+
这部分内容默认在整个页面都可以选择高亮,但如果启用了容器限制,则只能在指定容器内高亮。
|
|
127
|
+
</p>
|
|
128
|
+
<p>这是一个额外的测试段落,用来验证容器限制功能。</p>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<script src="./dist/lk-text-select-highlight.umd.js?v=1.0.5"></script>
|
|
132
|
+
<script>
|
|
133
|
+
// 初始化TextHighlighter实例
|
|
134
|
+
let highlighter;
|
|
135
|
+
let limitedHighlighter;
|
|
136
|
+
|
|
137
|
+
// 页面加载完成后初始化
|
|
138
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
139
|
+
// 创建普通高亮器(整个页面)
|
|
140
|
+
highlighter = new TextHighlighter({
|
|
141
|
+
className: "highlighted-text",
|
|
142
|
+
color: "#ffff00",
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// 创建限制在容器内的高亮器
|
|
146
|
+
const container = document.getElementById("container1");
|
|
147
|
+
limitedHighlighter = new TextHighlighter({
|
|
148
|
+
className: "highlighted-text",
|
|
149
|
+
color: "#aaffaa",
|
|
150
|
+
container: container,
|
|
151
|
+
strictMode: false,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
updateOutput("TextHighlighter 已初始化完成");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
function updateOutput(message) {
|
|
158
|
+
const output = document.getElementById("output");
|
|
159
|
+
output.textContent = message;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function highlightText() {
|
|
163
|
+
const useLimited =
|
|
164
|
+
document.getElementById("limitedContainer").checked;
|
|
165
|
+
const currentHighlighter = useLimited
|
|
166
|
+
? limitedHighlighter
|
|
167
|
+
: highlighter;
|
|
168
|
+
|
|
169
|
+
const success = currentHighlighter.highlightSelection();
|
|
170
|
+
if (success) {
|
|
171
|
+
updateOutput("文本高亮成功!");
|
|
172
|
+
} else {
|
|
173
|
+
updateOutput(
|
|
174
|
+
"高亮失败:可能是没有选中文本,或超出容器范围,或处于严格模式下选择了已高亮的文本",
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function removeAllHighlights() {
|
|
180
|
+
highlighter.removeAllHighlights();
|
|
181
|
+
limitedHighlighter.removeAllHighlights(); // 同时清理两个高亮器
|
|
182
|
+
updateOutput("所有高亮已清除");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function getHighlights() {
|
|
186
|
+
const highlights = highlighter.getHighlights();
|
|
187
|
+
const limitedHighlights = limitedHighlighter.getHighlights();
|
|
188
|
+
updateOutput(
|
|
189
|
+
`主高亮器数据:${JSON.stringify(highlights, null, 2)}\n\n限制容器高亮器数据:${JSON.stringify(limitedHighlights, null, 2)}`,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function setHighlightsData() {
|
|
194
|
+
try {
|
|
195
|
+
// 设置一些预设的高亮数据
|
|
196
|
+
const presetHighlights = [
|
|
197
|
+
{ uuid: "preset-1", text: "这段文字可以被高亮" },
|
|
198
|
+
{ uuid: "preset-2", text: "斜体文字也可以被高亮" },
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
highlighter.setHighlights(presetHighlights);
|
|
202
|
+
updateOutput(
|
|
203
|
+
`已设置预设高亮数据:${JSON.stringify(presetHighlights, null, 2)}`,
|
|
204
|
+
);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
updateOutput(`设置高亮数据失败:${error.message}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function removeSpecificHighlight() {
|
|
211
|
+
const highlights = highlighter.getHighlights();
|
|
212
|
+
if (highlights.length > 0) {
|
|
213
|
+
const highlightToRemove = highlights[0]; // 移除第一个高亮
|
|
214
|
+
const success =
|
|
215
|
+
highlighter.removeHighlight(highlightToRemove);
|
|
216
|
+
if (success) {
|
|
217
|
+
updateOutput(
|
|
218
|
+
`已移除特定高亮:${JSON.stringify(highlightToRemove)}`,
|
|
219
|
+
);
|
|
220
|
+
} else {
|
|
221
|
+
updateOutput(`移除高亮失败`);
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
updateOutput("没有可移除的高亮");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function toggleStrictMode() {
|
|
229
|
+
const strictMode =
|
|
230
|
+
document.getElementById("strictMode").checked;
|
|
231
|
+
// 更新两个高亮器的严格模式
|
|
232
|
+
highlighter.options.strictMode = strictMode;
|
|
233
|
+
limitedHighlighter.options.strictMode = strictMode;
|
|
234
|
+
updateOutput(`严格模式已${strictMode ? "启用" : "禁用"}`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function toggleContainer() {
|
|
238
|
+
const useLimited =
|
|
239
|
+
document.getElementById("limitedContainer").checked;
|
|
240
|
+
updateOutput(
|
|
241
|
+
`容器限制模式${useLimited ? "已启用(请在容器1内选择文本)" : "已禁用(可在整个页面选择文本)"}`,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
</script>
|
|
245
|
+
</body>
|
|
246
|
+
</html>
|
|
@@ -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
|
|
@@ -176,6 +196,36 @@ class TextHighlighter {
|
|
|
176
196
|
}
|
|
177
197
|
return false;
|
|
178
198
|
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Set highlights data
|
|
202
|
+
* @param {Array} highlights - Array of highlight objects with uuid and text properties
|
|
203
|
+
*/
|
|
204
|
+
setHighlights(highlights) {
|
|
205
|
+
// Validate the input to ensure it's an array of objects with required properties
|
|
206
|
+
if (!Array.isArray(highlights)) {
|
|
207
|
+
throw new Error("Highlights must be an array");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Validate each highlight object
|
|
211
|
+
for (const highlight of highlights) {
|
|
212
|
+
if (
|
|
213
|
+
typeof highlight !== "object" ||
|
|
214
|
+
!highlight.hasOwnProperty("uuid") ||
|
|
215
|
+
!highlight.hasOwnProperty("text")
|
|
216
|
+
) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
"Each highlight must be an object with uuid and text properties",
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Clear existing highlights
|
|
224
|
+
this.removeAllHighlights();
|
|
225
|
+
|
|
226
|
+
// Set the new highlights data
|
|
227
|
+
this.highlights = [...highlights];
|
|
228
|
+
}
|
|
179
229
|
}
|
|
180
230
|
|
|
181
231
|
module.exports = TextHighlighter;
|
|
@@ -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":";;AAAA;AACA;AACA;AACA;AACA;AACA,MAAM,eAAe,CAAC;AACtB,CAAC,WAAW,CAAC,OAAO,GAAG,EAAE,EAAE;AAC3B,EAAE,IAAI,CAAC,OAAO,GAAG;AACjB,GAAG,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,kBAAkB;AACrD,GAAG,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;AACpC,GAAG,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI;AAChD,GAAG,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK;AAC1C,GAAG,aAAa;AAChB,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS;AACvC,OAAO,OAAO,CAAC,aAAa;AAC5B,OAAO,IAAI;AACX,GAAG,GAAG,OAAO;AACb,GAAG,CAAC;AACJ;AACA,EAAE,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACvB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,kBAAkB,GAAG;AACtB,EAAE,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;AAC1C,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;AACpC,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA,EAAE,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACxC;AACA;AACA,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AAC3C,EAAE;AACF,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;AAC5C,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;AAC1C,IAAI;AACJ,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA;AACA,EAAE,MAAM,cAAc,GAAG,KAAK,CAAC,uBAAuB,CAAC;AACvD,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;AAC3C,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA;AACA,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;AAC/B,GAAG,IAAI,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE;AAC9C,IAAI,OAAO,KAAK,CAAC;AACjB,GAAG,CAAC;AACJ,EAAE,CAAC;AACH;AACA,EAAE,IAAI;AACN,GAAG,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACpD;AACA,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;AACxB,IAAI,OAAO,EAAE,kBAAkB;AAC/B,IAAI,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE;AAC9B,IAAI,CAAC,CAAC;AACN;AACA,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC,CAAC,OAAO,KAAK,EAAE;AAClB,GAAG,OAAO,CAAC,IAAI,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;AACzD,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,yBAAyB,CAAC,KAAK,EAAE;AAClC;AACA,EAAE,MAAM,YAAY;AACpB,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY;AACtD,MAAM,KAAK,CAAC,cAAc;AAC1B,MAAM,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC;AACzC;AACA,EAAE,MAAM,UAAU;AAClB,GAAG,KAAK,CAAC,YAAY,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY;AACpD,MAAM,KAAK,CAAC,YAAY;AACxB,MAAM,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC;AACvC;AACA,EAAE;AACF,GAAG,YAAY;AACf,GAAG,YAAY,CAAC,SAAS;AACzB,GAAG,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AAC1D,IAAI;AACJ,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC;AACH;AACA,EAAE;AACF,GAAG,UAAU;AACb,GAAG,UAAU,CAAC,SAAS;AACvB,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AACxD,IAAI;AACJ,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC;AACH;AACA;AACA,EAAE,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAChD,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;AAC7C;AACA;AACA,EAAE,MAAM,uBAAuB,GAAG,OAAO,CAAC,gBAAgB;AAC1D,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAC/B,GAAG,CAAC;AACJ,EAAE,OAAO,uBAAuB,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5C,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,CAAC,KAAK,EAAE;AAClB,EAAE,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;AACrD,EAAE,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AACjD,EAAE,WAAW,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;AACzD,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;AAClC,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;AACjC;AACA;AACA,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;AACtC;AACA,EAAE,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,mBAAmB,GAAG;AACvB,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,KAAK;AACzC,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE;AACrC,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7D,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY;AAC7C,KAAK,QAAQ;AACb,KAAK,SAAS,CAAC,OAAO;AACtB,KAAK,CAAC;AACN,GAAG,CAAC;AACJ,EAAE,CAAC,CAAC,CAAC;AACL;AACA,EAAE,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACvB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,aAAa,GAAG;AACjB,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,eAAe,CAAC,SAAS,EAAE;AAC5B,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACnD,EAAE,IAAI,KAAK,KAAK,EAAE,EAAE;AACpB;AACA,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE;AACrC,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7D,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY;AAC7C,KAAK,QAAQ;AACb,KAAK,SAAS,CAAC,OAAO;AACtB,KAAK,CAAC;AACN,GAAG,CAAC;AACJ;AACA;AACA,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACpC,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC;AACH,EAAE,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AACF;;;;"}
|
|
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\t/**\r\n\t * Set highlights data\r\n\t * @param {Array} highlights - Array of highlight objects with uuid and text properties\r\n\t */\r\n\tsetHighlights(highlights) {\r\n\t\t// Validate the input to ensure it's an array of objects with required properties\r\n\t\tif (!Array.isArray(highlights)) {\r\n\t\t\tthrow new Error(\"Highlights must be an array\");\r\n\t\t}\r\n\r\n\t\t// Validate each highlight object\r\n\t\tfor (const highlight of highlights) {\r\n\t\t\tif (\r\n\t\t\t\ttypeof highlight !== \"object\" ||\r\n\t\t\t\t!highlight.hasOwnProperty(\"uuid\") ||\r\n\t\t\t\t!highlight.hasOwnProperty(\"text\")\r\n\t\t\t) {\r\n\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\"Each highlight must be an object with uuid and text properties\",\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Clear existing highlights\r\n\t\tthis.removeAllHighlights();\r\n\r\n\t\t// Set the new highlights data\r\n\t\tthis.highlights = [...highlights];\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA,MAAM,eAAe,CAAC;AACtB,CAAC,WAAW,CAAC,OAAO,GAAG,EAAE,EAAE;AAC3B,EAAE,IAAI,CAAC,OAAO,GAAG;AACjB,GAAG,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,kBAAkB;AACrD,GAAG,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;AACpC,GAAG,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI;AAChD,GAAG,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK;AAC1C,GAAG,aAAa;AAChB,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS;AACvC,OAAO,OAAO,CAAC,aAAa;AAC5B,OAAO,IAAI;AACX,GAAG,GAAG,OAAO;AACb,GAAG,CAAC;AACJ;AACA,EAAE,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACvB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,YAAY,GAAG;AAChB,EAAE;AACF,GAAG,YAAY;AACf,GAAG,IAAI,CAAC,GAAG,EAAE;AACb,GAAG,GAAG;AACN,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC;AAC9C,IAAI;AACJ,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,kBAAkB,GAAG;AACtB,EAAE,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;AAC1C,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;AACpC,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA,EAAE,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACxC;AACA;AACA,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AAC3C,EAAE;AACF,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;AAC5C,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;AAC1C,IAAI;AACJ,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA;AACA,EAAE,MAAM,cAAc,GAAG,KAAK,CAAC,uBAAuB,CAAC;AACvD,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;AAC3C,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA;AACA,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;AAC/B,GAAG,IAAI,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE;AAC9C,IAAI,OAAO,KAAK,CAAC;AACjB,GAAG,CAAC;AACJ,EAAE,CAAC;AACH;AACA,EAAE,IAAI;AACN,GAAG,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;AACpC,GAAG,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC1D;AACA,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;AACxB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE;AAC9B,IAAI,CAAC,CAAC;AACN;AACA,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC,CAAC,OAAO,KAAK,EAAE;AAClB,GAAG,OAAO,CAAC,IAAI,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;AACzD,GAAG,OAAO,KAAK,CAAC;AAChB,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,yBAAyB,CAAC,KAAK,EAAE;AAClC;AACA,EAAE,MAAM,YAAY;AACpB,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY;AACtD,MAAM,KAAK,CAAC,cAAc;AAC1B,MAAM,KAAK,CAAC,cAAc,CAAC,aAAa,CAAC;AACzC;AACA,EAAE,MAAM,UAAU;AAClB,GAAG,KAAK,CAAC,YAAY,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY;AACpD,MAAM,KAAK,CAAC,YAAY;AACxB,MAAM,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC;AACvC;AACA,EAAE;AACF,GAAG,YAAY;AACf,GAAG,YAAY,CAAC,SAAS;AACzB,GAAG,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AAC1D,IAAI;AACJ,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC;AACH;AACA,EAAE;AACF,GAAG,UAAU;AACb,GAAG,UAAU,CAAC,SAAS;AACvB,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AACxD,IAAI;AACJ,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC;AACH;AACA;AACA,EAAE,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAChD,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;AAC7C;AACA;AACA,EAAE,MAAM,uBAAuB,GAAG,OAAO,CAAC,gBAAgB;AAC1D,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAC/B,GAAG,CAAC;AACJ,EAAE,OAAO,uBAAuB,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5C,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;AACxB,EAAE,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;AACrD,EAAE,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AACjD,EAAE,WAAW,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;AACzD,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;AAClC,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;AACjC;AACA;AACA,EAAE,WAAW,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAC9C;AACA;AACA,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;AACtC;AACA,EAAE,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,mBAAmB,GAAG;AACvB,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,KAAK;AACzC,GAAG,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa;AACzC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;AACrC,IAAI,CAAC;AACL,GAAG,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU,EAAE;AACtC,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7D,IAAI,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACvD,GAAG,CAAC;AACJ,EAAE,CAAC,CAAC,CAAC;AACL;AACA,EAAE,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACvB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA,CAAC,aAAa,GAAG;AACjB;AACA,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,eAAe,CAAC,SAAS,EAAE;AAC5B,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS;AACzC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;AACnC,GAAG,CAAC;AACJ,EAAE,IAAI,KAAK,KAAK,EAAE,EAAE;AACpB;AACA,GAAG,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa;AACzC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;AACrC,IAAI,CAAC;AACL,GAAG,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU,EAAE;AACtC,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7D,IAAI,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACvD,GAAG,CAAC;AACJ;AACA;AACA,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACpC,GAAG,OAAO,IAAI,CAAC;AACf,EAAE,CAAC;AACH,EAAE,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,aAAa,CAAC,UAAU,EAAE;AAC3B;AACA,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;AAClC,GAAG,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;AAClD,EAAE,CAAC;AACH;AACA;AACA,EAAE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;AACtC,GAAG;AACH,IAAI,OAAO,SAAS,KAAK,QAAQ;AACjC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC;AACrC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC;AACrC,KAAK;AACL,IAAI,MAAM,IAAI,KAAK;AACnB,KAAK,gEAAgE;AACrE,KAAK,CAAC;AACN,GAAG,CAAC;AACJ,EAAE,CAAC;AACH;AACA;AACA,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC;AAC7B;AACA;AACA,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;AACpC,CAAC,CAAC;AACF;;;;"}
|
|
@@ -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
|
|
@@ -174,6 +194,36 @@ class TextHighlighter {
|
|
|
174
194
|
}
|
|
175
195
|
return false;
|
|
176
196
|
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Set highlights data
|
|
200
|
+
* @param {Array} highlights - Array of highlight objects with uuid and text properties
|
|
201
|
+
*/
|
|
202
|
+
setHighlights(highlights) {
|
|
203
|
+
// Validate the input to ensure it's an array of objects with required properties
|
|
204
|
+
if (!Array.isArray(highlights)) {
|
|
205
|
+
throw new Error("Highlights must be an array");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Validate each highlight object
|
|
209
|
+
for (const highlight of highlights) {
|
|
210
|
+
if (
|
|
211
|
+
typeof highlight !== "object" ||
|
|
212
|
+
!highlight.hasOwnProperty("uuid") ||
|
|
213
|
+
!highlight.hasOwnProperty("text")
|
|
214
|
+
) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
"Each highlight must be an object with uuid and text properties",
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Clear existing highlights
|
|
222
|
+
this.removeAllHighlights();
|
|
223
|
+
|
|
224
|
+
// Set the new highlights data
|
|
225
|
+
this.highlights = [...highlights];
|
|
226
|
+
}
|
|
177
227
|
}
|
|
178
228
|
|
|
179
229
|
export { TextHighlighter as default };
|
|
@@ -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\t/**\r\n\t * Set highlights data\r\n\t * @param {Array} highlights - Array of highlight objects with uuid and text properties\r\n\t */\r\n\tsetHighlights(highlights) {\r\n\t\t// Validate the input to ensure it's an array of objects with required properties\r\n\t\tif (!Array.isArray(highlights)) {\r\n\t\t\tthrow new Error(\"Highlights must be an array\");\r\n\t\t}\r\n\r\n\t\t// Validate each highlight object\r\n\t\tfor (const highlight of highlights) {\r\n\t\t\tif (\r\n\t\t\t\ttypeof highlight !== \"object\" ||\r\n\t\t\t\t!highlight.hasOwnProperty(\"uuid\") ||\r\n\t\t\t\t!highlight.hasOwnProperty(\"text\")\r\n\t\t\t) {\r\n\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\"Each highlight must be an object with uuid and text properties\",\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Clear existing highlights\r\n\t\tthis.removeAllHighlights();\r\n\r\n\t\t// Set the new highlights data\r\n\t\tthis.highlights = [...highlights];\r\n\t}\r\n}\r\n\r\nexport default TextHighlighter;\r\n"],"names":[],"mappings":"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"}
|