Skip to content

Commit

Permalink
^ doesn't match after string-terminating LF (fixes #9)
Browse files Browse the repository at this point in the history
  • Loading branch information
slevithan committed Dec 17, 2024
1 parent 1fc0d5f commit 37699d9
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ Notice that nearly every feature below has at least subtle differences from Java
<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>
Allows leading unescaped <code>]</code><br>
Leading unescaped <code>]</code> OK<br>
✔ Fewer chars require escaping than JS<br>
</td>
</tr>
Expand Down Expand Up @@ -616,6 +616,7 @@ Notice that nearly every feature below has at least subtle differences from Java
<td>
✔ Always "multiline"<br>
✔ Only <code>\n</code> as newline<br>
✔ No match after string-terminating <code>\n</code><br>
</td>
</tr>
<tr valign="top">
Expand Down
8 changes: 7 additions & 1 deletion spec/match-assertion.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {toDetails} from '../dist/index.mjs';
import {toDetails, toRegExp} from '../dist/index.mjs';
import {r} from '../src/utils.js';
import {matchers} from './helpers/matchers.js';

Expand Down Expand Up @@ -50,6 +50,12 @@ describe('Assertion', () => {
it('should not match at positions other than the start of the string or after a line feed', () => {
expect('ba').not.toFindMatch('^a');
});

it('should not match after a string-terminating line feed', () => {
expect(''.match(toRegExp('^', {global: true}))).toHaveSize(1);
expect('\n'.match(toRegExp('^', {global: true}))).toHaveSize(1);
expect('\n\n'.match(toRegExp('^', {global: true}))).toHaveSize(2);
});
});

describe('string_end', () => {
Expand Down
3 changes: 2 additions & 1 deletion src/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ function genAssertion(node, _, gen) {
if (kind === AstAssertionKinds.string_start) {
return '^';
}
// If a word boundary came through the transformer unaltered, that means `wordIsAscii` is enabled
// If a word boundary came through the transformer unaltered, that means `wordIsAscii` or
// `asciiWordBoundaries` is enabled
if (kind === AstAssertionKinds.word_boundary) {
return negate ? r`\B` : r`\b`;
}
Expand Down
5 changes: 3 additions & 2 deletions src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ const FirstPassVisitor = {
// Onig's only line break char is line feed, unlike JS
replaceWith(parseFragment(r`(?=\z|\n)`));
} else if (kind === AstAssertionKinds.line_start) {
// Onig's only line break char is line feed, unlike JS
replaceWith(parseFragment(r`(?<=\A|\n)`));
// Onig's only line break char is line feed, unlike JS. Onig's `^` doesn't match after a
// string-terminating line feed
replaceWith(parseFragment(r`(?<=\A|\n(?!\z))`));
} else if (kind === AstAssertionKinds.search_start) {
if (!supportedGNodes.has(node) && !allowUnhandledGAnchors) {
throw new Error(r`Uses "\G" in a way that's unsupported`);
Expand Down

0 comments on commit 37699d9

Please sign in to comment.