From 1e35c138e0ae1e8c65d6b21aaef685eef3b0e8ae Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sun, 7 Aug 2022 15:13:16 -0700 Subject: [PATCH 1/3] Update serializer to use any `serializer_opts` option passed, which defaults to `JSON_STATE`. --- lib/json/ld/api.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/json/ld/api.rb b/lib/json/ld/api.rb index af0266e..274b07b 100644 --- a/lib/json/ld/api.rb +++ b/lib/json/ld/api.rb @@ -827,8 +827,10 @@ def self.load_html(input, url:, # other arguments that may be passed for some specific implementation. # @param [Hash] options # options passed from the invoking context. + # @option options [Object] :serializer_opts (JSON_STATE) def self.serializer(object, *args, **options) - MultiJson.dump(object, JSON_STATE) + serializer_opts = options.fetch(:serializer_opts, JSON_STATE) + MultiJson.dump(object, serializer_opts) end ## From a01667b4324d306d4ffa3cfef7420f77b73708eb Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sun, 7 Aug 2022 15:14:11 -0700 Subject: [PATCH 2/3] Consolidate CLI command processing and allow for other formats than `:jsonld`. This allows for YAML-LD to re-used the same commands. --- lib/json/ld/format.rb | 196 +++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 115 deletions(-) diff --git a/lib/json/ld/format.rb b/lib/json/ld/format.rb index 728b0e1..5022cc5 100644 --- a/lib/json/ld/format.rb +++ b/lib/json/ld/format.rb @@ -45,8 +45,80 @@ def self.detect(sample) !sample.include?("http://www.w3.org/ns/csvw") end + # Specify how to execute CLI commands for each supported format. + # Derived formats (e.g., YAML-LD) define their own entrypoints. + LD_FORMATS = { + jsonld: { + expand: ->(input, **options) { + JSON::LD::API.expand(input, + serializer: JSON::LD::API.method(:serializer), + **options) + }, + compact: ->(input, **options) { + JSON::LD::API.compact(input, + options[:context], + serializer: JSON::LD::API.method(:serializer), + **options) + }, + flatten: ->(input, **options) { + JSON::LD::API.flatten(input, + options[:context], + serializer: JSON::LD::API.method(:serializer), + **options) + }, + frame: ->(input, **options) { + JSON::LD::API.frame(input, + options[:frame], + serializer: JSON::LD::API.method(:serializer), + **options) + }, + } + } + + # Execute the body of a CLI command, generic for each different API method based on definitions on {LD_FORMATS}. + # + # Expands the input, or transforms from an RDF format based on the `:format` option, and then executes the appropriate command based on `:output_format` and does appropriate output serialization. + # @private + def self.cli_exec(command, files, output: $stdin, **options) + output.set_encoding(Encoding::UTF_8) if output.respond_to?(:set_encoding) && RUBY_PLATFORM == "java" + options[:base] ||= options[:base_uri] + + # Parse using input format, serialize using output format + in_fmt = LD_FORMATS[options.fetch(:format, :jsonld)] + out_fmt = LD_FORMATS[options.fetch(:output_format, :jsonld)] + + if in_fmt + # Input is a JSON-LD based source (or derived) + if files.empty? + # If files are empty, either use options[:evaluate] or STDIN + input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN + input.set_encoding(options.fetch(:encoding, Encoding::UTF_8)) + expanded = in_fmt[:expand].call(input, serializer: nil, **options) + output.puts out_fmt[command].call(expanded, expanded: true, **options) + else + files.each do |file| + expanded = in_fmt[:expand].call(file, serializer: nil, **options) + output.puts out_fmt[command].call(expanded, expanded: true, **options) + end + end + else + # Turn RDF into JSON-LD first + RDF::CLI.parse(files, **options) do |reader| + JSON::LD::API.fromRdf(reader, serializer: nil, **options) do |expanded| + output.puts out_fmt[command].call(expanded, expanded: true, **options) + end + end + end + end + ## - # Hash of CLI commands appropriate for this format + # Hash of CLI commands appropriate for this format: + # + # * `expand` => {JSON::LD::API.expand} + # * `compact` => {JSON::LD::API.compact} + # * `flatten` => {JSON::LD::API.flatten} + # * `frame` => {JSON::LD::API.frame} + # # @return [Hash{Symbol => Hash}] def self.cli_commands { @@ -54,73 +126,21 @@ def self.cli_commands description: "Expand JSON-LD or parsed RDF", parse: false, help: "expand [--context ] files ...", - filter: {output_format: :jsonld}, # Only shows output format set + filter: {output_format: LD_FORMATS.keys}, # Only shows output format set lambda: ->(files, **options) do - out = options[:output] || $stdout - out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java" options = options.merge(expandContext: options.delete(:context)) if options.key?(:context) - options[:base] ||= options[:base_uri] - if options[:format] == :jsonld - if files.empty? - # If files are empty, either use options[:evaluate] or STDIN - input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN - input.set_encoding(options.fetch(:encoding, Encoding::UTF_8)) - JSON::LD::API.expand(input, validate: false, **options) do |expanded| - out.puts expanded.to_json(JSON::LD::JSON_STATE) - end - else - files.each do |file| - JSON::LD::API.expand(file, validate: false, **options) do |expanded| - out.puts expanded.to_json(JSON::LD::JSON_STATE) - end - end - end - else - # Turn RDF into JSON-LD first - RDF::CLI.parse(files, **options) do |reader| - JSON::LD::API.fromRdf(reader) do |expanded| - out.puts expanded.to_json(JSON::LD::JSON_STATE) - end - end - end + cli_exec(:expand, files, **options) end, option_use: {context: :removed} }, compact: { description: "Compact JSON-LD or parsed RDF", parse: false, - filter: {output_format: :jsonld}, # Only shows output format set + filter: {output_format: LD_FORMATS.keys}, # Only shows output format set help: "compact --context files ...", lambda: ->(files, **options) do raise ArgumentError, "Compacting requires a context" unless options[:context] - out = options[:output] || $stdout - out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java" - options[:base] ||= options[:base_uri] - if options[:format] == :jsonld - if files.empty? - # If files are empty, either use options[:evaluate] or STDIN - input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN - input.set_encoding(options.fetch(:encoding, Encoding::UTF_8)) - JSON::LD::API.compact(input, options[:context], **options) do |compacted| - out.puts compacted.to_json(JSON::LD::JSON_STATE) - end - else - files.each do |file| - JSON::LD::API.compact(file, options[:context], **options) do |compacted| - out.puts compacted.to_json(JSON::LD::JSON_STATE) - end - end - end - else - # Turn RDF into JSON-LD first - RDF::CLI.parse(files, **options) do |reader| - JSON::LD::API.fromRdf(reader) do |expanded| - JSON::LD::API.compact(expanded, options[:context], **options) do |compacted| - out.puts compacted.to_json(JSON::LD::JSON_STATE) - end - end - end - end + cli_exec(:compact, files, **options) end, options: [ RDF::CLI::Option.new( @@ -136,36 +156,9 @@ def self.cli_commands description: "Flatten JSON-LD or parsed RDF", parse: false, help: "flatten [--context ] files ...", - filter: {output_format: :jsonld}, # Only shows output format set + filter: {output_format: LD_FORMATS.keys}, # Only shows output format set lambda: ->(files, **options) do - out = options[:output] || $stdout - out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java" - options[:base] ||= options[:base_uri] - if options[:format] == :jsonld - if files.empty? - # If files are empty, either use options[:evaluate] or STDIN - input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN - input.set_encoding(options.fetch(:encoding, Encoding::UTF_8)) - JSON::LD::API.flatten(input, options[:context], **options) do |flattened| - out.puts flattened.to_json(JSON::LD::JSON_STATE) - end - else - files.each do |file| - JSON::LD::API.flatten(file, options[:context], **options) do |flattened| - out.puts flattened.to_json(JSON::LD::JSON_STATE) - end - end - end - else - # Turn RDF into JSON-LD first - RDF::CLI.parse(files, **options) do |reader| - JSON::LD::API.fromRdf(reader) do |expanded| - JSON::LD::API.flatten(expanded, options[:context], **options) do |flattened| - out.puts flattened.to_json(JSON::LD::JSON_STATE) - end - end - end - end + cli_exec(:compact, files, **options) end, options: [ RDF::CLI::Option.new( @@ -188,37 +181,10 @@ def self.cli_commands description: "Frame JSON-LD or parsed RDF", parse: false, help: "frame --frame files ...", - filter: {output_format: :jsonld}, # Only shows output format set + filter: {output_format: LD_FORMATS.keys}, # Only shows output format set lambda: ->(files, **options) do raise ArgumentError, "Framing requires a frame" unless options[:frame] - out = options[:output] || $stdout - out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java" - options[:base] ||= options[:base_uri] - if options[:format] == :jsonld - if files.empty? - # If files are empty, either use options[:evaluate] or STDIN - input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN - input.set_encoding(options.fetch(:encoding, Encoding::UTF_8)) - JSON::LD::API.frame(input, options[:frame], **options) do |framed| - out.puts framed.to_json(JSON::LD::JSON_STATE) - end - else - files.each do |file| - JSON::LD::API.frame(file, options[:frame], **options) do |framed| - out.puts framed.to_json(JSON::LD::JSON_STATE) - end - end - end - else - # Turn RDF into JSON-LD first - RDF::CLI.parse(files, **options) do |reader| - JSON::LD::API.fromRdf(reader) do |expanded| - JSON::LD::API.frame(expanded, options[:frame], **options) do |framed| - out.puts framed.to_json(JSON::LD::JSON_STATE) - end - end - end - end + cli_exec(:compact, files, **options) end, option_use: {context: :removed}, options: [ From 3d4f8ea92ab6ad21095adf3b4645a80db38dc317 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sun, 7 Aug 2022 15:24:12 -0700 Subject: [PATCH 3/3] Version 3.2.3. --- VERSION | 2 +- json-ld.gemspec | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index be94e6f..b347b11 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.2 +3.2.3 diff --git a/json-ld.gemspec b/json-ld.gemspec index 0d8c553..37d9eed 100755 --- a/json-ld.gemspec +++ b/json-ld.gemspec @@ -32,13 +32,13 @@ Gem::Specification.new do |gem| gem.required_ruby_version = '>= 2.6' gem.requirements = [] - gem.add_runtime_dependency 'rdf', '~> 3.2' + gem.add_runtime_dependency 'rdf', '~> 3.2', '>= 3.2.9' gem.add_runtime_dependency 'multi_json', '~> 1.15' gem.add_runtime_dependency 'link_header', '~> 0.0', '>= 0.0.8' gem.add_runtime_dependency 'json-canonicalization', '~> 0.3' gem.add_runtime_dependency 'htmlentities', '~> 4.3' gem.add_runtime_dependency 'rack', '~> 2.2' - gem.add_development_dependency 'sinatra-linkeddata','~> 3.1' + gem.add_development_dependency 'sinatra-linkeddata','~> 3.2' gem.add_development_dependency 'jsonlint', '~> 0.3' unless is_java gem.add_development_dependency 'oj', '~> 3.13' unless is_java gem.add_development_dependency 'yajl-ruby', '~> 1.4' unless is_java @@ -49,7 +49,7 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'rdf-turtle', '~> 3.2' gem.add_development_dependency 'rdf-vocab', '~> 3.2' gem.add_development_dependency 'rdf-xsd', '~> 3.2' - gem.add_development_dependency 'rspec', '~> 3.10' + gem.add_development_dependency 'rspec', '~> 3.11' gem.add_development_dependency 'rspec-its', '~> 1.3' gem.add_development_dependency 'yard' , '~> 0.9'