lk-text-select-highlight 1.0.0

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/AGENTS.md ADDED
@@ -0,0 +1,56 @@
1
+ # lk-text-select-highlight - Project Structure
2
+
3
+ ## Overview
4
+ A lightweight JavaScript library for highlighting selected text on web pages.
5
+
6
+ ## File Structure
7
+ ```
8
+ lk-text-select-highlight/
9
+ ├── src/
10
+ │ └── index.js # Main source code (ES6)
11
+ ├── dist/ # Built distribution files
12
+ │ ├── lk-text-select-highlight.cjs.js # CommonJS version
13
+ │ ├── lk-text-select-highlight.cjs.js.map # Source map for CJS
14
+ │ ├── lk-text-select-highlight.esm.js # ES modules version
15
+ │ ├── lk-text-select-highlight.esm.js.map # Source map for ESM
16
+ │ ├── lk-text-select-highlight.umd.js # UMD version for browsers
17
+ │ ├── lk-text-select-highlight.umd.js.map # Source map for UMD
18
+ │ ├── lk-text-select-highlight.min.js # Minified UMD version
19
+ │ └── lk-text-select-highlight.min.js.map # Source map for minified
20
+ ├── test/
21
+ │ └── index.test.js # Test file
22
+ ├── demo.html # Demo/example HTML file
23
+ ├── styles.css # Optional default styles
24
+ ├── README.md # Project documentation
25
+ ├── LICENSE # MIT License
26
+ ├── .npmignore # Files to exclude from npm package
27
+ ├── package.json # Package manifest
28
+ ├── rollup.config.cjs # Build configuration
29
+ └── index.js # Legacy entry point (backward compatibility)
30
+ ```
31
+
32
+ ## Features
33
+ - Supports multiple module formats (CommonJS, ES Modules, UMD)
34
+ - Lightweight with no external dependencies
35
+ - Customizable highlight appearance
36
+ - Cross-browser compatibility
37
+ - Tree-shakeable exports
38
+
39
+ ## Build Process
40
+ The library uses Rollup to generate multiple builds:
41
+ - `cjs`: For Node.js usage
42
+ - `esm`: For modern bundlers
43
+ - `umd`: For direct browser usage
44
+ - `min`: Minified version for production
45
+
46
+ ## Publishing
47
+ To publish to npm:
48
+ 1. Update version in package.json
49
+ 2. Run tests: `npm test`
50
+ 3. Build: `npm run build`
51
+ 4. Publish: `npm publish`
52
+
53
+ ## Development
54
+ - Run in watch mode: `npm run dev`
55
+ - Run tests: `npm test`
56
+ - Build: `npm run build`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README-cn.md ADDED
@@ -0,0 +1,128 @@
1
+ # lk-text-select-highlight
2
+
3
+ 一个轻量级的JavaScript库,用于在网页上高亮选中的文本。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install lk-text-select-highlight
9
+ ```
10
+
11
+ ## 使用方法
12
+
13
+ ### ES6 模块导入
14
+ ```javascript
15
+ import TextHighlighter from 'lk-text-select-highlight';
16
+
17
+ const highlighter = new TextHighlighter({
18
+ className: 'my-highlight',
19
+ color: '#ffeb3b'
20
+ });
21
+
22
+ // 高亮选中的文本
23
+ document.addEventListener('mouseup', () => {
24
+ highlighter.highlightSelection();
25
+ });
26
+ ```
27
+
28
+ ### 浏览器脚本标签
29
+ ```html
30
+ <script src="https://unpkg.com/lk-text-select-highlight/dist/lk-text-select-highlight.min.js"></script>
31
+ <script>
32
+ const highlighter = new TextHighlighter({
33
+ className: 'my-highlight',
34
+ color: '#ffeb3b'
35
+ });
36
+
37
+ // 高亮选中的文本
38
+ document.addEventListener('mouseup', () => {
39
+ highlighter.highlightSelection();
40
+ });
41
+ </script>
42
+ ```
43
+
44
+ ## API
45
+
46
+ ### new TextHighlighter(options)
47
+
48
+ 使用以下选项初始化新的 TextHighlighter 实例:
49
+
50
+ - `className`: 高亮元素的CSS类名 (默认: 'highlighted-text')
51
+ - `color`: 高亮背景颜色 (默认: '#ffff00')
52
+ - `container`: 限制文本选择高亮的DOM元素 (默认: document.body)
53
+ - `strictMode`: 如果为true,则防止在包含目标className元素的选择上进行高亮 (默认: false)
54
+ - `caseSensitive`: 搜索是否区分大小写 (默认: true)
55
+
56
+ ### highlighter.highlightSelection()
57
+
58
+ 高亮页面上当前选中的文本。
59
+
60
+ ### highlighter.removeAllHighlights()
61
+
62
+ 移除所有现有的高亮。
63
+
64
+ ### highlighter.removeHighlight(highlight)
65
+
66
+ 移除指定的高亮对象。高亮对象可以从 getHighlights() 方法获取。
67
+
68
+ ### highlighter.getHighlights()
69
+
70
+ 返回所有当前高亮的数组。
71
+
72
+ ## 配置选项详解
73
+
74
+ ### container 选项
75
+ 允许您限制文本选择高亮的范围。如果您只想在特定DOM元素内启用高亮功能,可以使用此选项:
76
+
77
+ ```javascript
78
+ const container = document.getElementById('content-area');
79
+ const highlighter = new TextHighlighter({
80
+ container: container
81
+ });
82
+ ```
83
+
84
+ ### strictMode 选项
85
+ 启用严格模式后,如果选择的文本范围内包含相同类名的元素,将不会进行高亮。这对于防止嵌套高亮非常有用:
86
+
87
+ ```javascript
88
+ const highlighter = new TextHighlighter({
89
+ className: 'highlighted-text',
90
+ strictMode: true // 启用严格模式
91
+ });
92
+ ```
93
+
94
+ ## 示例
95
+
96
+ ```javascript
97
+ // 基本用法
98
+ const highlighter = new TextHighlighter();
99
+
100
+ // 自定义选项
101
+ const customHighlighter = new TextHighlighter({
102
+ className: 'custom-highlight',
103
+ color: '#ff6b6b',
104
+ container: document.querySelector('.content'),
105
+ strictMode: true
106
+ });
107
+
108
+ // 高亮选中的文本
109
+ document.addEventListener('mouseup', () => {
110
+ highlighter.highlightSelection();
111
+ });
112
+
113
+ // 获取所有高亮
114
+ const highlights = highlighter.getHighlights();
115
+
116
+ // 移除特定高亮
117
+ if (highlights.length > 0) {
118
+ highlighter.removeHighlight(highlights[0]);
119
+ }
120
+ ```
121
+
122
+ ## 浏览器兼容性
123
+
124
+ 支持所有现代浏览器 (Chrome, Firefox, Safari, Edge)。
125
+
126
+ ## 许可证
127
+
128
+ MIT
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # lk-text-select-highlight
2
+
3
+ A lightweight JavaScript library for highlighting selected text on web pages.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install lk-text-select-highlight
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### ES6 Import
14
+ ```javascript
15
+ import TextHighlighter from 'lk-text-select-highlight';
16
+
17
+ const highlighter = new TextHighlighter({
18
+ className: 'my-highlight',
19
+ color: '#ffeb3b'
20
+ });
21
+
22
+ // Highlight selected text
23
+ document.addEventListener('mouseup', () => {
24
+ highlighter.highlightSelection();
25
+ });
26
+ ```
27
+
28
+ ### Browser Script Tag
29
+ ```html
30
+ <script src="https://unpkg.com/lk-text-select-highlight/dist/lk-text-select-highlight.min.js"></script>
31
+ <script>
32
+ const highlighter = new TextHighlighter({
33
+ className: 'my-highlight',
34
+ color: '#ffeb3b'
35
+ });
36
+
37
+ // Highlight selected text
38
+ document.addEventListener('mouseup', () => {
39
+ highlighter.highlightSelection();
40
+ });
41
+ </script>
42
+ ```
43
+
44
+ ## API
45
+
46
+ ### new TextHighlighter(options)
47
+
48
+ Initialize a new TextHighlighter instance with the following options:
49
+
50
+ - `className`: CSS class name for highlighted elements (default: 'highlighted-text')
51
+ - `color`: Background color for highlights (default: '#ffff00')
52
+ - `container`: DOM element that limits where text selection highlighting occurs (default: document.body)
53
+ - `strictMode`: If true, prevents highlighting selections that contain elements with the target className (default: false)
54
+ - `caseSensitive`: Whether search should be case sensitive (default: true)
55
+
56
+ ### highlighter.highlightSelection()
57
+
58
+ Highlights the currently selected text on the page.
59
+
60
+ ### highlighter.removeAllHighlights()
61
+
62
+ Removes all existing highlights.
63
+
64
+ ### highlighter.getHighlights()
65
+
66
+ Returns an array of all current highlights.
67
+
68
+ ### highlighter.removeHighlight(highlight)
69
+
70
+ Removes a specific highlight object. The highlight object can be obtained from the getHighlights() method.
71
+
72
+ ### highlighter.removeAllHighlights()
73
+
74
+ Removes all existing highlights.
75
+
76
+ ## License
77
+
78
+ MIT
@@ -0,0 +1,182 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * lk-text-select-highlight - A lightweight text selection highlight library
5
+ * @module lk-text-select-highlight
6
+ */
7
+
8
+ class TextHighlighter {
9
+ constructor(options = {}) {
10
+ this.options = {
11
+ className: options.className || "highlighted-text",
12
+ color: options.color || "#ffff00",
13
+ container: options.container || document.body, // DOM容器,默认为整个body
14
+ strictMode: options.strictMode || false, // 严格模式,默认为false
15
+ caseSensitive:
16
+ options.caseSensitive !== undefined
17
+ ? options.caseSensitive
18
+ : true,
19
+ ...options,
20
+ };
21
+
22
+ this.highlights = [];
23
+ }
24
+
25
+ /**
26
+ * Highlight selected text
27
+ */
28
+ highlightSelection() {
29
+ const selection = window.getSelection();
30
+ if (!selection.toString().trim()) {
31
+ return false;
32
+ }
33
+
34
+ const range = selection.getRangeAt(0);
35
+
36
+ // 检查选择的范围是否在指定的容器内
37
+ const container = this.options.container;
38
+ if (
39
+ !container.contains(range.startContainer) ||
40
+ !container.contains(range.endContainer)
41
+ ) {
42
+ return false; // 选择超出了指定容器范围
43
+ }
44
+
45
+ // 更全面地检查整个范围是否在容器内
46
+ const commonAncestor = range.commonAncestorContainer;
47
+ if (!container.contains(commonAncestor)) {
48
+ return false; // 整个范围不在容器内
49
+ }
50
+
51
+ // 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素
52
+ if (this.options.strictMode) {
53
+ if (this.hasTargetClassInSelection(range)) {
54
+ return false; // 选择范围内包含目标className的元素,不允许高亮
55
+ }
56
+ }
57
+
58
+ try {
59
+ const highlightedElement = this.wrapRange(range);
60
+
61
+ this.highlights.push({
62
+ element: highlightedElement,
63
+ text: selection.toString(),
64
+ });
65
+
66
+ return true;
67
+ } catch (error) {
68
+ console.warn("Could not highlight selection:", error);
69
+ return false;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Check if the selection range contains elements with the target class
75
+ * @param {Range} range - The range to check
76
+ */
77
+ hasTargetClassInSelection(range) {
78
+ // Check if startContainer or endContainer themselves have the target class
79
+ const startElement =
80
+ range.startContainer.nodeType === Node.ELEMENT_NODE
81
+ ? range.startContainer
82
+ : range.startContainer.parentElement;
83
+
84
+ const endElement =
85
+ range.endContainer.nodeType === Node.ELEMENT_NODE
86
+ ? range.endContainer
87
+ : range.endContainer.parentElement;
88
+
89
+ if (
90
+ startElement &&
91
+ startElement.classList &&
92
+ startElement.classList.contains(this.options.className)
93
+ ) {
94
+ return true;
95
+ }
96
+
97
+ if (
98
+ endElement &&
99
+ endElement.classList &&
100
+ endElement.classList.contains(this.options.className)
101
+ ) {
102
+ return true;
103
+ }
104
+
105
+ // Create a temporary div to work with the range content
106
+ const tempDiv = document.createElement("div");
107
+ tempDiv.appendChild(range.cloneContents());
108
+
109
+ // Check if any child elements have the target class
110
+ const elementsWithTargetClass = tempDiv.querySelectorAll(
111
+ `.${this.options.className}`,
112
+ );
113
+ return elementsWithTargetClass.length > 0;
114
+ }
115
+
116
+ /**
117
+ * Wrap a range with highlight element
118
+ * @param {Range} range - The range to wrap
119
+ */
120
+ wrapRange(range) {
121
+ const highlightEl = document.createElement("span");
122
+ highlightEl.className = this.options.className;
123
+ highlightEl.style.backgroundColor = this.options.color;
124
+ highlightEl.style.padding = "0";
125
+ highlightEl.style.margin = "0";
126
+
127
+ // Clone the range and insert the highlight element
128
+ range.surroundContents(highlightEl);
129
+
130
+ return highlightEl;
131
+ }
132
+
133
+ /**
134
+ * Remove all highlights
135
+ */
136
+ removeAllHighlights() {
137
+ this.highlights.forEach((highlight) => {
138
+ if (highlight.element.parentNode) {
139
+ const textNode = document.createTextNode(highlight.text);
140
+ highlight.element.parentNode.replaceChild(
141
+ textNode,
142
+ highlight.element,
143
+ );
144
+ }
145
+ });
146
+
147
+ this.highlights = [];
148
+ }
149
+
150
+ /**
151
+ * Get all highlighted elements
152
+ */
153
+ getHighlights() {
154
+ return [...this.highlights];
155
+ }
156
+
157
+ /**
158
+ * Remove a specific highlight
159
+ * @param {Object} highlight - The highlight object to remove
160
+ */
161
+ removeHighlight(highlight) {
162
+ const index = this.highlights.indexOf(highlight);
163
+ if (index !== -1) {
164
+ // Restore the original text
165
+ if (highlight.element.parentNode) {
166
+ const textNode = document.createTextNode(highlight.text);
167
+ highlight.element.parentNode.replaceChild(
168
+ textNode,
169
+ highlight.element,
170
+ );
171
+ }
172
+
173
+ // Remove from the highlights array
174
+ this.highlights.splice(index, 1);
175
+ return true;
176
+ }
177
+ return false;
178
+ }
179
+ }
180
+
181
+ module.exports = TextHighlighter;
182
+ //# sourceMappingURL=lk-text-select-highlight.cjs.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * lk-text-select-highlight - A lightweight text selection highlight library
3
+ * @module lk-text-select-highlight
4
+ */
5
+
6
+ class TextHighlighter {
7
+ constructor(options = {}) {
8
+ this.options = {
9
+ className: options.className || "highlighted-text",
10
+ color: options.color || "#ffff00",
11
+ container: options.container || document.body, // DOM容器,默认为整个body
12
+ strictMode: options.strictMode || false, // 严格模式,默认为false
13
+ caseSensitive:
14
+ options.caseSensitive !== undefined
15
+ ? options.caseSensitive
16
+ : true,
17
+ ...options,
18
+ };
19
+
20
+ this.highlights = [];
21
+ }
22
+
23
+ /**
24
+ * Highlight selected text
25
+ */
26
+ highlightSelection() {
27
+ const selection = window.getSelection();
28
+ if (!selection.toString().trim()) {
29
+ return false;
30
+ }
31
+
32
+ const range = selection.getRangeAt(0);
33
+
34
+ // 检查选择的范围是否在指定的容器内
35
+ const container = this.options.container;
36
+ if (
37
+ !container.contains(range.startContainer) ||
38
+ !container.contains(range.endContainer)
39
+ ) {
40
+ return false; // 选择超出了指定容器范围
41
+ }
42
+
43
+ // 更全面地检查整个范围是否在容器内
44
+ const commonAncestor = range.commonAncestorContainer;
45
+ if (!container.contains(commonAncestor)) {
46
+ return false; // 整个范围不在容器内
47
+ }
48
+
49
+ // 严格模式检查:如果启用严格模式,检查选择范围内是否包含目标className的元素
50
+ if (this.options.strictMode) {
51
+ if (this.hasTargetClassInSelection(range)) {
52
+ return false; // 选择范围内包含目标className的元素,不允许高亮
53
+ }
54
+ }
55
+
56
+ try {
57
+ const highlightedElement = this.wrapRange(range);
58
+
59
+ this.highlights.push({
60
+ element: highlightedElement,
61
+ text: selection.toString(),
62
+ });
63
+
64
+ return true;
65
+ } catch (error) {
66
+ console.warn("Could not highlight selection:", error);
67
+ return false;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Check if the selection range contains elements with the target class
73
+ * @param {Range} range - The range to check
74
+ */
75
+ hasTargetClassInSelection(range) {
76
+ // Check if startContainer or endContainer themselves have the target class
77
+ const startElement =
78
+ range.startContainer.nodeType === Node.ELEMENT_NODE
79
+ ? range.startContainer
80
+ : range.startContainer.parentElement;
81
+
82
+ const endElement =
83
+ range.endContainer.nodeType === Node.ELEMENT_NODE
84
+ ? range.endContainer
85
+ : range.endContainer.parentElement;
86
+
87
+ if (
88
+ startElement &&
89
+ startElement.classList &&
90
+ startElement.classList.contains(this.options.className)
91
+ ) {
92
+ return true;
93
+ }
94
+
95
+ if (
96
+ endElement &&
97
+ endElement.classList &&
98
+ endElement.classList.contains(this.options.className)
99
+ ) {
100
+ return true;
101
+ }
102
+
103
+ // Create a temporary div to work with the range content
104
+ const tempDiv = document.createElement("div");
105
+ tempDiv.appendChild(range.cloneContents());
106
+
107
+ // Check if any child elements have the target class
108
+ const elementsWithTargetClass = tempDiv.querySelectorAll(
109
+ `.${this.options.className}`,
110
+ );
111
+ return elementsWithTargetClass.length > 0;
112
+ }
113
+
114
+ /**
115
+ * Wrap a range with highlight element
116
+ * @param {Range} range - The range to wrap
117
+ */
118
+ wrapRange(range) {
119
+ const highlightEl = document.createElement("span");
120
+ highlightEl.className = this.options.className;
121
+ highlightEl.style.backgroundColor = this.options.color;
122
+ highlightEl.style.padding = "0";
123
+ highlightEl.style.margin = "0";
124
+
125
+ // Clone the range and insert the highlight element
126
+ range.surroundContents(highlightEl);
127
+
128
+ return highlightEl;
129
+ }
130
+
131
+ /**
132
+ * Remove all highlights
133
+ */
134
+ removeAllHighlights() {
135
+ this.highlights.forEach((highlight) => {
136
+ if (highlight.element.parentNode) {
137
+ const textNode = document.createTextNode(highlight.text);
138
+ highlight.element.parentNode.replaceChild(
139
+ textNode,
140
+ highlight.element,
141
+ );
142
+ }
143
+ });
144
+
145
+ this.highlights = [];
146
+ }
147
+
148
+ /**
149
+ * Get all highlighted elements
150
+ */
151
+ getHighlights() {
152
+ return [...this.highlights];
153
+ }
154
+
155
+ /**
156
+ * Remove a specific highlight
157
+ * @param {Object} highlight - The highlight object to remove
158
+ */
159
+ removeHighlight(highlight) {
160
+ const index = this.highlights.indexOf(highlight);
161
+ if (index !== -1) {
162
+ // Restore the original text
163
+ if (highlight.element.parentNode) {
164
+ const textNode = document.createTextNode(highlight.text);
165
+ highlight.element.parentNode.replaceChild(
166
+ textNode,
167
+ highlight.element,
168
+ );
169
+ }
170
+
171
+ // Remove from the highlights array
172
+ this.highlights.splice(index, 1);
173
+ return true;
174
+ }
175
+ return false;
176
+ }
177
+ }
178
+
179
+ export { TextHighlighter as default };
180
+ //# sourceMappingURL=lk-text-select-highlight.esm.js.map
@@ -0,0 +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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"}