yaml-ld 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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('.')
|