Skip to content

Commit

Permalink
Merge pull request #19 from jg-rp/i-regexp
Browse files Browse the repository at this point in the history
Map JS RegExp to I-Regexp
  • Loading branch information
jg-rp authored May 9, 2024
2 parents 8ea4cde + e32b90e commit 52c4514
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 7 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# JSON P3 Change Log

## Version 1.3.1 (unreleased)

**Fixes**

- Fixed RegExp to I-Regex pattern mapping with the `match` and `search` filter functions. We now correctly match the special `.` character to everything other than `\r` and `\n`.

## Version 1.3.0

**Fixes**
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "json-p3",
"version": "1.3.0",
"version": "1.3.1",
"author": "James Prior",
"license": "MIT",
"description": "JSONPath, JSON Pointer and JSON Patch",
Expand Down
53 changes: 50 additions & 3 deletions src/path/functions/match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,56 @@ export class Match implements FilterFunction {

protected fullMatch(pattern: string): string {
const parts: string[] = [];
if (!pattern.startsWith("^")) parts.push("^");
parts.push(pattern);
if (!pattern.endsWith("$")) parts.push("$");
let nonCaptureGroup = false;

if (!pattern.startsWith("^") && !pattern.startsWith("^(")) {
nonCaptureGroup = true;
parts.push("^(?:");
}
parts.push(this.mapRegexp(pattern));

if (nonCaptureGroup && !pattern.endsWith("$") && !pattern.endsWith(")$")) {
parts.push(")$");
}

return parts.join("");
}

// See https://datatracker.ietf.org/doc/html/rfc9485#name-ecmascript-regexps
protected mapRegexp(pattern: string): string {
let escaped = false;
let charClass = false;
const parts: string[] = [];
for (const ch of pattern) {
switch (ch) {
case ".":
if (!escaped && !charClass) {
parts.push("(?:(?![\r\n])\\P{Cs}|\\p{Cs}\\p{Cs})");
} else {
parts.push(ch);
escaped = false;
}
break;
case "\\":
escaped = true;
parts.push(ch);
break;
case "[":
charClass = true;
escaped = false;
parts.push(ch);
break;
case "]":
charClass = false;
escaped = false;
parts.push(ch);
break;
default:
escaped = false;
parts.push(ch);
break;
}
}
return parts.join("");
}
}
40 changes: 39 additions & 1 deletion src/path/functions/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,50 @@ export class Search implements FilterFunction {
}

try {
const re = new RegExp(pattern, "u");
const re = new RegExp(this.mapRegexp(pattern), "u");
if (this.cacheSize > 0) this.#cache.set(pattern, re);
return !!s.match(re);
} catch (error) {
if (this.throwErrors) throw error;
return false;
}
}

// See https://datatracker.ietf.org/doc/html/rfc9485#name-ecmascript-regexps
protected mapRegexp(pattern: string): string {
let escaped = false;
let charClass = false;
const parts: string[] = [];
for (const ch of pattern) {
switch (ch) {
case ".":
if (!escaped && !charClass) {
parts.push("(?:(?![\r\n])\\P{Cs}|\\p{Cs}\\p{Cs})");
} else {
parts.push(ch);
escaped = false;
}
break;
case "\\":
escaped = true;
parts.push(ch);
break;
case "[":
charClass = true;
escaped = false;
parts.push(ch);
break;
case "]":
charClass = false;
escaped = false;
parts.push(ch);
break;
default:
escaped = false;
parts.push(ch);
break;
}
}
return parts.join("");
}
}
2 changes: 1 addition & 1 deletion src/path/lex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ function lexInsideBracketedSelection(l: Lexer): StateFn | null {
}

if (!l.environment.strict && l.acceptMatchRun(l.environment.keysPattern)) {
// FIXME: fall back to legacy behavior if keysPattern is not the default
switch (l.peek()) {
case "'":
l.ignore(); // ~
Expand All @@ -377,7 +378,6 @@ function lexInsideBracketedSelection(l: Lexer): StateFn | null {
l.next();
return lexDoubleQuoteKeyString(l);
case "?":
l.ignore(); // ~
l.next();
l.emit(TokenKind.KEYS_FILTER);
l.filterLevel += 1;
Expand Down
2 changes: 1 addition & 1 deletion tests/path/cts

0 comments on commit 52c4514

Please sign in to comment.