# coding: utf-8 require_relative 'spec_helper' describe JSON::LD::API do let(:logger) {RDF::Spec.logger} describe ".compact" do { "prefix" => { input: %({ "@id": "http://example.com/a", "http://example.com/b": {"@id": "http://example.com/c"} }), context: %({"ex": "http://example.com/"}), output: %({ "@context": {"ex": "http://example.com/"}, "@id": "ex:a", "ex:b": {"@id": "ex:c"} }) }, "term" => { input: %({ "@id": "http://example.com/a", "http://example.com/b": {"@id": "http://example.com/c"} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "http://example.com/a", "b": {"@id": "http://example.com/c"} }) }, "integer value" => { input: %({ "@id": "http://example.com/a", "http://example.com/b": {"@value": 1} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "http://example.com/a", "b": 1 }) }, "boolean value" => { input: %({ "@id": "http://example.com/a", "http://example.com/b": {"@value": true} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "http://example.com/a", "b": true }) }, "@id" => { input: %({"@id": "http://example.org/test#example"}), context: {}, output: {} }, "@id coercion" => { input: %({ "@id": "http://example.com/a", "http://example.com/b": {"@id": "http://example.com/c"} }), context: %({"b": {"@id": "http://example.com/b", "@type": "@id"}}), output: %({ "@context": {"b": {"@id": "http://example.com/b", "@type": "@id"}}, "@id": "http://example.com/a", "b": "http://example.com/c" }) }, "xsd:date coercion" => { input: %({ "http://example.com/b": {"@value": "2012-01-04", "@type": "http://www.w3.org/2001/XMLSchema#date"} }), context: %({ "xsd": "http://www.w3.org/2001/XMLSchema#", "b": {"@id": "http://example.com/b", "@type": "xsd:date"} }), output: %({ "@context": { "xsd": "http://www.w3.org/2001/XMLSchema#", "b": {"@id": "http://example.com/b", "@type": "xsd:date"} }, "b": "2012-01-04" }) }, "@list coercion": { input: %({ "http://example.com/b": {"@list": ["c", "d"]} }), context: %({"b": {"@id": "http://example.com/b", "@container": "@list"}}), output: %({ "@context": {"b": {"@id": "http://example.com/b", "@container": "@list"}}, "b": ["c", "d"] }) }, "@list coercion (integer)" => { input: %({ "http://example.com/term": [ {"@list": [1]} ] }), context: %({ "term4": {"@id": "http://example.com/term", "@container": "@list"}, "@language": "de" }), output: %({ "@context": { "term4": {"@id": "http://example.com/term", "@container": "@list"}, "@language": "de" }, "term4": [1] }) }, "@set coercion" => { input: %({ "http://example.com/b": {"@set": ["c"]} }), context: %({"b": {"@id": "http://example.com/b", "@container": "@set"}}), output: %({ "@context": {"b": {"@id": "http://example.com/b", "@container": "@set"}}, "b": ["c"] }) }, "@set coercion on @type" => { input: %({ "@type": "http://www.w3.org/2000/01/rdf-schema#Resource", "http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"} }), context: %({"@version": 1.1, "@type": {"@container": "@set"}}), output: %({ "@context": {"@version": 1.1, "@type": {"@container": "@set"}}, "@type": ["http://www.w3.org/2000/01/rdf-schema#Resource"], "http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"} }) }, "empty @set coercion" => { input: %({ "http://example.com/b": [] }), context: %({"b": {"@id": "http://example.com/b", "@container": "@set"}}), output: %({ "@context": {"b": {"@id": "http://example.com/b", "@container": "@set"}}, "b": [] }) }, "@type with string @id" => { input: %({ "@id": "http://example.com/", "@type": "#{RDF::RDFS.Resource}" }), context: {}, output: %({ "@id": "http://example.com/", "@type": "#{RDF::RDFS.Resource}" }), }, "@type with array @id" => { input: %({ "@id": "http://example.com/", "@type": ["#{RDF::RDFS.Resource}"] }), context: {}, output: %({ "@id": "http://example.com/", "@type": "#{RDF::RDFS.Resource}" }), }, "default language" => { input: %({ "http://example.com/term": [ "v5", {"@value": "plain literal"} ] }), context: %({ "term5": {"@id": "http://example.com/term", "@language": null}, "@language": "de" }), output: %({ "@context": { "term5": {"@id": "http://example.com/term", "@language": null}, "@language": "de" }, "term5": [ "v5", "plain literal" ] }) }, "default direction" => { input: %({ "http://example.com/term": [ "v5", {"@value": "plain literal"} ] }), context: %({ "term5": {"@id": "http://example.com/term", "@direction": null}, "@direction": "ltr" }), output: %({ "@context": { "term5": {"@id": "http://example.com/term", "@direction": null}, "@direction": "ltr" }, "term5": [ "v5", "plain literal" ] }) }, }.each_pair do |title, params| it(title) {run_compact(params)} end context "keyword aliasing" do { "@id" => { input: %({ "@id": "", "@type": "#{RDF::RDFS.Resource}" }), context: %({"id": "@id"}), output: %({ "@context": {"id": "@id"}, "id": "", "@type": "#{RDF::RDFS.Resource}" }) }, "@type": { input: %({ "@type": "http://www.w3.org/2000/01/rdf-schema#Resource", "http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"} }), context: %({"type": "@type"}), output: %({ "@context": {"type": "@type"}, "type": "http://www.w3.org/2000/01/rdf-schema#Resource", "http://example.org/foo": {"@value": "bar", "type": "http://example.com/type"} }) }, "@type with @container: @set": { input: %({ "@type": "http://www.w3.org/2000/01/rdf-schema#Resource", "http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"} }), context: %({"type": {"@id": "@type", "@container": "@set"}}), output: %({ "@context": {"type": {"@id": "@type", "@container": "@set"}}, "type": ["http://www.w3.org/2000/01/rdf-schema#Resource"], "http://example.org/foo": {"@value": "bar", "type": "http://example.com/type"} }), processingMode: 'json-ld-1.1' }, "@language" => { input: %({ "http://example.org/foo": {"@value": "bar", "@language": "baz"} }), context: %({"language": "@language"}), output: %({ "@context": {"language": "@language"}, "http://example.org/foo": {"@value": "bar", "language": "baz"} }) }, "@direction" => { input: %({ "http://example.org/foo": {"@value": "bar", "@direction": "ltr"} }), context: %({"direction": "@direction"}), output: %({ "@context": {"direction": "@direction"}, "http://example.org/foo": {"@value": "bar", "direction": "ltr"} }) }, "@value" => { input: %({ "http://example.org/foo": {"@value": "bar", "@language": "baz"} }), context: %({"literal": "@value"}), output: %({ "@context": {"literal": "@value"}, "http://example.org/foo": {"literal": "bar", "@language": "baz"} }) }, "@list" => { input: %({ "http://example.org/foo": {"@list": ["bar"]} }), context: %({"list": "@list"}), output: %({ "@context": {"list": "@list"}, "http://example.org/foo": {"list": ["bar"]} }) }, }.each do |title, params| it(title) {run_compact(params)} end end context "term selection" do { "Uses term with null language when two terms conflict on language" => { input: %([{ "http://example.com/term": {"@value": "v1"} }]), context: %({ "term5": {"@id": "http://example.com/term","@language": null}, "@language": "de" }), output: %({ "@context": { "term5": {"@id": "http://example.com/term","@language": null}, "@language": "de" }, "term5": "v1" }) }, "Uses term with null direction when two terms conflict on direction" => { input: %([{ "http://example.com/term": {"@value": "v1"} }]), context: %({ "term5": {"@id": "http://example.com/term","@direction": null}, "@direction": "ltr" }), output: %({ "@context": { "term5": {"@id": "http://example.com/term","@direction": null}, "@direction": "ltr" }, "term5": "v1" }) }, "Uses subject alias" => { input: %([{ "@id": "http://example.com/id1", "http://example.com/id1": {"@value": "foo", "@language": "de"} }]), context: %({ "id1": "http://example.com/id1", "@language": "de" }), output: %({ "@context": { "id1": "http://example.com/id1", "@language": "de" }, "@id": "http://example.com/id1", "id1": "foo" }) }, "compact-0007" => { input: %( {"http://example.org/vocab#contains": "this-is-not-an-IRI"} ), context: %({ "ex": "http://example.org/vocab#", "ex:contains": {"@type": "@id"} }), output: %({ "@context": { "ex": "http://example.org/vocab#", "ex:contains": {"@type": "@id"} }, "http://example.org/vocab#contains": "this-is-not-an-IRI" }) }, "Language map term with language value" => { input: %([{"http://example/t": {"@value": "foo", "@language": "en"}}]), context: %({"t": {"@id": "http://example/t", "@container": "@language"}}), output: %({ "@context": { "t": {"@id": "http://example/t", "@container": "@language"} }, "t": {"en": "foo"} }) }, "Datatyped term with datatyped value" => { input: %([{"http://example/t": {"@value": "foo", "@type": "http:/example/type"}}]), context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}), output: %({ "@context": { "t": {"@id": "http://example/t", "@type": "http:/example/type"} }, "t": "foo" }) }, "Datatyped term with simple value" => { input: %([{"http://example/t": {"@value": "foo"}}]), context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}), output: %({ "@context": { "t": {"@id": "http://example/t", "@type": "http:/example/type"} }, "http://example/t": "foo" }) }, "Datatyped term with object value" => { input: %([{"http://example/t": {"@id": "http://example/id"}}]), context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}), output: %({ "@context": { "t": {"@id": "http://example/t", "@type": "http:/example/type"} }, "http://example/t": {"@id": "http://example/id"} }) }, }.each_pair do |title, params| it(title) {run_compact(params)} end end context "IRI Compaction" do { "Expands and compacts to document base in 1.0" => { input: %({ "@id": "a", "http://example.com/b": {"@id": "c"} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "a", "b": {"@id": "c"} }), base: "http://example.org/" }, "Expands and compacts to document base in 1.1 with compactToRelative true" => { input: %({ "@id": "a", "http://example.com/b": {"@id": "c"} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "a", "b": {"@id": "c"} }), base: "http://example.org/", compactToRelative: true, processingMode: 'json-ld-1.1' }, "Expands but does not compact to document base in 1.1 with compactToRelative false" => { input: %({ "@id": "http://example.org/a", "http://example.com/b": {"@id": "http://example.org/c"} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "http://example.org/a", "b": {"@id": "http://example.org/c"} }), compactToRelative: false, processingMode: 'json-ld-1.1' }, "Expands and compacts to document base in 1.1 by default" => { input: %({ "@id": "a", "http://example.com/b": {"@id": "c"} }), context: %({"b": "http://example.com/b"}), output: %({ "@context": {"b": "http://example.com/b"}, "@id": "a", "b": {"@id": "c"} }), base: "http://example.org/", processingMode: 'json-ld-1.1' }, }.each_pair do |title, params| it(title) {run_compact(params)} end end context "@container: @reverse" do { "@container: @reverse" => { input: %([{ "@id": "http://example/one", "@reverse": { "http://example/forward": [ { "@id": "http://example/two" } ] } }]), context: %({ "@vocab": "http://example/", "rev": { "@reverse": "forward", "@type": "@id"} }), output: %({ "@context": { "@vocab": "http://example/", "rev": { "@reverse": "forward", "@type": "@id"} }, "@id": "http://example/one", "rev": "http://example/two" }) }, "compact-0033" => { input: %([ { "@id": "http://example.com/people/markus", "@reverse": { "http://xmlns.com/foaf/0.1/knows": [ { "@id": "http://example.com/people/dave", "http://xmlns.com/foaf/0.1/name": [ { "@value": "Dave Longley" } ] } ] }, "http://xmlns.com/foaf/0.1/name": [ { "@value": "Markus Lanthaler" } ] } ]), context: %({ "name": "http://xmlns.com/foaf/0.1/name", "isKnownBy": { "@reverse": "http://xmlns.com/foaf/0.1/knows" } }), output: %({ "@context": { "name": "http://xmlns.com/foaf/0.1/name", "isKnownBy": { "@reverse": "http://xmlns.com/foaf/0.1/knows" } }, "@id": "http://example.com/people/markus", "name": "Markus Lanthaler", "isKnownBy": { "@id": "http://example.com/people/dave", "name": "Dave Longley" } }) } }.each_pair do |title, params| it(title) {run_compact(params)} end end context "context as value" do { "includes the context in the output document" => { input: %({ "http://example.com/": "bar" }), context: %({ "foo": "http://example.com/" }), output: %({ "@context": { "foo": "http://example.com/" }, "foo": "bar" }) } }.each_pair do |title, params| it(title) {run_compact(params)} end end context "context as reference" do let(:remote_doc) do JSON::LD::API::RemoteDocument.new( %q({"@context": {"b": "http://example.com/b"}}), documentUrl: "http://example.com/context") end it "uses referenced context" do JSON::LD::Context.instance_variable_set(:@cache, nil) input = ::JSON.parse %({ "http://example.com/b": "c" }) expected = ::JSON.parse %({ "@context": "http://example.com/context", "b": "c" }) allow(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc) jld = JSON::LD::API.compact(input, "http://example.com/context", logger: logger, validate: true) expect(jld).to produce_jsonld(expected, logger) end end context "@list" do { "1 term 2 lists 2 languages" => { input: %([{ "http://example.com/foo": [ {"@list": [{"@value": "en", "@language": "en"}]}, {"@list": [{"@value": "de", "@language": "de"}]} ] }]), context: %({ "foo_en": {"@id": "http://example.com/foo", "@container": "@list", "@language": "en"}, "foo_de": {"@id": "http://example.com/foo", "@container": "@list", "@language": "de"} }), output: %({ "@context": { "foo_en": {"@id": "http://example.com/foo", "@container": "@list", "@language": "en"}, "foo_de": {"@id": "http://example.com/foo", "@container": "@list", "@language": "de"} }, "foo_en": ["en"], "foo_de": ["de"] }) }, "1 term 2 lists 2 directions" => { input: %([{ "http://example.com/foo": [ {"@list": [{"@value": "en", "@direction": "ltr"}]}, {"@list": [{"@value": "ar", "@direction": "rtl"}]} ] }]), context: %({ "foo_ltr": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "ltr"}, "foo_rtl": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "rtl"} }), output: %({ "@context": { "foo_ltr": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "ltr"}, "foo_rtl": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "rtl"} }, "foo_ltr": ["en"], "foo_rtl": ["ar"] }) }, "coerced @list containing an empty list" => { input: %([{ "http://example.com/foo": [{"@list": [{"@list": []}]}] }]), context: %({ "foo": {"@id": "http://example.com/foo", "@container": "@list"} }), output: %({ "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}}, "foo": [[]] }), }, "coerced @list containing a list" => { input: %([{ "http://example.com/foo": [{"@list": [{"@list": [{"@value": "baz"}]}]}] }]), context: %({ "foo": {"@id": "http://example.com/foo", "@container": "@list"} }), output: %({ "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}}, "foo": [["baz"]] }), }, "coerced @list containing an deep list" => { input: %([{ "http://example.com/foo": [{"@list": [{"@list": [{"@list": [{"@value": "baz"}]}]}]}] }]), context: %({ "foo": {"@id": "http://example.com/foo", "@container": "@list"} }), output: %({ "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}}, "foo": [[["baz"]]] }), }, "coerced @list containing multiple lists" => { input: %([{ "http://example.com/foo": [{"@list": [ {"@list": [{"@value": "a"}]}, {"@list": [{"@value": "b"}]} ]}] }]), context: %({ "foo": {"@id": "http://example.com/foo", "@container": "@list"} }), output: %({ "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}}, "foo": [["a"], ["b"]] }), }, "coerced @list containing mixed list values" => { input: %([{ "http://example.com/foo": [{"@list": [ {"@list": [{"@value": "a"}]}, {"@value": "b"} ]}] }]), context: %({ "foo": {"@id": "http://example.com/foo", "@container": "@list"} }), output: %({ "@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}}, "foo": [["a"], "b"] }), }, }.each_pair do |title, params| it(title) {run_compact(params)} end end context "with @type: @json" do { "true": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#bool", "@type": "@json"} }, "e": true }), input:%( [{ "http://example.org/vocab#bool": [{"@value": true, "@type": "@json"}] }]), }, "false": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#bool", "@type": "@json"} }, "e": false }), input: %([{ "http://example.org/vocab#bool": [{"@value": false, "@type": "@json"}] }]), }, "double": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#double", "@type": "@json"} }, "e": 1.23 }), input: %([{ "http://example.org/vocab#double": [{"@value": 1.23, "@type": "@json"}] }]), }, "double-zero": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#double", "@type": "@json"} }, "e": 0.0e0 }), input: %([{ "http://example.org/vocab#double": [{"@value": 0.0e0, "@type": "@json"}] }]), }, "integer": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#integer", "@type": "@json"} }, "e": 123 }), input: %([{ "http://example.org/vocab#integer": [{"@value": 123, "@type": "@json"}] }]), }, "string": { input: %([{ "http://example.org/vocab#string": [{ "@value": "string", "@type": "@json" }] }]), output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#string", "@type": "@json"} }, "e": "string" }) }, "null": { input: %([{ "http://example.org/vocab#null": [{ "@value": null, "@type": "@json" }] }]), output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#null", "@type": "@json"} }, "e": null }) }, "object": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#object", "@type": "@json"} }, "e": {"foo": "bar"} }), input: %([{ "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}] }]), }, "array": { output: %({ "@context": { "@version": 1.1, "e": {"@id": "http://example.org/vocab#array", "@type": "@json", "@container": "@set"} }, "e": [{"foo": "bar"}] }), input: %([{ "http://example.org/vocab#array": [{"@value": [{"foo": "bar"}], "@type": "@json"}] }]), }, "Already expanded object": { output: %({ "@context": {"@version": 1.1}, "http://example.org/vocab#object": {"@value": {"foo": "bar"}, "@type": "@json"} }), input: %([{ "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}] }]), }, "Already expanded object with aliased keys": { output: %({ "@context": {"@version": 1.1, "value": "@value", "type": "@type", "json": "@json"}, "http://example.org/vocab#object": {"value": {"foo": "bar"}, "type": "json"} }), input: %([{ "http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}] }]) }, }.each do |title, params| it(title) {run_compact(processingMode: 'json-ld-1.1', **params)} end end context "@container: @index" do { "compact-0029" => { input: %([{ "@id": "http://example.com/article", "http://example.com/vocab/author": [{ "@id": "http://example.org/person/1", "@index": "regular" }, { "@id": "http://example.org/guest/cd24f329aa", "@index": "guest" }] }]), context: %({ "author": {"@id": "http://example.com/vocab/author", "@container": "@index" } }), output: %({ "@context": { "author": { "@id": "http://example.com/vocab/author", "@container": "@index" } }, "@id": "http://example.com/article", "author": { "regular": { "@id": "http://example.org/person/1" }, "guest": { "@id": "http://example.org/guest/cd24f329aa" } } }) }, "simple map with @none node definition" => { input: %([{ "@id": "http://example.com/article", "http://example.com/vocab/author": [{ "@id": "http://example.org/person/1", "@index": "regular" }, { "@id": "http://example.org/guest/cd24f329aa" }] }]), context: %({ "author": {"@id": "http://example.com/vocab/author", "@container": "@index" } }), output: %({ "@context": { "author": { "@id": "http://example.com/vocab/author", "@container": "@index" } }, "@id": "http://example.com/article", "author": { "regular": { "@id": "http://example.org/person/1" }, "@none": { "@id": "http://example.org/guest/cd24f329aa" } } }), processingMode: 'json-ld-1.1' }, "simple map with @none value" => { input: %([{ "@id": "http://example.com/article", "http://example.com/vocab/author": [{ "@value": "Gregg", "@index": "regular" }, { "@value": "Manu" }] }]), context: %({ "author": {"@id": "http://example.com/vocab/author", "@container": "@index" } }), output: %({ "@context": { "author": { "@id": "http://example.com/vocab/author", "@container": "@index" } }, "@id": "http://example.com/article", "author": { "regular": "Gregg", "@none": "Manu" } }), processingMode: 'json-ld-1.1' }, "simple map with @none value using alias of @none" => { input: %([{ "@id": "http://example.com/article", "http://example.com/vocab/author": [{ "@value": "Gregg", "@index": "regular" }, { "@value": "Manu" }] }]), context: %({ "author": {"@id": "http://example.com/vocab/author", "@container": "@index" }, "none": "@none" }), output: %({ "@context": { "author": { "@id": "http://example.com/vocab/author", "@container": "@index" }, "none": "@none" }, "@id": "http://example.com/article", "author": { "regular": "Gregg", "none": "Manu" } }), processingMode: 'json-ld-1.1' }, "issue-514": { input: %({ "http://example.org/ns/prop": [{ "@id": "http://example.org/ns/bar", "http://example.org/ns/name": "bar" }, { "@id": "http://example.org/ns/foo", "http://example.org/ns/name": "foo" }] }), context: %({ "@context": { "ex": "http://example.org/ns/", "prop": { "@id": "ex:prop", "@container": "@index", "@index": "ex:name" } } }), output: %({ "@context": { "ex": "http://example.org/ns/", "prop": { "@id": "ex:prop", "@container": "@index", "@index": "ex:name" } }, "prop": { "foo": { "@id": "ex:foo"}, "bar": { "@id": "ex:bar"} } }) }, "issue-514b": { input: %({ "http://example.org/ns/prop": [{ "@id": "http://example.org/ns/bar", "http://example.org/ns/name": "bar" }, { "@id": "http://example.org/ns/foo", "http://example.org/ns/name": "foo" }] }), context: %({ "@context": { "ex": "http://example.org/ns/", "prop": { "@id": "ex:prop", "@container": "@index", "@index": "http://example.org/ns/name" } } }), output: %({ "@context": { "ex": "http://example.org/ns/", "prop": { "@id": "ex:prop", "@container": "@index", "@index": "http://example.org/ns/name" } }, "prop": { "foo": { "@id": "ex:foo"}, "bar": { "@id": "ex:bar"} } }) }, }.each_pair do |title, params| it(title) {run_compact(params)} end context "@index: property" do { "property-valued index indexes property value, instead of property (value)": { output: %({ "@context": { "@version": 1.1, "@base": "http://example.com/", "@vocab": "http://example.com/", "author": {"@type": "@id", "@container": "@index", "@index": "prop"} }, "@id": "article", "author": { "regular": {"@id": "person/1"}, "guest": [{"@id": "person/2"}, {"@id": "person/3"}] } }), input: %([{ "@id": "http://example.com/article", "http://example.com/author": [ {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@value": "regular"}]}, {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@value": "guest"}]}, {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@value": "guest"}]} ] }]) }, "property-valued index indexes property value, instead of @index (multiple values)": { output: %({ "@context": { "@version": 1.1, "@base": "http://example.com/", "@vocab": "http://example.com/", "author": {"@type": "@id", "@container": "@index", "@index": "prop"} }, "@id": "article", "author": { "regular": {"@id": "person/1", "prop": "foo"}, "guest": [ {"@id": "person/2", "prop": "foo"}, {"@id": "person/3", "prop": "foo"} ] } }), input: %([{ "@id": "http://example.com/article", "http://example.com/author": [ {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@value": "regular"}, {"@value": "foo"}]}, {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@value": "guest"}, {"@value": "foo"}]}, {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@value": "guest"}, {"@value": "foo"}]} ] }]) }, "property-valued index extracts property value, instead of @index (node)": { output: %({ "@context": { "@version": 1.1, "@base": "http://example.com/", "@vocab": "http://example.com/", "author": {"@type": "@vocab", "@container": "@index", "@index": "prop"}, "prop": {"@type": "@id"} }, "@id": "article", "author": { "regular": {"@id": "person/1"}, "guest": [ {"@id": "person/2"}, {"@id": "person/3"} ] } }), input: %([{ "@id": "http://example.com/article", "http://example.com/author": [ {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}]}, {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}]}, {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}]} ] }]) }, "property-valued index indexes property value, instead of property (multimple nodes)": { output: %({ "@context": { "@version": 1.1, "@base": "http://example.com/", "@vocab": "http://example.com/", "author": {"@type": "@vocab", "@container": "@index", "@index": "prop"}, "prop": {"@type": "@id"} }, "@id": "article", "author": { "regular": {"@id": "person/1", "prop": "foo"}, "guest": [ {"@id": "person/2", "prop": "foo"}, {"@id": "person/3", "prop": "foo"} ] } }), input: %([{ "@id": "http://example.com/article", "http://example.com/author": [ {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}, {"@id": "http://example.com/foo"}]}, {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}, {"@id": "http://example.com/foo"}]}, {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}, {"@id": "http://example.com/foo"}]} ] }]) }, "property-valued index indexes using @none if no property value exists": { output: %({ "@context": { "@version": 1.1, "@base": "http://example.com/", "@vocab": "http://example.com/", "author": {"@type": "@id", "@container": "@index", "@index": "prop"} }, "@id": "article", "author": { "@none": ["person/1", "person/2", "person/3"] } }), input: %([{ "@id": "http://example.com/article", "http://example.com/author": [ {"@id": "http://example.com/person/1"}, {"@id": "http://example.com/person/2"}, {"@id": "http://example.com/person/3"} ] }]) }, "property-valued index indexes using @none if no property value does not compact to string": { output: %({ "@context": { "@version": 1.1, "@base": "http://example.com/", "@vocab": "http://example.com/", "author": {"@type": "@id", "@container": "@index", "@index": "prop"} }, "@id": "article", "author": { "@none": [ {"@id": "person/1", "prop": {"@id": "regular"}}, {"@id": "person/2", "prop": {"@id": "guest"}}, {"@id": "person/3", "prop": {"@id": "guest"}} ] } }), input: %([{ "@id": "http://example.com/article", "http://example.com/author": [ {"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}]}, {"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}]}, {"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}]} ] }]) } }.each do |title, params| it(title) {run_compact(**params)} end end end context "@container: @language" do { "compact-0024" => { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "The Queen", "@language": "en"}, {"@value": "Die Königin", "@language": "de"}, {"@value": "Ihre Majestät", "@language": "de"} ] } ]), context: %({ "vocab": "http://example.com/vocab/", "label": {"@id": "vocab:label", "@container": "@language"} }), output: %({ "@context": { "vocab": "http://example.com/vocab/", "label": {"@id": "vocab:label", "@container": "@language"} }, "@id": "http://example.com/queen", "label": { "en": "The Queen", "de": ["Die Königin", "Ihre Majestät"] } }) }, "with no @language" => { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "The Queen", "@language": "en"}, {"@value": "Die Königin", "@language": "de"}, {"@value": "Ihre Majestät"} ] } ]), context: %({ "vocab": "http://example.com/vocab/", "label": {"@id": "vocab:label", "@container": "@language"} }), output: %({ "@context": { "vocab": "http://example.com/vocab/", "label": {"@id": "vocab:label", "@container": "@language"} }, "@id": "http://example.com/queen", "label": { "en": "The Queen", "de": "Die Königin", "@none": "Ihre Majestät" } }), processingMode: "json-ld-1.1" }, "with no @language using alias of @none" => { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "The Queen", "@language": "en"}, {"@value": "Die Königin", "@language": "de"}, {"@value": "Ihre Majestät"} ] } ]), context: %({ "vocab": "http://example.com/vocab/", "label": {"@id": "vocab:label", "@container": "@language"}, "none": "@none" }), output: %({ "@context": { "vocab": "http://example.com/vocab/", "label": {"@id": "vocab:label", "@container": "@language"}, "none": "@none" }, "@id": "http://example.com/queen", "label": { "en": "The Queen", "de": "Die Königin", "none": "Ihre Majestät" } }), processingMode: "json-ld-1.1" }, "simple map with term direction": { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "Die Königin", "@language": "de", "@direction": "ltr"}, {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"}, {"@value": "The Queen", "@language": "en", "@direction": "ltr"} ] } ]), context: %({ "@context": { "@version": 1.1, "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": "ltr", "@container": "@language" } } }), output: %({ "@context": { "@version": 1.1, "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": "ltr", "@container": "@language" } }, "@id": "http://example.com/queen", "label": { "en": "The Queen", "de": [ "Die Königin", "Ihre Majestät" ] } }), processingMode: "json-ld-1.1" }, "simple map with overriding term direction": { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "Die Königin", "@language": "de", "@direction": "ltr"}, {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"}, {"@value": "The Queen", "@language": "en", "@direction": "ltr"} ] } ]), context: %({ "@context": { "@version": 1.1, "@direction": "rtl", "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": "ltr", "@container": "@language" } } }), output: %({ "@context": { "@version": 1.1, "@direction": "rtl", "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": "ltr", "@container": "@language" } }, "@id": "http://example.com/queen", "label": { "en": "The Queen", "de": [ "Die Königin", "Ihre Majestät" ] } }), processingMode: "json-ld-1.1" }, "simple map with overriding null direction": { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "Die Königin", "@language": "de"}, {"@value": "Ihre Majestät", "@language": "de"}, {"@value": "The Queen", "@language": "en"} ] } ]), context: %({ "@context": { "@version": 1.1, "@direction": "rtl", "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": null, "@container": "@language" } } }), output: %({ "@context": { "@version": 1.1, "@direction": "rtl", "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": null, "@container": "@language" } }, "@id": "http://example.com/queen", "label": { "en": "The Queen", "de": [ "Die Königin", "Ihre Majestät" ] } }), processingMode: "json-ld-1.1" }, "simple map with mismatching term direction": { input: %([ { "@id": "http://example.com/queen", "http://example.com/vocab/label": [ {"@value": "Die Königin", "@language": "de"}, {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"}, {"@value": "The Queen", "@language": "en", "@direction": "rtl"} ] } ]), context: %({ "@context": { "@version": 1.1, "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": "rtl", "@container": "@language" } } }), output: %({ "@context": { "@version": 1.1, "vocab": "http://example.com/vocab/", "label": { "@id": "vocab:label", "@direction": "rtl", "@container": "@language" } }, "@id": "http://example.com/queen", "label": { "en": "The Queen" }, "vocab:label": [ {"@value": "Die Königin", "@language": "de"}, {"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"} ] }), processingMode: "json-ld-1.1" }, }.each_pair do |title, params| it(title) {run_compact(params)} end end context "@container: @id" do { "Indexes to object not having an @id" => { input: %([{ "http://example/idmap": [ {"http://example/label": [{"@value": "Object with @id _:bar"}], "@id": "_:bar"}, {"http://example/label": [{"@value": "Object with @id "}], "@id": "http://example.org/foo"} ] }]), context: %({ "@vocab": "http://example/", "idmap": {"@container": "@id"} }), output: %({ "@context": { "@vocab": "http://example/", "idmap": {"@container": "@id"} }, "idmap": { "http://example.org/foo": {"label": "Object with @id "}, "_:bar": {"label": "Object with @id _:bar"} } }), }, "Indexes to object already having an @id" => { input: %([{ "http://example/idmap": [ {"@id": "_:foo", "http://example/label": [{"@value": "Object with @id _:bar"}]}, {"@id": "http://example.org/bar", "http://example/label": [{"@value": "Object with @id "}]} ] }]), context: %({ "@vocab": "http://example/", "idmap": {"@container": "@id"} }), output: %({ "@context": { "@vocab": "http://example/", "idmap": {"@container": "@id"} }, "idmap": { "_:foo": {"label": "Object with @id _:bar"}, "http://example.org/bar": {"label": "Object with @id "} } }), }, "Indexes to object using compact IRI @id" => { input: %([{ "http://example/idmap": [ {"http://example/label": [{"@value": "Object with @id "}], "@id": "http://example.org/foo"} ] }]), context: %({ "@vocab": "http://example/", "ex": "http://example.org/", "idmap": {"@container": "@id"} }), output: %({ "@context": { "@vocab": "http://example/", "ex": "http://example.org/", "idmap": {"@container": "@id"} }, "idmap": { "ex:foo": {"label": "Object with @id "} } }) }, "Indexes using @none" => { input: %([{ "http://example/idmap": [ {"http://example/label": [{"@value": "Object with no @id"}]} ] }]), context: %({ "@vocab": "http://example/", "ex": "http://example.org/", "idmap": {"@container": "@id"} }), output: %({ "@context": { "@vocab": "http://example/", "ex": "http://example.org/", "idmap": {"@container": "@id"} }, "idmap": { "@none": {"label": "Object with no @id"} } }) }, "Indexes using @none with alias" => { input: %([{ "http://example/idmap": [ {"http://example/label": [{"@value": "Object with no @id"}]} ] }]), context: %({ "@vocab": "http://example/", "ex": "http://example.org/", "idmap": {"@container": "@id"}, "none": "@none" }), output: %({ "@context": { "@vocab": "http://example/", "ex": "http://example.org/", "idmap": {"@container": "@id"}, "none": "@none" }, "idmap": { "none": {"label": "Object with no @id"} } }) }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end context "@container: @type" do { "Indexes to object not having an @type" => { input: %([{ "http://example/typemap": [ {"http://example/label": [{"@value": "Object with @type _:bar"}], "@type": ["_:bar"]}, {"http://example/label": [{"@value": "Object with @type "}], "@type": ["http://example.org/foo"]} ] }]), context: %({ "@vocab": "http://example/", "typemap": {"@container": "@type"} }), output: %({ "@context": { "@vocab": "http://example/", "typemap": {"@container": "@type"} }, "typemap": { "http://example.org/foo": {"label": "Object with @type "}, "_:bar": {"label": "Object with @type _:bar"} } }) }, "Indexes to object already having an @type" => { input: %([{ "http://example/typemap": [ { "@type": ["_:bar", "_:foo"], "http://example/label": [{"@value": "Object with @type _:bar"}] }, { "@type": ["http://example.org/foo", "http://example.org/bar"], "http://example/label": [{"@value": "Object with @type "}] } ] }]), context: %({ "@vocab": "http://example/", "typemap": {"@container": "@type"} }), output: %({ "@context": { "@vocab": "http://example/", "typemap": {"@container": "@type"} }, "typemap": { "http://example.org/foo": {"@type": "http://example.org/bar", "label": "Object with @type "}, "_:bar": {"@type": "_:foo", "label": "Object with @type _:bar"} } }) }, "Indexes to object already having multiple @type values" => { input: %([{ "http://example/typemap": [ { "@type": ["_:bar", "_:foo", "_:baz"], "http://example/label": [{"@value": "Object with @type _:bar"}] }, { "@type": ["http://example.org/foo", "http://example.org/bar", "http://example.org/baz"], "http://example/label": [{"@value": "Object with @type "}] } ] }]), context: %({ "@vocab": "http://example/", "typemap": {"@container": "@type"} }), output: %({ "@context": { "@vocab": "http://example/", "typemap": {"@container": "@type"} }, "typemap": { "http://example.org/foo": {"@type": ["http://example.org/bar", "http://example.org/baz"], "label": "Object with @type "}, "_:bar": {"@type": ["_:foo", "_:baz"], "label": "Object with @type _:bar"} } }) }, "Indexes using compacted @type" => { input: %([{ "http://example/typemap": [ {"http://example/label": [{"@value": "Object with @type "}], "@type": ["http://example/Foo"]} ] }]), context: %({ "@vocab": "http://example/", "typemap": {"@container": "@type"} }), output: %({ "@context": { "@vocab": "http://example/", "typemap": {"@container": "@type"} }, "typemap": { "Foo": {"label": "Object with @type "} } }) }, "Indexes using @none" => { input: %([{ "http://example/typemap": [ {"http://example/label": [{"@value": "Object with no @type"}]} ] }]), context: %({ "@vocab": "http://example/", "ex": "http://example.org/", "typemap": {"@container": "@type"} }), output: %({ "@context": { "@vocab": "http://example/", "ex": "http://example.org/", "typemap": {"@container": "@type"} }, "typemap": { "@none": {"label": "Object with no @type"} } }) }, "Indexes using @none with alias" => { input: %([{ "http://example/typemap": [ {"http://example/label": [{"@value": "Object with no @id"}]} ] }]), context: %({ "@vocab": "http://example/", "ex": "http://example.org/", "typemap": {"@container": "@type"}, "none": "@none" }), output: %({ "@context": { "@vocab": "http://example/", "ex": "http://example.org/", "typemap": {"@container": "@type"}, "none": "@none" }, "typemap": { "none": {"label": "Object with no @id"} } }) }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end context "@container: @graph" do { "Compacts simple graph" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": "@graph"} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": "@graph"} }, "input": { "value": "x" } }) }, "Compacts simple graph with @set" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@set"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@set"]} }, "input": [{ "value": "x" }] }) }, "Compacts simple graph with @index" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }], "@index": "ndx" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": "@graph"} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": "@graph"} }, "input": { "value": "x" } }) }, "Compacts simple graph with @index and multiple nodes" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }, { "http://example.org/value": [{"@value": "y"}] }], "@index": "ndx" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": "@graph"} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": "@graph"} }, "input": { "@included": [{ "value": "x" }, { "value": "y" }] } }) }, "Does not compact graph with @id" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }], "@id": "http://example.org/id" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": "@graph"} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": "@graph"} }, "input": { "@id": "http://example.org/id", "@graph": {"value": "x"} } }) }, "Odd framing test" => { input: %([ { "http://example.org/claim": [ { "@graph": [ { "@id": "http://example.org/1", "https://example.com#test": [ { "@value": "foo" } ] } ] } ] } ] ), context: %( { "@version": 1.1, "@vocab": "https://example.com#", "ex": "http://example.org/", "claim": { "@id": "ex:claim", "@container": "@graph" }, "id": "@id" }), output: %({ "@context": { "@version": 1.1, "@vocab": "https://example.com#", "ex": "http://example.org/", "claim": { "@id": "ex:claim", "@container": "@graph" }, "id": "@id" }, "claim": { "id": "ex:1", "test": "foo" } }) } }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end context "+ @index" do { "Compacts simple graph" => { input: %([{ "http://example.org/input": [{ "@index": "g1", "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index"]} }, "input": { "g1": {"value": "x"} } }) }, "Compacts simple graph with @set" => { input: %([{ "http://example.org/input": [{ "@index": "g1", "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index", "@set"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index", "@set"]} }, "input": { "g1": [{"value": "x"}] } }) }, "Compacts simple graph with no @index" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index", "@set"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index", "@set"]} }, "input": { "@none": [{"value": "x"}] } }) }, "Does not compact graph with @id" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }], "@index": "g1", "@id": "http://example.org/id" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@index"]} }, "input": { "@id": "http://example.org/id", "@index": "g1", "@graph": {"value": "x"} } }) }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end context "+ @id" do { "Compacts simple graph" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }, "input": { "@none": {"value": "x"} } }) }, "Compacts simple graph with @set" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id", "@set"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id", "@set"]} }, "input": {"@none": [{"value": "x"}]} }) }, "Compacts simple graph with @index" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }], "@index": "ndx" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }, "input": { "@none": {"value": "x"} } }) }, "Compacts graph with @id" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }], "@id": "http://example.org/id" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }, "input": { "http://example.org/id" : {"value": "x"} } }) }, "Compacts graph with @id and @set" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }], "@id": "http://example.org/id" }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id", "@set"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id", "@set"]} }, "input": { "http://example.org/id" : [{"value": "x"}] } }) }, "Compacts graph without @id" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]} }, "input": { "@none" : {"value": "x"} } }) }, "Compacts graph without @id using alias of @none" => { input: %([{ "http://example.org/input": [{ "@graph": [{ "http://example.org/value": [{"@value": "x"}] }] }] }]), context: %({ "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]}, "none": "@none" }), output: %({ "@context": { "@vocab": "http://example.org/", "input": {"@container": ["@graph", "@id"]}, "none": "@none" }, "input": { "none" : {"value": "x"} } }) }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end end context "@included" do { "Basic Included array": { output: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/", "included": {"@id": "@included", "@container": "@set"} }, "prop": "value", "included": [{ "prop": "value2" }] }), input: %([{ "http://example.org/prop": [{"@value": "value"}], "@included": [{ "http://example.org/prop": [{"@value": "value2"}] }] }]) }, "Basic Included object": { output: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/" }, "prop": "value", "@included": { "prop": "value2" } }), input: %([{ "http://example.org/prop": [{"@value": "value"}], "@included": [{ "http://example.org/prop": [{"@value": "value2"}] }] }]) }, "Multiple properties mapping to @included are folded together": { output: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/", "included1": "@included", "included2": "@included" }, "included1": [ {"prop": "value1"}, {"prop": "value2"} ] }), input: %([{ "@included": [ {"http://example.org/prop": [{"@value": "value1"}]}, {"http://example.org/prop": [{"@value": "value2"}]} ] }]) }, "Included containing @included": { output: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/" }, "prop": "value", "@included": { "prop": "value2", "@included": { "prop": "value3" } } }), input: %([{ "http://example.org/prop": [{"@value": "value"}], "@included": [{ "http://example.org/prop": [{"@value": "value2"}], "@included": [{ "http://example.org/prop": [{"@value": "value3"}] }] }] }]) }, "Property value with @included": { output: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/" }, "prop": { "@type": "Foo", "@included": { "@type": "Bar" } } }), input: %([{ "http://example.org/prop": [{ "@type": ["http://example.org/Foo"], "@included": [{ "@type": ["http://example.org/Bar"] }] }] }]) }, }.each do |title, params| it(title) {run_compact(params)} end end context "@nest" do { "Indexes to @nest for property with @nest" => { input: %([{ "http://example.org/p1": [{"@value": "v1"}], "http://example.org/p2": [{"@value": "v2"}] }]), context: %({ "@vocab": "http://example.org/", "p2": {"@nest": "@nest"} }), output: %({ "@context": { "@vocab": "http://example.org/", "p2": {"@nest": "@nest"} }, "p1": "v1", "@nest": { "p2": "v2" } }) }, "Indexes to @nest for all properties with @nest" => { input: %([{ "http://example.org/p1": [{"@value": "v1"}], "http://example.org/p2": [{"@value": "v2"}] }]), context: %({ "@vocab": "http://example.org/", "p1": {"@nest": "@nest"}, "p2": {"@nest": "@nest"} }), output: %({ "@context": { "@vocab": "http://example.org/", "p1": {"@nest": "@nest"}, "p2": {"@nest": "@nest"} }, "@nest": { "p1": "v1", "p2": "v2" } }) }, "Nests using alias of @nest" => { input: %([{ "http://example.org/p1": [{"@value": "v1"}], "http://example.org/p2": [{"@value": "v2"}] }]), context: %({ "@vocab": "http://example.org/", "nest": "@nest", "p2": {"@nest": "nest"} }), output: %({ "@context": { "@vocab": "http://example.org/", "nest": "@nest", "p2": {"@nest": "nest"} }, "p1": "v1", "nest": { "p2": "v2" } }) }, "Arrays of nested values" => { input: %([{ "http://example.org/p1": [{"@value": "v1"}], "http://example.org/p2": [{"@value": "v2"}, {"@value": "v3"}] }]), context: %({ "@vocab": "http://example.org/", "p2": {"@nest": "@nest"} }), output: %({ "@context": { "@vocab": "http://example.org/", "p2": {"@nest": "@nest"} }, "p1": "v1", "@nest": { "p2": ["v2", "v3"] } }) }, "Nested @container: @list" => { input: %([{ "http://example.org/list": [{"@list": [ {"@value": "a"}, {"@value": "b"} ]}] }]), context: %({ "@vocab": "http://example.org/", "list": {"@container": "@list", "@nest": "nestedlist"}, "nestedlist": "@nest" }), output: %({ "@context": { "@vocab": "http://example.org/", "list": {"@container": "@list", "@nest": "nestedlist"}, "nestedlist": "@nest" }, "nestedlist": { "list": ["a", "b"] } }), }, "Nested @container: @index" => { input: %([{ "http://example.org/index": [ {"@value": "a", "@index": "A"}, {"@value": "b", "@index": "B"} ] }]), context: %({ "@vocab": "http://example.org/", "index": {"@container": "@index", "@nest": "nestedindex"}, "nestedindex": "@nest" }), output: %({ "@context": { "@vocab": "http://example.org/", "index": {"@container": "@index", "@nest": "nestedindex"}, "nestedindex": "@nest" }, "nestedindex": { "index": { "A": "a", "B": "b" } } }), }, "Nested @container: @language" => { input: %([{ "http://example.org/container": [ {"@value": "Die Königin", "@language": "de"}, {"@value": "The Queen", "@language": "en"} ] }]), context: %({ "@vocab": "http://example.org/", "container": {"@container": "@language", "@nest": "nestedlanguage"}, "nestedlanguage": "@nest" }), output: %({ "@context": { "@vocab": "http://example.org/", "container": {"@container": "@language", "@nest": "nestedlanguage"}, "nestedlanguage": "@nest" }, "nestedlanguage": { "container": { "en": "The Queen", "de": "Die Königin" } } }) }, "Nested @container: @type" => { input: %([{ "http://example/typemap": [ {"http://example/label": [{"@value": "Object with @type _:bar"}], "@type": ["_:bar"]}, {"http://example/label": [{"@value": "Object with @type "}], "@type": ["http://example.org/foo"]} ] }]), context: %({ "@vocab": "http://example/", "typemap": {"@container": "@type", "@nest": "nestedtypemap"}, "nestedtypemap": "@nest" }), output: %({ "@context": { "@vocab": "http://example/", "typemap": {"@container": "@type", "@nest": "nestedtypemap"}, "nestedtypemap": "@nest" }, "nestedtypemap": { "typemap": { "_:bar": {"label": "Object with @type _:bar"}, "http://example.org/foo": {"label": "Object with @type "} } } }) }, "Nested @container: @id" => { input: %([{ "http://example/idmap": [ {"http://example/label": [{"@value": "Object with @id _:bar"}], "@id": "_:bar"}, {"http://example/label": [{"@value": "Object with @id "}], "@id": "http://example.org/foo"} ] }]), context: %({ "@vocab": "http://example/", "idmap": {"@container": "@id", "@nest": "nestedidmap"}, "nestedidmap": "@nest" }), output: %({ "@context": { "@vocab": "http://example/", "idmap": {"@container": "@id", "@nest": "nestedidmap"}, "nestedidmap": "@nest" }, "nestedidmap": { "idmap": { "http://example.org/foo": {"label": "Object with @id "}, "_:bar": {"label": "Object with @id _:bar"} } } }) }, "Multiple nest aliases" => { input: %({ "http://example.org/foo": "bar", "http://example.org/bar": "foo" }), context: %({ "@vocab": "http://example.org/", "foonest": "@nest", "barnest": "@nest", "foo": {"@nest": "foonest"}, "bar": {"@nest": "barnest"} }), output: %({ "@context": { "@vocab": "http://example.org/", "foonest": "@nest", "barnest": "@nest", "foo": {"@nest": "foonest"}, "bar": {"@nest": "barnest"} }, "barnest": {"bar": "foo"}, "foonest": {"foo": "bar"} }) }, "Nest term not defined" => { input: %({ "http://example/foo": "bar" }), context: %({ "term": {"@id": "http://example/foo", "@nest": "unknown"} }), exception: JSON::LD::JsonLdError::InvalidNestValue }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end context "@graph" do { "Uses @graph given mutliple inputs" => { input: %([ {"http://example.com/foo": ["foo"]}, {"http://example.com/bar": ["bar"]} ]), context: %({"ex": "http://example.com/"}), output: %({ "@context": {"ex": "http://example.com/"}, "@graph": [ {"ex:foo": "foo"}, {"ex:bar": "bar"} ] }) }, }.each_pair do |title, params| it(title) {run_compact(params)} end end context "scoped context" do { "adding new term" => { input: %([{ "http://example/foo": [{"http://example.org/bar": [{"@value": "baz"}]}] }]), context: %({ "@vocab": "http://example/", "foo": {"@context": {"bar": "http://example.org/bar"}} }), output: %({ "@context": { "@vocab": "http://example/", "foo": {"@context": {"bar": "http://example.org/bar"}} }, "foo": { "bar": "baz" } }) }, "overriding a term" => { input: %([ { "http://example/foo": [{"http://example/bar": [{"@id": "http://example/baz"}]}] } ]), context: %({ "@vocab": "http://example/", "foo": {"@context": {"bar": {"@type": "@id"}}}, "bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"} }), output: %({ "@context": { "@vocab": "http://example/", "foo": {"@context": {"bar": {"@type": "@id"}}}, "bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"} }, "foo": { "bar": "http://example/baz" } }), }, "property and value with different terms mapping to the same expanded property" => { input: %([ { "http://example/foo": [{ "http://example/bar": [ {"@value": "baz"} ]} ] } ]), context: %({ "@vocab": "http://example/", "foo": {"@context": {"Bar": {"@id": "bar"}}} }), output: %({ "@context": { "@vocab": "http://example/", "foo": {"@context": {"Bar": {"@id": "bar"}}} }, "foo": { "Bar": "baz" } }), }, "deep @context affects nested nodes" => { input: %([ { "http://example/foo": [{ "http://example/bar": [{ "http://example/baz": [{"@id": "http://example/buzz"}] }] }] } ]), context: %({ "@vocab": "http://example/", "foo": {"@context": {"baz": {"@type": "@vocab"}}} }), output: %({ "@context": { "@vocab": "http://example/", "foo": {"@context": {"baz": {"@type": "@vocab"}}} }, "foo": { "bar": { "baz": "buzz" } } }), }, "scoped context layers on intemediate contexts" => { input: %([{ "http://example/a": [{ "http://example.com/c": [{"@value": "C in example.com"}], "http://example/b": [{ "http://example.com/a": [{"@value": "A in example.com"}], "http://example.org/c": [{"@value": "C in example.org"}] }] }], "http://example/c": [{"@value": "C in example"}] }]), context: %({ "@vocab": "http://example/", "b": {"@context": {"c": "http://example.org/c"}} }), output: %({ "@context": { "@vocab": "http://example/", "b": {"@context": {"c": "http://example.org/c"}} }, "a": { "b": { "c": "C in example.org", "http://example.com/a": "A in example.com" }, "http://example.com/c": "C in example.com" }, "c": "C in example" }), }, "Raises InvalidTermDefinition if processingMode is 1.0" => { input: %([{ "http://example/foo": [{"http://example.org/bar": [{"@value": "baz"}]}] }]), context: %({ "@vocab": "http://example/", "foo": {"@context": {"bar": "http://example.org/bar"}} }), processingMode: 'json-ld-1.0', validate: true, exception: JSON::LD::JsonLdError::InvalidTermDefinition }, "Scoped on id map": { output: %({ "@context": { "@version": 1.1, "schema": "http://schema.org/", "name": "schema:name", "body": "schema:articleBody", "words": "schema:wordCount", "post": { "@id": "schema:blogPost", "@container": "@id", "@context": { "@base": "http://example.com/posts/" } } }, "@id": "http://example.com/", "@type": "schema:Blog", "name": "World Financial News", "post": { "1/en": { "body": "World commodities were up today with heavy trading of crude oil...", "words": 1539 }, "1/de": { "body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...", "words": 1204 } } }), input: %([{ "@id": "http://example.com/", "@type": ["http://schema.org/Blog"], "http://schema.org/name": [{"@value": "World Financial News"}], "http://schema.org/blogPost": [{ "@id": "http://example.com/posts/1/en", "http://schema.org/articleBody": [ {"@value": "World commodities were up today with heavy trading of crude oil..."} ], "http://schema.org/wordCount": [{"@value": 1539}] }, { "@id": "http://example.com/posts/1/de", "http://schema.org/articleBody": [ {"@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."} ], "http://schema.org/wordCount": [{"@value": 1204}] }] }]) }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end context "scoped context on @type" do { "adding new term" => { input: %([ { "http://example/a": [{ "@type": ["http://example/Foo"], "http://example.org/bar": [{"@value": "baz"}] }] } ]), context: %({ "@vocab": "http://example/", "Foo": {"@context": {"bar": "http://example.org/bar"}} }), output: %({ "@context": { "@vocab": "http://example/", "Foo": {"@context": {"bar": "http://example.org/bar"}} }, "a": {"@type": "Foo", "bar": "baz"} }) }, "overriding a term" => { input: %([ { "http://example/a": [{ "@type": ["http://example/Foo"], "http://example/bar": [{"@id": "http://example/baz"}] }] } ]), context: %({ "@vocab": "http://example/", "Foo": {"@context": {"bar": {"@type": "@id"}}}, "bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"} }), output: %({ "@context": { "@vocab": "http://example/", "Foo": {"@context": {"bar": {"@type": "@id"}}}, "bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"} }, "a": {"@type": "Foo", "bar": "http://example/baz"} }), }, "alias of @type" => { input: %([ { "http://example/a": [{ "@type": ["http://example/Foo"], "http://example.org/bar": [{"@value": "baz"}] }] } ]), context: %({ "@vocab": "http://example/", "type": "@type", "Foo": {"@context": {"bar": "http://example.org/bar"}} }), output: %({ "@context": { "@vocab": "http://example/", "type": "@type", "Foo": {"@context": {"bar": "http://example.org/bar"}} }, "a": {"type": "Foo", "bar": "baz"} }), }, "deep @context does not affect nested nodes" => { input: %([ { "@type": ["http://example/Foo"], "http://example/bar": [{ "http://example/baz": [{"@id": "http://example/buzz"}] }] } ]), context: %({ "@vocab": "http://example/", "Foo": {"@context": {"baz": {"@type": "@vocab"}}} }), output: %({ "@context": { "@vocab": "http://example/", "Foo": {"@context": {"baz": {"@type": "@vocab"}}} }, "@type": "Foo", "bar": {"baz": {"@id": "http://example/buzz"}} }), }, "scoped context layers on intemediate contexts" => { input: %([{ "http://example/a": [{ "@type": ["http://example/B"], "http://example.com/a": [{"@value": "A in example.com"}], "http://example.org/c": [{"@value": "C in example.org"}] }], "http://example/c": [{"@value": "C in example"}] }]), context: %({ "@vocab": "http://example/", "B": {"@context": {"c": "http://example.org/c"}} }), output: %({ "@context": { "@vocab": "http://example/", "B": {"@context": {"c": "http://example.org/c"}} }, "a": { "@type": "B", "c": "C in example.org", "http://example.com/a": "A in example.com" }, "c": "C in example" }), }, "orders lexicographically" => { input: %([{ "@type": ["http://example/t2", "http://example/t1"], "http://example.org/foo": [ {"@id": "urn:bar"} ] }]), context: %({ "@vocab": "http://example/", "t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}}, "t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}} }), output: %({ "@context": { "@vocab": "http://example/", "t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}}, "t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}} }, "@type": ["t2", "t1"], "foo": "urn:bar" }), }, "with @container: @type" => { input: %([{ "http://example/typemap": [ {"http://example.org/a": [{"@value": "Object with @type "}], "@type": ["http://example/Type"]} ] }]), context: %({ "@vocab": "http://example/", "typemap": {"@container": "@type"}, "Type": {"@context": {"a": "http://example.org/a"}} }), output: %({ "@context": { "@vocab": "http://example/", "typemap": {"@container": "@type"}, "Type": {"@context": {"a": "http://example.org/a"}} }, "typemap": { "Type": {"a": "Object with @type "} } }) }, "Raises InvalidTermDefinition if processingMode is 1.0" => { input: %([ { "http://example/a": [{ "@type": ["http://example/Foo"], "http://example.org/bar": [{"@value": "baz"}] }] } ]), context: %({ "@vocab": "http://example/", "Foo": {"@context": {"bar": "http://example.org/bar"}} }), processingMode: 'json-ld-1.0', validate: true, exception: JSON::LD::JsonLdError::InvalidTermDefinition }, "applies context for all values" => { input: %([ { "@id": "http://example.org/id", "@type": ["http://example/type"], "http://example/a": [{ "@id": "http://example.org/Foo", "@type": ["http://example/Foo"], "http://example/bar": [{"@id": "http://example.org/baz"}] }] } ]), context: %({ "@vocab": "http://example/", "id": "@id", "type": "@type", "Foo": {"@context": {"id": null, "type": null}} }), output: %({ "@context": { "@vocab": "http://example/", "id": "@id", "type": "@type", "Foo": {"@context": {"id": null, "type": null}} }, "id": "http://example.org/id", "type": "http://example/type", "a": { "@id": "http://example.org/Foo", "@type": "Foo", "bar": {"@id": "http://example.org/baz"} } }), }, }.each_pair do |title, params| it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))} end end context "compact IRI selection" do { "does not compact using expanded term in 1.0" => { input: %({"http://example.org/foo": "term"}), context: %({"ex": {"@id": "http://example.org/"}}), output: %({ "@context": {"ex": {"@id": "http://example.org/"}}, "http://example.org/foo": "term" }), processingMode: "json-ld-1.0" }, "does not compact using expanded term in 1.1" => { input: %({"http://example.org/foo": "term"}), context: %({"ex": {"@id": "http://example.org/"}}), output: %({ "@context": {"ex": {"@id": "http://example.org/"}}, "http://example.org/foo": "term" }), processingMode: "json-ld-1.1" }, "does not compact using simple term not ending in gen-delim" => { input: %({"http://example.org/foo": "term"}), context: %({"ex": "http://example.org/f"}), output: %({ "@context": {"ex": "http://example.org/f"}, "http://example.org/foo": "term" }) }, "compacts using simple term ending in gen-delim ('/')" => { input: %({"http://example.org/foo": "term"}), context: %({"ex": "http://example.org/"}), output: %({ "@context": {"ex": "http://example.org/"}, "ex:foo": "term" }) }, "compacts using simple term ending in gen-delim (':')" => { input: %({"http://example.org/foo:bar": "term"}), context: %({"ex": "http://example.org/foo:"}), output: %({ "@context": {"ex": "http://example.org/foo:"}, "ex:bar": "term" }) }, "compacts using simple term ending in gen-delim ('?')" => { input: %({"http://example.org/foo?bar": "term"}), context: %({"ex": "http://example.org/foo?"}), output: %({ "@context": {"ex": "http://example.org/foo?"}, "ex:bar": "term" }) }, "compacts using simple term ending in gen-delim ('#')" => { input: %({"http://example.org/foo#bar": "term"}), context: %({"ex": "http://example.org/foo#"}), output: %({ "@context": {"ex": "http://example.org/foo#"}, "ex:bar": "term" }) }, "compacts using simple term ending in gen-delim ('[')" => { input: %({"http://example.org/foo[bar": "term"}), context: %({"ex": "http://example.org/foo["}), output: %({ "@context": {"ex": "http://example.org/foo["}, "ex:bar": "term" }) }, "compacts using simple term ending in gen-delim (']')" => { input: %({"http://example.org/foo]bar": "term"}), context: %({"ex": "http://example.org/foo]"}), output: %({ "@context": {"ex": "http://example.org/foo]"}, "ex:bar": "term" }) }, "compacts using simple term ending in gen-delim ('@')" => { input: %({"http://example.org/foo@bar": "term"}), context: %({"ex": "http://example.org/foo@"}), output: %({ "@context": {"ex": "http://example.org/foo@"}, "ex:bar": "term" }) }, "compacts using base if @vocab: relative" => { input: %({"http://example.org/foo/bar": "term"}), context: %({"@base": "http://example.org/foo/", "@vocab": ""}), output: %({ "@context": {"@base": "http://example.org/foo/", "@vocab": ""}, "bar": "term" }) }, }.each do |title, params| it(title) {run_compact(params)} end end end context "html" do { "Compacts embedded JSON-LD script element": { input: %( ), context: %({"foo": {"@id": "http://example.com/foo", "@container": "@list"}}), output: %({ "@context": { "foo": {"@id": "http://example.com/foo", "@container": "@list"} }, "foo": ["bar"] }) }, "Compacts first script element": { input: %( ), context: %({"foo": {"@id": "http://example.com/foo", "@container": "@list"}}), output: %({ "@context": { "foo": {"@id": "http://example.com/foo", "@container": "@list"} }, "foo": ["bar"] }) }, "Compacts targeted script element": { input: %( ), context: %({"ex": "http://example.com/"}), output: %({ "@context": {"ex": "http://example.com/"}, "@graph": [ {"ex:foo": "foo"}, {"ex:bar": "bar"} ] }), base: "http://example.org/doc#second" }, "Compacts all script elements with extractAllScripts option": { input: %( ), context: %({ "ex": "http://example.com/", "foo": {"@id": "http://example.com/foo", "@container": "@list"} }), output: %({ "@context": { "ex": "http://example.com/", "foo": {"@id": "http://example.com/foo", "@container": "@list"} }, "@graph": [ {"foo": ["bar"]}, { "@graph": [ {"ex:foo": "foo"}, {"ex:bar": "bar"} ] } ] }), extractAllScripts: true }, }.each do |title, params| it(title) do params[:input] = StringIO.new(params[:input]) params[:input].send(:define_singleton_method, :content_type) {"text/html"} run_compact params.merge(validate: true) end end end context "JSON-LD-star" do { "subject-iii": { input: %([{ "@id": { "@id": "http://example/s1", "http://example/p1": [{"@id": "http://example/o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": "ex:s1", "ex:p1": {"@id": "ex:o1"} }, "ex:p": {"@id": "ex:o"} }) }, "subject-iib": { input: %([{ "@id": { "@id": "http://example/s1", "http://example/p1": [{"@id": "_:o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": "ex:s1", "ex:p1": {"@id": "_:o1"} }, "ex:p": {"@id": "ex:o"} }) }, "subject-iil": { input: %([{ "@id": { "@id": "http://example/s1", "http://example/p1": [{"@value": "o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": "ex:s1", "ex:p1": "o1" }, "ex:p": {"@id": "ex:o"} }) }, "subject-bii": { input: %([{ "@id": { "@id": "_:s1", "http://example/p1": [{"@id": "http://example/o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": "_:s1", "ex:p1": {"@id": "ex:o1"} }, "ex:p": {"@id": "ex:o"} }) }, "subject-bib": { input: %([{ "@id": { "@id": "_:s1", "http://example/p1": [{"@id": "_:o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": "_:s1", "ex:p1": {"@id": "_:o1"} }, "ex:p": {"@id": "ex:o"} }) }, "subject-bil": { input: %([{ "@id": { "@id": "_:s1", "http://example/p1": [{"@value": "o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": "_:s1", "ex:p1": "o1" }, "ex:p": {"@id": "ex:o"} }) }, "object-iii": { input: %([{ "@id": "http://example/s", "http://example/p": [{ "@id": { "@id": "http://example/s1", "http://example/p1": [{"@id": "http://example/o1"}] } }] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": "ex:s", "ex:p": { "@id": { "@id": "ex:s1", "ex:p1": {"@id": "ex:o1"} } } }) }, "object-iib": { input: %([{ "@id": "http://example/s", "http://example/p": [{ "@id": { "@id": "http://example/s1", "http://example/p1": [{"@id": "_:o1"}] } }] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": "ex:s", "ex:p": { "@id": { "@id": "ex:s1", "ex:p1": {"@id": "_:o1"} } } }) }, "object-iil": { input: %([{ "@id": "http://example/s", "http://example/p": [{ "@id": { "@id": "http://example/s1", "http://example/p1": [{"@value": "o1"}] } }] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": "ex:s", "ex:p": { "@id": { "@id": "ex:s1", "ex:p1": "o1" } } }) }, "recursive-subject": { input: %([{ "@id": { "@id": { "@id": "http://example/s2", "http://example/p2": [{"@id": "http://example/o2"}] }, "http://example/p1": [{"@id": "http://example/o1"}] }, "http://example/p": [{"@id": "http://example/o"}] }]), context: %({"ex": "http://example/"}), output: %({ "@context": {"ex": "http://example/"}, "@id": { "@id": { "@id": "ex:s2", "ex:p2": {"@id": "ex:o2"} }, "ex:p1": {"@id": "ex:o1"} }, "ex:p": {"@id": "ex:o"} }) }, }.each do |name, params| it(name) {run_compact(params.merge(rdfstar: true))} end end context "problem cases" do { "issue json-ld-framing#64": { input: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/vocab#" }, "@id": "http://example.org/1", "@type": "HumanMadeObject", "produced_by": { "@type": "Production", "_label": "Top Production", "part": { "@type": "Production", "_label": "Test Part" } } }), context: %({ "@version": 1.1, "@vocab": "http://example.org/vocab#", "Production": { "@context": { "part": { "@type": "@id", "@container": "@set" } } } }), output: %({ "@context": { "@version": 1.1, "@vocab": "http://example.org/vocab#", "Production": { "@context": { "part": { "@type": "@id", "@container": "@set" } } } }, "@id": "http://example.org/1", "@type": "HumanMadeObject", "produced_by": { "@type": "Production", "part": [{ "@type": "Production", "_label": "Test Part" }], "_label": "Top Production" } }), processingMode: "json-ld-1.1" } }.each do |title, params| it title do run_compact(params) end end end def run_compact(params) input, output, context = params[:input], params[:output], params[:context] params[:base] ||= nil context ||= output # Since it will have the context input = ::JSON.parse(input) if input.is_a?(String) output = ::JSON.parse(output) if output.is_a?(String) context = ::JSON.parse(context) if context.is_a?(String) context = context['@context'] if context.key?('@context') pending params.fetch(:pending, "test implementation") unless input if params[:exception] expect {JSON::LD::API.compact(input, context, logger: logger, **params)}.to raise_error(params[:exception]) else jld = nil if params[:write] expect{jld = JSON::LD::API.compact(input, context, logger: logger, **params)}.to write(params[:write]).to(:error) else expect{jld = JSON::LD::API.compact(input, context, logger: logger, **params)}.not_to write.to(:error) end expect(jld).to produce_jsonld(output, logger) # Compare expanded jld/output too to make sure list values remain ordered exp_jld = JSON::LD::API.expand(jld, processingMode: 'json-ld-1.1', rdfstar: params[:rdfstar]) exp_output = JSON::LD::API.expand(output, processingMode: 'json-ld-1.1', rdfstar: params[:rdfstar]) expect(exp_jld).to produce_jsonld(exp_output, logger) end end end