Skip to content

Commit 845ead4

Browse files
authored
Feat: Add count parameter to match only the first 'n' items (#91)
Add count parameter to limit number of replacements Adds an optional 4th parameter 'count' to limit replacements to the first N matches. Resolves #45
1 parent 9cf8513 commit 845ead4

File tree

5 files changed

+3629
-3679
lines changed

5 files changed

+3629
-3679
lines changed

index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ declare module "react-string-replace" {
22
function reactStringReplace(
33
text?: string | React.ReactNode[],
44
regex?: string | RegExp,
5-
cb?: (match: string, index: number, offset: number) => React.ReactNode
5+
cb?: (match: string, index: number, offset: number) => React.ReactNode,
6+
count?: number
67
): React.ReactNode[];
78

89
export default reactStringReplace;

index.js

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var flatten = function (array) {
5050
* @param {function} fn
5151
* @return {array}
5252
*/
53-
function replaceString(str, match, fn) {
53+
function replaceString(str, match, fn, count = null) {
5454
var curCharStart = 0;
5555
var curCharLen = 0;
5656

@@ -70,6 +70,11 @@ function replaceString(str, match, fn) {
7070

7171
// Apply fn to all odd elements
7272
for (var i = 1, length = result.length; i < length; i += 2) {
73+
74+
if (Number.isInteger(count) && (count * 2 < i || count < 1)) {
75+
break;
76+
}
77+
7378
/** @see {@link https://github.com/iansinnott/react-string-replace/issues/74} */
7479
if (result[i] === undefined || result[i - 1] === undefined) {
7580
console.warn('reactStringReplace: Encountered undefined value during string replacement. Your RegExp may not be working the way you expect.');
@@ -85,10 +90,25 @@ function replaceString(str, match, fn) {
8590
return result;
8691
}
8792

88-
module.exports = function reactStringReplace(source, match, fn) {
93+
module.exports = function reactStringReplace(source, match, fn, count = null) {
8994
if (!Array.isArray(source)) source = [source];
9095

91-
return flatten(source.map(function(x) {
92-
return isString(x) ? replaceString(x, match, fn) : x;
93-
}));
94-
};
96+
return flatten(
97+
source.map(function (x) {
98+
let ret;
99+
if (isString(x)) {
100+
if (Number.isInteger(count) && count > 0) {
101+
ret = replaceString(x, match, fn, count);
102+
count -= (
103+
x.match(new RegExp("(" + escapeRegExp(match) + ")", "gi")) || []
104+
).length
105+
} else {
106+
ret = replaceString(x, match, fn, count);
107+
}
108+
} else {
109+
ret = x;
110+
}
111+
return ret;
112+
}),
113+
);
114+
}

readme.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ I wanted an easy way to do string replacement similar to `String.prototype.repla
128128

129129
## API
130130

131-
### reactStringReplace(string, match, replacementFunction)
131+
### reactStringReplace(string, match, replacementFunction, count)
132132

133133
#### string
134134

@@ -163,6 +163,18 @@ const replacementFunction = (match, index, offset) => <span key={index}>{match}<
163163
reactStringReplace('hey hey you', /(hey)/g, replacementFunction);
164164
```
165165

166+
#### count
167+
168+
Type: `number`
169+
170+
The number of substitutions to perform - for example if `count` is 1, then only the first occurrence of the string will be replaced.
171+
172+
Example: Replace first occurrence of `'hey'` with `<span>hey</span>`
173+
174+
```js
175+
reactStringReplace('hey hey you', 'hey', () => <span>hey</span>, 1)
176+
```
177+
166178
## API Stability
167179

168180
With v1.0.0 the API is considered stable and should be considered production ready. Pull requests are still welcome but there is currently no intent to make changes to this lib other than bug fixes (please submit an issue if you find something!).

test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable import/no-extraneous-dependencies */
22
import test from 'ava';
33
import replaceString from './';
4+
import reactStringReplace from '.';
45

56
test("Doesn't throw if not given invalid input", t => {
67
t.notThrows(() => replaceString());
@@ -170,3 +171,17 @@ test("Avoids undefined values due to regex", (t) => {
170171
replaceString(string, /(hey)|(you)/, x => x);
171172
});
172173
});
174+
175+
test("Fixed number of string replacements", (t) => {
176+
const string = `Test hey test hey test`;
177+
const replacedContent = reactStringReplace(string, 'hey', match => {
178+
return 'lo';
179+
},1);
180+
t.deepEqual(replacedContent, [
181+
'Test ',
182+
'lo',
183+
' test ',
184+
'hey',
185+
' test'
186+
])
187+
})

0 commit comments

Comments
 (0)