json-ld 3.3.1 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5715dffdbdb323f985e7bdf87089a40f2a1cf41d5087e57ab8247385fa6ac65
4
- data.tar.gz: ccc4d39e21b7842cfb80b605416cafffe1ea8ef65a4c7e52678804ce5dcdea64
3
+ metadata.gz: d001920e29ad882ce1ffd196b475b8fdbf4b7ed3f8bf5e569713fa93efda5cf9
4
+ data.tar.gz: f30409b4fc97e1e604a003f0973c20c75cb4c705852d9622aad15d94c574eafb
5
5
  SHA512:
6
- metadata.gz: 203ab67a38535c5c977b95a90efa691947e3d87db7cf4b5c052608590a1695362788f9a32c4896bc1a180607923013c2924d948e27fe4ffb3d8fdde2c14bf04b
7
- data.tar.gz: 22523bf4c3e6aa951e50ed0e0f942aaa6a5c83737d5686884106108391f253e73d76626288efb4934debea5064cc5ac88f9b056aa9339a55156aeccfdf210f3a
6
+ metadata.gz: cbb8283e5bf415a9cb05f17f29947d7f546699f8a5fa0c674559b5343ff344d87a36c15b26389bae813fb9daac26876b8ddaa2871181cd2c0ab49c513b5f96e6
7
+ data.tar.gz: 111003a143c84c9820c120bbc42c5199b493cbcd4b1b33de64ef65ea578ba4130aec6e4c534121299f5e2420d51984901056d52a5c856a7c79069c00fb9f257f
data/README.md CHANGED
@@ -603,6 +603,10 @@ To get a local working copy of the development repository, do:
603
603
 
604
604
  % git clone git://github.com/ruby-rdf/json-ld.git
605
605
 
606
+ ## Change Log
607
+
608
+ See [Release Notes on GitHub](https://github.com/ruby-rdf/json-ld/releases)
609
+
606
610
  ## Mailing List
607
611
  * <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
608
612
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.3.1
1
+ 3.3.2
data/lib/json/ld/api.rb CHANGED
@@ -290,8 +290,7 @@ module JSON
290
290
  def self.flatten(input, context, expanded: false, serializer: nil, **options)
291
291
  flattened = []
292
292
  options = {
293
- compactToRelative: true,
294
- extractAllScripts: true
293
+ compactToRelative: true
295
294
  }.merge(options)
296
295
 
297
296
  # Expand input to simplify processing
@@ -518,6 +517,8 @@ module JSON
518
517
  # @option options (see #initialize)
519
518
  # @option options [Boolean] :produceGeneralizedRdf (false)
520
519
  # If true, output will include statements having blank node predicates, otherwise they are dropped.
520
+ # @option options [Boolean] :extractAllScripts (true)
521
+ # 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.
521
522
  # @raise [JsonLdError]
522
523
  # @yield statement
523
524
  # @yieldparam [RDF::Statement] statement
@@ -638,7 +639,7 @@ module JSON
638
639
  options[:headers]['Accept'].sub('application/ld+json,',
639
640
  "application/ld+json;profile=#{requestProfile}, application/ld+json;q=0.9,")
640
641
  end
641
- documentLoader.call(url, **options) do |remote_doc|
642
+ documentLoader.call(url, extractAllScripts: extractAllScripts, **options) do |remote_doc|
642
643
  case remote_doc
643
644
  when RDF::Util::File::RemoteDocument
644
645
  # Convert to RemoteDocument
@@ -758,6 +759,28 @@ module JSON
758
759
  alias fromRDF fromRdf
759
760
  end
760
761
 
762
+ ##
763
+ # Hash of recognized script types and the loaders that decode them
764
+ # into a hash or array of hashes.
765
+ #
766
+ # @return Hash{type, Proc}
767
+ SCRIPT_LOADERS = {
768
+ 'application/ld+json' => ->(content, url:, **options) do
769
+ validate_input(content, url: url) if options[:validate]
770
+ mj_opts = options.keep_if { |k, v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v) }
771
+ MultiJson.load(content, **mj_opts)
772
+ end
773
+ }
774
+
775
+ ##
776
+ # Adds a loader for some specific content type
777
+ #
778
+ # @param [String] type
779
+ # @param [Proc] loader
780
+ def self.add_script_loader(type, loader)
781
+ SCRIPT_LOADERS[type] = loader
782
+ end
783
+
761
784
  ##
762
785
  # Load one or more script tags from an HTML source.
763
786
  # Unescapes and uncomments input, returns the internal representation
@@ -812,47 +835,52 @@ module JSON
812
835
  element = input.at_xpath("//script[@id='#{id}']")
813
836
  raise JSON::LD::JsonLdError::LoadingDocumentFailed, "No script tag found with id=#{id}" unless element
814
837
 
815
- unless element.attributes['type'].to_s.start_with?('application/ld+json')
838
+ script_type = SCRIPT_LOADERS.keys.detect {|type| element.attributes['type'].to_s.start_with?(type)}
839
+ unless script_type
816
840
  raise JSON::LD::JsonLdError::LoadingDocumentFailed,
817
841
  "Script tag has type=#{element.attributes['type']}"
818
842
  end
819
843
 
820
- content = element.inner_html
821
- validate_input(content, url: url) if options[:validate]
822
- mj_opts = options.keep_if { |k, v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v) }
823
- MultiJson.load(content, **mj_opts)
844
+ loader = SCRIPT_LOADERS[script_type]
845
+ loader.call(element.inner_html, url: url, **options)
824
846
  elsif extractAllScripts
825
847
  res = []
826
- elements = if profile
827
- es = input.xpath("//script[starts-with(@type, 'application/ld+json;profile=#{profile}')]")
828
- # If no profile script, just take a single script without profile
829
- es = [input.at_xpath("//script[starts-with(@type, 'application/ld+json')]")].compact if es.empty?
830
- es
831
- else
832
- input.xpath("//script[starts-with(@type, 'application/ld+json')]")
833
- end
834
- elements.each do |element|
835
- content = element.inner_html
836
- validate_input(content, url: url) if options[:validate]
837
- mj_opts = options.keep_if { |k, v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v) }
838
- r = MultiJson.load(content, **mj_opts)
839
- if r.is_a?(Hash)
840
- res << r
841
- elsif r.is_a?(Array)
842
- res.concat(r)
848
+
849
+ SCRIPT_LOADERS.each do |type, loader|
850
+ elements = if profile
851
+ es = input.xpath("//script[starts-with(@type, '#{type};profile=#{profile}')]")
852
+ # If no profile script, just take a single script without profile
853
+ es = [input.at_xpath("//script[starts-with(@type, '#{type}')]")].compact if es.empty?
854
+ es
855
+ else
856
+ input.xpath("//script[starts-with(@type, '#{type}')]")
857
+ end
858
+ elements.each do |element|
859
+ content = element.inner_html
860
+ r = loader.call(content, url: url, extractAllScripts: true, **options)
861
+ if r.is_a?(Hash)
862
+ res << r
863
+ elsif r.is_a?(Array)
864
+ res.concat(r)
865
+ end
843
866
  end
844
867
  end
845
868
  res
846
869
  else
847
- # Find the first script with type application/ld+json.
848
- element = input.at_xpath("//script[starts-with(@type, 'application/ld+json;profile=#{profile}')]") if profile
849
- element ||= input.at_xpath("//script[starts-with(@type, 'application/ld+json')]")
850
- raise JSON::LD::JsonLdError::LoadingDocumentFailed, "No script tag found" unless element
870
+ # Find the first script with a known type
871
+ script_type, element = nil, nil
872
+ SCRIPT_LOADERS.keys.each do |type|
873
+ next if script_type # already found the type
874
+ element = input.at_xpath("//script[starts-with(@type, '#{type};profile=#{profile}')]") if profile
875
+ element ||= input.at_xpath("//script[starts-with(@type, '#{type}')]")
876
+ script_type = type if element
877
+ end
878
+ unless script_type
879
+ raise JSON::LD::JsonLdError::LoadingDocumentFailed, "No script tag found" unless element
880
+ end
851
881
 
852
882
  content = element.inner_html
853
- validate_input(content, url: url) if options[:validate]
854
- mj_opts = options.keep_if { |k, v| k != :adapter || MUTLI_JSON_ADAPTERS.include?(v) }
855
- MultiJson.load(content, **mj_opts)
883
+ SCRIPT_LOADERS[script_type].call(content, url: url, **options)
856
884
  end
857
885
  rescue MultiJson::ParseError => e
858
886
  raise JSON::LD::JsonLdError::InvalidScriptElement, e.message
@@ -299,10 +299,10 @@ module JSON
299
299
  else
300
300
  index_key = context.expand_iri(index_key, vocab: true)
301
301
  container_key = context.compact_iri(index_key, vocab: true)
302
- map_key, *others = Array(compacted_item[container_key])
302
+ map_key, *others = Array(compacted_item.is_a?(Hash) && compacted_item[container_key])
303
303
  if map_key.is_a?(String)
304
304
  case others.length
305
- when 0 then compacted_item.delete(container_key)
305
+ when 0 then compacted_item.delete(container_key) if compacted_item.is_a?(Hash)
306
306
  when 1 then compacted_item[container_key] = others.first
307
307
  else compacted_item[container_key] = others
308
308
  end
@@ -316,15 +316,15 @@ module JSON
316
316
  map_key = expanded_item['@language']
317
317
  value?(expanded_item) ? expanded_item['@value'] : compacted_item
318
318
  elsif container.include?('@type')
319
- map_key, *types = Array(compacted_item[container_key])
319
+ map_key, *types = Array(compacted_item.is_a?(Hash) && compacted_item[container_key])
320
320
  case types.length
321
- when 0 then compacted_item.delete(container_key)
321
+ when 0 then compacted_item.delete(container_key) if compacted_item.is_a?(Hash)
322
322
  when 1 then compacted_item[container_key] = types.first
323
323
  else compacted_item[container_key] = types
324
324
  end
325
325
 
326
326
  # if compacted_item contains a single entry who's key maps to @id, then recompact the item without @type
327
- if compacted_item.keys.length == 1 && expanded_item.key?('@id')
327
+ if compacted_item.is_a?(Hash) && compacted_item.keys.length == 1 && expanded_item.key?('@id')
328
328
  compacted_item = compact({ '@id' => expanded_item['@id'] },
329
329
  base: base,
330
330
  property: item_active_property,
@@ -843,9 +843,11 @@ module JSON
843
843
  end
844
844
  end
845
845
 
846
- if previous_definition&.protected? && definition != previous_definition && !override_protected
846
+ if !override_protected && previous_definition&.protected?
847
+ if definition != previous_definition
848
+ raise JSON::LD::JsonLdError::ProtectedTermRedefinition, "Attempt to redefine protected term #{term}"
849
+ end
847
850
  definition = previous_definition
848
- raise JSON::LD::JsonLdError::ProtectedTermRedefinition, "Attempt to redefine protected term #{term}"
849
851
  end
850
852
 
851
853
  term_definitions[term] = definition
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-ld
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.1
4
+ version: 3.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-04 00:00:00.000000000 Z
11
+ date: 2024-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: htmlentities
@@ -106,6 +106,34 @@ dependencies:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
108
  version: '3.3'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rexml
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '3.2'
116
+ type: :runtime
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '3.2'
123
+ - !ruby/object:Gem::Dependency
124
+ name: getoptlong
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '0.2'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '0.2'
109
137
  - !ruby/object:Gem::Dependency
110
138
  name: jsonlint
111
139
  requirement: !ruby/object:Gem::Requirement