Skip to content

Commit 4222e24

Browse files
committed
Escape backslashes at the end of a character class option string
1 parent 80f07d9 commit 4222e24

File tree

5 files changed

+19
-6
lines changed

5 files changed

+19
-6
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,8 @@ at the beginning and end of each string in the list, so `` charIn`a-` `z` `` mat
362362
Apart from `-`, `^` and `]` are also escaped in the character class, so you cannot negate a `charIn` via a `^` character
363363
(you should use `notCharIn`), and you cannot close a character class prematurely.
364364

365-
All other characters are not escaped in `charIn`, so you can use escape sequences such as `\uffff` and `\xff` freely.
365+
Backslashes `\` are only escaped at the end of a string, so you can use escape sequences such as `\uffff` and `\xff` freely.
366+
If you want to include `\` in the character class, you should write it at the end of a string or escape with `\\`.
366367

367368
### Anchors
368369

src/expression.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1211,8 +1211,9 @@ export const unicode = r.unicode;
12111211
* Apart from `-`, `^` and `]` are also escaped in the character class, so you cannot negate a `charIn` via a `^`
12121212
* character (you should use `notCharIn`), and you cannot close a character class prematurely.
12131213
*
1214-
* All other characters are not escaped in `charIn`, so you can use escape sequences such as `\uffff` and `\xff`
1215-
* freely.
1214+
* Backslashes `\` are only escaped at the end of a string, so you can use escape sequences such as `\uffff` and
1215+
* `\xff` freely. If you want to include `\` in the character class, you should write it at the end of a string or
1216+
* escape with `\\`.
12161217
*
12171218
* @example
12181219
*

src/modifiers/CharacterClassModifier.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ function escapeForCharClass(option: string): string {
1313
if (charEscaped) {
1414
charEscaped = false;
1515
} else if (char === '\\') {
16-
charEscaped = true;
16+
if (i === option.length - 1) {
17+
// escape backslash at the end of the string
18+
option = option + '\\';
19+
break;
20+
} else {
21+
charEscaped = true;
22+
}
1723
} else if (char === ']' || char === '^') {
1824
// escape this character
1925
option = option.substring(0, i) + '\\' + option.substring(i);

src/types.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,9 @@ export interface RegExpToken {
666666
* Apart from `-`, `^` and `]` are also escaped in the character class, so you cannot negate a `charIn` via a `^`
667667
* character (you should use `notCharIn`), and you cannot close a character class prematurely.
668668
*
669-
* All other characters are not escaped in `charIn`, so you can use escape sequences such as `\uffff` and `\xff`
670-
* freely.
669+
* Backslashes `\` are only escaped at the end of a string, so you can use escape sequences such as `\uffff` and
670+
* `\xff` freely. If you want to include `\` in the character class, you should write it at the end of a string or
671+
* escape with `\\`.
671672
*
672673
* @example
673674
*

test/functions.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,10 @@ describe('charIn', () => {
930930
expect(charIn`[]`.toString()).toBe('[[\\]]');
931931
expect(charIn`^a[b]`.toString()).toBe('[\\^a[b\\]]');
932932
expect(charIn`(])`.toString()).toBe('[(\\])]');
933+
expect(charIn`\\`.toString()).toBe('[\\\\]');
934+
expect(charIn`\\\\`.toString()).toBe('[\\\\]');
935+
expect(charIn`a-z\\``s`.toString()).toBe('[a-z\\\\s]');
936+
expect(charIn`a-z``\\s`.toString()).toBe('[a-z\\s]');
933937
});
934938
it('is chainable and quantifiable', () => {
935939
expect(charIn`a``b``c`.char.toString()).toBe('[abc].');

0 commit comments

Comments
 (0)