react-highlight-me 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/README.md +228 -0
- package/highlight.tsx +94 -0
- package/package.json +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# TextHighlighter
|
|
2
|
+
|
|
3
|
+
A flexible React component for highlighting specific words or phrases within text content or React components.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Flexible Input**: Works with both plain text and React components
|
|
8
|
+
- 🔍 **Multiple Words**: Highlight single words or arrays of words
|
|
9
|
+
- 🎨 **Custom Styling**: Fully customizable highlight styles
|
|
10
|
+
- 📝 **Case Sensitivity**: Optional case-sensitive or case-insensitive matching
|
|
11
|
+
- 🔧 **TypeScript Support**: Written in TypeScript with proper type definitions
|
|
12
|
+
- 🚀 **Zero Dependencies**: Uses only React built-in functionality
|
|
13
|
+
- 🌳 **Deep Processing**: Recursively processes nested React components
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Copy the `TextHighlighter.tsx` component into your project, or install it as a package if published.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Basic Text Highlighting
|
|
22
|
+
|
|
23
|
+
```jsx
|
|
24
|
+
import TextHighlighter from './TextHighlighter';
|
|
25
|
+
|
|
26
|
+
function App() {
|
|
27
|
+
return (
|
|
28
|
+
<TextHighlighter words="React">
|
|
29
|
+
Hello React world!
|
|
30
|
+
</TextHighlighter>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Multiple Words
|
|
36
|
+
|
|
37
|
+
```jsx
|
|
38
|
+
<TextHighlighter
|
|
39
|
+
words={['React', 'TypeScript', 'JavaScript']}
|
|
40
|
+
highlightStyle={{ backgroundColor: '#fef3c7', padding: '2px 4px' }}
|
|
41
|
+
>
|
|
42
|
+
Learning React and TypeScript for JavaScript development
|
|
43
|
+
</TextHighlighter>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Component Highlighting
|
|
47
|
+
|
|
48
|
+
```jsx
|
|
49
|
+
<TextHighlighter
|
|
50
|
+
words={['important', 'notice']}
|
|
51
|
+
highlightStyle={{ backgroundColor: '#fca5a5', fontWeight: 'bold' }}
|
|
52
|
+
>
|
|
53
|
+
<div>
|
|
54
|
+
<h2>Important Notice</h2>
|
|
55
|
+
<p>This is an important message about our service.</p>
|
|
56
|
+
<ul>
|
|
57
|
+
<li>First important point</li>
|
|
58
|
+
<li>Another notice for users</li>
|
|
59
|
+
</ul>
|
|
60
|
+
</div>
|
|
61
|
+
</TextHighlighter>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Custom Styling
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
// Yellow background with rounded corners
|
|
68
|
+
<TextHighlighter
|
|
69
|
+
words="highlight"
|
|
70
|
+
highlightStyle={{
|
|
71
|
+
backgroundColor: 'yellow',
|
|
72
|
+
padding: '2px 6px',
|
|
73
|
+
borderRadius: '4px',
|
|
74
|
+
fontWeight: 'bold'
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
Text to highlight here
|
|
78
|
+
</TextHighlighter>
|
|
79
|
+
|
|
80
|
+
// Blue background with white text
|
|
81
|
+
<TextHighlighter
|
|
82
|
+
words="special"
|
|
83
|
+
highlightStyle={{
|
|
84
|
+
backgroundColor: '#3b82f6',
|
|
85
|
+
color: 'white',
|
|
86
|
+
padding: '3px 8px',
|
|
87
|
+
borderRadius: '6px'
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
This is special content
|
|
91
|
+
</TextHighlighter>
|
|
92
|
+
|
|
93
|
+
// Border style instead of background
|
|
94
|
+
<TextHighlighter
|
|
95
|
+
words="outlined"
|
|
96
|
+
highlightStyle={{
|
|
97
|
+
backgroundColor: 'transparent',
|
|
98
|
+
border: '2px solid #10b981',
|
|
99
|
+
padding: '1px 4px',
|
|
100
|
+
borderRadius: '4px',
|
|
101
|
+
color: '#059669',
|
|
102
|
+
fontWeight: 'bold'
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
Text with outlined highlights
|
|
106
|
+
</TextHighlighter>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Case Sensitivity
|
|
110
|
+
|
|
111
|
+
```jsx
|
|
112
|
+
// Case-insensitive (default)
|
|
113
|
+
<TextHighlighter words="react">
|
|
114
|
+
REACT and React and react will all be highlighted
|
|
115
|
+
</TextHighlighter>
|
|
116
|
+
|
|
117
|
+
// Case-sensitive
|
|
118
|
+
<TextHighlighter words="React" caseSensitive={true}>
|
|
119
|
+
Only React will be highlighted, not REACT or react
|
|
120
|
+
</TextHighlighter>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Props
|
|
124
|
+
|
|
125
|
+
| Prop | Type | Default | Description |
|
|
126
|
+
|------|------|---------|-------------|
|
|
127
|
+
| `children` | `React.ReactElement \| null` | `''` | The content to process for highlighting |
|
|
128
|
+
| `words` | `string[] \| string` | `[]` | Word or array of words to highlight |
|
|
129
|
+
| `highlightStyle` | `React.CSSProperties` | `{ backgroundColor: 'yellow', fontWeight: 'bold' }` | CSS styles to apply to highlighted text |
|
|
130
|
+
| `caseSensitive` | `boolean` | `false` | Whether to perform case-sensitive matching |
|
|
131
|
+
|
|
132
|
+
## Examples
|
|
133
|
+
|
|
134
|
+
### Search Results Highlighting
|
|
135
|
+
|
|
136
|
+
```jsx
|
|
137
|
+
function SearchResults({ results, searchTerm }) {
|
|
138
|
+
return (
|
|
139
|
+
<div>
|
|
140
|
+
{results.map((result, index) => (
|
|
141
|
+
<div key={index} className="search-result">
|
|
142
|
+
<TextHighlighter
|
|
143
|
+
words={searchTerm}
|
|
144
|
+
highlightStyle={{ backgroundColor: '#fbbf24' }}
|
|
145
|
+
>
|
|
146
|
+
<div>
|
|
147
|
+
<h3>{result.title}</h3>
|
|
148
|
+
<p>{result.description}</p>
|
|
149
|
+
</div>
|
|
150
|
+
</TextHighlighter>
|
|
151
|
+
</div>
|
|
152
|
+
))}
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Documentation Highlighting
|
|
159
|
+
|
|
160
|
+
```jsx
|
|
161
|
+
function Documentation({ content, keywords }) {
|
|
162
|
+
return (
|
|
163
|
+
<TextHighlighter
|
|
164
|
+
words={keywords}
|
|
165
|
+
highlightStyle={{
|
|
166
|
+
backgroundColor: '#ddd6fe',
|
|
167
|
+
padding: '2px 4px',
|
|
168
|
+
borderRadius: '3px',
|
|
169
|
+
fontWeight: 'bold'
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<article>
|
|
173
|
+
<h1>API Documentation</h1>
|
|
174
|
+
<p>{content}</p>
|
|
175
|
+
</article>
|
|
176
|
+
</TextHighlighter>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Multi-language Support
|
|
182
|
+
|
|
183
|
+
```jsx
|
|
184
|
+
function MultiLanguageHighlight() {
|
|
185
|
+
return (
|
|
186
|
+
<TextHighlighter
|
|
187
|
+
words={['JavaScript', 'React', 'TypeScript']}
|
|
188
|
+
highlightStyle={{ backgroundColor: '#c7d2fe' }}
|
|
189
|
+
>
|
|
190
|
+
<div>
|
|
191
|
+
<p>JavaScript is a programming language</p>
|
|
192
|
+
<p>React est une bibliothèque JavaScript</p>
|
|
193
|
+
<p>TypeScript adds static typing to JavaScript</p>
|
|
194
|
+
</div>
|
|
195
|
+
</TextHighlighter>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Technical Details
|
|
201
|
+
|
|
202
|
+
### How It Works
|
|
203
|
+
|
|
204
|
+
1. **Text Processing**: The component recursively traverses React elements and their children
|
|
205
|
+
2. **Pattern Matching**: Uses regular expressions to find and match specified words
|
|
206
|
+
3. **Safe Rendering**: Escapes regex special characters to prevent injection issues
|
|
207
|
+
4. **Element Cloning**: Preserves original component structure while adding highlights
|
|
208
|
+
|
|
209
|
+
### Performance Considerations
|
|
210
|
+
|
|
211
|
+
- The component processes content recursively, so very deep component trees may impact performance
|
|
212
|
+
- Regex compilation happens on each render - consider memoization for frequently changing props
|
|
213
|
+
- Large amounts of text with many highlight words may benefit from virtualization
|
|
214
|
+
|
|
215
|
+
### Browser Support
|
|
216
|
+
|
|
217
|
+
Works in all modern browsers that support:
|
|
218
|
+
- React 16.8+
|
|
219
|
+
- ES6 Regular Expressions
|
|
220
|
+
- Array methods (map, filter, some)
|
|
221
|
+
|
|
222
|
+
## Contributing
|
|
223
|
+
|
|
224
|
+
Feel free to submit issues, feature requests, or pull requests to improve the component.
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT License - feel free to use in your projects!
|
package/highlight.tsx
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type Props = {
|
|
4
|
+
children?: React.ReactElement | null;
|
|
5
|
+
words?: string[] | string;
|
|
6
|
+
highlightStyle?: React.CSSProperties;
|
|
7
|
+
caseSensitive?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const TextHighlighter = ({
|
|
11
|
+
children = '',
|
|
12
|
+
words = [],
|
|
13
|
+
highlightStyle = { backgroundColor: 'yellow', fontWeight: 'bold' },
|
|
14
|
+
caseSensitive = false,
|
|
15
|
+
}) => {
|
|
16
|
+
// Convert words to array if it's a string
|
|
17
|
+
const wordsArray = Array.isArray(words) ? words : [words];
|
|
18
|
+
|
|
19
|
+
// If no words to highlight, return original content
|
|
20
|
+
if (!wordsArray.length || wordsArray.every(word => !word)) {
|
|
21
|
+
return children;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Function to escape regex special characters
|
|
25
|
+
const escapeRegex = (string) => {
|
|
26
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Create a regex pattern for all words
|
|
30
|
+
const pattern = wordsArray
|
|
31
|
+
.filter(word => word && word.trim())
|
|
32
|
+
.map(word => escapeRegex(word.trim()))
|
|
33
|
+
.join('|');
|
|
34
|
+
|
|
35
|
+
if (!pattern) {
|
|
36
|
+
return children;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const regex = new RegExp(`(${pattern})`, caseSensitive ? 'g' : 'gi');
|
|
40
|
+
|
|
41
|
+
// Function to highlight text content
|
|
42
|
+
const highlightText = (textContent) => {
|
|
43
|
+
if (!textContent || typeof textContent !== 'string') {
|
|
44
|
+
return textContent;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const parts = textContent.split(regex);
|
|
48
|
+
|
|
49
|
+
return parts.map((part, index) => {
|
|
50
|
+
const shouldHighlight = wordsArray.some(word =>
|
|
51
|
+
caseSensitive
|
|
52
|
+
? part === word.trim()
|
|
53
|
+
: part.toLowerCase() === word.trim().toLowerCase()
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return shouldHighlight ? (
|
|
57
|
+
<mark key={index} style={highlightStyle}>
|
|
58
|
+
{part}
|
|
59
|
+
</mark>
|
|
60
|
+
) : (
|
|
61
|
+
part
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Function to recursively process React elements
|
|
67
|
+
const processElement = (element) => {
|
|
68
|
+
if (typeof element === 'string') {
|
|
69
|
+
return highlightText(element);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (typeof element === 'number') {
|
|
73
|
+
return element;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!React.isValidElement(element)) {
|
|
77
|
+
return element;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Clone element and process its children
|
|
81
|
+
const processedChildren = React.Children.map(element.props.children, (child) => {
|
|
82
|
+
if (typeof child === 'string') {
|
|
83
|
+
return highlightText(child);
|
|
84
|
+
}
|
|
85
|
+
return processElement(child);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return React.cloneElement(element, {}, processedChildren);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return processElement(children);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default TextHighlighter;
|
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-highlight-me",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Highligh words in React components or text",
|
|
5
|
+
"main": "highlight.tsx",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "Andrey Hohutkin <Andrey.Hohutkin@gmail.com",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"packageManager": "pnpm@10.9.0"
|
|
13
|
+
}
|