Skip to content

Commit

Permalink
XRegExp.escape: Escape whitespace in a way that works with ES6 flag u (
Browse files Browse the repository at this point in the history
…fixes #197)
  • Loading branch information
slevithan committed Feb 6, 2021
1 parent a514be2 commit e22a52b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
8 changes: 7 additions & 1 deletion src/xregexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,13 @@ XRegExp.cache.flush = (cacheName) => {
* XRegExp.escape('Escaped? <.>');
* // -> 'Escaped\?\ <\.>'
*/
XRegExp.escape = (str) => String(nullThrows(str)).replace(/[-\[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
XRegExp.escape = (str) => String(nullThrows(str)).replace(/[-\[\]{}()*+?.,\\^$|#\s]/g, (match) => {
if (/\s/.test(match)) {
// Converting to \uNNNN since whitespace can't be escaped when used with ES6 flag `u`
return `\\u${pad4(hex(match.charCodeAt(0)))}`;
}
return `\\${match}`;
});

/**
* Executes a regex search in a specified string. Returns a match array or `null`. If the provided
Expand Down
22 changes: 18 additions & 4 deletions tests/spec/s-xregexp-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,20 +219,34 @@ describe('XRegExp.cache()', function() {

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

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

it('should escape context-aware metacharacters', function() {
expect(XRegExp.escape(']{}-, \n#')).toBe('\\]\\{\\}\\-\\,\\ \\\n\\#');
it('should escape context-sensitive metacharacters, excluding whitespace', function() {
expect(XRegExp.escape(']{}-,#')).toBe('\\]\\{\\}\\-\\,\\#');
});

it('should escape context-sensitive whitespace', function() {
// Don't want to explicitly check the escape pattern like this since there are multiple
// valid representations of escaped whitespace
//expect(XRegExp.escape('\t\n\f\r\x20\u2028\u2029')).toBe('\\u0009\\u000a\\u000c\\u000d\\u0020\\u2028\\u2029');

var whitespace = '\t\n\f\r\x20\u2028\u2029';
expect(new RegExp('^' + XRegExp.escape(whitespace) + '$').test(whitespace)).toBe(true);
expect(XRegExp.escape(whitespace)).not.toBe(whitespace);
});

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

it('should escape a nonstring pattern after type converting to a string', function() {
expect(XRegExp.escape({})).toBe('\\[object\\ Object\\]');
// Don't want to explicitly check the escape pattern like this since there are multiple
// valid representations of escaped whitespace
//expect(XRegExp.escape({})).toBe('\\[object\\ Object\\]');

expect(new RegExp('^' + XRegExp.escape({}) + '$').test('[object Object]')).toBe(true);
});

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

0 comments on commit e22a52b

Please sign in to comment.