@@ -12,6 +12,7 @@ import {
12
12
PlainObject , IValidatorFn , AsyncIValidatorFn
13
13
} from './validator.functions' ;
14
14
import { forEachCopy } from './utility.functions' ;
15
+ import { jsonSchemaFormatTests , JsonSchemaFormatNames } from './format-regex.constants' ;
15
16
16
17
/**
17
18
* 'JsonValidators' class
@@ -53,15 +54,15 @@ import { forEachCopy } from './utility.functions';
53
54
* NOTE / TODO: The dependencies validator is not complete.
54
55
* NOTE / TODO: The contains validator is not complete.
55
56
*
56
- * Validators not used by JSON Schema, but included for Angular compatibility,
57
+ * Validators not used by JSON Schema ( but included for compatibility)
57
58
* and their JSON Schema equivalents:
58
59
*
59
- * Angular function : JSON Schema equivalent
60
- * -------------------: -----------------------
61
- * min(number) : minimum(number)
62
- * max(number) : maximum(number)
63
- * requiredTrue() : const(true)
64
- * email() : format('email')
60
+ * Angular validator | JSON Schema equivalent
61
+ * ------------------| -----------------------
62
+ * min(number) | minimum(number)
63
+ * max(number) | maximum(number)
64
+ * requiredTrue() | const(true)
65
+ * email() | format('email')
65
66
*
66
67
* Validator transformation functions:
67
68
* composeAnyOf, composeOneOf, composeAllOf, composeNot
@@ -92,10 +93,6 @@ import { forEachCopy } from './utility.functions';
92
93
* Original Angular Validators:
93
94
* https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
94
95
*/
95
-
96
- export type JsonSchemaStringFormat =
97
- 'date-time' | 'email' | 'hostname' | 'ipv4' | 'ipv6' | 'uri' | 'url' | 'color' ;
98
-
99
96
export class JsonValidators {
100
97
101
98
/**
@@ -319,14 +316,17 @@ export class JsonValidators {
319
316
* Requires a control to have a value of a certain format.
320
317
*
321
318
* This validator currently checks the following formsts:
322
- * 'date-time'|'email'|'hostname'|'ipv4'|'ipv6'|'uri'|'url'|'color'
319
+ * date, time, date-time, email, hostname, ipv4, ipv6,
320
+ * uri, uri-reference, uri-template, url, uuid, color,
321
+ * json-pointer, relative-json-pointer, regex
323
322
*
324
- * TODO: add 'regex'format
323
+ * Fast format regular expressions copied from AJV:
324
+ * https://github.com/epoberezkin/ajv/blob/master/lib/compile/formats.js
325
325
*
326
- * @param {JsonSchemaStringFormat } requiredFormat - format to check
326
+ * @param {JsonSchemaFormatNames } requiredFormat - format to check
327
327
* @return {IValidatorFn }
328
328
*/
329
- static format ( requiredFormat : JsonSchemaStringFormat ) : IValidatorFn {
329
+ static format ( requiredFormat : JsonSchemaFormatNames ) : IValidatorFn {
330
330
if ( ! hasValue ( requiredFormat ) ) { return JsonValidators . nullValidator ; }
331
331
return ( control : AbstractControl , invert = false ) : ValidationErrors | null => {
332
332
if ( isEmpty ( control . value ) ) { return null ; }
@@ -335,36 +335,14 @@ export class JsonValidators {
335
335
if ( ! isString ( currentValue ) ) {
336
336
isValid = false ;
337
337
} else {
338
- switch ( requiredFormat ) {
339
- case 'date-time' :
340
- isValid = ! ! currentValue . match ( / ^ ( [ 0 - 9 ] + ) - ( 0 [ 1 - 9 ] | 1 [ 0 1 2 ] ) - ( 0 [ 1 - 9 ] | [ 1 2 ] [ 0 - 9 ] | 3 [ 0 1 ] ) [ T t ] ( [ 0 1 ] [ 0 - 9 ] | 2 [ 0 - 3 ] ) : ( [ 0 - 5 ] [ 0 - 9 ] ) : ( [ 0 - 5 ] [ 0 - 9 ] | 6 0 ) ( \. [ 0 - 9 ] + ) ? ( ( [ Z z ] ) | ( [ \+ | \- ] ( [ 0 1 ] [ 0 - 9 ] | 2 [ 0 - 3 ] ) : [ 0 - 5 ] [ 0 - 9 ] ) ) $ / ) ;
341
- break ;
342
- case 'email' :
343
- let parts : string [ ] = currentValue . split ( '@' ) ;
344
- isValid =
345
- ! ! parts && parts . length === 2 &&
346
- ! ! parts [ 0 ] . match ( / ^ (?: [ a - z 0 - 9 ! # $ % & ' * + / = ? ^ _ ` { | } ~ - ] + (?: \. [ a - z 0 - 9 ! # $ % & ' * + / = ? ^ _ ` { | } ~ - ] + ) * | " (?: [ \x01 - \x08 \x0b \x0c \x0e - \x1f \x21 \x23 - \x5b \x5d - \x7f ] | \\ [ \x01 - \x09 \x0b \x0c \x0e - \x7f ] ) * " ) $ / )
347
- &&
348
- ! ! parts [ 1 ] . match ( / (? = .{ 1 , 255 } $ ) [ 0 - 9 A - Z a - z ] (?: (?: [ 0 - 9 A - Z a - z ] | \b - ) { 0 , 61 } [ 0 - 9 A - Z a - z ] ) ? (?: \. [ 0 - 9 A - Z a - z ] (?: (?: [ 0 - 9 A - Z a - z ] | \b - ) { 0 , 61 } [ 0 - 9 A - Z a - z ] ) ? ) * \. ? / ) ;
349
- break ;
350
- case 'hostname' :
351
- isValid = ! ! currentValue . match ( / (? = .{ 1 , 255 } $ ) [ 0 - 9 A - Z a - z ] (?: (?: [ 0 - 9 A - Z a - z ] | \b - ) { 0 , 61 } [ 0 - 9 A - Z a - z ] ) ? (?: \. [ 0 - 9 A - Z a - z ] (?: (?: [ 0 - 9 A - Z a - z ] | \b - ) { 0 , 61 } [ 0 - 9 A - Z a - z ] ) ? ) * \. ? / ) ;
352
- break ;
353
- case 'ipv4' :
354
- isValid = ! ! currentValue . match ( / ^ ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) \. ) { 3 } ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) $ / ) ;
355
- break ;
356
- case 'ipv6' :
357
- isValid = ! ! currentValue . match ( / ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 7 } ( [ 0 - 9 A - F a - f ] { 1 , 4 } | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 6 } ( : [ 0 - 9 A - F a - f ] { 1 , 4 } | ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 5 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 2 } ) | : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 4 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 3 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) ? : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 3 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 4 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 2 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 2 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 5 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 3 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 1 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 6 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 4 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( : ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 7 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 5 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) / ) ;
358
- break ;
359
- case 'uri' : case 'url' :
360
- isValid = ! ! currentValue . match ( / ^ ( ( ( [ A - Z a - z ] { 3 , 9 } : (?: \/ \/ ) ? ) (?: [ \- ; : & = \+ \$ , \w ] + @ ) ? [ A - Z a - z 0 - 9 \. \- ] + | (?: w w w \. | [ \- ; : & = \+ \$ , \w ] + @ ) [ A - Z a - z 0 - 9 \. \- ] + ) ( (?: \/ [ \+ ~ % \/ \. \w \- _ ] * ) ? \? ? (?: [ \- \+ = & ; % @ \. \w _ ] * ) # ? (?: [ \. \! \/ \\ \w ] * ) ) ? ) $ / ) ;
361
- break ;
362
- case 'color' :
363
- isValid = ! ! currentValue . match ( / ^ # [ A - F a - f 0 - 9 ] { 6 } $ / ) ;
364
- break ;
365
- default :
366
- console . error ( `format validator error: "${ requiredFormat } " is not a recognized format.` ) ;
367
- isValid = true ;
338
+ const formatTest : Function | RegExp = jsonSchemaFormatTests [ requiredFormat ] ;
339
+ if ( typeof formatTest === 'object' ) {
340
+ isValid = ( < RegExp > formatTest ) . test ( currentValue ) ;
341
+ } else if ( typeof formatTest === 'function' ) {
342
+ isValid = ( < Function > formatTest ) ( currentValue ) ;
343
+ } else {
344
+ console . error ( `format validator error: "${ requiredFormat } " is not a recognized format.` ) ;
345
+ isValid = true ;
368
346
}
369
347
}
370
348
return xor ( isValid , invert ) ?
@@ -378,8 +356,8 @@ export class JsonValidators {
378
356
* Requires a control's numeric value to be greater than or equal to
379
357
* a minimum amount.
380
358
*
381
- * Any non-numeric value is also valid (because a non-numeric value doesn't
382
- * have a minimum, according to the HTML forms spec ).
359
+ * Any non-numeric value is also valid (according to the HTML forms spec,
360
+ * a non-numeric value doesn't have a minimum ).
383
361
* https://www.w3.org/TR/html5/forms.html#attr-input-max
384
362
*
385
363
* @param {number } minimum - minimum allowed value
@@ -401,8 +379,8 @@ export class JsonValidators {
401
379
*
402
380
* Requires a control's numeric value to be less than a maximum amount.
403
381
*
404
- * Any non-numeric value is also valid (because a non-numeric value doesn't
405
- * have a maximum, according to the HTML forms spec ).
382
+ * Any non-numeric value is also valid (according to the HTML forms spec,
383
+ * a non-numeric value doesn't have a maximum ).
406
384
* https://www.w3.org/TR/html5/forms.html#attr-input-max
407
385
*
408
386
* @param {number } exclusiveMinimumValue - maximum allowed value
@@ -425,8 +403,8 @@ export class JsonValidators {
425
403
* Requires a control's numeric value to be less than or equal to
426
404
* a maximum amount.
427
405
*
428
- * Any non-numeric value is also valid (because a non-numeric value doesn't
429
- * have a maximum, according to the HTML forms spec ).
406
+ * Any non-numeric value is also valid (according to the HTML forms spec,
407
+ * a non-numeric value doesn't have a maximum ).
430
408
* https://www.w3.org/TR/html5/forms.html#attr-input-max
431
409
*
432
410
* @param {number } maximumValue - maximum allowed value
@@ -448,8 +426,8 @@ export class JsonValidators {
448
426
*
449
427
* Requires a control's numeric value to be less than a maximum amount.
450
428
*
451
- * Any non-numeric value is also valid (because a non-numeric value doesn't
452
- * have a maximum, according to the HTML forms spec ).
429
+ * Any non-numeric value is also valid (according to the HTML forms spec,
430
+ * a non-numeric value doesn't have a maximum ).
453
431
* https://www.w3.org/TR/html5/forms.html#attr-input-max
454
432
*
455
433
* @param {number } exclusiveMaximumValue - maximum allowed value
0 commit comments