lutaml-model 0.8.16 → 0.8.17
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 +4 -4
- data/.github/workflows/release.yml +0 -3
- data/.rubocop_todo.yml +70 -14
- data/docs/_guides/xml/namespace-semantics.adoc +2 -0
- data/docs/_guides/xml-namespace-qualification.adoc +142 -0
- data/docs/_tutorials/xml-element-attribute-namespace-guide.adoc +2 -0
- data/docs/_tutorials/xml-schema-primer-style-guide.adoc +2 -0
- data/docs/namespace-management.adoc +2 -0
- data/docs/xml-schema-qualification.md +6 -0
- data/lib/lutaml/jsonld.rb +1 -4
- data/lib/lutaml/model/choice.rb +34 -0
- data/lib/lutaml/model/compiled_rule.rb +7 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +1 -0
- data/lib/lutaml/{jsonld → rdf}/context.rb +1 -1
- data/lib/lutaml/{jsonld/transform.rb → rdf/linked_data_transform.rb} +33 -35
- data/lib/lutaml/{jsonld → rdf}/term_definition.rb +1 -1
- data/lib/lutaml/rdf.rb +3 -0
- data/lib/lutaml/xml/adapter_element.rb +2 -2
- data/lib/lutaml/xml/transformation/element_builder.rb +38 -23
- data/lib/lutaml/yamlld/adapter.rb +25 -0
- data/lib/lutaml/yamlld.rb +25 -0
- data/spec/lutaml/integration/multi_format_spec.rb +23 -0
- data/spec/lutaml/model/attribute_spec.rb +8 -1
- data/spec/lutaml/model/choice_restrict_spec.rb +225 -0
- data/spec/lutaml/model/custom_model_spec.rb +4 -4
- data/spec/lutaml/model/mixed_content_spec.rb +2 -2
- data/spec/lutaml/model/multiple_mapping_spec.rb +4 -4
- data/spec/lutaml/model/ordered_content_spec.rb +3 -3
- data/spec/lutaml/model/uninitialized_class_spec.rb +1 -1
- data/spec/lutaml/model/xsd_form_default_patterns_spec.rb +2 -2
- data/spec/lutaml/model/xsd_patterns_spec.rb +4 -4
- data/spec/lutaml/{jsonld → rdf}/context_spec.rb +2 -2
- data/spec/lutaml/{jsonld/transform_spec.rb → rdf/linked_data_transform_spec.rb} +15 -1
- data/spec/lutaml/{jsonld → rdf}/term_definition_spec.rb +2 -2
- data/spec/lutaml/turtle/transform_spec.rb +2 -2
- data/spec/lutaml/xml/enhanced_mapping_spec.rb +230 -1
- data/spec/lutaml/xml/mapping_spec.rb +4 -4
- data/spec/lutaml/xml/namespace_placement_spec.rb +11 -8
- data/spec/lutaml/xml/namespace_three_phase_spec.rb +1 -1
- data/spec/lutaml/xml/prefix_control_spec.rb +4 -4
- data/spec/lutaml/xml/serializable_namespace_spec.rb +6 -6
- data/spec/lutaml/xml/type_namespace_examples_spec.rb +1 -1
- data/spec/lutaml/xml/type_namespace_integration_spec.rb +3 -3
- data/spec/lutaml/yamlld/adapter_spec.rb +56 -0
- data/spec/lutaml/yamlld/registration_spec.rb +33 -0
- metadata +13 -8
|
@@ -187,6 +187,235 @@ RSpec.describe "Enhanced XML Mapping Features" do
|
|
|
187
187
|
expect(name_rule.form).to eq(:unqualified)
|
|
188
188
|
end
|
|
189
189
|
end
|
|
190
|
+
|
|
191
|
+
context "with Serializable child and form: :qualified" do
|
|
192
|
+
# Regression: form option on the parent's map_element rule must be
|
|
193
|
+
# propagated to the child XmlElement when the child is a Serializable
|
|
194
|
+
# (which goes through create_transformed_nested_element). Otherwise the
|
|
195
|
+
# ElementFormOptionRule cannot fire and the element is serialized
|
|
196
|
+
# without the namespace prefix.
|
|
197
|
+
let(:child_class) do
|
|
198
|
+
ns = namespace_class
|
|
199
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
200
|
+
attribute :label, :string
|
|
201
|
+
|
|
202
|
+
xml do
|
|
203
|
+
element "child"
|
|
204
|
+
namespace ns
|
|
205
|
+
map_element "label", to: :label
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
let(:model_class) do
|
|
211
|
+
ns = namespace_class
|
|
212
|
+
child = child_class
|
|
213
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
214
|
+
attribute :child, child
|
|
215
|
+
|
|
216
|
+
xml do
|
|
217
|
+
element "item"
|
|
218
|
+
namespace ns
|
|
219
|
+
map_element "child", to: :child, form: :qualified
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "stores form: :qualified on the parent rule" do
|
|
225
|
+
mapping = model_class.mappings_for(:xml)
|
|
226
|
+
child_rule = mapping.find_element(:child)
|
|
227
|
+
expect(child_rule.form).to eq(:qualified)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "serializes the nested Serializable with a namespace prefix" do
|
|
231
|
+
instance = model_class.new(child: child_class.new(label: "x"))
|
|
232
|
+
doc = Nokogiri::XML(instance.to_xml)
|
|
233
|
+
qualified = doc.at_xpath("//*[name()='ex:child']")
|
|
234
|
+
expect(qualified).not_to be_nil
|
|
235
|
+
expect(qualified.at_xpath("./xmlns:label").text).to eq("x")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "round-trips the qualified Serializable child" do
|
|
239
|
+
original = model_class.new(child: child_class.new(label: "round-trip"))
|
|
240
|
+
restored = model_class.from_xml(original.to_xml)
|
|
241
|
+
expect(restored.child.label).to eq("round-trip")
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
context "with Serializable child and form: :unqualified" do
|
|
246
|
+
# Symmetric to the :qualified case: form: :unqualified must propagate
|
|
247
|
+
# to the child XmlElement so ElementFormOptionRule can force the
|
|
248
|
+
# default (unprefixed) form.
|
|
249
|
+
let(:child_class) do
|
|
250
|
+
ns = namespace_class
|
|
251
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
252
|
+
attribute :label, :string
|
|
253
|
+
|
|
254
|
+
xml do
|
|
255
|
+
element "child"
|
|
256
|
+
namespace ns
|
|
257
|
+
map_element "label", to: :label
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
let(:model_class) do
|
|
263
|
+
ns = namespace_class
|
|
264
|
+
child = child_class
|
|
265
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
266
|
+
attribute :child, child
|
|
267
|
+
|
|
268
|
+
xml do
|
|
269
|
+
element "item"
|
|
270
|
+
namespace ns
|
|
271
|
+
map_element "child", to: :child, form: :unqualified
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it "propagates form: :unqualified and emits an unprefixed child" do
|
|
277
|
+
instance = model_class.new(child: child_class.new(label: "x"))
|
|
278
|
+
doc = Nokogiri::XML(instance.to_xml)
|
|
279
|
+
expect(doc.xpath("//*[name()='ex:child']")).to be_empty
|
|
280
|
+
expect(doc.at_xpath("//*[local-name()='child']")).not_to be_nil
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
context "with a collection of Serializable children" do
|
|
285
|
+
# The form option must propagate to every element produced for a
|
|
286
|
+
# collection attribute, not just the first.
|
|
287
|
+
let(:child_class) do
|
|
288
|
+
ns = namespace_class
|
|
289
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
290
|
+
attribute :label, :string
|
|
291
|
+
|
|
292
|
+
xml do
|
|
293
|
+
element "child"
|
|
294
|
+
namespace ns
|
|
295
|
+
map_element "label", to: :label
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
let(:model_class) do
|
|
301
|
+
ns = namespace_class
|
|
302
|
+
child = child_class
|
|
303
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
304
|
+
attribute :children, child, collection: true
|
|
305
|
+
|
|
306
|
+
xml do
|
|
307
|
+
element "item"
|
|
308
|
+
namespace ns
|
|
309
|
+
map_element "child", to: :children, form: :qualified
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it "qualifies every child in the collection" do
|
|
315
|
+
instance = model_class.new(
|
|
316
|
+
children: [child_class.new(label: "a"), child_class.new(label: "b")],
|
|
317
|
+
)
|
|
318
|
+
doc = Nokogiri::XML(instance.to_xml)
|
|
319
|
+
qualified = doc.xpath("//*[name()='ex:child']")
|
|
320
|
+
labels = qualified.map { |c| c.at_xpath("./xmlns:label").text }
|
|
321
|
+
expect(labels).to contain_exactly("a", "b")
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
context "with a Serializable child containing a Serializable grandchild" do
|
|
326
|
+
# form: :qualified is a per-rule override; it must NOT propagate
|
|
327
|
+
# transitively to grandchildren. Each level applies its own rule and
|
|
328
|
+
# its own parent_element_form_default.
|
|
329
|
+
let(:grandchild_class) do
|
|
330
|
+
ns = namespace_class
|
|
331
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
332
|
+
attribute :value, :string
|
|
333
|
+
|
|
334
|
+
xml do
|
|
335
|
+
element "grandchild"
|
|
336
|
+
namespace ns
|
|
337
|
+
map_element "value", to: :value
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
let(:child_class) do
|
|
343
|
+
ns = namespace_class
|
|
344
|
+
grandchild = grandchild_class
|
|
345
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
346
|
+
attribute :inner, grandchild
|
|
347
|
+
|
|
348
|
+
xml do
|
|
349
|
+
element "child"
|
|
350
|
+
namespace ns
|
|
351
|
+
map_element "grandchild", to: :inner
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
let(:model_class) do
|
|
357
|
+
ns = namespace_class
|
|
358
|
+
child = child_class
|
|
359
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
360
|
+
attribute :child, child
|
|
361
|
+
|
|
362
|
+
xml do
|
|
363
|
+
element "item"
|
|
364
|
+
namespace ns
|
|
365
|
+
map_element "child", to: :child, form: :qualified
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it "qualifies the child but leaves the grandchild unprefixed" do
|
|
371
|
+
instance = model_class.new(
|
|
372
|
+
child: child_class.new(inner: grandchild_class.new(value: "x")),
|
|
373
|
+
)
|
|
374
|
+
doc = Nokogiri::XML(instance.to_xml)
|
|
375
|
+
expect(doc.at_xpath("//*[name()='ex:child']")).not_to be_nil
|
|
376
|
+
expect(doc.xpath("//*[name()='ex:grandchild']")).to be_empty
|
|
377
|
+
expect(doc.at_xpath("//*[local-name()='grandchild']")).not_to be_nil
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
context "with Serializable child but no form override" do
|
|
382
|
+
# Sanity: when no form: :qualified is set on the rule, the W3C
|
|
383
|
+
# element_form_default :unqualified override should still kick in and
|
|
384
|
+
# the nested Serializable should serialize unprefixed.
|
|
385
|
+
let(:child_class) do
|
|
386
|
+
ns = namespace_class
|
|
387
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
388
|
+
attribute :label, :string
|
|
389
|
+
|
|
390
|
+
xml do
|
|
391
|
+
element "child"
|
|
392
|
+
namespace ns
|
|
393
|
+
map_element "label", to: :label
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
let(:model_class) do
|
|
399
|
+
ns = namespace_class
|
|
400
|
+
child = child_class
|
|
401
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
402
|
+
attribute :child, child
|
|
403
|
+
|
|
404
|
+
xml do
|
|
405
|
+
element "item"
|
|
406
|
+
namespace ns
|
|
407
|
+
map_element "child", to: :child
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "honors element_form_default :unqualified by leaving the child unprefixed" do
|
|
413
|
+
instance = model_class.new(child: child_class.new(label: "x"))
|
|
414
|
+
doc = Nokogiri::XML(instance.to_xml)
|
|
415
|
+
expect(doc.xpath("//*[name()='ex:child']")).to be_empty
|
|
416
|
+
expect(doc.at_xpath("//*[local-name()='child']")).not_to be_nil
|
|
417
|
+
end
|
|
418
|
+
end
|
|
190
419
|
end
|
|
191
420
|
|
|
192
421
|
describe "form option on map_attribute" do
|
|
@@ -222,7 +451,7 @@ RSpec.describe "Enhanced XML Mapping Features" do
|
|
|
222
451
|
instance = model_class.new(id: "ABC123")
|
|
223
452
|
xml = instance.to_xml
|
|
224
453
|
# Form affects qualification but implementation varies by adapter
|
|
225
|
-
expect(xml).to
|
|
454
|
+
expect(xml).to include('id="ABC123"')
|
|
226
455
|
end
|
|
227
456
|
end
|
|
228
457
|
|
|
@@ -86,16 +86,16 @@ module XmlMappingSpec
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
class Address < Lutaml::Model::Serializable
|
|
89
|
-
attribute :street, ::Lutaml::Model::Type::String
|
|
90
|
-
attribute :city, :string
|
|
89
|
+
attribute :street, ::Lutaml::Model::Type::String
|
|
90
|
+
attribute :city, :string
|
|
91
91
|
attribute :text, :string
|
|
92
92
|
attribute :address, Address
|
|
93
93
|
|
|
94
94
|
xml do
|
|
95
95
|
element "address"
|
|
96
96
|
|
|
97
|
-
map_element "street", to: :street
|
|
98
|
-
map_element "city", to: :city
|
|
97
|
+
map_element "street", to: :street, raw: :content
|
|
98
|
+
map_element "city", to: :city, raw: :content
|
|
99
99
|
map_element "text", to: :text
|
|
100
100
|
end
|
|
101
101
|
end
|
|
@@ -91,18 +91,21 @@ RSpec.describe "XML Namespace Placement" do
|
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
# This is the INCORRECT pattern - namespace at class level for Models
|
|
94
|
-
broken_model =
|
|
95
|
-
|
|
94
|
+
broken_model = nil
|
|
95
|
+
expect do
|
|
96
|
+
broken_model = Class.new do
|
|
97
|
+
include Lutaml::Model::Serialize
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
namespace ns # ❌ This doesn't work for Serializable classes!
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
attribute :value, :string
|
|
100
102
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
xml do
|
|
104
|
+
element "broken"
|
|
105
|
+
map_content to: :value
|
|
106
|
+
end
|
|
104
107
|
end
|
|
105
|
-
end
|
|
108
|
+
end.to output(/DEPRECATION WARNING.*Class-level.*namespace/).to_stderr
|
|
106
109
|
|
|
107
110
|
parent_ns = Class.new(Lutaml::Xml::W3c::XmlNamespace) do
|
|
108
111
|
uri "http://example.com/parent"
|
|
@@ -251,7 +251,7 @@ RSpec.describe "Three-phase namespace algorithm" do
|
|
|
251
251
|
expect(xml).to include("<version>4.0</version>")
|
|
252
252
|
|
|
253
253
|
# Should NOT add redundant prefix
|
|
254
|
-
expect(xml).not_to
|
|
254
|
+
expect(xml).not_to include("<vcard:version>")
|
|
255
255
|
end
|
|
256
256
|
end
|
|
257
257
|
end
|
|
@@ -100,8 +100,8 @@ RSpec.describe "XML Prefix Control" do
|
|
|
100
100
|
expect(xml).to include('<custom:Properties xmlns:custom="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">')
|
|
101
101
|
expect(xml).to include("<custom:Template>Normal.dotm</custom:Template>")
|
|
102
102
|
# Should not have redundant declarations
|
|
103
|
-
expect(xml).not_to
|
|
104
|
-
expect(xml).not_to
|
|
103
|
+
expect(xml).not_to include('xmlns="')
|
|
104
|
+
expect(xml).not_to include("xmlns:app=")
|
|
105
105
|
end
|
|
106
106
|
end
|
|
107
107
|
|
|
@@ -208,8 +208,8 @@ RSpec.describe "XML Prefix Control" do
|
|
|
208
208
|
expect(xml).to include('<custom:Properties xmlns:custom="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">')
|
|
209
209
|
expect(xml).to include("<custom:Template>Normal.dotm</custom:Template>")
|
|
210
210
|
# Should not have redundant declarations
|
|
211
|
-
expect(xml).not_to
|
|
212
|
-
expect(xml).not_to
|
|
211
|
+
expect(xml).not_to include('xmlns="')
|
|
212
|
+
expect(xml).not_to include("xmlns:app=")
|
|
213
213
|
end
|
|
214
214
|
end
|
|
215
215
|
|
|
@@ -22,7 +22,7 @@ RSpec.describe Lutaml::Model::Serializable, "namespace directive" do
|
|
|
22
22
|
model_class = Class.new do
|
|
23
23
|
include Lutaml::Model::Serialize
|
|
24
24
|
end
|
|
25
|
-
model_class.namespace(test_namespace)
|
|
25
|
+
expect { model_class.namespace(test_namespace) }.to output.to_stderr
|
|
26
26
|
|
|
27
27
|
expect(model_class.namespace).to eq(test_namespace)
|
|
28
28
|
end
|
|
@@ -49,7 +49,7 @@ RSpec.describe Lutaml::Model::Serializable, "namespace directive" do
|
|
|
49
49
|
model_class = Class.new do
|
|
50
50
|
include Lutaml::Model::Serialize
|
|
51
51
|
end
|
|
52
|
-
model_class.namespace(test_namespace)
|
|
52
|
+
expect { model_class.namespace(test_namespace) }.to output.to_stderr
|
|
53
53
|
model_class.namespace(other_namespace)
|
|
54
54
|
|
|
55
55
|
expect(model_class.namespace).to eq(other_namespace)
|
|
@@ -61,7 +61,7 @@ RSpec.describe Lutaml::Model::Serializable, "namespace directive" do
|
|
|
61
61
|
model_class = Class.new do
|
|
62
62
|
include Lutaml::Model::Serialize
|
|
63
63
|
end
|
|
64
|
-
model_class.namespace(test_namespace)
|
|
64
|
+
expect { model_class.namespace(test_namespace) }.to output.to_stderr
|
|
65
65
|
|
|
66
66
|
expect(model_class.namespace_uri).to eq("https://example.com/model")
|
|
67
67
|
end
|
|
@@ -80,7 +80,7 @@ RSpec.describe Lutaml::Model::Serializable, "namespace directive" do
|
|
|
80
80
|
model_class = Class.new do
|
|
81
81
|
include Lutaml::Model::Serialize
|
|
82
82
|
end
|
|
83
|
-
model_class.namespace(test_namespace)
|
|
83
|
+
expect { model_class.namespace(test_namespace) }.to output.to_stderr
|
|
84
84
|
|
|
85
85
|
expect(model_class.namespace_prefix).to eq("model")
|
|
86
86
|
end
|
|
@@ -103,7 +103,7 @@ RSpec.describe Lutaml::Model::Serializable, "namespace directive" do
|
|
|
103
103
|
attribute :value, :integer
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
model_class.namespace(test_namespace)
|
|
106
|
+
expect { model_class.namespace(test_namespace) }.to output.to_stderr
|
|
107
107
|
|
|
108
108
|
expect(model_class.namespace).to eq(test_namespace)
|
|
109
109
|
expect(model_class.attributes.keys).to include(:name, :value)
|
|
@@ -113,7 +113,7 @@ RSpec.describe Lutaml::Model::Serializable, "namespace directive" do
|
|
|
113
113
|
parent_class = Class.new do
|
|
114
114
|
include Lutaml::Model::Serialize
|
|
115
115
|
end
|
|
116
|
-
parent_class.namespace(test_namespace)
|
|
116
|
+
expect { parent_class.namespace(test_namespace) }.to output.to_stderr
|
|
117
117
|
|
|
118
118
|
child_class = Class.new(parent_class)
|
|
119
119
|
|
|
@@ -453,7 +453,7 @@ RSpec.describe "Type Namespace Examples" do
|
|
|
453
453
|
serialized = props.to_xml
|
|
454
454
|
|
|
455
455
|
# xsi:type attribute should use xsi: namespace from XsiTypeType
|
|
456
|
-
expect(serialized).to
|
|
456
|
+
expect(serialized).to include('xsi:type="dcterms:W3CDTF"')
|
|
457
457
|
end
|
|
458
458
|
|
|
459
459
|
it "handles multiple Type namespaces in single document" do
|
|
@@ -189,8 +189,8 @@ RSpec.describe "Type-level namespace integration" do
|
|
|
189
189
|
expect(xml).to include('id="doc1"')
|
|
190
190
|
expect(xml).to include('title="Test"')
|
|
191
191
|
# Should not have any namespace prefix
|
|
192
|
-
expect(xml).not_to
|
|
193
|
-
expect(xml).not_to
|
|
192
|
+
expect(xml).not_to include(":id=")
|
|
193
|
+
expect(xml).not_to include(":title=")
|
|
194
194
|
end
|
|
195
195
|
end
|
|
196
196
|
|
|
@@ -268,11 +268,11 @@ RSpec.describe "Type-level namespace integration" do
|
|
|
268
268
|
document_class = Class.new do
|
|
269
269
|
include Lutaml::Model::Serialize
|
|
270
270
|
|
|
271
|
-
namespace model_namespace
|
|
272
271
|
attribute :special_field, special_type
|
|
273
272
|
|
|
274
273
|
xml do
|
|
275
274
|
element "document"
|
|
275
|
+
namespace model_namespace
|
|
276
276
|
map_element "special_field", to: :special_field
|
|
277
277
|
end
|
|
278
278
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "lutaml/yamlld"
|
|
5
|
+
|
|
6
|
+
RSpec.describe Lutaml::YamlLd::Adapter do
|
|
7
|
+
let(:yamlld_hash) do
|
|
8
|
+
{
|
|
9
|
+
"@context" => { "name" => "http://example.org/name" },
|
|
10
|
+
"@type" => "Thing",
|
|
11
|
+
"name" => "test",
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe ".parse" do
|
|
16
|
+
it "parses valid YAML-LD string to hash" do
|
|
17
|
+
yaml = YAML.dump(yamlld_hash)
|
|
18
|
+
result = described_class.parse(yaml)
|
|
19
|
+
expect(result).to eq(yamlld_hash)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "#to_yamlld" do
|
|
24
|
+
it "generates YAML-LD string from hash" do
|
|
25
|
+
adapter = described_class.new(yamlld_hash)
|
|
26
|
+
result = adapter.to_yamlld
|
|
27
|
+
parsed = YAML.safe_load(result)
|
|
28
|
+
expect(parsed["@context"]).to eq({ "name" => "http://example.org/name" })
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "round-trips parse → generate" do
|
|
33
|
+
yaml = YAML.dump(yamlld_hash)
|
|
34
|
+
parsed = described_class.parse(yaml)
|
|
35
|
+
adapter = described_class.new(parsed)
|
|
36
|
+
result = adapter.to_yamlld
|
|
37
|
+
round_tripped = YAML.safe_load(result)
|
|
38
|
+
expect(round_tripped).to eq(yamlld_hash)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "safe_load enforcement" do
|
|
42
|
+
it "rejects YAML with disallowed class tags" do
|
|
43
|
+
unsafe = "--- !ruby/object:Object {}\n"
|
|
44
|
+
expect do
|
|
45
|
+
described_class.parse(unsafe)
|
|
46
|
+
end.to raise_error(Psych::DisallowedClass)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "rejects malformed YAML with Psych::SyntaxError" do
|
|
50
|
+
malformed = "@context: [unterminated"
|
|
51
|
+
expect do
|
|
52
|
+
described_class.parse(malformed)
|
|
53
|
+
end.to raise_error(Psych::SyntaxError)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "lutaml/jsonld"
|
|
5
|
+
require "lutaml/yamlld"
|
|
6
|
+
|
|
7
|
+
RSpec.describe ":yamlld format registration" do
|
|
8
|
+
it "is registered with FormatRegistry as an RDF format" do
|
|
9
|
+
expect(Lutaml::Model::FormatRegistry.rdf_formats).to include(:yamlld)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "uses Rdf::Mapping as the mapping class" do
|
|
13
|
+
expect(Lutaml::Model::FormatRegistry.mappings_class_for(:yamlld))
|
|
14
|
+
.to eq(Lutaml::Rdf::Mapping)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "uses YamlLd::Adapter as the adapter class" do
|
|
18
|
+
expect(Lutaml::Model::FormatRegistry.adapter_class_for(:yamlld))
|
|
19
|
+
.to eq(Lutaml::YamlLd::Adapter)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "shares LinkedDataTransform with :jsonld" do
|
|
23
|
+
expect(Lutaml::Model::FormatRegistry.transformer_for(:yamlld))
|
|
24
|
+
.to eq(Lutaml::Rdf::LinkedDataTransform)
|
|
25
|
+
expect(Lutaml::Model::FormatRegistry.transformer_for(:yamlld))
|
|
26
|
+
.to eq(Lutaml::Model::FormatRegistry.transformer_for(:jsonld))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "declares Psych::SyntaxError as a parse error type" do
|
|
30
|
+
expect(Lutaml::Model::FormatRegistry.error_types_for(:yamlld))
|
|
31
|
+
.to include("Psych::SyntaxError")
|
|
32
|
+
end
|
|
33
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lutaml-model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.17
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -322,9 +322,6 @@ files:
|
|
|
322
322
|
- lib/lutaml/jsonl/adapter/transform.rb
|
|
323
323
|
- lib/lutaml/jsonld.rb
|
|
324
324
|
- lib/lutaml/jsonld/adapter.rb
|
|
325
|
-
- lib/lutaml/jsonld/context.rb
|
|
326
|
-
- lib/lutaml/jsonld/term_definition.rb
|
|
327
|
-
- lib/lutaml/jsonld/transform.rb
|
|
328
325
|
- lib/lutaml/key_value.rb
|
|
329
326
|
- lib/lutaml/key_value/adapter.rb
|
|
330
327
|
- lib/lutaml/key_value/adapter/hash.rb
|
|
@@ -607,9 +604,11 @@ files:
|
|
|
607
604
|
- lib/lutaml/model/yaml.rb
|
|
608
605
|
- lib/lutaml/model/yamls.rb
|
|
609
606
|
- lib/lutaml/rdf.rb
|
|
607
|
+
- lib/lutaml/rdf/context.rb
|
|
610
608
|
- lib/lutaml/rdf/error.rb
|
|
611
609
|
- lib/lutaml/rdf/iri.rb
|
|
612
610
|
- lib/lutaml/rdf/language_tagged.rb
|
|
611
|
+
- lib/lutaml/rdf/linked_data_transform.rb
|
|
613
612
|
- lib/lutaml/rdf/literal.rb
|
|
614
613
|
- lib/lutaml/rdf/mapping.rb
|
|
615
614
|
- lib/lutaml/rdf/mapping_rule.rb
|
|
@@ -623,6 +622,7 @@ files:
|
|
|
623
622
|
- lib/lutaml/rdf/namespaces/rdfs_namespace.rb
|
|
624
623
|
- lib/lutaml/rdf/namespaces/skos_namespace.rb
|
|
625
624
|
- lib/lutaml/rdf/namespaces/xsd_namespace.rb
|
|
625
|
+
- lib/lutaml/rdf/term_definition.rb
|
|
626
626
|
- lib/lutaml/rdf/transform.rb
|
|
627
627
|
- lib/lutaml/toml.rb
|
|
628
628
|
- lib/lutaml/toml/adapter.rb
|
|
@@ -853,6 +853,8 @@ files:
|
|
|
853
853
|
- lib/lutaml/yaml/schema.rb
|
|
854
854
|
- lib/lutaml/yaml/schema/yaml_schema.rb
|
|
855
855
|
- lib/lutaml/yaml/type/serializers.rb
|
|
856
|
+
- lib/lutaml/yamlld.rb
|
|
857
|
+
- lib/lutaml/yamlld/adapter.rb
|
|
856
858
|
- lib/lutaml/yamls.rb
|
|
857
859
|
- lib/lutaml/yamls/adapter.rb
|
|
858
860
|
- lib/lutaml/yamls/adapter/document.rb
|
|
@@ -1560,9 +1562,6 @@ files:
|
|
|
1560
1562
|
- spec/lutaml/integration/multi_format_spec.rb
|
|
1561
1563
|
- spec/lutaml/integration/round_trip_spec.rb
|
|
1562
1564
|
- spec/lutaml/jsonld/adapter_spec.rb
|
|
1563
|
-
- spec/lutaml/jsonld/context_spec.rb
|
|
1564
|
-
- spec/lutaml/jsonld/term_definition_spec.rb
|
|
1565
|
-
- spec/lutaml/jsonld/transform_spec.rb
|
|
1566
1565
|
- spec/lutaml/key_value/transformation/collection_serializer_spec.rb
|
|
1567
1566
|
- spec/lutaml/key_value/transformation/rule_compiler_spec.rb
|
|
1568
1567
|
- spec/lutaml/key_value/transformation/value_serializer_spec.rb
|
|
@@ -1573,6 +1572,7 @@ files:
|
|
|
1573
1572
|
- spec/lutaml/model/attribute_spec.rb
|
|
1574
1573
|
- spec/lutaml/model/cached_type_resolver_spec.rb
|
|
1575
1574
|
- spec/lutaml/model/cdata_spec.rb
|
|
1575
|
+
- spec/lutaml/model/choice_restrict_spec.rb
|
|
1576
1576
|
- spec/lutaml/model/choice_spec.rb
|
|
1577
1577
|
- spec/lutaml/model/cli_spec.rb
|
|
1578
1578
|
- spec/lutaml/model/collection_index_spec.rb
|
|
@@ -1714,8 +1714,10 @@ files:
|
|
|
1714
1714
|
- spec/lutaml/model/yamls_sequence_spec.rb
|
|
1715
1715
|
- spec/lutaml/model/yamls_spec.rb
|
|
1716
1716
|
- spec/lutaml/model_spec.rb
|
|
1717
|
+
- spec/lutaml/rdf/context_spec.rb
|
|
1717
1718
|
- spec/lutaml/rdf/graph_serialization_spec.rb
|
|
1718
1719
|
- spec/lutaml/rdf/iri_spec.rb
|
|
1720
|
+
- spec/lutaml/rdf/linked_data_transform_spec.rb
|
|
1719
1721
|
- spec/lutaml/rdf/literal_spec.rb
|
|
1720
1722
|
- spec/lutaml/rdf/mapping_rule_spec.rb
|
|
1721
1723
|
- spec/lutaml/rdf/mapping_spec.rb
|
|
@@ -1723,6 +1725,7 @@ files:
|
|
|
1723
1725
|
- spec/lutaml/rdf/namespace_set_spec.rb
|
|
1724
1726
|
- spec/lutaml/rdf/namespace_spec.rb
|
|
1725
1727
|
- spec/lutaml/rdf/rdf_transform_spec.rb
|
|
1728
|
+
- spec/lutaml/rdf/term_definition_spec.rb
|
|
1726
1729
|
- spec/lutaml/turtle/adapter_spec.rb
|
|
1727
1730
|
- spec/lutaml/turtle/mapping_spec.rb
|
|
1728
1731
|
- spec/lutaml/turtle/transform_spec.rb
|
|
@@ -1849,6 +1852,8 @@ files:
|
|
|
1849
1852
|
- spec/lutaml/xml/xml_space_spec.rb
|
|
1850
1853
|
- spec/lutaml/xml/xml_space_type_spec.rb
|
|
1851
1854
|
- spec/lutaml/xml/xml_spec.rb
|
|
1855
|
+
- spec/lutaml/yamlld/adapter_spec.rb
|
|
1856
|
+
- spec/lutaml/yamlld/registration_spec.rb
|
|
1852
1857
|
- spec/parent_root_spec.rb
|
|
1853
1858
|
- spec/person_spec.rb
|
|
1854
1859
|
- spec/sample_model_spec.rb
|