Skip to content

Commit f2fe87d

Browse files
committed
Address PR #113 round 5: remove invalid 'e' flag, clarify parser comments
src/regex.ts — extractRegexToken(): - Remove 'e' from the allowed flag set: [gimsuydev]* -> [gimsuydv]* 'e' is not a valid JavaScript RegExp flag; its presence would cause /pattern/e to be tokenised as a regex and then fail compilation, instead of being passed through unchanged as a plain query token. src/regex.ts — splitTopLevelAlternation(): - Clarify truncated inline comments: depth: 'tracks unescaped ( nesting' → 'tracks unescaped \"(\" nesting depth outside character classes' inClass: 'tracks [...]' → 'tracks whether we are currently inside a character class [...]' src/regex.test.ts: - isRegexQuery('/pattern/e') → false (regression test) - buildApiQuery('/pattern/e') → passthrough, regexFilter null
1 parent 70e4f33 commit f2fe87d

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

src/regex.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ describe("isRegexQuery", () => {
3333
// a suffix of non-flag characters must not be silently swallowed.
3434
expect(isRegexQuery("/useState/iSomething")).toBe(false);
3535
});
36+
37+
it("returns false for /pattern/e ('e' is not a valid JS RegExp flag)", () => {
38+
expect(isRegexQuery("/pattern/e")).toBe(false);
39+
});
3640
});
3741

3842
// ─── buildApiQuery ────────────────────────────────────────────────────────────
@@ -51,6 +55,12 @@ describe("buildApiQuery — plain text passthrough", () => {
5155
expect(r.apiQuery).toBe("/useState/iSomething");
5256
expect(r.regexFilter).toBeNull();
5357
});
58+
59+
it("/pattern/e is NOT treated as a regex token ('e' is not a valid JS RegExp flag)", () => {
60+
const r = buildApiQuery("/pattern/e");
61+
expect(r.apiQuery).toBe("/pattern/e");
62+
expect(r.regexFilter).toBeNull();
63+
});
5464
});
5565

5666
describe("buildApiQuery — longest literal extraction", () => {

src/regex.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ function extractRegexToken(q: string): RegexToken | null {
9090
// - the token ends at end-of-string or a whitespace boundary, so we don't
9191
// accidentally match a prefix of a longer non-delimited word
9292
// (e.g. /foo/iSomething must NOT be recognised as a regex token).
93-
// The trailing flags cover all current JS RegExp flag letters:
93+
// The trailing flags cover all valid JS RegExp flag letters:
9494
// g (global), i (ignoreCase), m (multiline), s (dotAll),
9595
// u (unicode), y (sticky), d (hasIndices ES2022), v (unicodeSets ES2023).
96-
const m = q.match(/(?:^|\s)(\/(?:[^/\\\r\n]|\\.)+\/[gimsuydev]*)(?=$|\s)/);
96+
// Note: 'e' is intentionally excluded — it is not a valid JS RegExp flag.
97+
const m = q.match(/(?:^|\s)(\/(?:[^/\\\r\n]|\\.)+\/[gimsuydv]*)(?=$|\s)/);
9798
if (!m || !m[1]) return null;
9899
const raw = m[1].trim();
99100
const lastSlash = raw.lastIndexOf("/");
@@ -144,8 +145,8 @@ function extractApiTerm(pattern: string): { term: string; warn?: string } {
144145
*/
145146
function splitTopLevelAlternation(pattern: string): string[] {
146147
const branches: string[] = [];
147-
let depth = 0; // tracks unescaped ( nesting
148-
let inClass = false; // tracks [...]
148+
let depth = 0; // tracks unescaped '(' nesting depth outside character classes
149+
let inClass = false; // tracks whether we are currently inside a character class [...]
149150
let current = "";
150151
let escaped = false; // true when current char is escaped by a preceding backslash
151152

0 commit comments

Comments
 (0)