-
Notifications
You must be signed in to change notification settings - Fork 55
/
index.js
94 lines (81 loc) · 2.75 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* eslint-disable vars-on-top, no-var, prefer-template */
var isRegExp = function (re) {
return re instanceof RegExp;
};
var escapeRegExp = function escapeRegExp(string) {
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);
return (string && reHasRegExpChar.test(string))
? string.replace(reRegExpChar, '\\$&')
: string;
};
var isString = function (value) {
return typeof value === 'string';
};
var flatten = function (array) {
var newArray = [];
array.forEach(function (item) {
if (Array.isArray(item)) {
newArray = newArray.concat(item);
} else {
newArray.push(item);
}
});
return newArray;
};
/**
* Given a string, replace every substring that is matched by the `match` regex
* with the result of calling `fn` on matched substring. The result will be an
* array with all odd indexed elements containing the replacements. The primary
* use case is similar to using String.prototype.replace except for React.
*
* React will happily render an array as children of a react element, which
* makes this approach very useful for tasks like surrounding certain text
* within a string with react elements.
*
* Example:
* matchReplace(
* 'Emphasize all phone numbers like 884-555-4443.',
* /([\d|-]+)/g,
* (number, i) => <strong key={i}>{number}</strong>
* );
* // => ['Emphasize all phone numbers like ', <strong>884-555-4443</strong>, '.'
*
* @param {string} str
* @param {RegExp|str} match Must contain a matching group
* @param {function} fn
* @return {array}
*/
function replaceString(str, match, fn) {
var curCharStart = 0;
var curCharLen = 0;
if (str === '') {
return str;
} else if (!str || !isString(str)) {
throw new TypeError('First argument to react-string-replace#replaceString must be a string');
}
var re = match;
if (!isRegExp(re)) {
re = new RegExp('(' + escapeRegExp(re) + ')', 'gi');
}
var result = str.split(re);
// Apply fn to all odd elements
for (var i = 1, length = result.length; i < length; i += 2) {
/** @see {@link https://github.com/iansinnott/react-string-replace/issues/74} */
if (result[i] === undefined || result[i - 1] === undefined) {
console.warn('reactStringReplace: Encountered undefined value during string replacement. Your RegExp may not be working the way you expect.');
continue;
}
curCharLen = result[i].length;
curCharStart += result[i - 1].length;
result[i] = fn(result[i], i, curCharStart);
curCharStart += curCharLen;
}
return result;
}
module.exports = function reactStringReplace(source, match, fn) {
if (!Array.isArray(source)) source = [source];
return flatten(source.map(function(x) {
return isString(x) ? replaceString(x, match, fn) : x;
}));
};