json_schemer 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04dbbf738ea9253437566fb50075ee7603fd0b536324181aebb0573c32c7f7bc
4
- data.tar.gz: 29337d5892b33a2f74e435370986f059d7dd9762352bea610e7668dca3171e09
3
+ metadata.gz: b2867482fbfc50ef6a4d85bb7a36a5b87f58565c1dafa278ccda128a4221dd0a
4
+ data.tar.gz: a2c1605ebb2434197a581398aebb7326dad1713e95b2997da50e73617686cf56
5
5
  SHA512:
6
- metadata.gz: 90f1510bcc40ad9500904453dee34434b91ef45b8ab7d8be84dc728aae4d4c1a4556037f1ae8b48595198529973fe2d1e5c20a64e5aeb9871cd6fddd23636268
7
- data.tar.gz: c7e8a861d8f763d5248d79d486d8b253b9f81e40952e896d53b7dad84bdd5197a70224008e79de5cf5b6e7a3e9a8e646bd8af4188ae6a87c4a7ac9011998f36f
6
+ metadata.gz: 88cc1562df2d48949b1a1d2c66fd58e643023b783807f1a1cf4454b10bc6a8071a5a0b2dcb5bfb75632f0547fdaf038424094a8e0d8a2cf5df0a0141180cdd1f
7
+ data.tar.gz: e03ec9518f75946edacaf6d10f89f7117e672e4562c4a5f0fe9acf16fc8d8a35da5d7b374ccb0e5e1d30f2619f8e79f5424fe69a543133d81b01d2039d45e6cf
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.5.0] - 2025-12-08
4
+
5
+ ### Bug Fixes
6
+
7
+ - Apply `discriminator` before unevaluated keywords: https://github.com/davishmcclurg/json_schemer/pull/220
8
+ - Disallow trailing dots in hostname formats: https://github.com/davishmcclurg/json_schemer/pull/226
9
+ - Limit overall size in hostname formats: https://github.com/davishmcclurg/json_schemer/pull/226
10
+ - Support extended set of separators in hostname formats: https://github.com/davishmcclurg/json_schemer/pull/226
11
+
12
+ ### Features
13
+
14
+ - More interpolation variables for custom error messages: https://github.com/davishmcclurg/json_schemer/pull/211
15
+
16
+ [2.5.0]: https://github.com/davishmcclurg/json_schemer/releases/tag/v2.5.0
17
+
3
18
  ## [2.4.0] - 2025-02-01
4
19
 
5
20
  ### Bug Fixes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json_schemer (2.4.0)
4
+ json_schemer (2.5.0)
5
5
  bigdecimal
6
6
  hana (~> 1.3)
7
7
  regexp_parser (~> 2.0)
@@ -21,7 +21,11 @@ GEM
21
21
  concurrent-ruby (~> 1.0)
22
22
  i18n-debug (1.2.0)
23
23
  i18n (< 2)
24
+ jruby-openssl (0.15.5-java)
24
25
  minitest (5.25.4)
26
+ openssl (3.3.2)
27
+ openssl (3.3.2-java)
28
+ jruby-openssl (~> 0.14)
25
29
  rake (13.2.1)
26
30
  regexp_parser (2.10.0)
27
31
  simplecov (0.22.0)
@@ -44,6 +48,7 @@ DEPENDENCIES
44
48
  i18n-debug
45
49
  json_schemer!
46
50
  minitest (~> 5.0)
51
+ openssl (~> 3.3.2)
47
52
  rake (~> 13.0)
48
53
  simplecov (~> 0.22)
49
54
 
data/README.md CHANGED
@@ -224,7 +224,7 @@ JSONSchemer.schema(
224
224
  # 'net/http': proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
225
225
  # default: proc { |uri| raise UnknownRef, uri.to_s }
226
226
  ref_resolver: 'net/http',
227
-
227
+
228
228
  # use different method to match regexes
229
229
  # 'ruby'/'ecma'/proc/lambda/respond_to?(:call)
230
230
  # 'ruby': proc { |pattern| Regexp.new(pattern) }
@@ -313,27 +313,36 @@ schemer.validate('1').map { _1.fetch('error') }
313
313
  schemer.validate(1, :output_format => 'basic').fetch('error')
314
314
  # => "custom error for schema"
315
315
 
316
- # variable interpolation (instance/instanceLocation/keywordLocation/absoluteKeywordLocation)
316
+ # variable interpolation (instance/instanceLocation/formattedInstanceLocation/keywordValue/keywordLocation/absoluteKeywordLocation/details)
317
317
  schemer = JSONSchemer.schema({
318
318
  '$id' => 'https://example.com/schema',
319
319
  'properties' => {
320
320
  'abc' => {
321
- 'type' => 'string',
321
+ 'type' => 'object',
322
+ 'required' => ['xyz'],
322
323
  'x-error' => <<~ERROR
323
324
  instance: %{instance}
324
325
  instance location: %{instanceLocation}
326
+ formatted instance location: %{formattedInstanceLocation}
327
+ keyword value: %{keywordValue}
325
328
  keyword location: %{keywordLocation}
326
329
  absolute keyword location: %{absoluteKeywordLocation}
330
+ details: %{details}
331
+ details__missing_keys: %{details__missing_keys}
327
332
  ERROR
328
333
  }
329
334
  }
330
335
  })
331
336
 
332
- puts schemer.validate({ 'abc' => 1 }).first.fetch('error')
333
- # instance: 1
337
+ puts schemer.validate({ 'abc' => {} }).first.fetch('error')
338
+ # instance: {}
334
339
  # instance location: /abc
335
- # keyword location: /properties/abc/type
336
- # absolute keyword location: https://example.com/schema#/properties/abc/type
340
+ # formatted instance location: `/abc`
341
+ # keyword value: ["xyz"]
342
+ # keyword location: /properties/abc/required
343
+ # absolute keyword location: https://example.com/schema#/properties/abc/required
344
+ # details: {"missing_keys" => ["xyz"]}
345
+ # details__missing_keys: ["xyz"]
337
346
  ```
338
347
 
339
348
  ### I18n
@@ -358,26 +367,30 @@ Example translations file:
358
367
  en:
359
368
  json_schemer:
360
369
  errors:
361
- 'https://example.com/schema#/properties/abc/type': custom error for absolute keyword location
370
+ # variable interpolation (instance/instanceLocation/formattedInstanceLocation/keywordValue/keywordLocation/absoluteKeywordLocation/details)
371
+ 'https://example.com/schema#/properties/abc/required': |
372
+ custom error for absolute keyword location
373
+ instance: %{instance}
374
+ instance location: %{instanceLocation}
375
+ formatted instance location: %{formattedInstanceLocation}
376
+ keyword value: %{keywordValue}
377
+ keyword location: %{keywordLocation}
378
+ absolute keyword location: %{absoluteKeywordLocation}
379
+ details: %{details}
380
+ details__missing_keys: %{details__missing_keys}
362
381
  'https://example.com/schema':
363
- '#/properties/abc/type': custom error for keyword location, nested under schema $id
364
- 'type': custom error for `type` keyword, nested under schema $id
382
+ '#/properties/abc/required': custom error for keyword location, nested under schema $id
383
+ 'required': custom error for `required` keyword, nested under schema $id
365
384
  '^': custom error for schema, nested under schema $id
366
385
  '*': fallback error for schema and all keywords, nested under schema $id
367
- '#/properties/abc/type': custom error for keyword location
386
+ '#/properties/abc/required': custom error for keyword location
368
387
  'http://json-schema.org/draft-07/schema#':
369
- 'type': custom error for `type` keyword, nested under meta-schema $id ($schema)
388
+ 'required': custom error for `required` keyword, nested under meta-schema $id ($schema)
370
389
  '^': custom error for schema, nested under meta-schema $id
371
390
  '*': fallback error for schema and all keywords, nested under meta-schema $id ($schema)
372
- 'type': custom error for `type` keyword
391
+ 'required': custom error for `required` keyword
373
392
  '^': custom error for schema
374
- # variable interpolation (instance/instanceLocation/keywordLocation/absoluteKeywordLocation)
375
- '*': |
376
- fallback error for schema and all keywords
377
- instance: %{instance}
378
- instance location: %{instanceLocation}
379
- keyword location: %{keywordLocation}
380
- absolute keyword location: %{absoluteKeywordLocation}
393
+ '*': fallback error for schema and all keywords
381
394
  ```
382
395
 
383
396
  And output:
@@ -391,32 +404,45 @@ schemer = JSONSchemer.schema({
391
404
  '$schema' => 'http://json-schema.org/draft-07/schema#', # $META_SCHEMA_ID=http://json-schema.org/draft-07/schema#
392
405
  'properties' => {
393
406
  'abc' => {
394
- 'type' => 'integer' # $KEYWORD=type
395
- } # $KEYWORD_LOCATION=#/properties/abc/type
396
- } # $ABSOLUTE_KEYWORD_LOCATION=https://example.com/schema#/properties/abc/type
407
+ 'required' => ['xyz'] # $KEYWORD=required
408
+ } # $KEYWORD_LOCATION=#/properties/abc/required
409
+ } # $ABSOLUTE_KEYWORD_LOCATION=https://example.com/schema#/properties/abc/required
397
410
  })
398
411
 
399
- schemer.validate({ 'abc' => 'not-an-integer' }).first
400
- # => {"data"=>"not-an-integer",
401
- # "data_pointer"=>"/abc",
402
- # "schema"=>{"type"=>"integer"},
403
- # "schema_pointer"=>"/properties/abc",
404
- # "root_schema"=>{"$id"=>"https://example.com/schema", "$schema"=>"http://json-schema.org/draft-07/schema#", "properties"=>{"abc"=>{"type"=>"integer"}}},
405
- # "type"=>"integer",
406
- # "error"=>"custom error for absolute keyword location",
407
- # "i18n"=>true
412
+ schemer.validate({ 'abc' => {} }).first
413
+ # => {"data" => {},
414
+ # "data_pointer" => "/abc",
415
+ # "schema" => {"required" => ["xyz"]},
416
+ # "schema_pointer" => "/properties/abc",
417
+ # "root_schema" => {"$id" => "https://example.com/schema", "$schema" => "http://json-schema.org/draft-07/schema#", "properties" => {"abc" => {"required" => ["xyz"]}}},
418
+ # "type" => "required",
419
+ # "error" =>
420
+ # "custom error for absolute keyword location\ninstance: {}\ninstance location: /abc\nformatted instance location: `/abc`\nkeyword value: [\"xyz\"]\nkeyword location: /properties/abc/required\nabsolute keyword location: https://example.com/schema#/properties/abc/required\ndetails: {\"missing_keys\" => [\"xyz\"]}\ndetails__missing_keys: [\"xyz\"]\n",
421
+ # "i18n" => true,
422
+ # "details" => {"missing_keys" => ["xyz"]}}
423
+
424
+ puts schemer.validate({ 'abc' => {} }).first.fetch('error')
425
+ # custom error for absolute keyword location
426
+ # instance: {}
427
+ # instance location: /abc
428
+ # formatted instance location: `/abc`
429
+ # keyword value: ["xyz"]
430
+ # keyword location: /properties/abc/required
431
+ # absolute keyword location: https://example.com/schema#/properties/abc/required
432
+ # details: {"missing_keys" => ["xyz"]}
433
+ # details__missing_keys: ["xyz"]
408
434
  ```
409
435
 
410
436
  In the example above, custom error messsages are looked up using the following keys (in order until one is found):
411
437
 
412
- 1. `en.json_schemer.errors.'https://example.com/schema#/properties/abc/type'`
413
- 2. `en.json_schemer.errors.'https://example.com/schema'.'#/properties/abc/type'`
414
- 3. `en.json_schemer.errors.'#/properties/abc/type'`
415
- 4. `en.json_schemer.errors.'https://example.com/schema'.type`
438
+ 1. `en.json_schemer.errors.'https://example.com/schema#/properties/abc/required'`
439
+ 2. `en.json_schemer.errors.'https://example.com/schema'.'#/properties/abc/required'`
440
+ 3. `en.json_schemer.errors.'#/properties/abc/required'`
441
+ 4. `en.json_schemer.errors.'https://example.com/schema'.required`
416
442
  5. `en.json_schemer.errors.'https://example.com/schema'.*`
417
- 6. `en.json_schemer.errors.'http://json-schema.org/draft-07/schema#'.type`
443
+ 6. `en.json_schemer.errors.'http://json-schema.org/draft-07/schema#'.required`
418
444
  7. `en.json_schemer.errors.'http://json-schema.org/draft-07/schema#'.*`
419
- 8. `en.json_schemer.errors.type`
445
+ 8. `en.json_schemer.errors.required`
420
446
  9. `en.json_schemer.errors.*`
421
447
 
422
448
  ## OpenAPI
data/json_schemer.gemspec CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "csv"
31
31
  spec.add_development_dependency "i18n"
32
32
  spec.add_development_dependency "i18n-debug"
33
+ spec.add_development_dependency "openssl", "~> 3.3.2"
33
34
 
34
35
  spec.add_runtime_dependency "bigdecimal"
35
36
  spec.add_runtime_dependency "hana", "~> 1.3"
@@ -12,13 +12,16 @@ module JSONSchemer
12
12
  # https://datatracker.ietf.org/doc/html/rfc5891#section-4.2.3.2
13
13
  LEADING_CHARACTER_CLASS = "[#{LABEL_CHARACTER_CLASS}&&[^#{MARKS}]]"
14
14
  LABEL_REGEX_STRING = "#{LEADING_CHARACTER_CLASS}([#{LABEL_CHARACTER_CLASS}\-]*#{LABEL_CHARACTER_CLASS})?"
15
- HOSTNAME_REGEX = /\A(#{LABEL_REGEX_STRING}\.)*#{LABEL_REGEX_STRING}\z/i.freeze
15
+ # https://datatracker.ietf.org/doc/html/rfc3490#section-3.1
16
+ LABEL_SEPARATOR_CHARACTER_CLASS = '[\u{002E}\u{3002}\u{FF0E}\u{FF61}]'
17
+ LABEL_SEPARATOR_REGEX = /#{LABEL_SEPARATOR_CHARACTER_CLASS}/.freeze
18
+ HOSTNAME_REGEX = /\A(#{LABEL_REGEX_STRING}#{LABEL_SEPARATOR_CHARACTER_CLASS})*#{LABEL_REGEX_STRING}\z/i.freeze
16
19
  # bin/hostname_character_classes
17
- VIRAMA_CHARACTER_CLASS = '[\u{094D}\u{09CD}\u{0A4D}\u{0ACD}\u{0B4D}\u{0BCD}\u{0C4D}\u{0CCD}\u{0D3B}\u{0D3C}\u{0D4D}\u{0DCA}\u{0E3A}\u{0EBA}\u{0F84}\u{1039}\u{103A}\u{1714}\u{1715}\u{1734}\u{17D2}\u{1A60}\u{1B44}\u{1BAA}\u{1BAB}\u{1BF2}\u{1BF3}\u{2D7F}\u{A806}\u{A82C}\u{A8C4}\u{A953}\u{A9C0}\u{AAF6}\u{ABED}\u{10A3F}\u{11046}\u{11070}\u{1107F}\u{110B9}\u{11133}\u{11134}\u{111C0}\u{11235}\u{112EA}\u{1134D}\u{11442}\u{114C2}\u{115BF}\u{1163F}\u{116B6}\u{1172B}\u{11839}\u{1193D}\u{1193E}\u{119E0}\u{11A34}\u{11A47}\u{11A99}\u{11C3F}\u{11D44}\u{11D45}\u{11D97}\u{11F41}\u{11F42}]'
20
+ VIRAMA_CHARACTER_CLASS = '[\u{094D}\u{09CD}\u{0A4D}\u{0ACD}\u{0B4D}\u{0BCD}\u{0C4D}\u{0CCD}\u{0D3B}\u{0D3C}\u{0D4D}\u{0DCA}\u{0E3A}\u{0EBA}\u{0F84}\u{1039}\u{103A}\u{1714}\u{1715}\u{1734}\u{17D2}\u{1A60}\u{1B44}\u{1BAA}\u{1BAB}\u{1BF2}\u{1BF3}\u{2D7F}\u{A806}\u{A82C}\u{A8C4}\u{A953}\u{A9C0}\u{AAF6}\u{ABED}\u{10A3F}\u{11046}\u{11070}\u{1107F}\u{110B9}\u{11133}\u{11134}\u{111C0}\u{11235}\u{112EA}\u{1134D}\u{113CE}\u{113CF}\u{113D0}\u{11442}\u{114C2}\u{115BF}\u{1163F}\u{116B6}\u{1172B}\u{11839}\u{1193D}\u{1193E}\u{119E0}\u{11A34}\u{11A47}\u{11A99}\u{11C3F}\u{11D44}\u{11D45}\u{11D97}\u{11F41}\u{11F42}\u{1612F}]'
18
21
  JOINING_TYPE_L_CHARACTER_CLASS = '[\u{A872}\u{10ACD}\u{10AD7}\u{10D00}\u{10FCB}]'
19
- JOINING_TYPE_D_CHARACTER_CLASS = '[\u{0620}\u{0626}\u{0628}\u{062A}-\u{062E}\u{0633}-\u{063F}\u{0641}-\u{0647}\u{0649}-\u{064A}\u{066E}-\u{066F}\u{0678}-\u{0687}\u{069A}-\u{06BF}\u{06C1}-\u{06C2}\u{06CC}\u{06CE}\u{06D0}-\u{06D1}\u{06FA}-\u{06FC}\u{06FF}\u{0712}-\u{0714}\u{071A}-\u{071D}\u{071F}-\u{0727}\u{0729}\u{072B}\u{072D}-\u{072E}\u{074E}-\u{0758}\u{075C}-\u{076A}\u{076D}-\u{0770}\u{0772}\u{0775}-\u{0777}\u{077A}-\u{077F}\u{07CA}-\u{07EA}\u{0841}-\u{0845}\u{0848}\u{084A}-\u{0853}\u{0855}\u{0860}\u{0862}-\u{0865}\u{0868}\u{0886}\u{0889}-\u{088D}\u{08A0}-\u{08A9}\u{08AF}-\u{08B0}\u{08B3}-\u{08B8}\u{08BA}-\u{08C8}\u{1807}\u{1820}-\u{1842}\u{1843}\u{1844}-\u{1878}\u{1887}-\u{18A8}\u{18AA}\u{A840}-\u{A871}\u{10AC0}-\u{10AC4}\u{10AD3}-\u{10AD6}\u{10AD8}-\u{10ADC}\u{10ADE}-\u{10AE0}\u{10AEB}-\u{10AEE}\u{10B80}\u{10B82}\u{10B86}-\u{10B88}\u{10B8A}-\u{10B8B}\u{10B8D}\u{10B90}\u{10BAD}-\u{10BAE}\u{10D01}-\u{10D21}\u{10D23}\u{10F30}-\u{10F32}\u{10F34}-\u{10F44}\u{10F51}-\u{10F53}\u{10F70}-\u{10F73}\u{10F76}-\u{10F81}\u{10FB0}\u{10FB2}-\u{10FB3}\u{10FB8}\u{10FBB}-\u{10FBC}\u{10FBE}-\u{10FBF}\u{10FC1}\u{10FC4}\u{10FCA}\u{1E900}-\u{1E943}]'
20
- JOINING_TYPE_T_CHARACTER_CLASS = '[\u{00AD}\u{0300}-\u{036F}\u{0483}-\u{0487}\u{0488}-\u{0489}\u{0591}-\u{05BD}\u{05BF}\u{05C1}-\u{05C2}\u{05C4}-\u{05C5}\u{05C7}\u{0610}-\u{061A}\u{061C}\u{064B}-\u{065F}\u{0670}\u{06D6}-\u{06DC}\u{06DF}-\u{06E4}\u{06E7}-\u{06E8}\u{06EA}-\u{06ED}\u{070F}\u{0711}\u{0730}-\u{074A}\u{07A6}-\u{07B0}\u{07EB}-\u{07F3}\u{07FD}\u{0816}-\u{0819}\u{081B}-\u{0823}\u{0825}-\u{0827}\u{0829}-\u{082D}\u{0859}-\u{085B}\u{0898}-\u{089F}\u{08CA}-\u{08E1}\u{08E3}-\u{0902}\u{093A}\u{093C}\u{0941}-\u{0948}\u{094D}\u{0951}-\u{0957}\u{0962}-\u{0963}\u{0981}\u{09BC}\u{09C1}-\u{09C4}\u{09CD}\u{09E2}-\u{09E3}\u{09FE}\u{0A01}-\u{0A02}\u{0A3C}\u{0A41}-\u{0A42}\u{0A47}-\u{0A48}\u{0A4B}-\u{0A4D}\u{0A51}\u{0A70}-\u{0A71}\u{0A75}\u{0A81}-\u{0A82}\u{0ABC}\u{0AC1}-\u{0AC5}\u{0AC7}-\u{0AC8}\u{0ACD}\u{0AE2}-\u{0AE3}\u{0AFA}-\u{0AFF}\u{0B01}\u{0B3C}\u{0B3F}\u{0B41}-\u{0B44}\u{0B4D}\u{0B55}-\u{0B56}\u{0B62}-\u{0B63}\u{0B82}\u{0BC0}\u{0BCD}\u{0C00}\u{0C04}\u{0C3C}\u{0C3E}-\u{0C40}\u{0C46}-\u{0C48}\u{0C4A}-\u{0C4D}\u{0C55}-\u{0C56}\u{0C62}-\u{0C63}\u{0C81}\u{0CBC}\u{0CBF}\u{0CC6}\u{0CCC}-\u{0CCD}\u{0CE2}-\u{0CE3}\u{0D00}-\u{0D01}\u{0D3B}-\u{0D3C}\u{0D41}-\u{0D44}\u{0D4D}\u{0D62}-\u{0D63}\u{0D81}\u{0DCA}\u{0DD2}-\u{0DD4}\u{0DD6}\u{0E31}\u{0E34}-\u{0E3A}\u{0E47}-\u{0E4E}\u{0EB1}\u{0EB4}-\u{0EBC}\u{0EC8}-\u{0ECE}\u{0F18}-\u{0F19}\u{0F35}\u{0F37}\u{0F39}\u{0F71}-\u{0F7E}\u{0F80}-\u{0F84}\u{0F86}-\u{0F87}\u{0F8D}-\u{0F97}\u{0F99}-\u{0FBC}\u{0FC6}\u{102D}-\u{1030}\u{1032}-\u{1037}\u{1039}-\u{103A}\u{103D}-\u{103E}\u{1058}-\u{1059}\u{105E}-\u{1060}\u{1071}-\u{1074}\u{1082}\u{1085}-\u{1086}\u{108D}\u{109D}\u{135D}-\u{135F}\u{1712}-\u{1714}\u{1732}-\u{1733}\u{1752}-\u{1753}\u{1772}-\u{1773}\u{17B4}-\u{17B5}\u{17B7}-\u{17BD}\u{17C6}\u{17C9}-\u{17D3}\u{17DD}\u{180B}-\u{180D}\u{180F}\u{1885}-\u{1886}\u{18A9}\u{1920}-\u{1922}\u{1927}-\u{1928}\u{1932}\u{1939}-\u{193B}\u{1A17}-\u{1A18}\u{1A1B}\u{1A56}\u{1A58}-\u{1A5E}\u{1A60}\u{1A62}\u{1A65}-\u{1A6C}\u{1A73}-\u{1A7C}\u{1A7F}\u{1AB0}-\u{1ABD}\u{1ABE}\u{1ABF}-\u{1ACE}\u{1B00}-\u{1B03}\u{1B34}\u{1B36}-\u{1B3A}\u{1B3C}\u{1B42}\u{1B6B}-\u{1B73}\u{1B80}-\u{1B81}\u{1BA2}-\u{1BA5}\u{1BA8}-\u{1BA9}\u{1BAB}-\u{1BAD}\u{1BE6}\u{1BE8}-\u{1BE9}\u{1BED}\u{1BEF}-\u{1BF1}\u{1C2C}-\u{1C33}\u{1C36}-\u{1C37}\u{1CD0}-\u{1CD2}\u{1CD4}-\u{1CE0}\u{1CE2}-\u{1CE8}\u{1CED}\u{1CF4}\u{1CF8}-\u{1CF9}\u{1DC0}-\u{1DFF}\u{200B}\u{200E}-\u{200F}\u{202A}-\u{202E}\u{2060}-\u{2064}\u{206A}-\u{206F}\u{20D0}-\u{20DC}\u{20DD}-\u{20E0}\u{20E1}\u{20E2}-\u{20E4}\u{20E5}-\u{20F0}\u{2CEF}-\u{2CF1}\u{2D7F}\u{2DE0}-\u{2DFF}\u{302A}-\u{302D}\u{3099}-\u{309A}\u{A66F}\u{A670}-\u{A672}\u{A674}-\u{A67D}\u{A69E}-\u{A69F}\u{A6F0}-\u{A6F1}\u{A802}\u{A806}\u{A80B}\u{A825}-\u{A826}\u{A82C}\u{A8C4}-\u{A8C5}\u{A8E0}-\u{A8F1}\u{A8FF}\u{A926}-\u{A92D}\u{A947}-\u{A951}\u{A980}-\u{A982}\u{A9B3}\u{A9B6}-\u{A9B9}\u{A9BC}-\u{A9BD}\u{A9E5}\u{AA29}-\u{AA2E}\u{AA31}-\u{AA32}\u{AA35}-\u{AA36}\u{AA43}\u{AA4C}\u{AA7C}\u{AAB0}\u{AAB2}-\u{AAB4}\u{AAB7}-\u{AAB8}\u{AABE}-\u{AABF}\u{AAC1}\u{AAEC}-\u{AAED}\u{AAF6}\u{ABE5}\u{ABE8}\u{ABED}\u{FB1E}\u{FE00}-\u{FE0F}\u{FE20}-\u{FE2F}\u{FEFF}\u{FFF9}-\u{FFFB}\u{101FD}\u{102E0}\u{10376}-\u{1037A}\u{10A01}-\u{10A03}\u{10A05}-\u{10A06}\u{10A0C}-\u{10A0F}\u{10A38}-\u{10A3A}\u{10A3F}\u{10AE5}-\u{10AE6}\u{10D24}-\u{10D27}\u{10EAB}-\u{10EAC}\u{10EFD}-\u{10EFF}\u{10F46}-\u{10F50}\u{10F82}-\u{10F85}\u{11001}\u{11038}-\u{11046}\u{11070}\u{11073}-\u{11074}\u{1107F}-\u{11081}\u{110B3}-\u{110B6}\u{110B9}-\u{110BA}\u{110C2}\u{11100}-\u{11102}\u{11127}-\u{1112B}\u{1112D}-\u{11134}\u{11173}\u{11180}-\u{11181}\u{111B6}-\u{111BE}\u{111C9}-\u{111CC}\u{111CF}\u{1122F}-\u{11231}\u{11234}\u{11236}-\u{11237}\u{1123E}\u{11241}\u{112DF}\u{112E3}-\u{112EA}\u{11300}-\u{11301}\u{1133B}-\u{1133C}\u{11340}\u{11366}-\u{1136C}\u{11370}-\u{11374}\u{11438}-\u{1143F}\u{11442}-\u{11444}\u{11446}\u{1145E}\u{114B3}-\u{114B8}\u{114BA}\u{114BF}-\u{114C0}\u{114C2}-\u{114C3}\u{115B2}-\u{115B5}\u{115BC}-\u{115BD}\u{115BF}-\u{115C0}\u{115DC}-\u{115DD}\u{11633}-\u{1163A}\u{1163D}\u{1163F}-\u{11640}\u{116AB}\u{116AD}\u{116B0}-\u{116B5}\u{116B7}\u{1171D}-\u{1171F}\u{11722}-\u{11725}\u{11727}-\u{1172B}\u{1182F}-\u{11837}\u{11839}-\u{1183A}\u{1193B}-\u{1193C}\u{1193E}\u{11943}\u{119D4}-\u{119D7}\u{119DA}-\u{119DB}\u{119E0}\u{11A01}-\u{11A0A}\u{11A33}-\u{11A38}\u{11A3B}-\u{11A3E}\u{11A47}\u{11A51}-\u{11A56}\u{11A59}-\u{11A5B}\u{11A8A}-\u{11A96}\u{11A98}-\u{11A99}\u{11C30}-\u{11C36}\u{11C38}-\u{11C3D}\u{11C3F}\u{11C92}-\u{11CA7}\u{11CAA}-\u{11CB0}\u{11CB2}-\u{11CB3}\u{11CB5}-\u{11CB6}\u{11D31}-\u{11D36}\u{11D3A}\u{11D3C}-\u{11D3D}\u{11D3F}-\u{11D45}\u{11D47}\u{11D90}-\u{11D91}\u{11D95}\u{11D97}\u{11EF3}-\u{11EF4}\u{11F00}-\u{11F01}\u{11F36}-\u{11F3A}\u{11F40}\u{11F42}\u{13430}-\u{1343F}\u{13440}\u{13447}-\u{13455}\u{16AF0}-\u{16AF4}\u{16B30}-\u{16B36}\u{16F4F}\u{16F8F}-\u{16F92}\u{16FE4}\u{1BC9D}-\u{1BC9E}\u{1BCA0}-\u{1BCA3}\u{1CF00}-\u{1CF2D}\u{1CF30}-\u{1CF46}\u{1D167}-\u{1D169}\u{1D173}-\u{1D17A}\u{1D17B}-\u{1D182}\u{1D185}-\u{1D18B}\u{1D1AA}-\u{1D1AD}\u{1D242}-\u{1D244}\u{1DA00}-\u{1DA36}\u{1DA3B}-\u{1DA6C}\u{1DA75}\u{1DA84}\u{1DA9B}-\u{1DA9F}\u{1DAA1}-\u{1DAAF}\u{1E000}-\u{1E006}\u{1E008}-\u{1E018}\u{1E01B}-\u{1E021}\u{1E023}-\u{1E024}\u{1E026}-\u{1E02A}\u{1E08F}\u{1E130}-\u{1E136}\u{1E2AE}\u{1E2EC}-\u{1E2EF}\u{1E4EC}-\u{1E4EF}\u{1E8D0}-\u{1E8D6}\u{1E944}-\u{1E94A}\u{1E94B}\u{E0001}\u{E0020}-\u{E007F}\u{E0100}-\u{E01EF}]'
21
- JOINING_TYPE_R_CHARACTER_CLASS = '[\u{0622}-\u{0625}\u{0627}\u{0629}\u{062F}-\u{0632}\u{0648}\u{0671}-\u{0673}\u{0675}-\u{0677}\u{0688}-\u{0699}\u{06C0}\u{06C3}-\u{06CB}\u{06CD}\u{06CF}\u{06D2}-\u{06D3}\u{06D5}\u{06EE}-\u{06EF}\u{0710}\u{0715}-\u{0719}\u{071E}\u{0728}\u{072A}\u{072C}\u{072F}\u{074D}\u{0759}-\u{075B}\u{076B}-\u{076C}\u{0771}\u{0773}-\u{0774}\u{0778}-\u{0779}\u{0840}\u{0846}-\u{0847}\u{0849}\u{0854}\u{0856}-\u{0858}\u{0867}\u{0869}-\u{086A}\u{0870}-\u{0882}\u{088E}\u{08AA}-\u{08AC}\u{08AE}\u{08B1}-\u{08B2}\u{08B9}\u{10AC5}\u{10AC7}\u{10AC9}-\u{10ACA}\u{10ACE}-\u{10AD2}\u{10ADD}\u{10AE1}\u{10AE4}\u{10AEF}\u{10B81}\u{10B83}-\u{10B85}\u{10B89}\u{10B8C}\u{10B8E}-\u{10B8F}\u{10B91}\u{10BA9}-\u{10BAC}\u{10D22}\u{10F33}\u{10F54}\u{10F74}-\u{10F75}\u{10FB4}-\u{10FB6}\u{10FB9}-\u{10FBA}\u{10FBD}\u{10FC2}-\u{10FC3}\u{10FC9}]'
22
+ JOINING_TYPE_D_CHARACTER_CLASS = '[\u{0620}\u{0626}\u{0628}\u{062A}-\u{062E}\u{0633}-\u{063F}\u{0641}-\u{0647}\u{0649}-\u{064A}\u{066E}-\u{066F}\u{0678}-\u{0687}\u{069A}-\u{06BF}\u{06C1}-\u{06C2}\u{06CC}\u{06CE}\u{06D0}-\u{06D1}\u{06FA}-\u{06FC}\u{06FF}\u{0712}-\u{0714}\u{071A}-\u{071D}\u{071F}-\u{0727}\u{0729}\u{072B}\u{072D}-\u{072E}\u{074E}-\u{0758}\u{075C}-\u{076A}\u{076D}-\u{0770}\u{0772}\u{0775}-\u{0777}\u{077A}-\u{077F}\u{07CA}-\u{07EA}\u{0841}-\u{0845}\u{0848}\u{084A}-\u{0853}\u{0855}\u{0860}\u{0862}-\u{0865}\u{0868}\u{0886}\u{0889}-\u{088D}\u{088F}\u{08A0}-\u{08A9}\u{08AF}-\u{08B0}\u{08B3}-\u{08B8}\u{08BA}-\u{08C8}\u{1807}\u{1820}-\u{1842}\u{1843}\u{1844}-\u{1878}\u{1887}-\u{18A8}\u{18AA}\u{A840}-\u{A871}\u{10AC0}-\u{10AC4}\u{10AD3}-\u{10AD6}\u{10AD8}-\u{10ADC}\u{10ADE}-\u{10AE0}\u{10AEB}-\u{10AEE}\u{10B80}\u{10B82}\u{10B86}-\u{10B88}\u{10B8A}-\u{10B8B}\u{10B8D}\u{10B90}\u{10BAD}-\u{10BAE}\u{10D01}-\u{10D21}\u{10D23}\u{10EC3}-\u{10EC4}\u{10EC6}-\u{10EC7}\u{10F30}-\u{10F32}\u{10F34}-\u{10F44}\u{10F51}-\u{10F53}\u{10F70}-\u{10F73}\u{10F76}-\u{10F81}\u{10FB0}\u{10FB2}-\u{10FB3}\u{10FB8}\u{10FBB}-\u{10FBC}\u{10FBE}-\u{10FBF}\u{10FC1}\u{10FC4}\u{10FCA}\u{1E900}-\u{1E943}]'
23
+ JOINING_TYPE_T_CHARACTER_CLASS = '[\u{00AD}\u{0300}-\u{036F}\u{0483}-\u{0487}\u{0488}-\u{0489}\u{0591}-\u{05BD}\u{05BF}\u{05C1}-\u{05C2}\u{05C4}-\u{05C5}\u{05C7}\u{0610}-\u{061A}\u{061C}\u{064B}-\u{065F}\u{0670}\u{06D6}-\u{06DC}\u{06DF}-\u{06E4}\u{06E7}-\u{06E8}\u{06EA}-\u{06ED}\u{070F}\u{0711}\u{0730}-\u{074A}\u{07A6}-\u{07B0}\u{07EB}-\u{07F3}\u{07FD}\u{0816}-\u{0819}\u{081B}-\u{0823}\u{0825}-\u{0827}\u{0829}-\u{082D}\u{0859}-\u{085B}\u{0897}-\u{089F}\u{08CA}-\u{08E1}\u{08E3}-\u{0902}\u{093A}\u{093C}\u{0941}-\u{0948}\u{094D}\u{0951}-\u{0957}\u{0962}-\u{0963}\u{0981}\u{09BC}\u{09C1}-\u{09C4}\u{09CD}\u{09E2}-\u{09E3}\u{09FE}\u{0A01}-\u{0A02}\u{0A3C}\u{0A41}-\u{0A42}\u{0A47}-\u{0A48}\u{0A4B}-\u{0A4D}\u{0A51}\u{0A70}-\u{0A71}\u{0A75}\u{0A81}-\u{0A82}\u{0ABC}\u{0AC1}-\u{0AC5}\u{0AC7}-\u{0AC8}\u{0ACD}\u{0AE2}-\u{0AE3}\u{0AFA}-\u{0AFF}\u{0B01}\u{0B3C}\u{0B3F}\u{0B41}-\u{0B44}\u{0B4D}\u{0B55}-\u{0B56}\u{0B62}-\u{0B63}\u{0B82}\u{0BC0}\u{0BCD}\u{0C00}\u{0C04}\u{0C3C}\u{0C3E}-\u{0C40}\u{0C46}-\u{0C48}\u{0C4A}-\u{0C4D}\u{0C55}-\u{0C56}\u{0C62}-\u{0C63}\u{0C81}\u{0CBC}\u{0CBF}\u{0CC6}\u{0CCC}-\u{0CCD}\u{0CE2}-\u{0CE3}\u{0D00}-\u{0D01}\u{0D3B}-\u{0D3C}\u{0D41}-\u{0D44}\u{0D4D}\u{0D62}-\u{0D63}\u{0D81}\u{0DCA}\u{0DD2}-\u{0DD4}\u{0DD6}\u{0E31}\u{0E34}-\u{0E3A}\u{0E47}-\u{0E4E}\u{0EB1}\u{0EB4}-\u{0EBC}\u{0EC8}-\u{0ECE}\u{0F18}-\u{0F19}\u{0F35}\u{0F37}\u{0F39}\u{0F71}-\u{0F7E}\u{0F80}-\u{0F84}\u{0F86}-\u{0F87}\u{0F8D}-\u{0F97}\u{0F99}-\u{0FBC}\u{0FC6}\u{102D}-\u{1030}\u{1032}-\u{1037}\u{1039}-\u{103A}\u{103D}-\u{103E}\u{1058}-\u{1059}\u{105E}-\u{1060}\u{1071}-\u{1074}\u{1082}\u{1085}-\u{1086}\u{108D}\u{109D}\u{135D}-\u{135F}\u{1712}-\u{1714}\u{1732}-\u{1733}\u{1752}-\u{1753}\u{1772}-\u{1773}\u{17B4}-\u{17B5}\u{17B7}-\u{17BD}\u{17C6}\u{17C9}-\u{17D3}\u{17DD}\u{180B}-\u{180D}\u{180F}\u{1885}-\u{1886}\u{18A9}\u{1920}-\u{1922}\u{1927}-\u{1928}\u{1932}\u{1939}-\u{193B}\u{1A17}-\u{1A18}\u{1A1B}\u{1A56}\u{1A58}-\u{1A5E}\u{1A60}\u{1A62}\u{1A65}-\u{1A6C}\u{1A73}-\u{1A7C}\u{1A7F}\u{1AB0}-\u{1ABD}\u{1ABE}\u{1ABF}-\u{1ADD}\u{1AE0}-\u{1AEB}\u{1B00}-\u{1B03}\u{1B34}\u{1B36}-\u{1B3A}\u{1B3C}\u{1B42}\u{1B6B}-\u{1B73}\u{1B80}-\u{1B81}\u{1BA2}-\u{1BA5}\u{1BA8}-\u{1BA9}\u{1BAB}-\u{1BAD}\u{1BE6}\u{1BE8}-\u{1BE9}\u{1BED}\u{1BEF}-\u{1BF1}\u{1C2C}-\u{1C33}\u{1C36}-\u{1C37}\u{1CD0}-\u{1CD2}\u{1CD4}-\u{1CE0}\u{1CE2}-\u{1CE8}\u{1CED}\u{1CF4}\u{1CF8}-\u{1CF9}\u{1DC0}-\u{1DFF}\u{200B}\u{200E}-\u{200F}\u{202A}-\u{202E}\u{2060}-\u{2064}\u{206A}-\u{206F}\u{20D0}-\u{20DC}\u{20DD}-\u{20E0}\u{20E1}\u{20E2}-\u{20E4}\u{20E5}-\u{20F0}\u{2CEF}-\u{2CF1}\u{2D7F}\u{2DE0}-\u{2DFF}\u{302A}-\u{302D}\u{3099}-\u{309A}\u{A66F}\u{A670}-\u{A672}\u{A674}-\u{A67D}\u{A69E}-\u{A69F}\u{A6F0}-\u{A6F1}\u{A802}\u{A806}\u{A80B}\u{A825}-\u{A826}\u{A82C}\u{A8C4}-\u{A8C5}\u{A8E0}-\u{A8F1}\u{A8FF}\u{A926}-\u{A92D}\u{A947}-\u{A951}\u{A980}-\u{A982}\u{A9B3}\u{A9B6}-\u{A9B9}\u{A9BC}-\u{A9BD}\u{A9E5}\u{AA29}-\u{AA2E}\u{AA31}-\u{AA32}\u{AA35}-\u{AA36}\u{AA43}\u{AA4C}\u{AA7C}\u{AAB0}\u{AAB2}-\u{AAB4}\u{AAB7}-\u{AAB8}\u{AABE}-\u{AABF}\u{AAC1}\u{AAEC}-\u{AAED}\u{AAF6}\u{ABE5}\u{ABE8}\u{ABED}\u{FB1E}\u{FE00}-\u{FE0F}\u{FE20}-\u{FE2F}\u{FEFF}\u{FFF9}-\u{FFFB}\u{101FD}\u{102E0}\u{10376}-\u{1037A}\u{10A01}-\u{10A03}\u{10A05}-\u{10A06}\u{10A0C}-\u{10A0F}\u{10A38}-\u{10A3A}\u{10A3F}\u{10AE5}-\u{10AE6}\u{10D24}-\u{10D27}\u{10D69}-\u{10D6D}\u{10EAB}-\u{10EAC}\u{10EFA}-\u{10EFF}\u{10F46}-\u{10F50}\u{10F82}-\u{10F85}\u{11001}\u{11038}-\u{11046}\u{11070}\u{11073}-\u{11074}\u{1107F}-\u{11081}\u{110B3}-\u{110B6}\u{110B9}-\u{110BA}\u{110C2}\u{11100}-\u{11102}\u{11127}-\u{1112B}\u{1112D}-\u{11134}\u{11173}\u{11180}-\u{11181}\u{111B6}-\u{111BE}\u{111C9}-\u{111CC}\u{111CF}\u{1122F}-\u{11231}\u{11234}\u{11236}-\u{11237}\u{1123E}\u{11241}\u{112DF}\u{112E3}-\u{112EA}\u{11300}-\u{11301}\u{1133B}-\u{1133C}\u{11340}\u{11366}-\u{1136C}\u{11370}-\u{11374}\u{113BB}-\u{113C0}\u{113CE}\u{113D0}\u{113D2}\u{113E1}-\u{113E2}\u{11438}-\u{1143F}\u{11442}-\u{11444}\u{11446}\u{1145E}\u{114B3}-\u{114B8}\u{114BA}\u{114BF}-\u{114C0}\u{114C2}-\u{114C3}\u{115B2}-\u{115B5}\u{115BC}-\u{115BD}\u{115BF}-\u{115C0}\u{115DC}-\u{115DD}\u{11633}-\u{1163A}\u{1163D}\u{1163F}-\u{11640}\u{116AB}\u{116AD}\u{116B0}-\u{116B5}\u{116B7}\u{1171D}\u{1171F}\u{11722}-\u{11725}\u{11727}-\u{1172B}\u{1182F}-\u{11837}\u{11839}-\u{1183A}\u{1193B}-\u{1193C}\u{1193E}\u{11943}\u{119D4}-\u{119D7}\u{119DA}-\u{119DB}\u{119E0}\u{11A01}-\u{11A0A}\u{11A33}-\u{11A38}\u{11A3B}-\u{11A3E}\u{11A47}\u{11A51}-\u{11A56}\u{11A59}-\u{11A5B}\u{11A8A}-\u{11A96}\u{11A98}-\u{11A99}\u{11B60}\u{11B62}-\u{11B64}\u{11B66}\u{11C30}-\u{11C36}\u{11C38}-\u{11C3D}\u{11C3F}\u{11C92}-\u{11CA7}\u{11CAA}-\u{11CB0}\u{11CB2}-\u{11CB3}\u{11CB5}-\u{11CB6}\u{11D31}-\u{11D36}\u{11D3A}\u{11D3C}-\u{11D3D}\u{11D3F}-\u{11D45}\u{11D47}\u{11D90}-\u{11D91}\u{11D95}\u{11D97}\u{11EF3}-\u{11EF4}\u{11F00}-\u{11F01}\u{11F36}-\u{11F3A}\u{11F40}\u{11F42}\u{11F5A}\u{13430}-\u{1343F}\u{13440}\u{13447}-\u{13455}\u{1611E}-\u{16129}\u{1612D}-\u{1612F}\u{16AF0}-\u{16AF4}\u{16B30}-\u{16B36}\u{16F4F}\u{16F8F}-\u{16F92}\u{16FE4}\u{1BC9D}-\u{1BC9E}\u{1BCA0}-\u{1BCA3}\u{1CF00}-\u{1CF2D}\u{1CF30}-\u{1CF46}\u{1D167}-\u{1D169}\u{1D173}-\u{1D17A}\u{1D17B}-\u{1D182}\u{1D185}-\u{1D18B}\u{1D1AA}-\u{1D1AD}\u{1D242}-\u{1D244}\u{1DA00}-\u{1DA36}\u{1DA3B}-\u{1DA6C}\u{1DA75}\u{1DA84}\u{1DA9B}-\u{1DA9F}\u{1DAA1}-\u{1DAAF}\u{1E000}-\u{1E006}\u{1E008}-\u{1E018}\u{1E01B}-\u{1E021}\u{1E023}-\u{1E024}\u{1E026}-\u{1E02A}\u{1E08F}\u{1E130}-\u{1E136}\u{1E2AE}\u{1E2EC}-\u{1E2EF}\u{1E4EC}-\u{1E4EF}\u{1E5EE}-\u{1E5EF}\u{1E6E3}\u{1E6E6}\u{1E6EE}-\u{1E6EF}\u{1E6F5}\u{1E8D0}-\u{1E8D6}\u{1E944}-\u{1E94A}\u{1E94B}\u{E0001}\u{E0020}-\u{E007F}\u{E0100}-\u{E01EF}]'
24
+ JOINING_TYPE_R_CHARACTER_CLASS = '[\u{0622}-\u{0625}\u{0627}\u{0629}\u{062F}-\u{0632}\u{0648}\u{0671}-\u{0673}\u{0675}-\u{0677}\u{0688}-\u{0699}\u{06C0}\u{06C3}-\u{06CB}\u{06CD}\u{06CF}\u{06D2}-\u{06D3}\u{06D5}\u{06EE}-\u{06EF}\u{0710}\u{0715}-\u{0719}\u{071E}\u{0728}\u{072A}\u{072C}\u{072F}\u{074D}\u{0759}-\u{075B}\u{076B}-\u{076C}\u{0771}\u{0773}-\u{0774}\u{0778}-\u{0779}\u{0840}\u{0846}-\u{0847}\u{0849}\u{0854}\u{0856}-\u{0858}\u{0867}\u{0869}-\u{086A}\u{0870}-\u{0882}\u{088E}\u{08AA}-\u{08AC}\u{08AE}\u{08B1}-\u{08B2}\u{08B9}\u{10AC5}\u{10AC7}\u{10AC9}-\u{10ACA}\u{10ACE}-\u{10AD2}\u{10ADD}\u{10AE1}\u{10AE4}\u{10AEF}\u{10B81}\u{10B83}-\u{10B85}\u{10B89}\u{10B8C}\u{10B8E}-\u{10B8F}\u{10B91}\u{10BA9}-\u{10BAC}\u{10D22}\u{10EC2}\u{10F33}\u{10F54}\u{10F74}-\u{10F75}\u{10FB4}-\u{10FB6}\u{10FB9}-\u{10FBA}\u{10FBD}\u{10FC2}-\u{10FC3}\u{10FC9}]'
22
25
  # https://datatracker.ietf.org/doc/html/rfc5892#appendix-A.1
23
26
  # https://datatracker.ietf.org/doc/html/rfc5892#appendix-A.2
24
27
  ZERO_WIDTH_VIRAMA = "#{VIRAMA_CHARACTER_CLASS}[\\u{200C}\\u{200D}]"
@@ -39,9 +42,16 @@ module JSONSchemer
39
42
  ARABIC_INDIC_DIGITS_REGEX = /[\u{0660}-\u{0669}]/.freeze
40
43
  ARABIC_EXTENDED_DIGITS_REGEX = /[\u{06F0}-\u{06F9}]/.freeze
41
44
 
45
+ MAX_A_LABEL_SIZE = 63
46
+ MAX_HOSTNAME_SIZE = 253
47
+
42
48
  def valid_hostname?(data)
43
- data.split('.').map do |a_label|
44
- return false if a_label.size > 63
49
+ hostname_size = 0
50
+ data.split(LABEL_SEPARATOR_REGEX, -1).map do |label|
51
+ a_label = SimpleIDN.to_ascii(label)
52
+ return false if a_label.size > MAX_A_LABEL_SIZE
53
+ hostname_size += a_label.size + 1 # include separator
54
+ return false if hostname_size > MAX_HOSTNAME_SIZE
45
55
  u_label = SimpleIDN.to_unicode(a_label)
46
56
  # https://datatracker.ietf.org/doc/html/rfc5891#section-4.2.3.1
47
57
  return false if u_label.slice(2, 2) == '--'
@@ -4,7 +4,7 @@ module JSONSchemer
4
4
  I18N_SEPARATOR = "\x1F" # unit separator
5
5
  I18N_SCOPE = 'json_schemer'
6
6
  I18N_ERRORS_SCOPE = "#{I18N_SCOPE}#{I18N_SEPARATOR}errors"
7
- X_ERROR_REGEX = /%\{(instance|instanceLocation|keywordLocation|absoluteKeywordLocation)\}/
7
+ X_ERROR_REGEX = /%\{(instance|instanceLocation|formattedInstanceLocation|keywordValue|keywordLocation|absoluteKeywordLocation|details|details__\w+)\}/
8
8
  CLASSIC_ERROR_TYPES = Hash.new do |hash, klass|
9
9
  hash[klass] = klass.name.rpartition('::').last.sub(/\A[[:alpha:]]/, &:downcase)
10
10
  end
@@ -30,18 +30,11 @@ module JSONSchemer
30
30
  def error
31
31
  return @error if defined?(@error)
32
32
  if source.x_error
33
+ x_error_replacements = interpolation_variables.transform_keys { |key| "%{#{key}}" }
33
34
  # not using sprintf because it warns: "too many arguments for format string"
34
- @error = source.x_error.gsub(
35
- X_ERROR_REGEX,
36
- '%{instance}' => instance,
37
- '%{instanceLocation}' => Location.resolve(instance_location),
38
- '%{keywordLocation}' => Location.resolve(keyword_location),
39
- '%{absoluteKeywordLocation}' => source.absolute_keyword_location
40
- )
35
+ @error = source.x_error.gsub(X_ERROR_REGEX, x_error_replacements)
41
36
  @x_error = true
42
37
  else
43
- resolved_instance_location = Location.resolve(instance_location)
44
- formatted_instance_location = resolved_instance_location.empty? ? 'root' : "`#{resolved_instance_location}`"
45
38
  @error = source.error(:formatted_instance_location => formatted_instance_location, :details => details)
46
39
  if i18n?
47
40
  begin
@@ -62,7 +55,6 @@ module JSONSchemer
62
55
  def i18n!
63
56
  base_uri_str = source.schema.base_uri.to_s
64
57
  meta_schema_base_uri_str = source.schema.meta_schema.base_uri.to_s
65
- resolved_keyword_location = Location.resolve(keyword_location)
66
58
  error_key = source.error_key
67
59
  I18n.translate!(
68
60
  source.absolute_keyword_location,
@@ -78,19 +70,16 @@ module JSONSchemer
78
70
  ].map!(&:to_sym),
79
71
  :separator => I18N_SEPARATOR,
80
72
  :scope => I18N_ERRORS_SCOPE,
81
- :instance => instance,
82
- :instanceLocation => Location.resolve(instance_location),
83
- :keywordLocation => resolved_keyword_location,
84
- :absoluteKeywordLocation => source.absolute_keyword_location
73
+ **interpolation_variables
85
74
  )
86
75
  end
87
76
 
88
77
  def to_output_unit
89
78
  out = {
90
79
  'valid' => valid,
91
- 'keywordLocation' => Location.resolve(keyword_location),
80
+ 'keywordLocation' => resolved_keyword_location,
92
81
  'absoluteKeywordLocation' => source.absolute_keyword_location,
93
- 'instanceLocation' => Location.resolve(instance_location)
82
+ 'instanceLocation' => resolved_instance_location
94
83
  }
95
84
  if valid
96
85
  out['annotation'] = annotation if annotation
@@ -106,7 +95,7 @@ module JSONSchemer
106
95
  schema = source.schema
107
96
  out = {
108
97
  'data' => instance,
109
- 'data_pointer' => Location.resolve(instance_location),
98
+ 'data_pointer' => resolved_instance_location,
110
99
  'schema' => schema.value,
111
100
  'schema_pointer' => schema.schema_pointer,
112
101
  'root_schema' => schema.root.value,
@@ -229,6 +218,18 @@ module JSONSchemer
229
218
 
230
219
  private
231
220
 
221
+ def resolved_instance_location
222
+ @resolved_instance_location ||= Location.resolve(instance_location)
223
+ end
224
+
225
+ def formatted_instance_location
226
+ @formatted_instance_location ||= resolved_instance_location.empty? ? 'root' : "`#{resolved_instance_location}`"
227
+ end
228
+
229
+ def resolved_keyword_location
230
+ @resolved_keyword_location ||= Location.resolve(keyword_location)
231
+ end
232
+
232
233
  def default_keyword_instance(schema)
233
234
  schema.parsed.fetch('default') do
234
235
  schema.parsed.find do |_keyword, keyword_instance|
@@ -238,5 +239,21 @@ module JSONSchemer
238
239
  end
239
240
  end
240
241
  end
242
+
243
+ def interpolation_variables
244
+ interpolation_variables = {
245
+ :instance => instance,
246
+ :instanceLocation => resolved_instance_location,
247
+ :formattedInstanceLocation => formatted_instance_location,
248
+ :keywordValue => source.value,
249
+ :keywordLocation => resolved_keyword_location,
250
+ :absoluteKeywordLocation => source.absolute_keyword_location,
251
+ :details => details,
252
+ }
253
+ details&.each do |key, value|
254
+ interpolation_variables["details__#{key}".to_sym] = value
255
+ end
256
+ interpolation_variables
257
+ end
241
258
  end
242
259
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module JSONSchemer
3
- VERSION = '2.4.0'
3
+ VERSION = '2.5.0'
4
4
  end
data/lib/json_schemer.rb CHANGED
@@ -80,6 +80,7 @@ module JSONSchemer
80
80
  VOCABULARIES = {
81
81
  'https://json-schema.org/draft/2020-12/vocab/core' => Draft202012::Vocab::CORE,
82
82
  'https://json-schema.org/draft/2020-12/vocab/applicator' => Draft202012::Vocab::APPLICATOR,
83
+ 'https://spec.openapis.org/oas/3.1/vocab/base' => OpenAPI31::Vocab::BASE,
83
84
  'https://json-schema.org/draft/2020-12/vocab/unevaluated' => Draft202012::Vocab::UNEVALUATED,
84
85
  'https://json-schema.org/draft/2020-12/vocab/validation' => Draft202012::Vocab::VALIDATION,
85
86
  'https://json-schema.org/draft/2020-12/vocab/format-annotation' => Draft202012::Vocab::FORMAT_ANNOTATION,
@@ -97,8 +98,6 @@ module JSONSchemer
97
98
  'json-schemer://draft7' => Draft7::Vocab::ALL,
98
99
  'json-schemer://draft6' => Draft6::Vocab::ALL,
99
100
  'json-schemer://draft4' => Draft4::Vocab::ALL,
100
-
101
- 'https://spec.openapis.org/oas/3.1/vocab/base' => OpenAPI31::Vocab::BASE,
102
101
  'json-schemer://openapi30' => OpenAPI30::Vocab::BASE
103
102
  }
104
103
  VOCABULARY_ORDER = VOCABULARIES.transform_values.with_index { |_vocabulary, index| index }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_schemer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Harsha
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-02 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -121,6 +121,20 @@ dependencies:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: openssl
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 3.3.2
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 3.3.2
124
138
  - !ruby/object:Gem::Dependency
125
139
  name: bigdecimal
126
140
  requirement: !ruby/object:Gem::Requirement
@@ -266,7 +280,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
280
  - !ruby/object:Gem::Version
267
281
  version: '0'
268
282
  requirements: []
269
- rubygems_version: 3.6.2
283
+ rubygems_version: 3.6.9
270
284
  specification_version: 4
271
285
  summary: JSON Schema validator. Supports drafts 4, 6, 7, 2019-09, 2020-12, OpenAPI
272
286
  3.0, and OpenAPI 3.1.