lib/yaml_ld/representation.rb in yaml-ld-0.0.2 vs lib/yaml_ld/representation.rb in yaml-ld-0.0.3
- old
+ new
@@ -37,10 +37,20 @@
else
as_jsonld_ir(Psych.parse_stream(yaml, filename: filename), **options)
end
result.is_a?(Array) && result.empty? ? fallback : result
+ rescue Psych::SyntaxError => e
+ msg = filename ? "file: #{filename} #{e.message}" : e.message
+ if yaml.respond_to?(:read)
+ msg << "Content:\n" + yaml.tap(:rewind).read
+ end
+ if e.message.match?(/invalid leading UTF-8 octet/)
+ raise YAML_LD::Error::InvalidEncoding, msg
+ else
+ raise JSON::LD::JsonLdError::LoadingDocumentFailed, msg
+ end
end
module_function :load_stream
##
# Load a single document from +yaml+.
@@ -98,21 +108,49 @@
# Use the expanded internal representation.
# @return [Object]
def as_jsonld_ir(node, **options)
# Scans scalars for built-in classes
@ss ||= Psych::ScalarScanner.new(Psych::ClassLoader::Restricted.new([], %i()))
+
+ # Record in-scope anchors to check for circular alias references.
+ in_scope_anchors = options[:in_scope_anchors] ||= {}
+
case node
when Psych::Nodes::Stream
node.children.map {|n| as_jsonld_ir(n, **options)}
- when Psych::Nodes::Document then as_jsonld_ir(node.children.first, **options)
- when Psych::Nodes::Sequence then node.children.map {|n| as_jsonld_ir(n, **options)}
+ when Psych::Nodes::Document
+ as_jsonld_ir(node.children.first, named_nodes: {}, **options)
+ when Psych::Nodes::Sequence
+ value = []
+ if node.anchor
+ options = options.merge(in_scope_anchors: in_scope_anchors.merge(node.anchor => true))
+ options[:named_nodes][node.anchor] = value
+ end
+ node.children.each {|n| value << as_jsonld_ir(n, **options)}
+ value
when Psych::Nodes::Mapping
- node.children.each_slice(2).inject({}) do |memo, (k,v)|
- memo.merge(as_jsonld_ir(k) => as_jsonld_ir(v, **options))
+ value = {}
+ if node.anchor
+ options = options.merge(in_scope_anchors: in_scope_anchors.merge(node.anchor => true))
+ options[:named_nodes][node.anchor] = value
end
- when ::Psych::Nodes::Scalar then scan_scalar(node, **options)
+ node.children.each_slice(2) do |k, v|
+ key = as_jsonld_ir(k)
+ raise YAML_LD::Error::MappingKeyError, "mapping key #{k} (#{key.inspect}) not a string" unless key.is_a?(String)
+ value[as_jsonld_ir(k)] = as_jsonld_ir(v, **options)
+ end
+ value
+ when ::Psych::Nodes::Scalar
+ value = scan_scalar(node, **options)
+ if node.anchor
+ options = options.merge(in_scope_anchors: in_scope_anchors.merge(node.anchor => true))
+ options[:named_nodes][node.anchor] = value
+ end
+ value
when ::Psych::Nodes::Alias
- # FIXME
+ raise JSON::LD::JsonLdError::LoadingDocumentFailed, "anchor for *#{node.anchor} not found" unless options[:named_nodes].key?(node.anchor)
+ raise JSON::LD::JsonLdError::LoadingDocumentFailed, "anchor for *#{node.anchor} creates a cycle" if in_scope_anchors.key?(node.anchor)
+ options[:named_nodes][node.anchor]
end
end
module_function :as_jsonld_ir
##
\ No newline at end of file