Skip to content

Commit e22a52b

Browse files
committed
XRegExp.escape: Escape whitespace in a way that works with ES6 flag u (fixes #197)
1 parent a514be2 commit e22a52b

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

src/xregexp.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,13 @@ XRegExp.cache.flush = (cacheName) => {
788788
* XRegExp.escape('Escaped? <.>');
789789
* // -> 'Escaped\?\ <\.>'
790790
*/
791-
XRegExp.escape = (str) => String(nullThrows(str)).replace(/[-\[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
791+
XRegExp.escape = (str) => String(nullThrows(str)).replace(/[-\[\]{}()*+?.,\\^$|#\s]/g, (match) => {
792+
if (/\s/.test(match)) {
793+
// Converting to \uNNNN since whitespace can't be escaped when used with ES6 flag `u`
794+
return `\\u${pad4(hex(match.charCodeAt(0)))}`;
795+
}
796+
return `\\${match}`;
797+
});
792798

793799
/**
794800
* Executes a regex search in a specified string. Returns a match array or `null`. If the provided

tests/spec/s-xregexp-methods.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,20 +219,34 @@ describe('XRegExp.cache()', function() {
219219

220220
describe('XRegExp.escape()', function() {
221221

222-
it('should escape metacharacters', function() {
222+
it('should escape standard metacharacters', function() {
223223
expect(XRegExp.escape('[()*+?.\\^$|')).toBe('\\[\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|');
224224
});
225225

226-
it('should escape context-aware metacharacters', function() {
227-
expect(XRegExp.escape(']{}-, \n#')).toBe('\\]\\{\\}\\-\\,\\ \\\n\\#');
226+
it('should escape context-sensitive metacharacters, excluding whitespace', function() {
227+
expect(XRegExp.escape(']{}-,#')).toBe('\\]\\{\\}\\-\\,\\#');
228+
});
229+
230+
it('should escape context-sensitive whitespace', function() {
231+
// Don't want to explicitly check the escape pattern like this since there are multiple
232+
// valid representations of escaped whitespace
233+
//expect(XRegExp.escape('\t\n\f\r\x20\u2028\u2029')).toBe('\\u0009\\u000a\\u000c\\u000d\\u0020\\u2028\\u2029');
234+
235+
var whitespace = '\t\n\f\r\x20\u2028\u2029';
236+
expect(new RegExp('^' + XRegExp.escape(whitespace) + '$').test(whitespace)).toBe(true);
237+
expect(XRegExp.escape(whitespace)).not.toBe(whitespace);
228238
});
229239

230240
it('should not escape nonmetacharacters', function() {
231241
expect(XRegExp.escape('abc_<123>!\0\uFFFF')).toBe('abc_<123>!\0\uFFFF');
232242
});
233243

234244
it('should escape a nonstring pattern after type converting to a string', function() {
235-
expect(XRegExp.escape({})).toBe('\\[object\\ Object\\]');
245+
// Don't want to explicitly check the escape pattern like this since there are multiple
246+
// valid representations of escaped whitespace
247+
//expect(XRegExp.escape({})).toBe('\\[object\\ Object\\]');
248+
249+
expect(new RegExp('^' + XRegExp.escape({}) + '$').test('[object Object]')).toBe(true);
236250
});
237251

238252
it('should throw an exception when given a null or undefined pattern', function() {

0 commit comments

Comments
 (0)