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