Skip to content

Commit

Permalink
Escape literal [ in class with target ES2018 (closes #5)
Browse files Browse the repository at this point in the history
  • Loading branch information
slevithan committed Nov 23, 2024
1 parent 621e4d3 commit 4c5b27a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 20 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ Notice that nearly every feature below has at least subtle differences from Java
<td align="middle">✅</td>
<td>
✔ Unescaped <code>-</code> outside of range is literal in some contexts (different than JS rules in any mode)<br>
✔ Error for unescaped <code>[</code> that doesn't form nested class<br>
✔ Fewer chars require escaping than JS<br>
</td>
</tr>
Expand Down
82 changes: 62 additions & 20 deletions spec/match-group.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,65 @@ beforeEach(() => {
jasmine.addMatchers(matchers);
});

// TODO: Add me
// describe('Group', () => {
// describe('atomic', () => {
// it('should', () => {
// expect('').toExactlyMatch(r``);
// });
// });

// describe('flags', () => {
// it('should', () => {
// expect('').toExactlyMatch(r``);
// });
// });

// describe('noncapturing', () => {
// it('should', () => {
// expect('').toExactlyMatch(r``);
// });
// });
// });
describe('Group', () => {
describe('atomic', () => {
it('should not remember backtracking positions within atomic groups', () => {
expect('abc').not.toFindMatch(`a(?>bc|b)c`);
expect('abcc').toExactlyMatch(`a(?>bc|b)c`);
expect('aaaaaab').not.toFindMatch(`(?>a+)ab`);
expect('aaaaaab').toExactlyMatch(`(?>a)+ab`);
});

it('should allow quantifying atomic groups', () => {
expect('one two').toExactlyMatch(r`(?>\w+\s?)+`);
});

it('should work for multiple atomic groups', () => {
expect('ab').toExactlyMatch(`(?>a)(?>b)`);
});

it('should work for nested atomic groups', () => {
expect('integerrr+').toExactlyMatch(r`\b(?>int(?>eger+)?|insert)\b(?>.)`);
expect('integerrr+').not.toFindMatch(r`\b(?>int(?>eger+)??|insert)\b(?>.)`);
});

it('should work when named capturing groups present', () => {
expect('abcc').toExactlyMatch(`(?<n>)a(?>bc|b)c`);
expect('abc').not.toFindMatch(`(?<n>)a(?>bc|b)c`);
expect('abcc').toExactlyMatch(`a(?>(?<n>)bc|b)c`);
expect('abc').not.toFindMatch(`a(?>(?<n>)bc|b)c`);
});

it('should work when unnamed capturing groups present', () => {
expect('abcc').toExactlyMatch(`()a(?>bc|b)c`);
expect('abc').not.toFindMatch(`()a(?>bc|b)c`);
expect('abcc').toExactlyMatch(`a(?>()bc|b)c`);
expect('abc').not.toFindMatch(`a(?>()bc|b)c`);
});

it('should work with numbered backreferences', () => {
expect('aax').toExactlyMatch(r`(a)\1(?>x)`);
expect('xaa').toExactlyMatch(r`(?>x(a)\1)`);
expect('xaa').toExactlyMatch(r`(?>x)(a)\1`);
expect('aaabababcabc').toExactlyMatch(r`(a)\1(?>\1(b)\1\2(?>\1\2))(c)\1\2\3`);
});

it('should handle regression cases', () => {
expect('[').toExactlyMatch(r`(?>[\[])`);
});
});

// TODO: Add me
// describe('flags', () => {
// it('should', () => {
// expect('').toExactlyMatch(r``);
// });
// });

// TODO: Add me
// describe('noncapturing', () => {
// it('should', () => {
// expect('').toExactlyMatch(r``);
// });
// });
});
3 changes: 3 additions & 0 deletions src/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ const BaseEscapeChars = new Set([
]);
const CharClassEscapeChars = new Set([
'-', '\\', ']', '^',
// Literal `[` doesn't require escaping with flag u, but this can help work around regex source
// linters and regex syntax processors that expect unescaped `[` to create a nested class
'[',
]);
const CharClassEscapeCharsFlagV = new Set([
'(', ')', '-', '/', '[', '\\', ']', '^', '{', '|', '}',
Expand Down

0 comments on commit 4c5b27a

Please sign in to comment.