rng 0.1.2 → 0.3.4

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.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +63 -0
  3. data/.github/workflows/release.yml +8 -3
  4. data/.gitignore +11 -0
  5. data/.rubocop.yml +10 -7
  6. data/.rubocop_todo.yml +229 -23
  7. data/CHANGELOG.md +317 -0
  8. data/CLAUDE.md +139 -0
  9. data/Gemfile +11 -12
  10. data/README.adoc +1538 -11
  11. data/Rakefile +11 -3
  12. data/docs/Gemfile +8 -0
  13. data/docs/_config.yml +23 -0
  14. data/docs/getting-started/index.adoc +75 -0
  15. data/docs/guides/error-handling.adoc +137 -0
  16. data/docs/guides/external-references.adoc +128 -0
  17. data/docs/guides/index.adoc +24 -0
  18. data/docs/guides/parsing-rnc.adoc +141 -0
  19. data/docs/guides/parsing-rng-xml.adoc +81 -0
  20. data/docs/guides/rng-to-rnc.adoc +101 -0
  21. data/docs/guides/validation.adoc +85 -0
  22. data/docs/index.adoc +52 -0
  23. data/docs/reference/api.adoc +126 -0
  24. data/docs/reference/cli.adoc +182 -0
  25. data/docs/understanding/architecture.adoc +58 -0
  26. data/docs/understanding/rng-vs-rnc.adoc +118 -0
  27. data/exe/rng +5 -0
  28. data/lib/rng/any_name.rb +10 -8
  29. data/lib/rng/attribute.rb +28 -26
  30. data/lib/rng/choice.rb +24 -24
  31. data/lib/rng/cli.rb +607 -0
  32. data/lib/rng/data.rb +10 -10
  33. data/lib/rng/datatype_declaration.rb +26 -0
  34. data/lib/rng/define.rb +44 -41
  35. data/lib/rng/div.rb +36 -0
  36. data/lib/rng/documentation.rb +9 -0
  37. data/lib/rng/element.rb +39 -37
  38. data/lib/rng/empty.rb +7 -7
  39. data/lib/rng/except.rb +25 -25
  40. data/lib/rng/external_ref.rb +8 -8
  41. data/lib/rng/external_ref_resolver.rb +602 -0
  42. data/lib/rng/foreign_attribute.rb +26 -0
  43. data/lib/rng/foreign_element.rb +33 -0
  44. data/lib/rng/grammar.rb +14 -12
  45. data/lib/rng/group.rb +26 -24
  46. data/lib/rng/include.rb +5 -6
  47. data/lib/rng/include_processor.rb +461 -0
  48. data/lib/rng/interleave.rb +23 -23
  49. data/lib/rng/list.rb +22 -22
  50. data/lib/rng/mixed.rb +23 -23
  51. data/lib/rng/name.rb +6 -7
  52. data/lib/rng/namespace_declaration.rb +47 -0
  53. data/lib/rng/namespaces.rb +15 -0
  54. data/lib/rng/not_allowed.rb +7 -7
  55. data/lib/rng/ns_name.rb +9 -9
  56. data/lib/rng/one_or_more.rb +23 -23
  57. data/lib/rng/optional.rb +23 -23
  58. data/lib/rng/param.rb +7 -8
  59. data/lib/rng/parent_ref.rb +8 -8
  60. data/lib/rng/parse_tree_processor.rb +695 -0
  61. data/lib/rng/pattern.rb +7 -7
  62. data/lib/rng/ref.rb +8 -8
  63. data/lib/rng/rnc_builder.rb +927 -0
  64. data/lib/rng/rnc_parser.rb +605 -305
  65. data/lib/rng/rnc_to_rng_converter.rb +1408 -0
  66. data/lib/rng/schema_preamble.rb +73 -0
  67. data/lib/rng/schema_validator.rb +1622 -0
  68. data/lib/rng/start.rb +27 -25
  69. data/lib/rng/test_suite_parser.rb +168 -0
  70. data/lib/rng/text.rb +11 -8
  71. data/lib/rng/to_rnc.rb +4 -35
  72. data/lib/rng/value.rb +6 -7
  73. data/lib/rng/version.rb +1 -1
  74. data/lib/rng/zero_or_more.rb +23 -23
  75. data/lib/rng.rb +68 -17
  76. data/rng.gemspec +18 -19
  77. data/scripts/extract_spectest_resources.rb +96 -0
  78. data/spec/fixtures/compacttest.xml +2511 -0
  79. data/spec/fixtures/external/circular_a.rng +7 -0
  80. data/spec/fixtures/external/circular_b.rng +7 -0
  81. data/spec/fixtures/external/circular_main.rng +7 -0
  82. data/spec/fixtures/external/external_ref_lib.rng +7 -0
  83. data/spec/fixtures/external/external_ref_main.rng +7 -0
  84. data/spec/fixtures/external/include_lib.rng +7 -0
  85. data/spec/fixtures/external/include_main.rng +3 -0
  86. data/spec/fixtures/external/nested_chain.rng +6 -0
  87. data/spec/fixtures/external/nested_leaf.rng +7 -0
  88. data/spec/fixtures/external/nested_mid.rng +8 -0
  89. data/spec/fixtures/metanorma/3gpp.rnc +35 -0
  90. data/spec/fixtures/metanorma/3gpp.rng +105 -0
  91. data/spec/fixtures/metanorma/basicdoc.rnc +11 -0
  92. data/spec/fixtures/metanorma/bipm.rnc +148 -0
  93. data/spec/fixtures/metanorma/bipm.rng +376 -0
  94. data/spec/fixtures/metanorma/bsi.rnc +104 -0
  95. data/spec/fixtures/metanorma/bsi.rng +332 -0
  96. data/spec/fixtures/metanorma/csa.rnc +45 -0
  97. data/spec/fixtures/metanorma/csa.rng +131 -0
  98. data/spec/fixtures/metanorma/csd.rnc +43 -0
  99. data/spec/fixtures/metanorma/csd.rng +132 -0
  100. data/spec/fixtures/metanorma/gbstandard.rnc +99 -0
  101. data/spec/fixtures/metanorma/gbstandard.rng +316 -0
  102. data/spec/fixtures/metanorma/iec.rnc +49 -0
  103. data/spec/fixtures/metanorma/iec.rng +193 -0
  104. data/spec/fixtures/metanorma/ietf.rnc +275 -0
  105. data/spec/fixtures/metanorma/ietf.rng +925 -0
  106. data/spec/fixtures/metanorma/iho.rnc +58 -0
  107. data/spec/fixtures/metanorma/iho.rng +179 -0
  108. data/spec/fixtures/metanorma/isodoc.rnc +873 -0
  109. data/spec/fixtures/metanorma/isodoc.rng +2704 -0
  110. data/spec/fixtures/metanorma/isostandard-amd.rnc +43 -0
  111. data/spec/fixtures/metanorma/isostandard-amd.rng +108 -0
  112. data/spec/fixtures/metanorma/isostandard.rnc +166 -0
  113. data/spec/fixtures/metanorma/isostandard.rng +494 -0
  114. data/spec/fixtures/metanorma/itu.rnc +122 -0
  115. data/spec/fixtures/metanorma/itu.rng +377 -0
  116. data/spec/fixtures/metanorma/m3d.rnc +41 -0
  117. data/spec/fixtures/metanorma/m3d.rng +122 -0
  118. data/spec/fixtures/metanorma/mpfd.rnc +36 -0
  119. data/spec/fixtures/metanorma/mpfd.rng +95 -0
  120. data/spec/fixtures/metanorma/nist.rnc +77 -0
  121. data/spec/fixtures/metanorma/nist.rng +216 -0
  122. data/spec/fixtures/metanorma/ogc.rnc +51 -0
  123. data/spec/fixtures/metanorma/ogc.rng +151 -0
  124. data/spec/fixtures/metanorma/reqt.rnc +6 -0
  125. data/spec/fixtures/metanorma/rsd.rnc +36 -0
  126. data/spec/fixtures/metanorma/rsd.rng +95 -0
  127. data/spec/fixtures/metanorma/un.rnc +103 -0
  128. data/spec/fixtures/metanorma/un.rng +367 -0
  129. data/spec/fixtures/rnc/base.rnc +4 -0
  130. data/spec/fixtures/rnc/grammar_with_trailing.rnc +8 -0
  131. data/spec/fixtures/rnc/main_include_trailing.rnc +3 -0
  132. data/spec/fixtures/rnc/main_with_include.rnc +5 -0
  133. data/spec/fixtures/rnc/test_augment.rnc +10 -0
  134. data/spec/fixtures/rnc/test_isodoc_simple.rnc +9 -0
  135. data/spec/fixtures/rnc/top_level_include.rnc +8 -0
  136. data/spec/fixtures/spectest_external/case_10_4.7/x +3 -0
  137. data/spec/fixtures/spectest_external/case_10_4.7/y +7 -0
  138. data/spec/fixtures/spectest_external/case_11_4.7/x +3 -0
  139. data/spec/fixtures/spectest_external/case_12_4.7/x +3 -0
  140. data/spec/fixtures/spectest_external/case_13_4.7/x +3 -0
  141. data/spec/fixtures/spectest_external/case_13_4.7/y +3 -0
  142. data/spec/fixtures/spectest_external/case_14_4.7/x +7 -0
  143. data/spec/fixtures/spectest_external/case_15_4.7/x +7 -0
  144. data/spec/fixtures/spectest_external/case_16_4.7/x +5 -0
  145. data/spec/fixtures/spectest_external/case_17_4.7/x +5 -0
  146. data/spec/fixtures/spectest_external/case_18_4.7/x +7 -0
  147. data/spec/fixtures/spectest_external/case_19_4.7/level1.rng +9 -0
  148. data/spec/fixtures/spectest_external/case_19_4.7/level2.rng +7 -0
  149. data/spec/fixtures/spectest_external/case_1_4.5/sub1/x +3 -0
  150. data/spec/fixtures/spectest_external/case_1_4.5/sub3/x +3 -0
  151. data/spec/fixtures/spectest_external/case_1_4.5/x +3 -0
  152. data/spec/fixtures/spectest_external/case_20_4.6/x +3 -0
  153. data/spec/fixtures/spectest_external/case_2_4.5/x +3 -0
  154. data/spec/fixtures/spectest_external/case_3_4.6/x +3 -0
  155. data/spec/fixtures/spectest_external/case_4_4.6/x +3 -0
  156. data/spec/fixtures/spectest_external/case_5_4.6/x +1 -0
  157. data/spec/fixtures/spectest_external/case_6_4.6/x +5 -0
  158. data/spec/fixtures/spectest_external/case_7_4.6/x +1 -0
  159. data/spec/fixtures/spectest_external/case_7_4.6/y +1 -0
  160. data/spec/fixtures/spectest_external/case_8_4.7/x +7 -0
  161. data/spec/fixtures/spectest_external/case_9_4.7/x +7 -0
  162. data/spec/fixtures/spectest_external/resources.json +149 -0
  163. data/spec/rng/advanced_rnc_spec.rb +101 -0
  164. data/spec/rng/compacttest_spec.rb +197 -0
  165. data/spec/rng/datatype_declaration_spec.rb +28 -0
  166. data/spec/rng/div_spec.rb +207 -0
  167. data/spec/rng/external_ref_resolver_spec.rb +122 -0
  168. data/spec/rng/metanorma_conversion_spec.rb +159 -0
  169. data/spec/rng/namespace_declaration_spec.rb +60 -0
  170. data/spec/rng/namespace_support_spec.rb +199 -0
  171. data/spec/rng/rnc_parser_spec.rb +498 -22
  172. data/spec/rng/rnc_roundtrip_spec.rb +96 -82
  173. data/spec/rng/rng_generation_spec.rb +288 -0
  174. data/spec/rng/roundtrip_spec.rb +342 -0
  175. data/spec/rng/schema_preamble_spec.rb +145 -0
  176. data/spec/rng/schema_spec.rb +68 -64
  177. data/spec/rng/spectest_spec.rb +168 -90
  178. data/spec/rng_spec.rb +2 -2
  179. data/spec/spec_helper.rb +7 -42
  180. metadata +141 -8
data/lib/rng/start.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "lutaml/model"
4
-
5
3
  module Rng
6
4
  class Start < Lutaml::Model::Serializable
7
5
  attribute :id, :string
@@ -25,39 +23,43 @@ module Rng
25
23
  attribute :parentRef, ParentRef
26
24
  attribute :notAllowed, NotAllowed
27
25
  attribute :grammar, Grammar
26
+ attribute :documentation, Documentation
28
27
 
29
28
  xml do
30
- root "start", ordered: true
31
- namespace "http://relaxng.org/ns/structure/1.0"
29
+ element 'start'
30
+ ordered
31
+
32
+ namespace ::Rng::Namespaces::RngNamespace
32
33
 
33
- map_attribute "id", to: :id
34
- map_attribute "ns", to: :ns, value_map: {
34
+ map_attribute 'id', to: :id
35
+ map_attribute 'ns', to: :ns, value_map: {
35
36
  from: { empty: :empty, omitted: :omitted, nil: :nil },
36
37
  to: { empty: :empty, omitted: :omitted, nil: :nil }
37
38
  }
38
- map_attribute "datatypeLibrary", to: :datatypeLibrary, value_map: {
39
+ map_attribute 'datatypeLibrary', to: :datatypeLibrary, value_map: {
39
40
  from: { empty: :empty, omitted: :omitted, nil: :nil },
40
41
  to: { empty: :empty, omitted: :omitted, nil: :nil }
41
42
  }
42
- map_attribute "combine", to: :combine
43
+ map_attribute 'combine', to: :combine
43
44
 
44
- map_element "ref", to: :ref
45
- map_element "element", to: :element
46
- map_element "choice", to: :choice
47
- map_element "group", to: :group
48
- map_element "interleave", to: :interleave
49
- map_element "mixed", to: :mixed
50
- map_element "optional", to: :optional
51
- map_element "zeroOrMore", to: :zeroOrMore
52
- map_element "oneOrMore", to: :oneOrMore
53
- map_element "text", to: :text
54
- map_element "empty", to: :empty
55
- map_element "value", to: :value
56
- map_element "data", to: :data
57
- map_element "list", to: :list
58
- map_element "parentRef", to: :parentRef
59
- map_element "notAllowed", to: :notAllowed
60
- map_element "grammar", to: :grammar
45
+ map_element 'ref', to: :ref
46
+ map_element 'element', to: :element
47
+ map_element 'choice', to: :choice
48
+ map_element 'group', to: :group
49
+ map_element 'interleave', to: :interleave
50
+ map_element 'mixed', to: :mixed
51
+ map_element 'optional', to: :optional
52
+ map_element 'zeroOrMore', to: :zeroOrMore
53
+ map_element 'oneOrMore', to: :oneOrMore
54
+ map_element 'text', to: :text
55
+ map_element 'empty', to: :empty
56
+ map_element 'value', to: :value
57
+ map_element 'data', to: :data
58
+ map_element 'list', to: :list
59
+ map_element 'parentRef', to: :parentRef
60
+ map_element 'notAllowed', to: :notAllowed
61
+ map_element 'grammar', to: :grammar
62
+ map_element 'documentation', to: :documentation
61
63
  end
62
64
  end
63
65
  end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+
5
+ module Rng
6
+ # Parses RELAX NG test suite XML files (like compacttest.xml)
7
+ class TestSuiteParser
8
+ # Represents a single test case with RNC and RNG versions
9
+ class TestCase
10
+ attr_reader :id, :compact_correct, :compact_incorrect,
11
+ :xml_correct, :xml_incorrect,
12
+ :compact_resources, :xml_resources
13
+
14
+ def initialize(id:)
15
+ @id = id
16
+ @compact_correct = nil
17
+ @compact_incorrect = nil
18
+ @xml_correct = nil
19
+ @xml_incorrect = nil
20
+ @compact_resources = {}
21
+ @xml_resources = {}
22
+ end
23
+
24
+ def valid_rnc?
25
+ !compact_correct.nil?
26
+ end
27
+
28
+ def invalid_rnc?
29
+ !compact_incorrect.nil?
30
+ end
31
+
32
+ def valid_rng?
33
+ !xml_correct.nil?
34
+ end
35
+
36
+ def has_resources?
37
+ !compact_resources.empty? || !xml_resources.empty?
38
+ end
39
+
40
+ def description
41
+ if valid_rnc? && valid_rng?
42
+ 'RNC ↔ RNG conversion'
43
+ elsif valid_rnc?
44
+ 'Valid RNC parsing'
45
+ elsif invalid_rnc?
46
+ 'Invalid RNC rejection'
47
+ else
48
+ 'Test case'
49
+ end
50
+ end
51
+ end
52
+
53
+ attr_reader :test_cases
54
+
55
+ def initialize(xml_content)
56
+ @doc = Nokogiri::XML(xml_content)
57
+ @test_cases = []
58
+ parse_test_cases
59
+ end
60
+
61
+ # Load test suite from file path
62
+ def self.load(file_path)
63
+ content = File.read(file_path)
64
+ new(content)
65
+ end
66
+
67
+ # Get test cases with valid RNC that should parse
68
+ def valid_rnc_cases
69
+ test_cases.select(&:valid_rnc?)
70
+ end
71
+
72
+ # Get test cases with invalid RNC that should fail
73
+ def invalid_rnc_cases
74
+ test_cases.select(&:invalid_rnc?)
75
+ end
76
+
77
+ # Get test cases with both RNC and RNG for round-trip testing
78
+ def roundtrip_cases
79
+ test_cases.select { |tc| tc.valid_rnc? && tc.valid_rng? }
80
+ end
81
+
82
+ # Get test cases with resources (external files)
83
+ def resource_cases
84
+ test_cases.select(&:has_resources?)
85
+ end
86
+
87
+ private
88
+
89
+ def parse_test_cases
90
+ @doc.xpath('//testCase').each_with_index do |test_node, index|
91
+ test_case = TestCase.new(id: index + 1)
92
+
93
+ # Parse compact syntax (RNC)
94
+ parse_compact_section(test_node, test_case)
95
+
96
+ # Parse XML syntax (RNG)
97
+ parse_xml_section(test_node, test_case)
98
+
99
+ @test_cases << test_case
100
+ end
101
+ end
102
+
103
+ def parse_compact_section(test_node, test_case)
104
+ compact_node = test_node.at_xpath('compact')
105
+ return unless compact_node
106
+
107
+ # Parse resources
108
+ compact_node.xpath('resource').each do |resource_node|
109
+ name = resource_node['name']
110
+ content = resource_node.text.strip
111
+ test_case.compact_resources[name] = content
112
+ end
113
+
114
+ # Parse correct RNC
115
+ correct_node = compact_node.at_xpath('correct')
116
+ if correct_node
117
+ test_case.instance_variable_set(
118
+ :@compact_correct,
119
+ correct_node.text.strip
120
+ )
121
+ end
122
+
123
+ # Parse incorrect RNC
124
+ incorrect_node = compact_node.at_xpath('incorrect')
125
+ return unless incorrect_node
126
+
127
+ test_case.instance_variable_set(
128
+ :@compact_incorrect,
129
+ incorrect_node.text.strip
130
+ )
131
+ end
132
+
133
+ def parse_xml_section(test_node, test_case)
134
+ xml_node = test_node.at_xpath('xml')
135
+ return unless xml_node
136
+
137
+ # Parse resources
138
+ xml_node.xpath('resource').each do |resource_node|
139
+ name = resource_node['name']
140
+ # Get the first element child as RNG content
141
+ content_node = resource_node.elements.first
142
+ content = content_node ? content_node.to_xml : ''
143
+ test_case.xml_resources[name] = content
144
+ end
145
+
146
+ # Parse correct RNG
147
+ correct_node = xml_node.at_xpath('correct')
148
+ if correct_node
149
+ # Get the first element child as RNG content
150
+ rng_node = correct_node.elements.first
151
+ test_case.instance_variable_set(
152
+ :@xml_correct,
153
+ rng_node ? rng_node.to_xml : ''
154
+ )
155
+ end
156
+
157
+ # Parse incorrect RNG (if any)
158
+ incorrect_node = xml_node.at_xpath('incorrect')
159
+ return unless incorrect_node
160
+
161
+ rng_node = incorrect_node.elements.first
162
+ test_case.instance_variable_set(
163
+ :@xml_incorrect,
164
+ rng_node ? rng_node.to_xml : ''
165
+ )
166
+ end
167
+ end
168
+ end
data/lib/rng/text.rb CHANGED
@@ -1,26 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "lutaml/model"
4
-
5
3
  module Rng
6
4
  class Text < Lutaml::Model::Serializable
7
5
  attribute :id, :string
8
6
  attribute :ns, :string
9
7
  attribute :datatypeLibrary, :string
10
- attribute :value, :string, default: ""
8
+ attribute :value, :string
11
9
 
12
10
  xml do
13
- root "text"
14
- map_attribute "id", to: :id
15
- map_attribute "ns", to: :ns, value_map: {
11
+ element 'text'
12
+ namespace ::Rng::Namespaces::RngNamespace
13
+
14
+ map_attribute 'id', to: :id
15
+ map_attribute 'ns', to: :ns, value_map: {
16
+ from: { empty: :empty, omitted: :omitted, nil: :nil },
17
+ to: { empty: :empty, omitted: :omitted, nil: :nil }
18
+ }
19
+ map_attribute 'datatypeLibrary', to: :datatypeLibrary, value_map: {
16
20
  from: { empty: :empty, omitted: :omitted, nil: :nil },
17
21
  to: { empty: :empty, omitted: :omitted, nil: :nil }
18
22
  }
19
- map_attribute "datatypeLibrary", to: :datatypeLibrary, value_map: {
23
+ map_content to: :value, value_map: {
20
24
  from: { empty: :empty, omitted: :omitted, nil: :nil },
21
25
  to: { empty: :empty, omitted: :omitted, nil: :nil }
22
26
  }
23
- map_content to: :value
24
27
  end
25
28
  end
26
29
  end
data/lib/rng/to_rnc.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'rnc_parser'
4
+
3
5
  module Rng
4
6
  # RNG to RNC converter module
5
7
  # Provides functionality to convert RELAX NG XML Schema (RNG) to RELAX NG Compact Syntax (RNC)
@@ -9,41 +11,8 @@ module Rng
9
11
  # @param schema [Rng::Grammar] The schema to convert
10
12
  # @return [String] The RNC representation of the schema
11
13
  def convert(schema)
12
- # This is a placeholder implementation
13
- # The actual conversion logic would need to be implemented
14
-
15
- # Return a simple template indicating this is a stub
16
- "# RELAX NG Compact Syntax (RNC) - STUB IMPLEMENTATION\n" \
17
- "# This is a placeholder for the actual RNG to RNC conversion\n\n" \
18
- "start = element #{element_name(schema)} {\n" \
19
- " # Conversion not yet implemented\n" \
20
- " text\n" \
21
- "}\n"
22
- end
23
-
24
- private
25
-
26
- # Extract a sensible element name from the schema
27
- # @param schema [Rng::Grammar] The schema to extract element name from
28
- # @return [String] The element name or a default
29
- def element_name(schema)
30
- # Try to determine the root element name from the schema
31
- if schema.respond_to?(:start) &&
32
- schema.start.respond_to?(:element) &&
33
- schema.start.element.any? &&
34
- schema.start.element.first.respond_to?(:name)
35
- return schema.start.element.first.name
36
- end
37
-
38
- # Try other options if available
39
- if schema.respond_to?(:element) &&
40
- schema.element.respond_to?(:name) &&
41
- schema.element.name.is_a?(String)
42
- return schema.element.name
43
- end
44
-
45
- # Use default name if we can't determine from schema
46
- "root"
14
+ # Delegate to RncParser which has the actual implementation via RncBuilder
15
+ RncParser.to_rnc(schema)
47
16
  end
48
17
  end
49
18
  end
data/lib/rng/value.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "lutaml/model"
4
-
5
3
  module Rng
6
4
  class Value < Lutaml::Model::Serializable
7
5
  attribute :id, :string
@@ -11,15 +9,16 @@ module Rng
11
9
  attribute :value, :string
12
10
 
13
11
  xml do
14
- root "value"
12
+ element 'value'
13
+ namespace ::Rng::Namespaces::RngNamespace
15
14
 
16
- map_attribute "type", to: :type
17
- map_attribute "id", to: :id
18
- map_attribute "ns", to: :ns, value_map: {
15
+ map_attribute 'type', to: :type
16
+ map_attribute 'id', to: :id
17
+ map_attribute 'ns', to: :ns, value_map: {
19
18
  from: { empty: :empty, omitted: :omitted, nil: :nil },
20
19
  to: { empty: :empty, omitted: :omitted, nil: :nil }
21
20
  }
22
- map_attribute "datatypeLibrary", to: :datatypeLibrary, value_map: {
21
+ map_attribute 'datatypeLibrary', to: :datatypeLibrary, value_map: {
23
22
  from: { empty: :empty, omitted: :omitted, nil: :nil },
24
23
  to: { empty: :empty, omitted: :omitted, nil: :nil }
25
24
  }
data/lib/rng/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rng
4
- VERSION = "0.1.2"
4
+ VERSION = '0.3.4'
5
5
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "lutaml/model"
4
-
5
3
  module Rng
6
4
  class ZeroOrMore < Lutaml::Model::Serializable
7
5
  attribute :id, :string
@@ -25,34 +23,36 @@ module Rng
25
23
  attribute :notAllowed, NotAllowed, collection: true, initialize_empty: true
26
24
 
27
25
  xml do
28
- root "zeroOrMore", ordered: true
29
- namespace "http://relaxng.org/ns/structure/1.0"
26
+ element 'zeroOrMore'
27
+ ordered
28
+
29
+ namespace ::Rng::Namespaces::RngNamespace
30
30
 
31
- map_attribute "id", to: :id
32
- map_attribute "ns", to: :ns, value_map: {
31
+ map_attribute 'id', to: :id
32
+ map_attribute 'ns', to: :ns, value_map: {
33
33
  from: { empty: :empty, omitted: :omitted, nil: :nil },
34
34
  to: { empty: :empty, omitted: :omitted, nil: :nil }
35
35
  }
36
- map_attribute "datatypeLibrary", to: :datatypeLibrary, value_map: {
36
+ map_attribute 'datatypeLibrary', to: :datatypeLibrary, value_map: {
37
37
  from: { empty: :empty, omitted: :omitted, nil: :nil },
38
38
  to: { empty: :empty, omitted: :omitted, nil: :nil }
39
39
  }
40
- map_element "element", to: :element
41
- map_element "attribute", to: :attribute
42
- map_element "ref", to: :ref
43
- map_element "choice", to: :choice
44
- map_element "group", to: :group
45
- map_element "interleave", to: :interleave
46
- map_element "mixed", to: :mixed
47
- map_element "optional", to: :optional
48
- map_element "zeroOrMore", to: :zeroOrMore
49
- map_element "oneOrMore", to: :oneOrMore
50
- map_element "text", to: :text
51
- map_element "empty", to: :empty
52
- map_element "value", to: :value
53
- map_element "data", to: :data
54
- map_element "list", to: :list
55
- map_element "notAllowed", to: :notAllowed
40
+ map_element 'element', to: :element
41
+ map_element 'attribute', to: :attribute
42
+ map_element 'ref', to: :ref
43
+ map_element 'choice', to: :choice
44
+ map_element 'group', to: :group
45
+ map_element 'interleave', to: :interleave
46
+ map_element 'mixed', to: :mixed
47
+ map_element 'optional', to: :optional
48
+ map_element 'zeroOrMore', to: :zeroOrMore
49
+ map_element 'oneOrMore', to: :oneOrMore
50
+ map_element 'text', to: :text
51
+ map_element 'empty', to: :empty
52
+ map_element 'value', to: :value
53
+ map_element 'data', to: :data
54
+ map_element 'list', to: :list
55
+ map_element 'notAllowed', to: :notAllowed
56
56
  end
57
57
  end
58
58
  end
data/lib/rng.rb CHANGED
@@ -1,35 +1,86 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "lutaml/model"
4
- require "lutaml/model/xml_adapter/nokogiri_adapter"
5
-
6
- Lutaml::Model::Config.configure do |config|
7
- config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter
8
- end
3
+ require 'lutaml/model'
9
4
 
10
5
  module Rng
11
6
  class Error < StandardError; end
12
- end
13
7
 
14
- require "zeitwerk"
15
- loader = Zeitwerk::Loader.for_gem
16
- loader.setup # ready!
8
+ autoload :Namespaces, File.expand_path('rng/namespaces', __dir__)
17
9
 
18
- loader.eager_load
10
+ # Autoload all model classes - avoids circular dependency issues
11
+ autoload :Pattern, File.expand_path('rng/pattern', __dir__)
12
+ autoload :Text, File.expand_path('rng/text', __dir__)
13
+ autoload :Empty, File.expand_path('rng/empty', __dir__)
14
+ autoload :Value, File.expand_path('rng/value', __dir__)
15
+ autoload :Param, File.expand_path('rng/param', __dir__)
16
+ autoload :NotAllowed, File.expand_path('rng/not_allowed', __dir__)
17
+ autoload :Name, File.expand_path('rng/name', __dir__)
18
+ autoload :AnyName, File.expand_path('rng/any_name', __dir__)
19
+ autoload :NsName, File.expand_path('rng/ns_name', __dir__)
20
+ autoload :Except, File.expand_path('rng/except', __dir__)
21
+ autoload :Data, File.expand_path('rng/data', __dir__)
22
+ autoload :List, File.expand_path('rng/list', __dir__)
23
+ autoload :Ref, File.expand_path('rng/ref', __dir__)
24
+ autoload :ParentRef, File.expand_path('rng/parent_ref', __dir__)
25
+ autoload :ExternalRef, File.expand_path('rng/external_ref', __dir__)
26
+ autoload :Optional, File.expand_path('rng/optional', __dir__)
27
+ autoload :ZeroOrMore, File.expand_path('rng/zero_or_more', __dir__)
28
+ autoload :OneOrMore, File.expand_path('rng/one_or_more', __dir__)
29
+ autoload :Choice, File.expand_path('rng/choice', __dir__)
30
+ autoload :Group, File.expand_path('rng/group', __dir__)
31
+ autoload :Interleave, File.expand_path('rng/interleave', __dir__)
32
+ autoload :Mixed, File.expand_path('rng/mixed', __dir__)
33
+ autoload :Attribute, File.expand_path('rng/attribute', __dir__)
34
+ autoload :Element, File.expand_path('rng/element', __dir__)
35
+ autoload :Define, File.expand_path('rng/define', __dir__)
36
+ autoload :Start, File.expand_path('rng/start', __dir__)
37
+ autoload :Div, File.expand_path('rng/div', __dir__)
38
+ autoload :Include, File.expand_path('rng/include', __dir__)
39
+ autoload :Grammar, File.expand_path('rng/grammar', __dir__)
40
+ autoload :Documentation, File.expand_path('rng/documentation', __dir__)
41
+ autoload :TestSuiteParser, File.expand_path('rng/test_suite_parser', __dir__)
42
+ autoload :Value, File.expand_path('rng/value', __dir__)
43
+
44
+ # Autoload parser support classes
45
+ autoload :ParseTreeProcessor, File.expand_path('rng/parse_tree_processor', __dir__)
46
+ autoload :RncToRngConverter, File.expand_path('rng/rnc_to_rng_converter', __dir__)
47
+ autoload :SchemaPreamble, File.expand_path('rng/schema_preamble', __dir__)
48
+ autoload :NamespaceDeclaration, File.expand_path('rng/namespace_declaration', __dir__)
49
+ autoload :DatatypeDeclaration, File.expand_path('rng/datatype_declaration', __dir__)
50
+
51
+ # Schema validation
52
+ autoload :SchemaValidator, File.expand_path('rng/schema_validator', __dir__)
53
+ autoload :SchemaValidationError, File.expand_path('rng/schema_validator', __dir__)
54
+
55
+ # External reference resolution
56
+ autoload :ExternalRefResolver, File.expand_path('rng/external_ref_resolver', __dir__)
57
+
58
+ # Autoload parsers and builders
59
+ autoload :RncParser, File.expand_path('rng/rnc_parser', __dir__)
60
+ autoload :ParseRnc, File.expand_path('rng/parse_rnc', __dir__)
61
+ autoload :ToRnc, File.expand_path('rng/to_rnc', __dir__)
62
+ autoload :RncBuilder, File.expand_path('rng/rnc_builder', __dir__)
63
+ autoload :IncludeProcessor, File.expand_path('rng/include_processor', __dir__)
19
64
 
20
- module Rng
21
65
  module_function
22
66
 
23
- def parse(rng, location: nil, nested_schema: false)
24
- Grammar.from_xml(rng)
67
+ def parse(rng, location: nil, nested_schema: false, validate: false, resolve_external: false)
68
+ SchemaValidator.validate(rng) if validate && !nested_schema
69
+ grammar = Grammar.from_xml(rng)
70
+ return grammar unless resolve_external
71
+
72
+ ExternalRefResolver.new(grammar, location: location).resolve
25
73
  end
26
74
 
27
- def parse_rnc(rnc)
28
- # Parse RNC and convert to RNG
75
+ def self.parse_rnc(rnc)
29
76
  ParseRnc.parse(rnc)
30
77
  end
31
78
 
32
- def to_rnc(schema)
79
+ def self.parse_file(file_path)
80
+ RncParser.parse_file(file_path)
81
+ end
82
+
83
+ def self.to_rnc(schema)
33
84
  # Convert RNG schema to RNC
34
85
  ToRnc.convert(schema)
35
86
  end
data/rng.gemspec CHANGED
@@ -1,39 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/rng/version"
3
+ require_relative 'lib/rng/version'
4
4
 
5
5
  all_files_in_git = Dir.chdir(File.expand_path(__dir__)) do
6
6
  `git ls-files -z`.split("\x0")
7
7
  end
8
8
 
9
9
  Gem::Specification.new do |spec|
10
- spec.name = "rng"
10
+ spec.name = 'rng'
11
11
  spec.version = Rng::VERSION
12
- spec.authors = ["Ribose"]
13
- spec.email = ["open.source@ribose.com"]
12
+ spec.authors = ['Ribose']
13
+ spec.email = ['open.source@ribose.com']
14
14
 
15
- spec.summary = "Library to parse and build RELAX NG (RNG) and RELAX NG Compact Syntax (RNC) schemas."
16
- spec.homepage = "https://github.com/lutaml/rng"
17
- spec.license = "BSD-2-Clause"
18
- spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
15
+ spec.summary = 'Library to parse and build RELAX NG (RNG) and RELAX NG Compact Syntax (RNC) schemas.'
16
+ spec.homepage = 'https://github.com/lutaml/rng'
17
+ spec.license = 'BSD-2-Clause'
18
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
19
19
 
20
- spec.metadata["homepage_uri"] = spec.homepage
21
- spec.metadata["source_code_uri"] = spec.homepage
22
- spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = spec.homepage
22
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
23
23
 
24
24
  # Specify which files should be added to the gem when it is released.
25
25
  spec.files = all_files_in_git
26
26
  .reject { |f| f.match(%r{\A(?:test|features|bin|\.)/}) }
27
27
 
28
- spec.bindir = "exe"
28
+ spec.bindir = 'exe'
29
29
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
- spec.require_paths = ["lib"]
30
+ spec.require_paths = ['lib']
31
31
 
32
- spec.add_dependency "lutaml-model"
33
- spec.add_dependency "nokogiri"
34
- spec.add_dependency "parslet"
35
- spec.add_dependency "zeitwerk"
32
+ spec.add_dependency 'lutaml-model', '~> 0.8.0'
33
+ spec.add_dependency 'nokogiri'
34
+ spec.add_dependency 'parslet'
36
35
 
37
- # spec.add_dependency "thor"
38
- spec.metadata["rubygems_mfa_required"] = "true"
36
+ spec.add_dependency 'thor'
37
+ spec.metadata['rubygems_mfa_required'] = 'true'
39
38
  end