Skip to content

Commit e5fc668

Browse files
committed
add: support configuration of regex flags in schema and globally
1 parent d1f74a9 commit e5fc668

File tree

7 files changed

+40
-7
lines changed

7 files changed

+40
-7
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,26 @@ const { errors } = compileSchema({
13361336
assert.deepEqual(errors[0].message, "Custom error 2");
13371337
```
13381338

1339+
### regexFlags
1340+
1341+
In order to allow customization of regular expressions a schema property `regexFlags` is supported for `pattern`, `patternProperties` and format `regex`:
1342+
1343+
```ts
1344+
const { errors } = compileSchema({
1345+
type: "string",
1346+
pattern: "^[a-zA-Z0-9+_.\-]+"
1347+
regexFlags: "v"
1348+
}).validate("-");
1349+
```
1350+
1351+
Per default, a regexFlags `"u"` is used. To change this setting globally, change `REGEX_FLAGS` in settings:
1352+
1353+
```ts
1354+
import settings from "json-schema-library";
1355+
1356+
settings.REGEX_FLAGS = "v";
1357+
```
1358+
13391359
## Breaking Changes
13401360

13411361
### v10.1.0

src/SchemaNode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { hasProperty } from "./utils/hasProperty";
1919
import { getNode } from "./getNode";
2020
import { getNodeChild } from "./getNodeChild";
2121

22-
const { DYNAMIC_PROPERTIES } = settings;
22+
const { DYNAMIC_PROPERTIES, REGEX_FLAGS } = settings;
2323

2424
export function isSchemaNode(value: unknown): value is SchemaNode {
2525
return isObject(value) && Array.isArray(value?.reducers) && Array.isArray(value?.resolvers);
@@ -42,7 +42,7 @@ function getDraft(drafts: Draft[], $schema: string) {
4242
if (drafts.length === 1) {
4343
return drafts[0];
4444
}
45-
return drafts.find((d) => new RegExp(d.$schemaRegEx).test($schema)) ?? drafts[drafts.length - 1];
45+
return drafts.find((d) => new RegExp(d.$schemaRegEx, REGEX_FLAGS).test($schema)) ?? drafts[drafts.length - 1];
4646
}
4747

4848
export type Context = {

src/compileSchema.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { pick } from "./utils/pick";
99
import { JsonSchema, Draft } from "./types";
1010
import { TemplateOptions } from "./methods/getData";
1111
import { SchemaNode, SchemaNodeMethods, addKeywords, isSchemaNode } from "./SchemaNode";
12+
import settings from "./settings";
13+
14+
const { REGEX_FLAGS } = settings;
1215

1316
export type CompileOptions = {
1417
drafts?: Draft[];
@@ -20,7 +23,7 @@ export type CompileOptions = {
2023
const defaultDrafts: Draft[] = [draft04, draft06, draft07, draft2019, draft2020];
2124

2225
function getDraft(drafts: Draft[], $schema: string) {
23-
return drafts.find((d) => new RegExp(d.$schemaRegEx).test($schema)) ?? drafts[drafts.length - 1];
26+
return drafts.find((d) => new RegExp(d.$schemaRegEx, REGEX_FLAGS).test($schema)) ?? drafts[drafts.length - 1];
2427
}
2528

2629
/**

src/formats/formats.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import validUrl from "valid-url";
44
import { JsonSchemaValidatorParams, ValidationResult } from "../Keyword";
55
import { parse as parseIdnEmail } from "smtp-address-parser";
66
import { JsonError } from "../types";
7+
import settings from "../settings";
78

9+
const { REGEX_FLAGS } = settings;
810
const isValidIPV4 = /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
911
const isValidIPV6 =
1012
/^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i;
@@ -223,7 +225,7 @@ export const formats: Record<
223225
}
224226
if (typeof data === "string" && /\\Z$/.test(data) === false) {
225227
try {
226-
new RegExp(data, "u");
228+
new RegExp(data, schema.regexFlags ?? REGEX_FLAGS);
227229
return undefined;
228230
} catch (e) {} // eslint-disable-line no-empty
229231

src/keywords/pattern.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { Keyword, JsonSchemaValidatorParams } from "../Keyword";
2+
import settings from "../settings";
3+
4+
const { REGEX_FLAGS } = settings;
25

36
export const patternKeyword: Keyword = {
47
id: "pattern",
@@ -12,7 +15,7 @@ function validatePattern({ node, data, pointer = "#" }: JsonSchemaValidatorParam
1215
if (typeof data !== "string") {
1316
return;
1417
}
15-
const pattern = new RegExp(schema.pattern, "u");
18+
const pattern = new RegExp(schema.pattern, schema.regexFlags ?? REGEX_FLAGS);
1619
if (pattern.test(data) === false) {
1720
return node.createError("pattern-error", {
1821
pattern: schema.pattern,

src/keywords/patternProperties.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import {
1010
} from "../Keyword";
1111
import { getValue } from "../utils/getValue";
1212
import { validateNode } from "../validateNode";
13+
import settings from "../settings";
14+
15+
const { REGEX_FLAGS } = settings;
1316

1417
export const patternPropertiesKeyword: Keyword = {
1518
id: "patternProperties",
@@ -32,9 +35,10 @@ export function parsePatternProperties(node: SchemaNode) {
3235
if (patterns.length === 0) {
3336
return;
3437
}
38+
3539
node.patternProperties = patterns.map((pattern) => ({
3640
name: pattern,
37-
pattern: new RegExp(pattern, "u"),
41+
pattern: new RegExp(pattern, schema.regexFlags ?? REGEX_FLAGS),
3842
node: node.compileSchema(
3943
schema.patternProperties[pattern],
4044
`${node.evaluationPath}/patternProperties/${pattern}`,

src/settings.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ export default {
1515
"definitions",
1616
"dependencies",
1717
"patternProperties"
18-
]
18+
],
19+
REGEX_FLAGS: "u"
1920
};

0 commit comments

Comments
 (0)