json_schemer 2.3.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: e5ec5b8e547dc3a64b134054ec80b0f40cf9453cba4cce430995e6ae165a6e07
4
- data.tar.gz: 943423f15ba47e7b8ecc5fbf3d1b566679c43e84e3d70bbc4e0f47f126e4275f
3
+ metadata.gz: b2867482fbfc50ef6a4d85bb7a36a5b87f58565c1dafa278ccda128a4221dd0a
4
+ data.tar.gz: a2c1605ebb2434197a581398aebb7326dad1713e95b2997da50e73617686cf56
5
5
  SHA512:
6
- metadata.gz: 43c26354e594ae3219e0edd22e18b6d89a64b6cbad6bc4ac3e85750ccc128c3827d7aa38b1dc0d48a232c733250467939eaa8d6049ab8d34c75f5a0ac6f0e715
7
- data.tar.gz: eced2c5592c64adfffb89923d28a363494f09bdd87202233706baa24ad4067e8240a85120a29eb2145b70a5f9bbf85e3a7f2f71fbdd1a89a74bc2cc6e3a243ed
6
+ metadata.gz: 88cc1562df2d48949b1a1d2c66fd58e643023b783807f1a1cf4454b10bc6a8071a5a0b2dcb5bfb75632f0547fdaf038424094a8e0d8a2cf5df0a0141180cdd1f
7
+ data.tar.gz: e03ec9518f75946edacaf6d10f89f7117e672e4562c4a5f0fe9acf16fc8d8a35da5d7b374ccb0e5e1d30f2619f8e79f5424fe69a543133d81b01d2039d45e6cf
@@ -6,7 +6,7 @@ jobs:
6
6
  fail-fast: false
7
7
  matrix:
8
8
  os: [ubuntu-latest, windows-latest, macos-latest]
9
- ruby: [2.7, 3.0, 3.1, 3.2, 3.3, head, jruby, jruby-head, truffleruby, truffleruby-head]
9
+ ruby: [2.7, 3.0, 3.1, 3.2, 3.3, 3.4, head, jruby, jruby-head, truffleruby, truffleruby-head]
10
10
  exclude:
11
11
  - os: ubuntu-latest
12
12
  ruby: head
data/CHANGELOG.md CHANGED
@@ -1,12 +1,39 @@
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
+
18
+ ## [2.4.0] - 2025-02-01
19
+
20
+ ### Bug Fixes
21
+
22
+ - Store schema resource file URIs as strings to prevent conflicts: https://github.com/davishmcclurg/json_schemer/pull/189
23
+ - Require OpenAPI `discriminator` instances to be objects: https://github.com/davishmcclurg/json_schemer/pull/206
24
+ - Pass configuration options to subschemas: https://github.com/davishmcclurg/json_schemer/pull/208
25
+ - Check applicable instance types in OpenAPI `format` extensions: https://github.com/davishmcclurg/json_schemer/pull/209
26
+ - Use correct max values for OpenAPI `int32`/`int64` formats: https://github.com/davishmcclurg/json_schemer/commit/386c2a6fe089350c61775716643ef0600898060e
27
+
28
+ [2.4.0]: https://github.com/davishmcclurg/json_schemer/releases/tag/v2.4.0
29
+
3
30
  ## [2.3.0] - 2024-05-30
4
31
 
5
- ## Ruby Versions
32
+ ### Ruby Versions
6
33
 
7
34
  - Ruby 2.5 and 2.6 are no longer supported.
8
35
 
9
- ## Bug Fixes
36
+ ### Bug Fixes
10
37
 
11
38
  - Remove `base64` runtime dependency: https://github.com/davishmcclurg/json_schemer/pull/182
12
39
  - Relax `uuid` format validation: https://github.com/davishmcclurg/json_schemer/pull/183
@@ -15,7 +42,7 @@
15
42
 
16
43
  ## [2.2.0] - 2024-03-02
17
44
 
18
- ## Bug Fixes
45
+ ### Bug Fixes
19
46
 
20
47
  - Support symbol keys when accessing original instance: https://github.com/davishmcclurg/json_schemer/commit/d52c130e9967919c6cf1c9dbc3f0babfb8b01cf8
21
48
  - Support custom keywords in nested schemas: https://github.com/davishmcclurg/json_schemer/commit/93c85a5006981347c7e9a4c11b73c6bdb65d8ba2
@@ -24,7 +51,7 @@
24
51
  - Handle parse errors during schema validation: https://github.com/davishmcclurg/json_schemer/pull/171
25
52
  - Follow refs when finding default property values: https://github.com/davishmcclurg/json_schemer/pull/175
26
53
 
27
- ## Features
54
+ ### Features
28
55
 
29
56
  - Global configuration with `Configuration` object: https://github.com/davishmcclurg/json_schemer/pull/170
30
57
  - Symbol key property defaults with `insert_property_defaults: :symbol`: https://github.com/davishmcclurg/json_schemer/commit/a72473dc84199107ddedc8998950e5b82273232a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json_schemer (2.3.0)
4
+ json_schemer (2.5.0)
5
5
  bigdecimal
6
6
  hana (~> 1.3)
7
7
  regexp_parser (~> 2.0)
@@ -11,24 +11,28 @@ GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
13
  base64 (0.2.0)
14
- bigdecimal (3.1.8)
15
- bigdecimal (3.1.8-java)
16
- concurrent-ruby (1.2.2)
17
- csv (3.2.8)
18
- docile (1.4.0)
14
+ bigdecimal (3.1.9)
15
+ bigdecimal (3.1.9-java)
16
+ concurrent-ruby (1.3.5)
17
+ csv (3.3.2)
18
+ docile (1.4.1)
19
19
  hana (1.3.7)
20
- i18n (1.14.1)
20
+ i18n (1.14.6)
21
21
  concurrent-ruby (~> 1.0)
22
22
  i18n-debug (1.2.0)
23
23
  i18n (< 2)
24
- minitest (5.15.0)
25
- rake (13.1.0)
26
- regexp_parser (2.9.2)
24
+ jruby-openssl (0.15.5-java)
25
+ minitest (5.25.4)
26
+ openssl (3.3.2)
27
+ openssl (3.3.2-java)
28
+ jruby-openssl (~> 0.14)
29
+ rake (13.2.1)
30
+ regexp_parser (2.10.0)
27
31
  simplecov (0.22.0)
28
32
  docile (~> 1.1)
29
33
  simplecov-html (~> 0.11)
30
34
  simplecov_json_formatter (~> 0.1)
31
- simplecov-html (0.12.3)
35
+ simplecov-html (0.13.1)
32
36
  simplecov_json_formatter (0.1.4)
33
37
  simpleidn (0.2.3)
34
38
 
@@ -38,14 +42,15 @@ PLATFORMS
38
42
 
39
43
  DEPENDENCIES
40
44
  base64
41
- bundler (~> 2.0)
45
+ bundler (~> 2.4.0)
42
46
  csv
43
47
  i18n
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
 
50
55
  BUNDLED WITH
51
- 2.3.27
56
+ 2.4.22
data/README.md CHANGED
@@ -95,18 +95,6 @@ JSONSchemer.validate_schema({ '$id' => '#invalid' }).to_a
95
95
  # "type"=>"pattern",
96
96
  # "error"=>"string at `/$id` does not match pattern: ^[^#]*#?$"}]
97
97
 
98
- JSONSchemer.schema({ '$id' => 'valid' }).valid_schema?
99
- # => true
100
-
101
- JSONSchemer.schema({ '$id' => '#invalid' }).validate_schema.to_a
102
- # => [{"data"=>"#invalid",
103
- # "data_pointer"=>"/$id",
104
- # "schema"=>{"$ref"=>"#/$defs/uriReferenceString", "$comment"=>"Non-empty fragments not allowed.", "pattern"=>"^[^#]*#?$"},
105
- # "schema_pointer"=>"/properties/$id",
106
- # "root_schema"=>{...meta schema},
107
- # "type"=>"pattern",
108
- # "error"=>"string at `/$id` does not match pattern: ^[^#]*#?$"}]
109
-
110
98
  # subschemas
111
99
 
112
100
  schema = {
@@ -236,7 +224,7 @@ JSONSchemer.schema(
236
224
  # 'net/http': proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
237
225
  # default: proc { |uri| raise UnknownRef, uri.to_s }
238
226
  ref_resolver: 'net/http',
239
-
227
+
240
228
  # use different method to match regexes
241
229
  # 'ruby'/'ecma'/proc/lambda/respond_to?(:call)
242
230
  # 'ruby': proc { |pattern| Regexp.new(pattern) }
@@ -325,27 +313,36 @@ schemer.validate('1').map { _1.fetch('error') }
325
313
  schemer.validate(1, :output_format => 'basic').fetch('error')
326
314
  # => "custom error for schema"
327
315
 
328
- # variable interpolation (instance/instanceLocation/keywordLocation/absoluteKeywordLocation)
316
+ # variable interpolation (instance/instanceLocation/formattedInstanceLocation/keywordValue/keywordLocation/absoluteKeywordLocation/details)
329
317
  schemer = JSONSchemer.schema({
330
318
  '$id' => 'https://example.com/schema',
331
319
  'properties' => {
332
320
  'abc' => {
333
- 'type' => 'string',
321
+ 'type' => 'object',
322
+ 'required' => ['xyz'],
334
323
  'x-error' => <<~ERROR
335
324
  instance: %{instance}
336
325
  instance location: %{instanceLocation}
326
+ formatted instance location: %{formattedInstanceLocation}
327
+ keyword value: %{keywordValue}
337
328
  keyword location: %{keywordLocation}
338
329
  absolute keyword location: %{absoluteKeywordLocation}
330
+ details: %{details}
331
+ details__missing_keys: %{details__missing_keys}
339
332
  ERROR
340
333
  }
341
334
  }
342
335
  })
343
336
 
344
- puts schemer.validate({ 'abc' => 1 }).first.fetch('error')
345
- # instance: 1
337
+ puts schemer.validate({ 'abc' => {} }).first.fetch('error')
338
+ # instance: {}
346
339
  # instance location: /abc
347
- # keyword location: /properties/abc/type
348
- # 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"]
349
346
  ```
350
347
 
351
348
  ### I18n
@@ -370,26 +367,30 @@ Example translations file:
370
367
  en:
371
368
  json_schemer:
372
369
  errors:
373
- '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}
374
381
  'https://example.com/schema':
375
- '#/properties/abc/type': custom error for keyword location, nested under schema $id
376
- '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
377
384
  '^': custom error for schema, nested under schema $id
378
385
  '*': fallback error for schema and all keywords, nested under schema $id
379
- '#/properties/abc/type': custom error for keyword location
386
+ '#/properties/abc/required': custom error for keyword location
380
387
  'http://json-schema.org/draft-07/schema#':
381
- '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)
382
389
  '^': custom error for schema, nested under meta-schema $id
383
390
  '*': fallback error for schema and all keywords, nested under meta-schema $id ($schema)
384
- 'type': custom error for `type` keyword
391
+ 'required': custom error for `required` keyword
385
392
  '^': custom error for schema
386
- # variable interpolation (instance/instanceLocation/keywordLocation/absoluteKeywordLocation)
387
- '*': |
388
- fallback error for schema and all keywords
389
- instance: %{instance}
390
- instance location: %{instanceLocation}
391
- keyword location: %{keywordLocation}
392
- absolute keyword location: %{absoluteKeywordLocation}
393
+ '*': fallback error for schema and all keywords
393
394
  ```
394
395
 
395
396
  And output:
@@ -403,32 +404,45 @@ schemer = JSONSchemer.schema({
403
404
  '$schema' => 'http://json-schema.org/draft-07/schema#', # $META_SCHEMA_ID=http://json-schema.org/draft-07/schema#
404
405
  'properties' => {
405
406
  'abc' => {
406
- 'type' => 'integer' # $KEYWORD=type
407
- } # $KEYWORD_LOCATION=#/properties/abc/type
408
- } # $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
409
410
  })
410
411
 
411
- schemer.validate({ 'abc' => 'not-an-integer' }).first
412
- # => {"data"=>"not-an-integer",
413
- # "data_pointer"=>"/abc",
414
- # "schema"=>{"type"=>"integer"},
415
- # "schema_pointer"=>"/properties/abc",
416
- # "root_schema"=>{"$id"=>"https://example.com/schema", "$schema"=>"http://json-schema.org/draft-07/schema#", "properties"=>{"abc"=>{"type"=>"integer"}}},
417
- # "type"=>"integer",
418
- # "error"=>"custom error for absolute keyword location",
419
- # "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"]
420
434
  ```
421
435
 
422
436
  In the example above, custom error messsages are looked up using the following keys (in order until one is found):
423
437
 
424
- 1. `en.json_schemer.errors.'https://example.com/schema#/properties/abc/type'`
425
- 2. `en.json_schemer.errors.'https://example.com/schema'.'#/properties/abc/type'`
426
- 3. `en.json_schemer.errors.'#/properties/abc/type'`
427
- 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`
428
442
  5. `en.json_schemer.errors.'https://example.com/schema'.*`
429
- 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`
430
444
  7. `en.json_schemer.errors.'http://json-schema.org/draft-07/schema#'.*`
431
- 8. `en.json_schemer.errors.type`
445
+ 8. `en.json_schemer.errors.required`
432
446
  9. `en.json_schemer.errors.*`
433
447
 
434
448
  ## OpenAPI
data/json_schemer.gemspec CHANGED
@@ -23,13 +23,14 @@ Gem::Specification.new do |spec|
23
23
  spec.required_ruby_version = '>= 2.7'
24
24
 
25
25
  spec.add_development_dependency "base64"
26
- spec.add_development_dependency "bundler", "~> 2.0"
26
+ spec.add_development_dependency "bundler", "~> 2.4.0"
27
27
  spec.add_development_dependency "rake", "~> 13.0"
28
28
  spec.add_development_dependency "minitest", "~> 5.0"
29
29
  spec.add_development_dependency "simplecov", "~> 0.22"
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"
@@ -4,6 +4,10 @@ module JSONSchemer
4
4
  module Vocab
5
5
  module Validation
6
6
  class Type < Keyword
7
+ def self.valid_integer?(instance)
8
+ instance.is_a?(Numeric) && (instance.is_a?(Integer) || instance.floor == instance)
9
+ end
10
+
7
11
  def error(formatted_instance_location:, **)
8
12
  case value
9
13
  when 'null'
@@ -45,7 +49,7 @@ module JSONSchemer
45
49
  when 'number'
46
50
  instance.is_a?(Numeric)
47
51
  when 'integer'
48
- instance.is_a?(Numeric) && (instance.is_a?(Integer) || instance.floor == instance)
52
+ self.class.valid_integer?(instance)
49
53
  when 'string'
50
54
  instance.is_a?(String)
51
55
  when 'array'
@@ -4,9 +4,8 @@ module JSONSchemer
4
4
  module Vocab
5
5
  module Validation
6
6
  class Type < Draft202012::Vocab::Validation::Type
7
- private
8
- def valid_type(type, instance)
9
- type == 'integer' ? instance.is_a?(Integer) : super
7
+ def self.valid_integer?(instance)
8
+ instance.is_a?(Integer)
10
9
  end
11
10
  end
12
11
 
@@ -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,8 +4,10 @@ module JSONSchemer
4
4
  BASE_URI = URI('json-schemer://openapi30/schema')
5
5
  # https://spec.openapis.org/oas/v3.0.3#data-types
6
6
  FORMATS = OpenAPI31::FORMATS.merge(
7
- 'byte' => proc { |instance, _value| ContentEncoding::BASE64.call(instance).first },
8
- 'binary' => proc { |instance, _value| instance.is_a?(String) && instance.encoding == Encoding::BINARY },
7
+ 'int32' => proc { |instance, _format| !Draft4::Vocab::Validation::Type.valid_integer?(instance) || instance.floor.bit_length < 32 },
8
+ 'int64' => proc { |instance, _format| !Draft4::Vocab::Validation::Type.valid_integer?(instance) || instance.floor.bit_length < 64 },
9
+ 'byte' => proc { |instance, _value| !instance.is_a?(String) || ContentEncoding::BASE64.call(instance).first },
10
+ 'binary' => proc { |instance, _value| !instance.is_a?(String) || instance.encoding == Encoding::BINARY },
9
11
  'date' => Format::DATE
10
12
  )
11
13
  SCHEMA = {
@@ -4,10 +4,10 @@ module JSONSchemer
4
4
  BASE_URI = URI('https://spec.openapis.org/oas/3.1/dialect/base')
5
5
  # https://spec.openapis.org/oas/v3.1.0#data-types
6
6
  FORMATS = {
7
- 'int32' => proc { |instance, _format| instance.is_a?(Integer) && instance.bit_length <= 32 },
8
- 'int64' => proc { |instance, _format| instance.is_a?(Integer) && instance.bit_length <= 64 },
9
- 'float' => proc { |instance, _format| instance.is_a?(Float) },
10
- 'double' => proc { |instance, _format| instance.is_a?(Float) },
7
+ 'int32' => proc { |instance, _format| !Draft202012::Vocab::Validation::Type.valid_integer?(instance) || instance.floor.bit_length < 32 },
8
+ 'int64' => proc { |instance, _format| !Draft202012::Vocab::Validation::Type.valid_integer?(instance) || instance.floor.bit_length < 64 },
9
+ 'float' => proc { |instance, _format| !instance.is_a?(Numeric) || instance.is_a?(Float) },
10
+ 'double' => proc { |instance, _format| !instance.is_a?(Numeric) || instance.is_a?(Float) },
11
11
  'password' => proc { |_instance, _format| true }
12
12
  }
13
13
  SCHEMA = {
@@ -100,7 +100,7 @@ module JSONSchemer
100
100
  end
101
101
 
102
102
  def validate(instance, instance_location, keyword_location, context)
103
- return result(instance, instance_location, keyword_location, true) unless instance.is_a?(Hash)
103
+ return result(instance, instance_location, keyword_location, false) unless instance.is_a?(Hash)
104
104
 
105
105
  property_name = value.fetch('propertyName')
106
106
 
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module JSONSchemer
3
+ class Resources
4
+ def initialize
5
+ @resources = {}
6
+ end
7
+
8
+ def [](uri)
9
+ @resources[uri.to_s]
10
+ end
11
+
12
+ def []=(uri, resource)
13
+ @resources[uri.to_s] = resource
14
+ end
15
+
16
+ def fetch(uri)
17
+ @resources.fetch(uri.to_s)
18
+ end
19
+
20
+ def key?(uri)
21
+ @resources.key?(uri.to_s)
22
+ end
23
+ end
24
+ end
@@ -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
@@ -15,6 +15,7 @@ module JSONSchemer
15
15
  end
16
16
  end
17
17
 
18
+ extend Forwardable
18
19
  include Output
19
20
 
20
21
  SCHEMA_KEYWORD_CLASS = Draft202012::Vocab::Core::Schema
@@ -44,7 +45,8 @@ module JSONSchemer
44
45
 
45
46
  attr_accessor :base_uri, :meta_schema, :keywords, :keyword_order
46
47
  attr_reader :value, :parent, :root, :configuration, :parsed
47
- attr_reader :vocabulary, :format, :formats, :content_encodings, :content_media_types, :custom_keywords, :before_property_validation, :after_property_validation, :insert_property_defaults
48
+ def_delegators :@configuration, :vocabulary, :format, :formats, :content_encodings, :content_media_types, :before_property_validation, :after_property_validation, :insert_property_defaults
49
+ def_delegator :@configuration, :keywords, :custom_keywords
48
50
 
49
51
  def initialize(
50
52
  value,
@@ -75,24 +77,27 @@ module JSONSchemer
75
77
  @root = root
76
78
  @keyword = keyword
77
79
  @schema = self
78
- @configuration = configuration
79
80
  @base_uri = base_uri
80
81
  @meta_schema = meta_schema
81
- @vocabulary = vocabulary
82
- @format = format
83
- @formats = formats
84
- @content_encodings = content_encodings
85
- @content_media_types = content_media_types
86
- @custom_keywords = keywords
87
- @before_property_validation = Array(before_property_validation)
88
- @after_property_validation = Array(after_property_validation)
89
- @insert_property_defaults = insert_property_defaults
90
- @property_default_resolver = property_default_resolver
91
- @original_ref_resolver = ref_resolver
92
- @original_regexp_resolver = regexp_resolver
93
- @output_format = output_format
94
- @resolve_enumerators = resolve_enumerators
95
- @access_mode = access_mode
82
+ @configuration = Configuration.new(
83
+ :base_uri => base_uri,
84
+ :meta_schema => meta_schema,
85
+ :vocabulary => vocabulary,
86
+ :format => format,
87
+ :formats => formats,
88
+ :content_encodings => content_encodings,
89
+ :content_media_types => content_media_types,
90
+ :keywords => keywords,
91
+ :before_property_validation => Array(before_property_validation),
92
+ :after_property_validation => Array(after_property_validation),
93
+ :insert_property_defaults => insert_property_defaults,
94
+ :property_default_resolver => property_default_resolver,
95
+ :ref_resolver => ref_resolver,
96
+ :regexp_resolver => regexp_resolver,
97
+ :output_format => output_format,
98
+ :resolve_enumerators => resolve_enumerators,
99
+ :access_mode => access_mode
100
+ )
96
101
  @parsed = parse
97
102
  end
98
103
 
@@ -100,7 +105,7 @@ module JSONSchemer
100
105
  validate(instance, :output_format => 'flag', **options).fetch('valid')
101
106
  end
102
107
 
103
- def validate(instance, output_format: @output_format, resolve_enumerators: @resolve_enumerators, access_mode: @access_mode)
108
+ def validate(instance, output_format: @configuration.output_format, resolve_enumerators: @configuration.resolve_enumerators, access_mode: @configuration.access_mode)
104
109
  instance_location = Location.root
105
110
  context = Context.new(instance, [], nil, (!insert_property_defaults && output_format == 'flag'), access_mode)
106
111
  result = validate_instance(deep_stringify_keys(instance), instance_location, root_keyword_location, context)
@@ -328,7 +333,7 @@ module JSONSchemer
328
333
  end
329
334
 
330
335
  def resources
331
- @resources ||= { :lexical => {}, :dynamic => {} }
336
+ @resources ||= { :lexical => Resources.new, :dynamic => Resources.new }
332
337
  end
333
338
 
334
339
  def error(formatted_instance_location:, **options)
@@ -340,17 +345,17 @@ module JSONSchemer
340
345
  end
341
346
 
342
347
  def ref_resolver
343
- @ref_resolver ||= @original_ref_resolver == 'net/http' ? CachedResolver.new(&NET_HTTP_REF_RESOLVER) : @original_ref_resolver
348
+ @ref_resolver ||= @configuration.ref_resolver == 'net/http' ? CachedResolver.new(&NET_HTTP_REF_RESOLVER) : @configuration.ref_resolver
344
349
  end
345
350
 
346
351
  def regexp_resolver
347
- @regexp_resolver ||= case @original_regexp_resolver
352
+ @regexp_resolver ||= case @configuration.regexp_resolver
348
353
  when 'ecma'
349
354
  CachedResolver.new(&ECMA_REGEXP_RESOLVER)
350
355
  when 'ruby'
351
356
  CachedResolver.new(&RUBY_REGEXP_RESOLVER)
352
357
  else
353
- @original_regexp_resolver
358
+ @configuration.regexp_resolver
354
359
  end
355
360
  end
356
361
 
@@ -407,7 +412,11 @@ module JSONSchemer
407
412
  end
408
413
 
409
414
  def property_default_resolver
410
- @property_default_resolver ||= insert_property_defaults == :symbol ? SYMBOL_PROPERTY_DEFAULT_RESOLVER : DEFAULT_PROPERTY_DEFAULT_RESOLVER
415
+ @property_default_resolver ||= if @configuration.property_default_resolver
416
+ @configuration.property_default_resolver
417
+ else
418
+ insert_property_defaults == :symbol ? SYMBOL_PROPERTY_DEFAULT_RESOLVER : DEFAULT_PROPERTY_DEFAULT_RESOLVER
419
+ end
411
420
  end
412
421
 
413
422
  def resolve_enumerators!(output)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module JSONSchemer
3
- VERSION = '2.3.0'
3
+ VERSION = '2.5.0'
4
4
  end
data/lib/json_schemer.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'bigdecimal'
3
+ require 'forwardable'
3
4
  require 'ipaddr'
4
5
  require 'json'
5
6
  require 'net/http'
@@ -59,6 +60,7 @@ require 'json_schemer/openapi30/vocab/base'
59
60
  require 'json_schemer/openapi30/vocab'
60
61
  require 'json_schemer/openapi'
61
62
  require 'json_schemer/configuration'
63
+ require 'json_schemer/resources'
62
64
  require 'json_schemer/schema'
63
65
 
64
66
  module JSONSchemer
@@ -78,6 +80,7 @@ module JSONSchemer
78
80
  VOCABULARIES = {
79
81
  'https://json-schema.org/draft/2020-12/vocab/core' => Draft202012::Vocab::CORE,
80
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,
81
84
  'https://json-schema.org/draft/2020-12/vocab/unevaluated' => Draft202012::Vocab::UNEVALUATED,
82
85
  'https://json-schema.org/draft/2020-12/vocab/validation' => Draft202012::Vocab::VALIDATION,
83
86
  'https://json-schema.org/draft/2020-12/vocab/format-annotation' => Draft202012::Vocab::FORMAT_ANNOTATION,
@@ -95,20 +98,22 @@ module JSONSchemer
95
98
  'json-schemer://draft7' => Draft7::Vocab::ALL,
96
99
  'json-schemer://draft6' => Draft6::Vocab::ALL,
97
100
  'json-schemer://draft4' => Draft4::Vocab::ALL,
98
-
99
- 'https://spec.openapis.org/oas/3.1/vocab/base' => OpenAPI31::Vocab::BASE,
100
101
  'json-schemer://openapi30' => OpenAPI30::Vocab::BASE
101
102
  }
102
103
  VOCABULARY_ORDER = VOCABULARIES.transform_values.with_index { |_vocabulary, index| index }
103
104
 
104
105
  WINDOWS_URI_PATH_REGEX = /\A\/[a-z]:/i
105
106
 
107
+ # :nocov:
108
+ URI_PARSER = URI.const_defined?(:RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
109
+ # :nocov:
110
+
106
111
  FILE_URI_REF_RESOLVER = proc do |uri|
107
112
  raise InvalidFileURI, 'must use `file` scheme' unless uri.scheme == 'file'
108
113
  raise InvalidFileURI, 'cannot have a host (use `file:///`)' if uri.host && !uri.host.empty?
109
114
  path = uri.path
110
115
  path = path[1..-1] if path.match?(WINDOWS_URI_PATH_REGEX)
111
- JSON.parse(File.read(URI::DEFAULT_PARSER.unescape(path)))
116
+ JSON.parse(File.read(URI_PARSER.unescape(path)))
112
117
  end
113
118
 
114
119
  class << self
@@ -246,7 +251,7 @@ module JSONSchemer
246
251
  when String
247
252
  JSON.parse(schema)
248
253
  when Pathname
249
- base_uri = URI.parse(File.join('file:', URI::DEFAULT_PARSER.escape(schema.realpath.to_s)))
254
+ base_uri = URI.parse(File.join('file:', URI_PARSER.escape(schema.realpath.to_s)))
250
255
  options[:base_uri] = base_uri
251
256
  if options.key?(:ref_resolver)
252
257
  FILE_URI_REF_RESOLVER.call(base_uri)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_schemer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Harsha
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-05-30 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: base64
@@ -30,14 +29,14 @@ dependencies:
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
- version: '2.0'
32
+ version: 2.4.0
34
33
  type: :development
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - "~>"
39
38
  - !ruby/object:Gem::Version
40
- version: '2.0'
39
+ version: 2.4.0
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: rake
43
42
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +121,20 @@ dependencies:
122
121
  - - ">="
123
122
  - !ruby/object:Gem::Version
124
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
125
138
  - !ruby/object:Gem::Dependency
126
139
  name: bigdecimal
127
140
  requirement: !ruby/object:Gem::Requirement
@@ -178,7 +191,6 @@ dependencies:
178
191
  - - "~>"
179
192
  - !ruby/object:Gem::Version
180
193
  version: '0.2'
181
- description:
182
194
  email:
183
195
  - davishmcclurg@gmail.com
184
196
  executables:
@@ -246,6 +258,7 @@ files:
246
258
  - lib/json_schemer/openapi31/vocab.rb
247
259
  - lib/json_schemer/openapi31/vocab/base.rb
248
260
  - lib/json_schemer/output.rb
261
+ - lib/json_schemer/resources.rb
249
262
  - lib/json_schemer/result.rb
250
263
  - lib/json_schemer/schema.rb
251
264
  - lib/json_schemer/version.rb
@@ -253,7 +266,6 @@ homepage: https://github.com/davishmcclurg/json_schemer
253
266
  licenses:
254
267
  - MIT
255
268
  metadata: {}
256
- post_install_message:
257
269
  rdoc_options: []
258
270
  require_paths:
259
271
  - lib
@@ -268,8 +280,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
268
280
  - !ruby/object:Gem::Version
269
281
  version: '0'
270
282
  requirements: []
271
- rubygems_version: 3.5.3
272
- signing_key:
283
+ rubygems_version: 3.6.9
273
284
  specification_version: 4
274
285
  summary: JSON Schema validator. Supports drafts 4, 6, 7, 2019-09, 2020-12, OpenAPI
275
286
  3.0, and OpenAPI 3.1.