yaml-ld 0.0.1 → 0.0.2
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/VERSION +1 -1
- data/lib/psych/amazing_print.rb +61 -0
- data/lib/yaml_ld/api.rb +69 -11
- data/lib/yaml_ld/format.rb +25 -0
- data/lib/yaml_ld/reader.rb +3 -1
- data/lib/yaml_ld/representation.rb +256 -0
- data/lib/yaml_ld/version.rb +1 -1
- data/lib/yaml_ld.rb +1 -0
- data/spec/api_spec.rb +21 -27
- data/spec/compact_spec.rb +1 -1
- data/spec/expand_spec.rb +1 -1
- data/spec/format_spec.rb +56 -0
- data/spec/frame_spec.rb +55 -110
- data/spec/from_rdf_spec.rb +3 -3
- data/spec/matchers.rb +2 -2
- data/spec/reader_spec.rb +1 -1
- data/spec/representation_spec.rb +170 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/test-files/test-1-compacted.yamlld +9 -0
- data/spec/test-files/test-1-context.yamlld +6 -0
- data/spec/test-files/test-1-expanded.yamlld +8 -0
- data/spec/test-files/test-1-input.yamlld +1 -0
- data/spec/test-files/test-2-compacted.yamlld +17 -0
- data/spec/test-files/test-2-context.yamlld +5 -0
- data/spec/test-files/test-2-expanded.yamlld +21 -0
- data/spec/test-files/test-3-compacted.yamlld +14 -0
- data/spec/test-files/test-3-context.yamlld +11 -0
- data/spec/test-files/test-3-expanded.yamlld +9 -0
- data/spec/test-files/test-4-compacted.yamlld +10 -0
- data/spec/test-files/test-4-context.yamlld +5 -0
- data/spec/test-files/test-4-expanded.yamlld +9 -0
- data/spec/test-files/test-5-compacted.yamlld +11 -0
- data/spec/test-files/test-5-context.yamlld +5 -0
- data/spec/test-files/test-5-expanded.yamlld +12 -0
- data/spec/test-files/test-6-compacted.yamlld +13 -0
- data/spec/test-files/test-6-context.yamlld +5 -0
- data/spec/test-files/test-6-expanded.yamlld +12 -0
- data/spec/test-files/test-7-compacted.yamlld +17 -0
- data/spec/test-files/test-7-context.yamlld +4 -0
- data/spec/test-files/test-7-expanded.yamlld +23 -0
- data/spec/test-files/test-8-compacted.yamlld +25 -0
- data/spec/test-files/test-8-context.yamlld +12 -0
- data/spec/test-files/test-8-expanded.yamlld +23 -0
- data/spec/test-files/test-8-frame.yamlld +15 -0
- data/spec/test-files/test-8-framed.yamlld +22 -0
- data/spec/test-files/test-9-compacted.yamlld +31 -0
- data/spec/test-files/test-9-context.yamlld +20 -0
- data/spec/test-files/test-9-expanded.yamlld +17 -0
- data/spec/to_rdf_spec.rb +10 -8
- metadata +89 -61
- data/spec/test-files/test-1-expanded.jsonld +0 -5
- data/spec/test-files/test-2-compacted.jsonld +0 -20
- data/spec/test-files/test-2-context.jsonld +0 -7
- data/spec/test-files/test-2-expanded.jsonld +0 -16
- data/spec/test-files/test-3-compacted.jsonld +0 -11
- data/spec/test-files/test-3-context.jsonld +0 -8
- data/spec/test-files/test-3-expanded.jsonld +0 -10
- data/spec/test-files/test-4-compacted.jsonld +0 -10
- data/spec/test-files/test-4-context.jsonld +0 -7
- data/spec/test-files/test-4-expanded.jsonld +0 -6
- data/spec/test-files/test-5-compacted.jsonld +0 -13
- data/spec/test-files/test-5-context.jsonld +0 -7
- data/spec/test-files/test-5-expanded.jsonld +0 -9
- data/spec/test-files/test-6-compacted.jsonld +0 -10
- data/spec/test-files/test-6-context.jsonld +0 -7
- data/spec/test-files/test-6-expanded.jsonld +0 -10
- data/spec/test-files/test-7-compacted.jsonld +0 -23
- data/spec/test-files/test-7-context.jsonld +0 -4
- data/spec/test-files/test-7-expanded.jsonld +0 -20
- data/spec/test-files/test-8-compacted.jsonld +0 -34
- data/spec/test-files/test-8-context.jsonld +0 -11
- data/spec/test-files/test-8-expanded.jsonld +0 -24
- data/spec/test-files/test-8-frame.jsonld +0 -18
- data/spec/test-files/test-8-framed.jsonld +0 -25
- data/spec/test-files/test-9-compacted.jsonld +0 -20
- data/spec/test-files/test-9-context.jsonld +0 -13
- data/spec/test-files/test-9-expanded.jsonld +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1da1570067d55e5cf71f757cfb5a2e2d8313dc9f63fe045bafde65dcb220a02
|
4
|
+
data.tar.gz: '0096c9115d43889554b3e7f6d7ac92d7c8b94b4adce85d8b811f0321186d9dd0'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea19a5310f145f5abb060fd54903f42312a60d197a268ec3a66ba4421ed0497e3f93b1b8b930cda9797bc00aa92d18d9ca1fb7a633cdf9bf7f37bcac1cc50426
|
7
|
+
data.tar.gz: a861b85988b30f42bb3afdf7d2ecae69663ca069081b4921303c07c72bc17bc19d4fea27c21ce8a2d027b256a5079581deeb5c9dc0a864fe95edd5420b9a8b8b
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Amazing Print extensions for Psych
|
4
|
+
#------------------------------------------------------------------------------
|
5
|
+
module AmazingPrint
|
6
|
+
module Psych
|
7
|
+
def self.included(base)
|
8
|
+
base.send :alias_method, :cast_without_psych, :cast
|
9
|
+
base.send :alias_method, :cast, :cast_with_psych
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add Psych Node names to the dispatcher pipeline.
|
13
|
+
#------------------------------------------------------------------------------
|
14
|
+
def cast_with_psych(object, type)
|
15
|
+
cast = cast_without_psych(object, type)
|
16
|
+
if (defined?(::Psych::Nodes::Node) && object.is_a?(::Psych::Nodes::Node))
|
17
|
+
cast = :psych_node
|
18
|
+
end
|
19
|
+
cast
|
20
|
+
end
|
21
|
+
|
22
|
+
STYLES = %w(ANY BLOCK FLOW) #------------------------------------------------------------------------------
|
23
|
+
def awesome_psych_node(object)
|
24
|
+
contents = []
|
25
|
+
contents << colorize(object.class.name.split('::').last, :class)
|
26
|
+
contents << colorize("!<#{object.tag}>", :args) if object.tag
|
27
|
+
contents << colorize("&#{object.anchor}", :args) if object.respond_to?(:anchor) && object.anchor
|
28
|
+
contents << colorize("(implicit)", :args) if object.respond_to?(:implicit) && object.implicit
|
29
|
+
contents << colorize("(implicit end)", :args) if object.respond_to?(:implicit_end) && object.implicit_end
|
30
|
+
case object
|
31
|
+
when ::Psych::Nodes::Stream
|
32
|
+
contents << awesome_array(object.children)
|
33
|
+
when ::Psych::Nodes::Document
|
34
|
+
contents << colorize('%TAG(' + object.tag_directives.flatten.join(' ') + ')', :args) unless Array(object.tag_directives).empty?
|
35
|
+
contents << colorize("version #{object.version.join('.')}", :args) if object.version
|
36
|
+
contents << awesome_array(object.children)
|
37
|
+
when ::Psych::Nodes::Sequence
|
38
|
+
style = %w(ANY BLOCK FLOW)[object.style.to_i]
|
39
|
+
contents << awesome_array(object.children)
|
40
|
+
when ::Psych::Nodes::Mapping
|
41
|
+
style = %w(ANY BLOCK FLOW)[object.style.to_i]
|
42
|
+
contents << colorize(style, :args) if object.style
|
43
|
+
contents << awesome_hash(object.children.each_slice(2).to_h)
|
44
|
+
when ::Psych::Nodes::Scalar
|
45
|
+
style = %w(ANY PLAIN SINGLE_QUOTED DOUBLE_QUOTED LITERAL FOLDED)[object.style.to_i]
|
46
|
+
contents << colorize(style, :args) if object.style
|
47
|
+
contents << colorize("(plain)", :args) if object.plain
|
48
|
+
contents << colorize("(quoted)", :args) if object.quoted
|
49
|
+
contents << awesome_simple(object.value.inspect, :variable)
|
50
|
+
when ::Psych::Nodes::Alias
|
51
|
+
# No children
|
52
|
+
else
|
53
|
+
"Unknown node type: #{object.inspect}"
|
54
|
+
end
|
55
|
+
|
56
|
+
contents.join(' ')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
AmazingPrint::Formatter.include AmazingPrint::Psych
|
data/lib/yaml_ld/api.rb
CHANGED
@@ -9,7 +9,6 @@ module YAML_LD
|
|
9
9
|
# @see https://www.w3.org/TR/json-ld11-api/#the-application-programming-interface
|
10
10
|
# @author [Gregg Kellogg](http://greggkellogg.net/)
|
11
11
|
class API < ::JSON::LD::API
|
12
|
-
|
13
12
|
# The following constants are used to reduce object allocations
|
14
13
|
LINK_REL_CONTEXT = %w(rel http://www.w3.org/ns/yaml-ld#context).freeze
|
15
14
|
LINK_REL_ALTERNATE = %w(rel alternate).freeze
|
@@ -30,6 +29,35 @@ module YAML_LD
|
|
30
29
|
# A Serializer method used for generating the YAML serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to YAML externally via `#to_yaml`.
|
31
30
|
# See {YAML_LD::API.serializer}.
|
32
31
|
# @param [Hash{Symbol => Object}] options
|
32
|
+
# @option options [RDF::URI, String, #to_s] :base
|
33
|
+
# The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context. If not specified, and a base IRI is found from `input`, options[:base] will be modified with this value.
|
34
|
+
# @option options [Boolean] :compactArrays (true)
|
35
|
+
# If set to `true`, the JSON-LD processor replaces arrays with just one element with that element during compaction. If set to `false`, all arrays will remain arrays even if they have just one element.
|
36
|
+
# @option options [Boolean] :compactToRelative (true)
|
37
|
+
# Creates document relative IRIs when compacting, if `true`, otherwise leaves expanded.
|
38
|
+
# @option options [Proc] :documentLoader
|
39
|
+
# The callback of the loader to be used to retrieve remote documents and contexts. If specified, it must be used to retrieve remote documents and contexts; otherwise, if not specified, the processor's built-in loader must be used. See {documentLoader} for the method signature.
|
40
|
+
# @option options [String, #read, Hash, Array, JSON::LD::Context] :expandContext
|
41
|
+
# A context that is used to initialize the active context when expanding a document.
|
42
|
+
# @option options [Boolean] :extendedYAML (false)
|
43
|
+
# Use the expanded internal representation.
|
44
|
+
# @option options [Boolean] :extractAllScripts
|
45
|
+
# If set, when given an HTML input without a fragment identifier, extracts all `script` elements with type `application/ld+json` into an array during expansion.
|
46
|
+
# @option options [Boolean, String, RDF::URI] :flatten
|
47
|
+
# If set to a value that is not `false`, the JSON-LD processor must modify the output of the Compaction Algorithm or the Expansion Algorithm by coalescing all properties associated with each subject via the Flattening Algorithm. The value of `flatten must` be either an _IRI_ value representing the name of the graph to flatten, or `true`. If the value is `true`, then the first graph encountered in the input document is selected and flattened.
|
48
|
+
# @option options [String] :language
|
49
|
+
# When set, this has the effect of inserting a context definition with `@language` set to the associated value, creating a default language for interpreting string values.
|
50
|
+
# @option options [Boolean] :lowercaseLanguage
|
51
|
+
# By default, language tags are left as is. To normalize to lowercase, set this option to `true`.
|
52
|
+
# @option options [Boolean] :ordered (true)
|
53
|
+
# Order traversal of dictionary members by key when performing algorithms.
|
54
|
+
# @option options [Boolean] :rdfstar (false)
|
55
|
+
# support parsing JSON-LD-star statement resources.
|
56
|
+
# @option options [Boolean] :rename_bnodes (true)
|
57
|
+
# Rename bnodes as part of expansion, or keep them the same.
|
58
|
+
# @option options [Boolean] :unique_bnodes (false)
|
59
|
+
# Use unique bnode identifiers, defaults to using the identifier which the node was originally initialized with (if any).
|
60
|
+
# @option options [Boolean] :validate Validate input, if a string or readable object.
|
33
61
|
# @raise [JsonLdError]
|
34
62
|
# @yield YAML_LD, base_iri
|
35
63
|
# @yieldparam [Array<Hash>] yamlld
|
@@ -46,7 +74,10 @@ module YAML_LD
|
|
46
74
|
**options,
|
47
75
|
&block)
|
48
76
|
JSON::LD::API.expand(input,
|
77
|
+
allowed_content_types: %r(application/(.+\+)?yaml),
|
49
78
|
documentLoader: documentLoader,
|
79
|
+
extendedRepresentation: options[:extendedYAML],
|
80
|
+
processingMode: 'json-ld-1.1',
|
50
81
|
serializer: serializer,
|
51
82
|
**options,
|
52
83
|
&block)
|
@@ -68,7 +99,7 @@ module YAML_LD
|
|
68
99
|
# See {YAML_LD::API.serializer}.
|
69
100
|
# @param [Boolean] expanded (false) Input is already expanded
|
70
101
|
# @param [Hash{Symbol => Object}] options
|
71
|
-
# @option options (see
|
102
|
+
# @option options (see expand)
|
72
103
|
# @yield YAML_LD
|
73
104
|
# @yieldparam [Array<Hash>] yamlld
|
74
105
|
# The expanded YAML-LD document
|
@@ -83,7 +114,10 @@ module YAML_LD
|
|
83
114
|
**options,
|
84
115
|
&block)
|
85
116
|
JSON::LD::API.compact(input, context, expanded: expanded,
|
117
|
+
allowed_content_types: %r(application/(.+\+)?yaml),
|
86
118
|
documentLoader: documentLoader,
|
119
|
+
extendedRepresentation: options[:extendedYAML],
|
120
|
+
processingMode: 'json-ld-1.1',
|
87
121
|
serializer: serializer,
|
88
122
|
**options,
|
89
123
|
&block)
|
@@ -103,9 +137,11 @@ module YAML_LD
|
|
103
137
|
# A Serializer method used for generating the YAML serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to YAML externally via `#to_yaml`.
|
104
138
|
# See {YAML_LD::API.serializer}.
|
105
139
|
# @param [Hash{Symbol => Object}] options
|
106
|
-
# @option options (see
|
140
|
+
# @option options (see expand)
|
107
141
|
# @option options [Boolean] :createAnnotations
|
108
142
|
# Unfold embedded nodes which can be represented using `@annotation`.
|
143
|
+
# @option options [Boolean] :extendedYAML (false)
|
144
|
+
# Use the expanded internal representation.
|
109
145
|
# @yield YAML_LD
|
110
146
|
# @yieldparam [Array<Hash>] yamlld
|
111
147
|
# The expanded YAML-LD document
|
@@ -119,7 +155,10 @@ module YAML_LD
|
|
119
155
|
**options,
|
120
156
|
&block)
|
121
157
|
JSON::LD::API.flatten(input, context, expanded: expanded,
|
158
|
+
allowed_content_types: %r(application/(.+\+)?yaml),
|
122
159
|
documentLoader: documentLoader,
|
160
|
+
extendedRepresentation: options[:extendedYAML],
|
161
|
+
processingMode: 'json-ld-1.1',
|
123
162
|
serializer: serializer,
|
124
163
|
**options,
|
125
164
|
&block)
|
@@ -135,11 +174,13 @@ module YAML_LD
|
|
135
174
|
# @param [String, #read, Hash, Array] frame
|
136
175
|
# The frame to use when re-arranging the data.
|
137
176
|
# @param [Boolean] expanded (false) Input is already expanded
|
138
|
-
# @option options (see
|
177
|
+
# @option options (see expand)
|
139
178
|
# @option options ['@always', '@link', '@once', '@never'] :embed ('@once')
|
140
179
|
# a flag specifying that objects should be directly embedded in the output, instead of being referred to by their IRI.
|
141
180
|
# @option options [Boolean] :explicit (false)
|
142
181
|
# a flag specifying that for properties to be included in the output, they must be explicitly declared in the framing context.
|
182
|
+
# @option options [Boolean] :extendedYAML (false)
|
183
|
+
# Use the expanded internal representation.
|
143
184
|
# @option options [Boolean] :requireAll (false)
|
144
185
|
# A flag specifying that all properties present in the input frame must either have a default value or be present in the JSON-LD input for the frame to match.
|
145
186
|
# @option options [Boolean] :omitDefault (false)
|
@@ -160,7 +201,10 @@ module YAML_LD
|
|
160
201
|
**options,
|
161
202
|
&block)
|
162
203
|
JSON::LD::API.frame(input, frame, expanded: expanded,
|
204
|
+
allowed_content_types: %r(application/(.+\+)?yaml),
|
163
205
|
documentLoader: documentLoader,
|
206
|
+
extendedRepresentation: options[:extendedYAML],
|
207
|
+
processingMode: 'json-ld-1.1',
|
164
208
|
serializer: serializer,
|
165
209
|
**options,
|
166
210
|
&block)
|
@@ -172,7 +216,9 @@ module YAML_LD
|
|
172
216
|
# @param [String, #read, Hash, Array] input
|
173
217
|
# The YAML-LD object to process when outputting statements.
|
174
218
|
# @param [Boolean] expanded (false) Input is already expanded
|
175
|
-
# @option options (see
|
219
|
+
# @option options (see expand)
|
220
|
+
# @option options [Boolean] :extendedYAML (false)
|
221
|
+
# Use the expanded internal representation.
|
176
222
|
# @option options [Boolean] :produceGeneralizedRdf (false)
|
177
223
|
# If true, output will include statements having blank node predicates, otherwise they are dropped.
|
178
224
|
# @raise [JsonLdError]
|
@@ -184,7 +230,10 @@ module YAML_LD
|
|
184
230
|
**options,
|
185
231
|
&block)
|
186
232
|
JSON::LD::API.toRdf(input, expanded: expanded,
|
233
|
+
allowed_content_types: %r(application/(.+\+)?yaml),
|
187
234
|
documentLoader: documentLoader,
|
235
|
+
extendedRepresentation: options[:extendedYAML],
|
236
|
+
processingMode: 'json-ld-1.1',
|
188
237
|
**options,
|
189
238
|
&block)
|
190
239
|
end
|
@@ -202,7 +251,9 @@ module YAML_LD
|
|
202
251
|
# A Serializer method used for generating the YAML serialization of the result. If absent, the internal Ruby objects are returned, which can be transformed to YAML externally via `#to_yaml`.
|
203
252
|
# See {YAML_LD::API.serializer}.
|
204
253
|
# @param [Hash{Symbol => Object}] options
|
205
|
-
# @option options (see
|
254
|
+
# @option options (see expand)
|
255
|
+
# @option options [Boolean] :extendedYAML (false)
|
256
|
+
# Use the expanded internal representation.
|
206
257
|
# @yield jsonld
|
207
258
|
# @yieldparam [Hash] jsonld
|
208
259
|
# The JSON-LD document in expanded form
|
@@ -215,10 +266,13 @@ module YAML_LD
|
|
215
266
|
**options,
|
216
267
|
&block)
|
217
268
|
JSON::LD::API.fromRdf(input,
|
218
|
-
|
219
|
-
useNativeTypes: useNativeTypes,
|
269
|
+
allowed_content_types: %r(application/(.+\+)?yaml),
|
220
270
|
documentLoader: documentLoader,
|
271
|
+
extendedRepresentation: options[:extendedYAML],
|
272
|
+
processingMode: 'json-ld-1.1',
|
221
273
|
serializer: serializer,
|
274
|
+
useRdfType: useRdfType,
|
275
|
+
useNativeTypes: useNativeTypes,
|
222
276
|
**options,
|
223
277
|
&block)
|
224
278
|
end
|
@@ -257,7 +311,7 @@ module YAML_LD
|
|
257
311
|
content = case content_type
|
258
312
|
when nil, %r(application/(\w+\+)*yaml)
|
259
313
|
# Parse YAML
|
260
|
-
|
314
|
+
Representation.load(url.read, filename: url.to_s, **options)
|
261
315
|
else
|
262
316
|
url.read
|
263
317
|
end
|
@@ -267,7 +321,11 @@ module YAML_LD
|
|
267
321
|
contextUrl: context_url))
|
268
322
|
elsif url.to_s.match?(/\.yaml\w*$/) || content_type.to_s.match?(%r(application/(\w+\+)*yaml))
|
269
323
|
# Parse YAML
|
270
|
-
|
324
|
+
content = Representation.load(RDF::Util::File.open_file(url.to_s).read,
|
325
|
+
filename: url.to_s,
|
326
|
+
**options)
|
327
|
+
|
328
|
+
block.call(RemoteDocument.new(content,
|
271
329
|
documentUrl: base_uri,
|
272
330
|
contentType: content_type,
|
273
331
|
contextUrl: context_url))
|
@@ -288,7 +346,7 @@ module YAML_LD
|
|
288
346
|
# options passed from the invoking context.
|
289
347
|
def self.serializer(object, *args, **options)
|
290
348
|
# de-alias any objects to avoid the use of aliases and anchors
|
291
|
-
"%YAML 1.2\n" +
|
349
|
+
"%YAML 1.2\n" + Representation.dump(object, **options)
|
292
350
|
end
|
293
351
|
end
|
294
352
|
end
|
data/lib/yaml_ld/format.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
|
+
require 'json/ld/format'
|
4
|
+
|
3
5
|
module YAML_LD
|
4
6
|
##
|
5
7
|
# YAML-LD format specification.
|
@@ -28,6 +30,25 @@ module YAML_LD
|
|
28
30
|
reader { YAML_LD::Reader }
|
29
31
|
writer { YAML_LD::Writer }
|
30
32
|
|
33
|
+
# Specify how to execute CLI commands for each supported format. These are added to the `LD_FORMATS` defined for `JSON::LD::Format`
|
34
|
+
# Derived formats (e.g., YAML-LD) define their own entrypoints.
|
35
|
+
LD_FORMATS = {
|
36
|
+
yamlld: {
|
37
|
+
expand: ->(input, **options) {
|
38
|
+
YAML_LD::API.expand(input, validate: false, **options)
|
39
|
+
},
|
40
|
+
compact: ->(input, **options) {
|
41
|
+
YAML_LD::API.compact(input, options[:context], **options)
|
42
|
+
},
|
43
|
+
flatten: ->(input, **options) {
|
44
|
+
YAML_LD::API.flatten(input, options[:context], **options)
|
45
|
+
},
|
46
|
+
frame: ->(input, **options) {
|
47
|
+
YAML_LD::API.frame(input, options[:frame], **options)
|
48
|
+
},
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
31
52
|
##
|
32
53
|
# Sample detection to see if it matches YAML-LD
|
33
54
|
#
|
@@ -54,3 +75,7 @@ module YAML_LD
|
|
54
75
|
end
|
55
76
|
end
|
56
77
|
end
|
78
|
+
|
79
|
+
|
80
|
+
# Load into JSON::LD::Format::LD_FORMATS
|
81
|
+
::JSON::LD::Format.const_get(:LD_FORMATS).merge!(::YAML_LD::Format::LD_FORMATS)
|
data/lib/yaml_ld/reader.rb
CHANGED
@@ -24,7 +24,9 @@ module YAML_LD
|
|
24
24
|
def initialize(input = $stdin,
|
25
25
|
documentLoader: YAML_LD::API.method(:documentLoader),
|
26
26
|
**options, &block)
|
27
|
-
input = StringIO.new(input)
|
27
|
+
input = StringIO.new(input).tap do |d|
|
28
|
+
d.define_singleton_method(:content_type) {'application/ld+yaml'}
|
29
|
+
end if input.is_a?(String)
|
28
30
|
super(input, documentLoader: documentLoader, **options, &block)
|
29
31
|
end
|
30
32
|
|
@@ -0,0 +1,256 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'psych'
|
4
|
+
require 'rdf/xsd'
|
5
|
+
|
6
|
+
module YAML_LD
|
7
|
+
##
|
8
|
+
# Transforms a Psych AST to the JSON-LD (extended) Internal Representation build using `Psych.parse`, `.parse_stream`, or `parse_file`.
|
9
|
+
#
|
10
|
+
# FIXME: Aliases
|
11
|
+
module Representation
|
12
|
+
###
|
13
|
+
# Load multiple documents given in +yaml+. Returns the parsed documents
|
14
|
+
# as a list. If a block is given, each document will be converted to Ruby
|
15
|
+
# and passed to the block during parsing
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
#
|
19
|
+
# load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
|
20
|
+
#
|
21
|
+
# list = []
|
22
|
+
# load_stream("--- foo\n...\n--- bar\n...") do |ruby|
|
23
|
+
# list << ruby
|
24
|
+
# end
|
25
|
+
# list # => ['foo', 'bar']
|
26
|
+
#
|
27
|
+
# @param [String] yaml
|
28
|
+
# @param [String] filename
|
29
|
+
# @param [Object] fallback
|
30
|
+
# @param [Hash{Symbol => Object}] options
|
31
|
+
# @return [Array<Object>]
|
32
|
+
def load_stream(yaml, filename: nil, fallback: [], **options)
|
33
|
+
result = if block_given?
|
34
|
+
Psych.parse_stream(yaml, filename: filename) do |node|
|
35
|
+
yield as_jsonld_ir(node, **options)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
as_jsonld_ir(Psych.parse_stream(yaml, filename: filename), **options)
|
39
|
+
end
|
40
|
+
|
41
|
+
result.is_a?(Array) && result.empty? ? fallback : result
|
42
|
+
end
|
43
|
+
module_function :load_stream
|
44
|
+
|
45
|
+
##
|
46
|
+
# Load a single document from +yaml+.
|
47
|
+
# @param (see load_stream)
|
48
|
+
# @return [Object]
|
49
|
+
def load(yaml, filename: nil, fallback: nil, **options)
|
50
|
+
result = if block_given?
|
51
|
+
load_stream(yaml, filename: filename, **options) do |node|
|
52
|
+
yield node.first
|
53
|
+
end
|
54
|
+
else
|
55
|
+
load_stream(yaml, filename: filename, **options).first
|
56
|
+
end
|
57
|
+
|
58
|
+
result || fallback
|
59
|
+
end
|
60
|
+
module_function :load
|
61
|
+
|
62
|
+
##
|
63
|
+
# Dump internal representaiton to YAML
|
64
|
+
#
|
65
|
+
# @option options[Boolean] :extendedYAML
|
66
|
+
# Allows the use of aliases and encodes RDF::Literals
|
67
|
+
def dump(ir, **options)
|
68
|
+
if options[:extendedYAML]
|
69
|
+
options = {
|
70
|
+
aliases: true,
|
71
|
+
permitted_classes: [RDF::Literal]
|
72
|
+
}.merge(options)
|
73
|
+
else
|
74
|
+
# Deep duplicate representation to avoid alias nodes
|
75
|
+
ir = deep_dup(ir)
|
76
|
+
end
|
77
|
+
visitor = Representation::IRTree.create(options)
|
78
|
+
visitor << ir
|
79
|
+
visitor.tree.yaml
|
80
|
+
end
|
81
|
+
module_function :dump
|
82
|
+
|
83
|
+
def deep_dup(obj)
|
84
|
+
case obj
|
85
|
+
when Array then obj.map {|e| deep_dup(e)}
|
86
|
+
when Hash then obj.inject({}) {|memo, (k,v)| memo.merge(k => deep_dup(v))}
|
87
|
+
else obj # No need to de-dup
|
88
|
+
end
|
89
|
+
end
|
90
|
+
module_function :deep_dup
|
91
|
+
|
92
|
+
##
|
93
|
+
# Transform a Psych::Nodes::Node to the JSON-LD Internal Representation
|
94
|
+
#
|
95
|
+
# @param [Psych::Nodes::Node] node
|
96
|
+
# @param [Hash{Symbol => Object}] options
|
97
|
+
# @option options [Boolean] :extendedYAML (false)
|
98
|
+
# Use the expanded internal representation.
|
99
|
+
# @return [Object]
|
100
|
+
def as_jsonld_ir(node, **options)
|
101
|
+
# Scans scalars for built-in classes
|
102
|
+
@ss ||= Psych::ScalarScanner.new(Psych::ClassLoader::Restricted.new([], %i()))
|
103
|
+
case node
|
104
|
+
when Psych::Nodes::Stream
|
105
|
+
node.children.map {|n| as_jsonld_ir(n, **options)}
|
106
|
+
when Psych::Nodes::Document then as_jsonld_ir(node.children.first, **options)
|
107
|
+
when Psych::Nodes::Sequence then node.children.map {|n| as_jsonld_ir(n, **options)}
|
108
|
+
when Psych::Nodes::Mapping
|
109
|
+
node.children.each_slice(2).inject({}) do |memo, (k,v)|
|
110
|
+
memo.merge(as_jsonld_ir(k) => as_jsonld_ir(v, **options))
|
111
|
+
end
|
112
|
+
when ::Psych::Nodes::Scalar then scan_scalar(node, **options)
|
113
|
+
when ::Psych::Nodes::Alias
|
114
|
+
# FIXME
|
115
|
+
end
|
116
|
+
end
|
117
|
+
module_function :as_jsonld_ir
|
118
|
+
|
119
|
+
##
|
120
|
+
# Scans a scalar value to a JSON-LD IR scalar value.
|
121
|
+
# Quoted scalar values are not interpreted.
|
122
|
+
#
|
123
|
+
# @param [Psych::Nodes::Scalar] node
|
124
|
+
# @param [Hash{Symbol => Object}] options
|
125
|
+
# @option options [Boolean] :extendedYAML (false)
|
126
|
+
# Use the expanded internal representation.
|
127
|
+
# @return [Object]
|
128
|
+
def scan_scalar(node, **options)
|
129
|
+
return node.value if node.quoted # No interpretation
|
130
|
+
case node.tag
|
131
|
+
when "", NilClass
|
132
|
+
# Tokenize, but prohibit certain types
|
133
|
+
case node.value
|
134
|
+
# Don't scan some scalar values to types other than string
|
135
|
+
when Psych::ScalarScanner::TIME,
|
136
|
+
/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/, # Date
|
137
|
+
/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/, # Time to seconds
|
138
|
+
/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/ # Time to seconds
|
139
|
+
node.value
|
140
|
+
else
|
141
|
+
@ss.tokenize(node.value)
|
142
|
+
end
|
143
|
+
when '!str', 'tag:yaml.org,2002:str'
|
144
|
+
node.value
|
145
|
+
when '!int', 'tag:yaml.org,2002:int'
|
146
|
+
Integer(node.value)
|
147
|
+
when "!float", "tag:yaml.org,2002:float"
|
148
|
+
Float(@ss.tokenize(node.value))
|
149
|
+
when "!null", "tag:yaml.org,2002:null"
|
150
|
+
nil
|
151
|
+
when "!bool", "tag:yaml.org,2002:bool"
|
152
|
+
node.value.downcase == 'true'
|
153
|
+
when %r(^https://www.w3.org/ns/i18n)
|
154
|
+
l_d = node.tag[26..-1]
|
155
|
+
l_d = l_d[1..-1] if l_d.start_with?('#')
|
156
|
+
l, d = l_d.split('_')
|
157
|
+
if !options[:extendedYAML]
|
158
|
+
(node.style== Psych::Nodes::Scalar::PLAIN ? @ss.tokenize(node.value) : node.value)
|
159
|
+
elsif d.nil?
|
160
|
+
# Just use language component
|
161
|
+
RDF::Literal(node.value, language: l)
|
162
|
+
else
|
163
|
+
# Language and direction
|
164
|
+
RDF::Literal(node.value, datatype: RDF::URI("https://www.w3.org/ns/i18n##{l_d}"))
|
165
|
+
end
|
166
|
+
else
|
167
|
+
tag = node.tag
|
168
|
+
options[:extendedYAML] ?
|
169
|
+
RDF::Literal(node.value, datatype: RDF::URI(tag), validate: true) :
|
170
|
+
(node.style== Psych::Nodes::Scalar::PLAIN ? @ss.tokenize(node.value) : node.value)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
module_function :scan_scalar
|
174
|
+
|
175
|
+
##
|
176
|
+
# Build a YAML AST with an RDF::Literal visitor
|
177
|
+
#
|
178
|
+
#
|
179
|
+
# builder = Psych::Visitors::YAMLTree.new
|
180
|
+
# builder << { :foo => 'bar' }
|
181
|
+
# builder.tree # => #<Psych::Nodes::Stream .. }
|
182
|
+
# builder.tree.yaml # => "..."
|
183
|
+
#
|
184
|
+
# @note Rails 6.0 not compatible with Psych 4.0, which defines `RestrictedYamlTree`.
|
185
|
+
class IRTree < (Psych::Visitors.const_defined?(:RestrictedYamlTree) ? Psych::Visitors::RestrictedYAMLTree : Psych::Visitors::YAMLTree)
|
186
|
+
##
|
187
|
+
# Retrive the literals from an object
|
188
|
+
def datatypes(object)
|
189
|
+
case object
|
190
|
+
when Array then object.inject([]) {|memo, o| memo += datatypes(o)}
|
191
|
+
when Hash then object.values.inject([]) {|memo, o| memo += datatypes(o)}
|
192
|
+
when RDF::Literal then object.datatype? ? [object.datatype] : []
|
193
|
+
else []
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
##
|
198
|
+
# Add the object to be emitted. If the `:extended` option is set when the visitor is created, tags are added to the document.
|
199
|
+
def push object
|
200
|
+
start unless started?
|
201
|
+
version = []
|
202
|
+
version = [1,1] if @options[:header]
|
203
|
+
|
204
|
+
case @options[:version]
|
205
|
+
when Array
|
206
|
+
version = @options[:version]
|
207
|
+
when String
|
208
|
+
version = @options[:version].split('.').map { |x| x.to_i }
|
209
|
+
else
|
210
|
+
version = [1,1]
|
211
|
+
end if @options.key? :version
|
212
|
+
|
213
|
+
dts = datatypes(object).uniq
|
214
|
+
tags = dts.inject({}) do |memo, dt|
|
215
|
+
# Find the most suitable voabulary, if any
|
216
|
+
if memo.keys.any? {|u| dt.to_s.start_with?(u)}
|
217
|
+
memo
|
218
|
+
# Already have a prefix for this
|
219
|
+
elsif vocab = RDF::Vocabulary.each.to_a.detect {|v| dt.to_s.index(v.to_uri.to_s) == 0}
|
220
|
+
# Index by vocabulary URI
|
221
|
+
memo.merge(vocab.to_uri.to_s => "!#{vocab.__prefix__}!")
|
222
|
+
else
|
223
|
+
memo
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
@emitter.start_document version, tags.invert.to_a, false
|
228
|
+
accept object
|
229
|
+
@emitter.end_document !@emitter.streaming?
|
230
|
+
end
|
231
|
+
alias :<< :push
|
232
|
+
|
233
|
+
##
|
234
|
+
# Emit an RDF Literal. If `extended` is set, use the datatype as an tag,
|
235
|
+
# otherwise, emit in expanded form.
|
236
|
+
def visit_RDF_Literal o
|
237
|
+
tag = case o.datatype
|
238
|
+
when nil then nil
|
239
|
+
when RDF::XSD.string then nil
|
240
|
+
when RDF.langString
|
241
|
+
"https://www.w3.org/ns/i18n##{o.language}" if @options[:extendedYAML]
|
242
|
+
else
|
243
|
+
if o.datatype.to_s.start_with?('https://www.w3.org/ns/i18n#')
|
244
|
+
o.datatype.to_s if @options[:extendedYAML]
|
245
|
+
elsif @options[:extendedYAML]
|
246
|
+
o.datatype.to_s
|
247
|
+
else
|
248
|
+
nil
|
249
|
+
end
|
250
|
+
end
|
251
|
+
formatted = o.value
|
252
|
+
register o, @emitter.scalar(formatted, nil, tag, false, false, Psych::Nodes::Scalar::PLAIN)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
data/lib/yaml_ld/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
3
|
module YAML_LD::VERSION
|
4
|
-
VERSION_FILE = File.
|
4
|
+
VERSION_FILE = File.expand_path("../../../VERSION", __FILE__)
|
5
5
|
MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
|
6
6
|
|
7
7
|
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|