json-ld 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/json/ld.rb +1 -1
- data/lib/json/ld/api.rb +12 -12
- data/lib/json/ld/compact.rb +26 -33
- data/lib/json/ld/context.rb +54 -47
- data/lib/json/ld/expand.rb +27 -32
- data/lib/json/ld/frame.rb +1 -1
- data/lib/json/ld/from_rdf.rb +1 -1
- data/lib/json/ld/to_rdf.rb +9 -3
- data/lib/json/ld/writer.rb +2 -2
- data/spec/context_spec.rb +43 -43
- data/spec/suite_expand_spec.rb +2 -0
- data/spec/suite_helper.rb +5 -0
- data/spec/to_rdf_spec.rb +3 -3
- metadata +5 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 686aaec1dba1b51a5f37e1d4ebd28395c189c0944022b1b9877c7c5a8500cef3
         | 
| 4 | 
            +
              data.tar.gz: 5a9f07dd8fc17e3b4b3129b45cbd783e5390b7921da10c62d7d087621e1e123d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f3bb2f7b57db9b1689e43ceca7fbe497f0c67fffd5c12a8a7b451f07e0acf45be1f45f30d3acfd2e7e5ab1a52b9486954e8af1ebceb40478599b1fa8d9809035
         | 
| 7 | 
            +
              data.tar.gz: 8acfd478567cec305f2a37e189a7ba11c2bb75463746bc1a114be79b71ea3e84b19632224515b0e2097c2a2a16293f098eb06556d74bb6a2a7e32516ad1476d3
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            3.1. | 
| 1 | 
            +
            3.1.1
         | 
    
        data/lib/json/ld.rb
    CHANGED
    
    | @@ -115,7 +115,7 @@ module JSON | |
| 115 115 | 
             
                  class CyclicIRIMapping < JsonLdError; @code = "cyclic IRI mapping"; end
         | 
| 116 116 | 
             
                  class InvalidBaseIRI < JsonLdError; @code = "invalid base IRI"; end
         | 
| 117 117 | 
             
                  class InvalidContainerMapping < JsonLdError; @code = "invalid container mapping"; end
         | 
| 118 | 
            -
                  class  | 
| 118 | 
            +
                  class InvalidContextEntry < JsonLdError; @code = "invalid context entry"; end
         | 
| 119 119 | 
             
                  class InvalidContextNullification < JsonLdError; @code = "invalid context nullification"; end
         | 
| 120 120 | 
             
                  class InvalidDefaultLanguage < JsonLdError; @code = "invalid default language"; end
         | 
| 121 121 | 
             
                  class InvalidIdValue < JsonLdError; @code = "invalid @id value"; end
         | 
    
        data/lib/json/ld/api.rb
    CHANGED
    
    | @@ -35,7 +35,7 @@ module JSON::LD | |
| 35 35 |  | 
| 36 36 | 
             
                # Options used for open_file
         | 
| 37 37 | 
             
                OPEN_OPTS = {
         | 
| 38 | 
            -
                  headers: {"Accept" => "application/ld+json, text/html;q=0.8, application/json;q=0.5"}
         | 
| 38 | 
            +
                  headers: {"Accept" => "application/ld+json, text/html;q=0.8, application/xhtml+xml;q=0.8, application/json;q=0.5"}
         | 
| 39 39 | 
             
                }
         | 
| 40 40 |  | 
| 41 41 | 
             
                # The following constants are used to reduce object allocations
         | 
| @@ -229,7 +229,7 @@ module JSON::LD | |
| 229 229 | 
             
                    # xxx) Add the given context to the output
         | 
| 230 230 | 
             
                    ctx = self.context.serialize
         | 
| 231 231 | 
             
                    if result.is_a?(Array)
         | 
| 232 | 
            -
                      kwgraph = self.context.compact_iri('@graph', vocab: true | 
| 232 | 
            +
                      kwgraph = self.context.compact_iri('@graph', vocab: true)
         | 
| 233 233 | 
             
                      result = result.empty? ? {} : {kwgraph => result}
         | 
| 234 234 | 
             
                    end
         | 
| 235 235 | 
             
                    result = ctx.merge(result) unless ctx.empty?
         | 
| @@ -295,7 +295,7 @@ module JSON::LD | |
| 295 295 | 
             
                    if context && !flattened.empty?
         | 
| 296 296 | 
             
                      # Otherwise, return the result of compacting flattened according the Compaction algorithm passing context ensuring that the compaction result uses the @graph keyword (or its alias) at the top-level, even if the context is empty or if there is only one element to put in the @graph array. This ensures that the returned document has a deterministic structure.
         | 
| 297 297 | 
             
                      compacted = as_array(compact(flattened, ordered: @options[:ordered]))
         | 
| 298 | 
            -
                      kwgraph = self.context.compact_iri('@graph' | 
| 298 | 
            +
                      kwgraph = self.context.compact_iri('@graph')
         | 
| 299 299 | 
             
                      flattened = self.context.serialize.merge(kwgraph => compacted)
         | 
| 300 300 | 
             
                    end
         | 
| 301 301 | 
             
                  end
         | 
| @@ -313,11 +313,11 @@ module JSON::LD | |
| 313 313 | 
             
                # @param [String, #read, Hash, Array] frame
         | 
| 314 314 | 
             
                #   The frame to use when re-arranging the data.
         | 
| 315 315 | 
             
                # @option options (see #initialize)
         | 
| 316 | 
            -
                # @option options ['@always', '@ | 
| 316 | 
            +
                # @option options ['@always', '@link', '@once', '@never'] :embed ('@once')
         | 
| 317 317 | 
             
                #   a flag specifying that objects should be directly embedded in the output, instead of being referred to by their IRI.
         | 
| 318 318 | 
             
                # @option options [Boolean] :explicit (false)
         | 
| 319 319 | 
             
                #   a flag specifying that for properties to be included in the output, they must be explicitly declared in the framing context.
         | 
| 320 | 
            -
                # @option options [Boolean] :requireAll ( | 
| 320 | 
            +
                # @option options [Boolean] :requireAll (false)
         | 
| 321 321 | 
             
                #   A flag specifying that all properties present in the input frame must either have a default value or be present in the JSON-LD input for the frame to match.
         | 
| 322 322 | 
             
                # @option options [Boolean] :omitDefault (false)
         | 
| 323 323 | 
             
                #   a flag specifying that properties that are missing from the JSON-LD input should be omitted from the output.
         | 
| @@ -394,7 +394,7 @@ module JSON::LD | |
| 394 394 | 
             
                    # Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
         | 
| 395 395 | 
             
                    create_node_map(value, framing_state[:graphMap], active_graph: '@default')
         | 
| 396 396 |  | 
| 397 | 
            -
                    frame_keys = frame.keys.map {|k| context.expand_iri(k, vocab: true | 
| 397 | 
            +
                    frame_keys = frame.keys.map {|k| context.expand_iri(k, vocab: true)}
         | 
| 398 398 | 
             
                    if frame_keys.include?('@graph')
         | 
| 399 399 | 
             
                      # If frame contains @graph, it matches the default graph.
         | 
| 400 400 | 
             
                      framing_state[:graph] = '@default'
         | 
| @@ -436,7 +436,7 @@ module JSON::LD | |
| 436 436 | 
             
                    result = if !compacted.is_a?(Array)
         | 
| 437 437 | 
             
                      context.serialize.merge(compacted)
         | 
| 438 438 | 
             
                    else
         | 
| 439 | 
            -
                      kwgraph = context.compact_iri('@graph' | 
| 439 | 
            +
                      kwgraph = context.compact_iri('@graph')
         | 
| 440 440 | 
             
                      context.serialize.merge({kwgraph => compacted})
         | 
| 441 441 | 
             
                    end
         | 
| 442 442 | 
             
                    log_debug(".frame") {"after compact: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
         | 
| @@ -535,7 +535,7 @@ module JSON::LD | |
| 535 535 | 
             
                # @param [Boolean] extractAllScripts
         | 
| 536 536 | 
             
                #   If set to `true`, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary.
         | 
| 537 537 | 
             
                # @param [String] profile
         | 
| 538 | 
            -
                #   When the resulting `contentType` is `text/html`, this option determines the profile to use for selecting a JSON-LD script elements.
         | 
| 538 | 
            +
                #   When the resulting `contentType` is `text/html` or `application/xhtml+xml`, this option determines the profile to use for selecting a JSON-LD script elements.
         | 
| 539 539 | 
             
                # @param [String] requestProfile
         | 
| 540 540 | 
             
                #   One or more IRIs to use in the request as a profile parameter.
         | 
| 541 541 | 
             
                # @param [Boolean] validate
         | 
| @@ -612,7 +612,7 @@ module JSON::LD | |
| 612 612 | 
             
                    # Parse any HTML
         | 
| 613 613 | 
             
                    if remote_doc.document.is_a?(String)
         | 
| 614 614 | 
             
                      remote_doc.document = case remote_doc.contentType
         | 
| 615 | 
            -
                      when 'text/html'
         | 
| 615 | 
            +
                      when 'text/html', 'application/xhtml+xml'
         | 
| 616 616 | 
             
                        load_html(remote_doc.document,
         | 
| 617 617 | 
             
                                  url: remote_doc.documentUrl,
         | 
| 618 618 | 
             
                                  extractAllScripts: extractAllScripts,
         | 
| @@ -628,7 +628,7 @@ module JSON::LD | |
| 628 628 |  | 
| 629 629 | 
             
                    if remote_doc.contentType && validate
         | 
| 630 630 | 
             
                      raise IOError, "url: #{url}, contentType: #{remote_doc.contentType}" unless
         | 
| 631 | 
            -
                        remote_doc.contentType.match?(/application\/(.+\+)?json|text\/html/)
         | 
| 631 | 
            +
                        remote_doc.contentType.match?(/application\/(.+\+)?json|text\/html|application\/xhtml\+xml/)
         | 
| 632 632 | 
             
                    end
         | 
| 633 633 | 
             
                    block_given? ? yield(remote_doc) : remote_doc
         | 
| 634 634 | 
             
                  end
         | 
| @@ -642,7 +642,7 @@ module JSON::LD | |
| 642 642 | 
             
                # @param [Boolean] extractAllScripts
         | 
| 643 643 | 
             
                #   If set to `true`, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary.
         | 
| 644 644 | 
             
                # @param [String] profile
         | 
| 645 | 
            -
                #   When the resulting `contentType` is `text/html`, this option determines the profile to use for selecting a JSON-LD script elements.
         | 
| 645 | 
            +
                #   When the resulting `contentType` is `text/html` or `application/xhtml+xml`, this option determines the profile to use for selecting a JSON-LD script elements.
         | 
| 646 646 | 
             
                # @param [String] requestProfile
         | 
| 647 647 | 
             
                #   One or more IRIs to use in the request as a profile parameter.
         | 
| 648 648 | 
             
                # @param [Hash<Symbol => Object>] options
         | 
| @@ -739,7 +739,7 @@ module JSON::LD | |
| 739 739 | 
             
                    elements = if profile
         | 
| 740 740 | 
             
                      es = input.xpath("//script[starts-with(@type, 'application/ld+json;profile=#{profile}')]")
         | 
| 741 741 | 
             
                      # If no profile script, just take a single script without profile
         | 
| 742 | 
            -
                      es = [input.at_xpath("//script[starts-with(@type, 'application/ld+json')]")] if es.empty?
         | 
| 742 | 
            +
                      es = [input.at_xpath("//script[starts-with(@type, 'application/ld+json')]")].compact if es.empty?
         | 
| 743 743 | 
             
                      es
         | 
| 744 744 | 
             
                    else
         | 
| 745 745 | 
             
                      input.xpath("//script[starts-with(@type, 'application/ld+json')]")
         | 
    
        data/lib/json/ld/compact.rb
    CHANGED
    
    | @@ -5,12 +5,7 @@ module JSON::LD | |
| 5 5 | 
             
                include Utils
         | 
| 6 6 |  | 
| 7 7 | 
             
                # The following constant is used to reduce object allocations in #compact below
         | 
| 8 | 
            -
                CONTAINER_MAPPING_ID = %w(@id).freeze
         | 
| 9 | 
            -
                CONTAINER_MAPPING_INDEX = %w(@index).freeze
         | 
| 10 | 
            -
                CONTAINER_MAPPING_LANGUAGE = %w(@language).freeze
         | 
| 11 8 | 
             
                CONTAINER_MAPPING_LANGUAGE_INDEX_ID_TYPE = Set.new(%w(@language @index @id @type)).freeze
         | 
| 12 | 
            -
                CONTAINER_MAPPING_LIST = %w(@list).freeze
         | 
| 13 | 
            -
                CONTAINER_MAPPING_TYPE = %w(@type).freeze
         | 
| 14 9 | 
             
                EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE = %w(@direction @index @language @value).freeze
         | 
| 15 10 |  | 
| 16 11 | 
             
                ##
         | 
| @@ -71,7 +66,7 @@ module JSON::LD | |
| 71 66 | 
             
                    end
         | 
| 72 67 |  | 
| 73 68 | 
             
                    # If expanded property is @list and we're contained within a list container, recursively compact this item to an array
         | 
| 74 | 
            -
                    if list?(element) && context.container(property) | 
| 69 | 
            +
                    if list?(element) && context.container(property).include?('@list')
         | 
| 75 70 | 
             
                      return compact(element['@list'], property: property, ordered: ordered)
         | 
| 76 71 | 
             
                    end
         | 
| 77 72 |  | 
| @@ -110,8 +105,7 @@ module JSON::LD | |
| 110 105 | 
             
                                   (context.as_array?(kw_alias) &&
         | 
| 111 106 | 
             
                                    !value?(element) &&
         | 
| 112 107 | 
             
                                    context.processingMode('json-ld-1.1'))
         | 
| 113 | 
            -
                         | 
| 114 | 
            -
                        result[kw_alias] = compacted_value
         | 
| 108 | 
            +
                        add_value(result, kw_alias, compacted_value, property_is_array: as_array)
         | 
| 115 109 | 
             
                        next
         | 
| 116 110 | 
             
                      end
         | 
| 117 111 |  | 
| @@ -128,7 +122,7 @@ module JSON::LD | |
| 128 122 | 
             
                        end
         | 
| 129 123 |  | 
| 130 124 | 
             
                        unless compacted_value.empty?
         | 
| 131 | 
            -
                          al = context.compact_iri('@reverse' | 
| 125 | 
            +
                          al = context.compact_iri('@reverse')
         | 
| 132 126 | 
             
                          #log_debug("") {"remainder: #{al} => #{compacted_value.inspect}"}
         | 
| 133 127 | 
             
                          result[al] = compacted_value
         | 
| 134 128 | 
             
                        end
         | 
| @@ -146,14 +140,14 @@ module JSON::LD | |
| 146 140 | 
             
                        next
         | 
| 147 141 | 
             
                      end
         | 
| 148 142 |  | 
| 149 | 
            -
                      if expanded_property == '@index' && context.container(property) | 
| 143 | 
            +
                      if expanded_property == '@index' && context.container(property).include?('@index')
         | 
| 150 144 | 
             
                        #log_debug("@index") {"drop @index"}
         | 
| 151 145 | 
             
                        next
         | 
| 152 146 | 
             
                      end
         | 
| 153 147 |  | 
| 154 148 | 
             
                      # Otherwise, if expanded property is @direction, @index, @value, or @language:
         | 
| 155 149 | 
             
                      if EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE.include?(expanded_property)
         | 
| 156 | 
            -
                        al = context.compact_iri(expanded_property, vocab: true | 
| 150 | 
            +
                        al = context.compact_iri(expanded_property, vocab: true)
         | 
| 157 151 | 
             
                        #log_debug(expanded_property) {"#{al} => #{expanded_value.inspect}"}
         | 
| 158 152 | 
             
                        result[al] = expanded_value
         | 
| 159 153 | 
             
                        next
         | 
| @@ -209,11 +203,11 @@ module JSON::LD | |
| 209 203 | 
             
                        # handle @list
         | 
| 210 204 | 
             
                        if list?(expanded_item)
         | 
| 211 205 | 
             
                          compacted_item = as_array(compacted_item)
         | 
| 212 | 
            -
                          unless container | 
| 213 | 
            -
                            al = context.compact_iri('@list', vocab: true | 
| 206 | 
            +
                          unless container.include?('@list')
         | 
| 207 | 
            +
                            al = context.compact_iri('@list', vocab: true)
         | 
| 214 208 | 
             
                            compacted_item = {al => compacted_item}
         | 
| 215 209 | 
             
                            if expanded_item.has_key?('@index')
         | 
| 216 | 
            -
                              key = context.compact_iri('@index', vocab: true | 
| 210 | 
            +
                              key = context.compact_iri('@index', vocab: true)
         | 
| 217 211 | 
             
                              compacted_item[key] = expanded_item['@index']
         | 
| 218 212 | 
             
                            end
         | 
| 219 213 | 
             
                          else
         | 
| @@ -231,11 +225,11 @@ module JSON::LD | |
| 231 225 | 
             
                            map_object = nest_result[item_active_property] ||= {}
         | 
| 232 226 | 
             
                            # If there is no @id, create a blank node identifier to use as an index
         | 
| 233 227 | 
             
                            map_key = if container.include?('@id') && expanded_item['@id']
         | 
| 234 | 
            -
                              context.compact_iri(expanded_item['@id'] | 
| 228 | 
            +
                              context.compact_iri(expanded_item['@id'])
         | 
| 235 229 | 
             
                            elsif container.include?('@index') && expanded_item['@index']
         | 
| 236 | 
            -
                              context.compact_iri(expanded_item['@index'] | 
| 230 | 
            +
                              context.compact_iri(expanded_item['@index'])
         | 
| 237 231 | 
             
                            else
         | 
| 238 | 
            -
                              context.compact_iri('@none', vocab: true | 
| 232 | 
            +
                              context.compact_iri('@none', vocab: true)
         | 
| 239 233 | 
             
                            end
         | 
| 240 234 | 
             
                            add_value(map_object, map_key, compacted_item,
         | 
| 241 235 | 
             
                              property_is_array: as_array)
         | 
| @@ -243,7 +237,7 @@ module JSON::LD | |
| 243 237 | 
             
                            # container includes @graph but not @id or @index and value is a simple graph object
         | 
| 244 238 | 
             
                            if compacted_item.is_a?(Array) && compacted_item.length > 1
         | 
| 245 239 | 
             
                              # Mutple objects in the same graph can't be represented directly, as they would be interpreted as two different graphs. Need to wrap in @included.
         | 
| 246 | 
            -
                              included_key = context.compact_iri('@included', vocab: true) | 
| 240 | 
            +
                              included_key = context.compact_iri('@included', vocab: true)
         | 
| 247 241 | 
             
                              compacted_item = {included_key => compacted_item}
         | 
| 248 242 | 
             
                            end
         | 
| 249 243 | 
             
                            # Drop through, where compacted_item will be added
         | 
| @@ -251,35 +245,34 @@ module JSON::LD | |
| 251 245 | 
             
                              property_is_array: as_array)
         | 
| 252 246 | 
             
                          else
         | 
| 253 247 | 
             
                            # container does not include @graph or otherwise does not match one of the previous cases, redo compacted_item
         | 
| 254 | 
            -
                            al = context.compact_iri('@graph', vocab: true | 
| 248 | 
            +
                            al = context.compact_iri('@graph', vocab: true)
         | 
| 255 249 | 
             
                            compacted_item = {al => compacted_item}
         | 
| 256 250 | 
             
                            if expanded_item['@id']
         | 
| 257 | 
            -
                              al = context.compact_iri('@id', vocab: true | 
| 258 | 
            -
                              compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false | 
| 251 | 
            +
                              al = context.compact_iri('@id', vocab: true)
         | 
| 252 | 
            +
                              compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false)
         | 
| 259 253 | 
             
                            end
         | 
| 260 254 | 
             
                            if expanded_item.has_key?('@index')
         | 
| 261 | 
            -
                              key = context.compact_iri('@index', vocab: true | 
| 255 | 
            +
                              key = context.compact_iri('@index', vocab: true)
         | 
| 262 256 | 
             
                              compacted_item[key] = expanded_item['@index']
         | 
| 263 257 | 
             
                            end
         | 
| 264 258 | 
             
                            add_value(nest_result, item_active_property, compacted_item,
         | 
| 265 259 | 
             
                              property_is_array: as_array)
         | 
| 266 260 | 
             
                          end
         | 
| 267 | 
            -
                        elsif container. | 
| 261 | 
            +
                        elsif container.intersect?(CONTAINER_MAPPING_LANGUAGE_INDEX_ID_TYPE) && !container.include?('@graph')
         | 
| 268 262 | 
             
                          map_object = nest_result[item_active_property] ||= {}
         | 
| 269 263 | 
             
                          c = container.first
         | 
| 270 | 
            -
                          container_key = context.compact_iri(c, vocab: true | 
| 271 | 
            -
                          compacted_item = case | 
| 272 | 
            -
                          when  | 
| 264 | 
            +
                          container_key = context.compact_iri(c, vocab: true)
         | 
| 265 | 
            +
                          compacted_item = case
         | 
| 266 | 
            +
                          when container.include?('@id')
         | 
| 273 267 | 
             
                            map_key = compacted_item[container_key]
         | 
| 274 268 | 
             
                            compacted_item.delete(container_key)
         | 
| 275 269 | 
             
                            compacted_item
         | 
| 276 | 
            -
                          when  | 
| 270 | 
            +
                          when container.include?('@index')
         | 
| 277 271 | 
             
                            index_key = context.term_definitions[item_active_property].index || '@index'
         | 
| 278 272 | 
             
                            if index_key == '@index'
         | 
| 279 273 | 
             
                              map_key = expanded_item['@index']
         | 
| 280 | 
            -
                              compacted_item.delete(container_key) if compacted_item.is_a?(Hash)
         | 
| 281 274 | 
             
                            else
         | 
| 282 | 
            -
                              container_key = context.compact_iri(index_key, vocab: true | 
| 275 | 
            +
                              container_key = context.compact_iri(index_key, vocab: true)
         | 
| 283 276 | 
             
                              map_key, *others = Array(compacted_item[container_key])
         | 
| 284 277 | 
             
                              if map_key.is_a?(String)
         | 
| 285 278 | 
             
                                case others.length
         | 
| @@ -288,15 +281,15 @@ module JSON::LD | |
| 288 281 | 
             
                                else        compacted_item[container_key] = others
         | 
| 289 282 | 
             
                                end
         | 
| 290 283 | 
             
                              else
         | 
| 291 | 
            -
                                map_key = context.compact_iri('@none', vocab: true | 
| 284 | 
            +
                                map_key = context.compact_iri('@none', vocab: true)
         | 
| 292 285 | 
             
                              end
         | 
| 293 286 | 
             
                            end
         | 
| 294 287 | 
             
                            # Note, if compacted_item is a node reference and key is @id-valued, then this could be compacted further.
         | 
| 295 288 | 
             
                            compacted_item
         | 
| 296 | 
            -
                          when  | 
| 289 | 
            +
                          when container.include?('@language')
         | 
| 297 290 | 
             
                            map_key = expanded_item['@language']
         | 
| 298 291 | 
             
                            value?(expanded_item) ? expanded_item['@value'] : compacted_item
         | 
| 299 | 
            -
                          when  | 
| 292 | 
            +
                          when container.include?('@type')
         | 
| 300 293 | 
             
                            map_key, *types = Array(compacted_item[container_key])
         | 
| 301 294 | 
             
                            case types.length
         | 
| 302 295 | 
             
                            when 0 then compacted_item.delete(container_key)
         | 
| @@ -310,7 +303,7 @@ module JSON::LD | |
| 310 303 | 
             
                            end
         | 
| 311 304 | 
             
                            compacted_item
         | 
| 312 305 | 
             
                          end
         | 
| 313 | 
            -
                          map_key ||= context.compact_iri('@none', vocab: true | 
| 306 | 
            +
                          map_key ||= context.compact_iri('@none', vocab: true)
         | 
| 314 307 | 
             
                          add_value(map_object, map_key, compacted_item,
         | 
| 315 308 | 
             
                            property_is_array: as_array)
         | 
| 316 309 | 
             
                        else
         | 
    
        data/lib/json/ld/context.rb
    CHANGED
    
    | @@ -3,6 +3,12 @@ | |
| 3 3 | 
             
            require 'json'
         | 
| 4 4 | 
             
            require 'bigdecimal'
         | 
| 5 5 | 
             
            require 'set'
         | 
| 6 | 
            +
            begin
         | 
| 7 | 
            +
              # Attempt to load this to avoid unnecessary context fetches
         | 
| 8 | 
            +
              require 'json-ld-preloaded'
         | 
| 9 | 
            +
            rescue LoadError
         | 
| 10 | 
            +
              # Silently allow this to fail
         | 
| 11 | 
            +
            end
         | 
| 6 12 |  | 
| 7 13 | 
             
            module JSON::LD
         | 
| 8 14 | 
             
              class Context
         | 
| @@ -94,7 +100,7 @@ module JSON::LD | |
| 94 100 | 
             
                  # @param [String] term
         | 
| 95 101 | 
             
                  # @param [String] id
         | 
| 96 102 | 
             
                  # @param [String] type_mapping Type mapping
         | 
| 97 | 
            -
                  # @param [ | 
| 103 | 
            +
                  # @param [Set<'@index', '@language', '@index', '@set', '@type', '@id', '@graph'>] container_mapping
         | 
| 98 104 | 
             
                  # @param [String] language_mapping
         | 
| 99 105 | 
             
                  #   Language mapping of term, `false` is used if there is an explicit language mapping for this term
         | 
| 100 106 | 
             
                  # @param ["ltr", "rtl"] direction_mapping
         | 
| @@ -140,12 +146,19 @@ module JSON::LD | |
| 140 146 |  | 
| 141 147 | 
             
                  # Set container mapping, from an array which may include @set
         | 
| 142 148 | 
             
                  def container_mapping=(mapping)
         | 
| 143 | 
            -
                    mapping =  | 
| 149 | 
            +
                    mapping = case mapping
         | 
| 150 | 
            +
                    when Set then mapping
         | 
| 151 | 
            +
                    when Array then Set.new(mapping)
         | 
| 152 | 
            +
                    when String then Set[mapping]
         | 
| 153 | 
            +
                    when nil then Set.new
         | 
| 154 | 
            +
                    else
         | 
| 155 | 
            +
                      raise "Shouldn't happen with #{mapping.inspect}"
         | 
| 156 | 
            +
                    end
         | 
| 144 157 | 
             
                    if @as_set = mapping.include?('@set')
         | 
| 145 158 | 
             
                      mapping = mapping.dup
         | 
| 146 159 | 
             
                      mapping.delete('@set')
         | 
| 147 160 | 
             
                    end
         | 
| 148 | 
            -
                    @container_mapping = mapping | 
| 161 | 
            +
                    @container_mapping = mapping
         | 
| 149 162 | 
             
                    @index ||= '@index' if mapping.include?('@index')
         | 
| 150 163 | 
             
                  end
         | 
| 151 164 |  | 
| @@ -201,7 +214,8 @@ module JSON::LD | |
| 201 214 | 
             
                      v = instance_variable_get("@#{acc}".to_sym)
         | 
| 202 215 | 
             
                      v = v.to_s if v.is_a?(RDF::Term)
         | 
| 203 216 | 
             
                      if acc == 'container_mapping'
         | 
| 204 | 
            -
                        v | 
| 217 | 
            +
                        v = v.to_a
         | 
| 218 | 
            +
                        v << '@set' if as_set?
         | 
| 205 219 | 
             
                        v = v.first if v.length <= 1
         | 
| 206 220 | 
             
                      end
         | 
| 207 221 | 
             
                      defn << "#{acc}: #{v.inspect}" if v
         | 
| @@ -492,7 +506,7 @@ module JSON::LD | |
| 492 506 | 
             
                #
         | 
| 493 507 | 
             
                # @param [Boolean] value
         | 
| 494 508 | 
             
                def propagate=(value, **options)
         | 
| 495 | 
            -
                  raise JsonLdError:: | 
| 509 | 
            +
                  raise JsonLdError::InvalidContextEntry, "@propagate may only be set in 1.1 mode" if processingMode("json-ld-1.0")
         | 
| 496 510 | 
             
                  raise JsonLdError::InvalidPropagateValue, "@propagate must be boolean valued: #{value.inspect}" unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
         | 
| 497 511 | 
             
                  value
         | 
| 498 512 | 
             
                end
         | 
| @@ -626,7 +640,7 @@ module JSON::LD | |
| 626 640 | 
             
                        next unless context.has_key?(key)
         | 
| 627 641 | 
             
                        if key == '@import'
         | 
| 628 642 | 
             
                          # Retrieve remote context and merge the remaining context object into the result.
         | 
| 629 | 
            -
                          raise JsonLdError:: | 
| 643 | 
            +
                          raise JsonLdError::InvalidContextEntry, "@import may only be used in 1.1 mode}" if result.processingMode("json-ld-1.0")
         | 
| 630 644 | 
             
                          raise JsonLdError::InvalidImportValue, "@import must be a string: #{context['@import'].inspect}" unless context['@import'].is_a?(String)
         | 
| 631 645 | 
             
                          source = RDF::URI(result.context_base || result.base).join(context['@import'])
         | 
| 632 646 | 
             
                          begin
         | 
| @@ -640,7 +654,7 @@ module JSON::LD | |
| 640 654 | 
             
                              raise JsonLdError::InvalidRemoteContext, "#{source}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.has_key?('@context')
         | 
| 641 655 | 
             
                              import_context = remote_doc.document['@context']
         | 
| 642 656 | 
             
                              raise JsonLdError::InvalidRemoteContext, "#{import_context.to_json} must be an object" unless import_context.is_a?(Hash)
         | 
| 643 | 
            -
                              raise JsonLdError:: | 
| 657 | 
            +
                              raise JsonLdError::InvalidContextEntry, "#{import_context.to_json} must not include @import entry" if import_context.has_key?('@import')
         | 
| 644 658 | 
             
                              context.delete(key)
         | 
| 645 659 | 
             
                              context = import_context.merge(context)
         | 
| 646 660 | 
             
                            end
         | 
| @@ -1162,7 +1176,7 @@ module JSON::LD | |
| 1162 1176 | 
             
                def container(term)
         | 
| 1163 1177 | 
             
                  return [term] if term == '@list'
         | 
| 1164 1178 | 
             
                  term = find_definition(term)
         | 
| 1165 | 
            -
                  term ? term.container_mapping :  | 
| 1179 | 
            +
                  term ? term.container_mapping : Set.new
         | 
| 1166 1180 | 
             
                end
         | 
| 1167 1181 |  | 
| 1168 1182 | 
             
                ##
         | 
| @@ -1281,18 +1295,24 @@ module JSON::LD | |
| 1281 1295 | 
             
                #   Used during Context Processing.
         | 
| 1282 1296 | 
             
                # @param [Hash] defined
         | 
| 1283 1297 | 
             
                #   Used during Context Processing.
         | 
| 1284 | 
            -
                # @param [Boolean]  | 
| 1298 | 
            +
                # @param [Boolean] as_string (false) transform RDF::Resource values to string
         | 
| 1285 1299 | 
             
                # @param  [Hash{Symbol => Object}] options
         | 
| 1286 | 
            -
                # @return [RDF:: | 
| 1300 | 
            +
                # @return [RDF::Resource, String]
         | 
| 1287 1301 | 
             
                #   IRI or String, if it's a keyword
         | 
| 1288 1302 | 
             
                # @raise [JSON::LD::JsonLdError::InvalidIRIMapping] if the value cannot be expanded
         | 
| 1289 1303 | 
             
                # @see https://www.w3.org/TR/json-ld11-api/#iri-expansion
         | 
| 1290 | 
            -
                def expand_iri(value, | 
| 1291 | 
            -
                   | 
| 1304 | 
            +
                def expand_iri(value,
         | 
| 1305 | 
            +
                  documentRelative: false,
         | 
| 1306 | 
            +
                  vocab: false,
         | 
| 1307 | 
            +
                  local_context: nil,
         | 
| 1308 | 
            +
                  defined: nil,
         | 
| 1309 | 
            +
                  as_string: false,
         | 
| 1310 | 
            +
                  **options
         | 
| 1311 | 
            +
                )
         | 
| 1312 | 
            +
                  return (value && as_string ? value.to_s : value) unless value.is_a?(String)
         | 
| 1292 1313 |  | 
| 1293 1314 | 
             
                  return value if KEYWORDS.include?(value)
         | 
| 1294 1315 | 
             
                  return nil if value.match?(/^@[a-zA-Z]+$/)
         | 
| 1295 | 
            -
                  #log_debug("expand_iri") {"value: #{value.inspect}"} unless quiet
         | 
| 1296 1316 |  | 
| 1297 1317 | 
             
                  defined = defined || {} # if we initialized in the keyword arg we would allocate {} at each invokation, even in the 2 (common) early returns above.
         | 
| 1298 1318 |  | 
| @@ -1302,25 +1322,28 @@ module JSON::LD | |
| 1302 1322 | 
             
                  end
         | 
| 1303 1323 |  | 
| 1304 1324 | 
             
                  if (v_td = term_definitions[value]) && KEYWORDS.include?(v_td.id)
         | 
| 1305 | 
            -
                     | 
| 1306 | 
            -
                    return v_td.id
         | 
| 1325 | 
            +
                    return (as_string ? v_td.id.to_s : v_td.id)
         | 
| 1307 1326 | 
             
                  end
         | 
| 1308 1327 |  | 
| 1309 1328 | 
             
                  # If active context has a term definition for value, and the associated mapping is a keyword, return that keyword.
         | 
| 1310 1329 | 
             
                  # If vocab is true and the active context has a term definition for value, return the associated IRI mapping.
         | 
| 1311 1330 | 
             
                  if (v_td = term_definitions[value]) && (vocab || KEYWORDS.include?(v_td.id))
         | 
| 1312 | 
            -
                     | 
| 1313 | 
            -
                    return v_td.id
         | 
| 1331 | 
            +
                    return (as_string ? v_td.id.to_s : v_td.id)
         | 
| 1314 1332 | 
             
                  end
         | 
| 1315 1333 |  | 
| 1316 1334 | 
             
                  # If value contains a colon (:), it is either an absolute IRI or a compact IRI:
         | 
| 1317 1335 | 
             
                  if value[1..-1].to_s.include?(':')
         | 
| 1318 1336 | 
             
                    prefix, suffix = value.split(':', 2)
         | 
| 1319 | 
            -
                    #log_debug("") {"prefix: #{prefix.inspect}, suffix: #{suffix.inspect}, vocab: #{self.vocab.inspect}"} unless quiet
         | 
| 1320 1337 |  | 
| 1321 1338 | 
             
                    # If prefix is underscore (_) or suffix begins with double-forward-slash (//), return value as it is already an absolute IRI or a blank node identifier.
         | 
| 1322 | 
            -
                     | 
| 1323 | 
            -
             | 
| 1339 | 
            +
                    if prefix == '_'
         | 
| 1340 | 
            +
                      v = RDF::Node.new(namer.get_sym(suffix))
         | 
| 1341 | 
            +
                      return (as_string ? v.to_s : v)
         | 
| 1342 | 
            +
                    end
         | 
| 1343 | 
            +
                    if suffix.start_with?('//')
         | 
| 1344 | 
            +
                      v = RDF::URI(value)
         | 
| 1345 | 
            +
                      return (as_string ? v.to_s : v)
         | 
| 1346 | 
            +
                    end
         | 
| 1324 1347 |  | 
| 1325 1348 | 
             
                    # If local context is not null, it contains a key that equals prefix, and the value associated with the key that equals prefix in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, prefix as term, and defined. This will ensure that a term definition is created for prefix in active context during Context Processing.
         | 
| 1326 1349 | 
             
                    if local_context && local_context.has_key?(prefix) && !defined[prefix]
         | 
| @@ -1329,15 +1352,14 @@ module JSON::LD | |
| 1329 1352 |  | 
| 1330 1353 | 
             
                    # If active context contains a term definition for prefix, return the result of concatenating the IRI mapping associated with prefix and suffix.
         | 
| 1331 1354 | 
             
                    if (td = term_definitions[prefix]) && !td.id.nil? && td.prefix?
         | 
| 1332 | 
            -
                      return td.id + suffix
         | 
| 1355 | 
            +
                      return (as_string ? td.id.to_s : td.id) + suffix
         | 
| 1333 1356 | 
             
                    elsif RDF::URI(value).absolute?
         | 
| 1334 1357 | 
             
                      # Otherwise, if the value has the form of an absolute IRI, return it
         | 
| 1335 | 
            -
                      return RDF::URI(value)
         | 
| 1358 | 
            +
                      return (as_string ? value.to_s : RDF::URI(value))
         | 
| 1336 1359 | 
             
                    else
         | 
| 1337 1360 | 
             
                      # Otherwise, it is a relative IRI
         | 
| 1338 1361 | 
             
                    end
         | 
| 1339 1362 | 
             
                  end
         | 
| 1340 | 
            -
                  #log_debug("") {"=> #{result.inspect}"} unless quiet
         | 
| 1341 1363 |  | 
| 1342 1364 | 
             
                  result = if vocab && self.vocab
         | 
| 1343 1365 | 
             
                    # If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
         | 
| @@ -1352,8 +1374,7 @@ module JSON::LD | |
| 1352 1374 | 
             
                  else
         | 
| 1353 1375 | 
             
                    RDF::URI(value)
         | 
| 1354 1376 | 
             
                  end
         | 
| 1355 | 
            -
                   | 
| 1356 | 
            -
                  result
         | 
| 1377 | 
            +
                  result && as_string ? result.to_s : result
         | 
| 1357 1378 | 
             
                end
         | 
| 1358 1379 |  | 
| 1359 1380 | 
             
                # The following constants are used to reduce object allocations in #compact_iri below
         | 
| @@ -1378,18 +1399,15 @@ module JSON::LD | |
| 1378 1399 | 
             
                #   specifies whether the passed iri should be compacted using the active context's vocabulary mapping
         | 
| 1379 1400 | 
             
                # @param [Boolean] reverse
         | 
| 1380 1401 | 
             
                #   specifies whether a reverse property is being compacted
         | 
| 1381 | 
            -
                # @param [Boolean] quiet (false)
         | 
| 1382 1402 | 
             
                # @param  [Hash{Symbol => Object}] options ({})
         | 
| 1383 1403 | 
             
                #
         | 
| 1384 1404 | 
             
                # @return [String] compacted form of IRI
         | 
| 1385 1405 | 
             
                # @see https://www.w3.org/TR/json-ld11-api/#iri-compaction
         | 
| 1386 | 
            -
                def compact_iri(iri, value: nil, vocab: nil, reverse: false,  | 
| 1406 | 
            +
                def compact_iri(iri, value: nil, vocab: nil, reverse: false, **options)
         | 
| 1387 1407 | 
             
                  return if iri.nil?
         | 
| 1388 1408 | 
             
                  iri = iri.to_s
         | 
| 1389 | 
            -
                  #log_debug("compact_iri(#{iri.inspect}", options) {[value, vocab, reverse].inspect} unless quiet
         | 
| 1390 1409 |  | 
| 1391 1410 | 
             
                  if vocab && inverse_context.has_key?(iri)
         | 
| 1392 | 
            -
                    #log_debug("") {"vocab and key in inverse context"} unless quiet
         | 
| 1393 1411 | 
             
                    default_language = if self.default_direction
         | 
| 1394 1412 | 
             
                      "#{self.default_language}_#{self.default_direction}".downcase
         | 
| 1395 1413 | 
             
                    else
         | 
| @@ -1406,7 +1424,6 @@ module JSON::LD | |
| 1406 1424 | 
             
                      tl, tl_value = "@type", "@reverse"
         | 
| 1407 1425 | 
             
                      containers << '@set'
         | 
| 1408 1426 | 
             
                    elsif list?(value)
         | 
| 1409 | 
            -
                      #log_debug("") {"list(#{value.inspect})"} unless quiet
         | 
| 1410 1427 | 
             
                      # if value is a list object, then set type/language and type/language value to the most specific values that work for all items in the list as follows:
         | 
| 1411 1428 | 
             
                      containers << "@list" unless index?(value)
         | 
| 1412 1429 | 
             
                      list = value['@list']
         | 
| @@ -1429,25 +1446,21 @@ module JSON::LD | |
| 1429 1446 | 
             
                        end
         | 
| 1430 1447 | 
             
                        common_language ||= item_language
         | 
| 1431 1448 | 
             
                        if item_language != common_language && value?(item)
         | 
| 1432 | 
            -
                          #log_debug("") {"-- #{item_language} conflicts with #{common_language}, use @none"} unless quiet
         | 
| 1433 1449 | 
             
                          common_language = '@none'
         | 
| 1434 1450 | 
             
                        end
         | 
| 1435 1451 | 
             
                        common_type ||= item_type
         | 
| 1436 1452 | 
             
                        if item_type != common_type
         | 
| 1437 1453 | 
             
                          common_type = '@none'
         | 
| 1438 | 
            -
                          #log_debug("") {"#{item_type} conflicts with #{common_type}, use @none"} unless quiet
         | 
| 1439 1454 | 
             
                        end
         | 
| 1440 1455 | 
             
                      end
         | 
| 1441 1456 |  | 
| 1442 1457 | 
             
                      common_language ||= '@none'
         | 
| 1443 1458 | 
             
                      common_type ||= '@none'
         | 
| 1444 | 
            -
                      #log_debug("") {"common type: #{common_type}, common language: #{common_language}"} unless quiet
         | 
| 1445 1459 | 
             
                      if common_type != '@none'
         | 
| 1446 1460 | 
             
                        tl, tl_value = '@type', common_type
         | 
| 1447 1461 | 
             
                      else
         | 
| 1448 1462 | 
             
                        tl_value = common_language
         | 
| 1449 1463 | 
             
                      end
         | 
| 1450 | 
            -
                      #log_debug("") {"list: containers: #{containers.inspect}, type/language: #{tl.inspect}, type/language value: #{tl_value.inspect}"} unless quiet
         | 
| 1451 1464 | 
             
                    elsif graph?(value)
         | 
| 1452 1465 | 
             
                      # Prefer @index and @id containers, then @graph, then @index
         | 
| 1453 1466 | 
             
                      containers.concat(CONTAINERS_GRAPH_INDEX_INDEX) if index?(value)
         | 
| @@ -1482,7 +1495,6 @@ module JSON::LD | |
| 1482 1495 | 
             
                        tl, tl_value = '@type', '@id'
         | 
| 1483 1496 | 
             
                      end
         | 
| 1484 1497 | 
             
                      containers << '@set'
         | 
| 1485 | 
            -
                      #log_debug("") {"value: containers: #{containers.inspect}, type/language: #{tl.inspect}, type/language value: #{tl_value.inspect}"} unless quiet
         | 
| 1486 1498 | 
             
                    end
         | 
| 1487 1499 |  | 
| 1488 1500 | 
             
                    containers << '@none'
         | 
| @@ -1506,7 +1518,6 @@ module JSON::LD | |
| 1506 1518 | 
             
                      tl = '@any' if list?(value) && value['@list'].empty?
         | 
| 1507 1519 | 
             
                      preferred_values.concat([tl_value, '@none'].compact)
         | 
| 1508 1520 | 
             
                    end
         | 
| 1509 | 
            -
                    #log_debug("") {"preferred_values: #{preferred_values.inspect}"} unless quiet
         | 
| 1510 1521 | 
             
                    preferred_values << '@any'
         | 
| 1511 1522 |  | 
| 1512 1523 | 
             
                    # if containers included `@language` and preferred_values includes something of the form language-tag_direction, add just the _direction part, to select terms that have that direction.
         | 
| @@ -1515,7 +1526,6 @@ module JSON::LD | |
| 1515 1526 | 
             
                    end
         | 
| 1516 1527 |  | 
| 1517 1528 | 
             
                    if p_term = select_term(iri, containers, tl, preferred_values)
         | 
| 1518 | 
            -
                      #log_debug("") {"=> term: #{p_term.inspect}"} unless quiet
         | 
| 1519 1529 | 
             
                      return p_term
         | 
| 1520 1530 | 
             
                    end
         | 
| 1521 1531 | 
             
                  end
         | 
| @@ -1523,7 +1533,6 @@ module JSON::LD | |
| 1523 1533 | 
             
                  # At this point, there is no simple term that iri can be compacted to. If vocab is true and active context has a vocabulary mapping:
         | 
| 1524 1534 | 
             
                  if vocab && self.vocab && iri.start_with?(self.vocab) && iri.length > self.vocab.length
         | 
| 1525 1535 | 
             
                    suffix = iri[self.vocab.length..-1]
         | 
| 1526 | 
            -
                    #log_debug("") {"=> vocab suffix: #{suffix.inspect}"} unless quiet
         | 
| 1527 1536 | 
             
                    return suffix unless term_definitions.has_key?(suffix)
         | 
| 1528 1537 | 
             
                  end
         | 
| 1529 1538 |  | 
| @@ -1566,10 +1575,8 @@ module JSON::LD | |
| 1566 1575 | 
             
                  if !vocab
         | 
| 1567 1576 | 
             
                    # transform iri to a relative IRI using the document's base IRI
         | 
| 1568 1577 | 
             
                    iri = remove_base(iri)
         | 
| 1569 | 
            -
                    #log_debug("") {"=> relative iri: #{iri.inspect}"} unless quiet
         | 
| 1570 1578 | 
             
                    return iri
         | 
| 1571 1579 | 
             
                  else
         | 
| 1572 | 
            -
                    #log_debug("") {"=> absolute iri: #{iri.inspect}"} unless quiet
         | 
| 1573 1580 | 
             
                    return iri
         | 
| 1574 1581 | 
             
                  end
         | 
| 1575 1582 | 
             
                end
         | 
| @@ -1830,9 +1837,9 @@ module JSON::LD | |
| 1830 1837 |  | 
| 1831 1838 | 
             
              private
         | 
| 1832 1839 |  | 
| 1833 | 
            -
                CONTEXT_CONTAINER_ARRAY_TERMS = %w(@set @list @graph).freeze
         | 
| 1834 | 
            -
                CONTEXT_CONTAINER_ID_GRAPH = %w(@id @graph).freeze
         | 
| 1835 | 
            -
                CONTEXT_CONTAINER_INDEX_GRAPH = %w(@index @graph).freeze
         | 
| 1840 | 
            +
                CONTEXT_CONTAINER_ARRAY_TERMS = Set.new(%w(@set @list @graph)).freeze
         | 
| 1841 | 
            +
                CONTEXT_CONTAINER_ID_GRAPH = Set.new(%w(@id @graph)).freeze
         | 
| 1842 | 
            +
                CONTEXT_CONTAINER_INDEX_GRAPH = Set.new(%w(@index @graph)).freeze
         | 
| 1836 1843 | 
             
                CONTEXT_BASE_FRAG_OR_QUERY = %w(? #).freeze
         | 
| 1837 1844 | 
             
                CONTEXT_TYPE_ID_VOCAB = %w(@id @vocab).freeze
         | 
| 1838 1845 |  | 
| @@ -1906,7 +1913,7 @@ module JSON::LD | |
| 1906 1913 | 
             
                    end.each do |term|
         | 
| 1907 1914 | 
             
                      next unless td = term_definitions[term]
         | 
| 1908 1915 |  | 
| 1909 | 
            -
                      container = td.container_mapping.join('')
         | 
| 1916 | 
            +
                      container = td.container_mapping.to_a.join('')
         | 
| 1910 1917 | 
             
                      if container.empty?
         | 
| 1911 1918 | 
             
                        container = td.as_set? ? %(@set) : %(@none)
         | 
| 1912 1919 | 
             
                      end
         | 
| @@ -1943,7 +1950,7 @@ module JSON::LD | |
| 1943 1950 | 
             
                        lang_dir = td.direction_mapping ? "_#{td.direction_mapping}" : '@none'
         | 
| 1944 1951 | 
             
                        language_map[lang_dir] ||= term
         | 
| 1945 1952 | 
             
                      elsif default_direction
         | 
| 1946 | 
            -
                        language_map[ | 
| 1953 | 
            +
                        language_map["_#{default_direction}"] ||= term
         | 
| 1947 1954 | 
             
                        language_map['@none'] ||= term
         | 
| 1948 1955 | 
             
                        type_map['@none'] ||= term
         | 
| 1949 1956 | 
             
                      else
         | 
| @@ -2058,7 +2065,7 @@ module JSON::LD | |
| 2058 2065 | 
             
                          "'@container' on term #{term.inspect} must be a string: #{container.inspect}"
         | 
| 2059 2066 | 
             
                  end
         | 
| 2060 2067 |  | 
| 2061 | 
            -
                  val = Array(container) | 
| 2068 | 
            +
                  val = Set.new(Array(container))
         | 
| 2062 2069 | 
             
                  val.delete('@set') if has_set = val.include?('@set')
         | 
| 2063 2070 |  | 
| 2064 2071 | 
             
                  if val.include?('@list')
         | 
| @@ -2088,7 +2095,7 @@ module JSON::LD | |
| 2088 2095 | 
             
                           processingMode('json-ld-1.0')
         | 
| 2089 2096 | 
             
                    raise JsonLdError::InvalidContainerMapping,
         | 
| 2090 2097 | 
             
                      "'@container' on term #{term.inspect} using @id cannot have any values other than @set and/or @graph, found  #{container.inspect}" unless
         | 
| 2091 | 
            -
                      ( | 
| 2098 | 
            +
                      val.subset?(CONTEXT_CONTAINER_ID_GRAPH)
         | 
| 2092 2099 | 
             
                    # Okay
         | 
| 2093 2100 | 
             
                  elsif val.include?('@type') || val.include?('@graph')
         | 
| 2094 2101 | 
             
                    raise JsonLdError::InvalidContainerMapping,
         | 
    
        data/lib/json/ld/expand.rb
    CHANGED
    
    | @@ -9,13 +9,8 @@ module JSON::LD | |
| 9 9 | 
             
                include Utils
         | 
| 10 10 |  | 
| 11 11 | 
             
                # The following constant is used to reduce object allocations
         | 
| 12 | 
            -
                CONTAINER_INDEX_ID_TYPE = Set | 
| 13 | 
            -
                 | 
| 14 | 
            -
                CONTAINER_INDEX = %w(@index).freeze
         | 
| 15 | 
            -
                CONTAINER_ID = %w(@id).freeze
         | 
| 16 | 
            -
                CONTAINER_LIST = %w(@list).freeze
         | 
| 17 | 
            -
                CONTAINER_TYPE = %w(@type).freeze
         | 
| 18 | 
            -
                CONTAINER_GRAPH_ID = %w(@graph @id).freeze
         | 
| 12 | 
            +
                CONTAINER_INDEX_ID_TYPE = Set['@index', '@id', '@type'].freeze
         | 
| 13 | 
            +
                KEY_ID = %w(@id).freeze
         | 
| 19 14 | 
             
                KEYS_VALUE_LANGUAGE_TYPE_INDEX_DIRECTION = %w(@value @language @type @index @direction).freeze
         | 
| 20 15 | 
             
                KEYS_SET_LIST_INDEX = %w(@set @list @index).freeze
         | 
| 21 16 | 
             
                KEYS_INCLUDED_TYPE = %w(@included @type).freeze
         | 
| @@ -36,7 +31,7 @@ module JSON::LD | |
| 36 31 | 
             
                def expand(input, active_property, context, ordered: false, framing: false, from_map: false)
         | 
| 37 32 | 
             
                  #log_debug("expand") {"input: #{input.inspect}, active_property: #{active_property.inspect}, context: #{context.inspect}"}
         | 
| 38 33 | 
             
                  framing = false if active_property == '@default'
         | 
| 39 | 
            -
                  expanded_active_property = context.expand_iri(active_property, vocab: true) | 
| 34 | 
            +
                  expanded_active_property = context.expand_iri(active_property, vocab: true, as_string: true) if active_property
         | 
| 40 35 |  | 
| 41 36 | 
             
                  # Use a term-specific context, if defined, based on the non-type-scoped context.
         | 
| 42 37 | 
             
                  property_scoped_context = context.term_definitions[active_property].context if active_property && context.term_definitions[active_property]
         | 
| @@ -44,7 +39,7 @@ module JSON::LD | |
| 44 39 | 
             
                  result = case input
         | 
| 45 40 | 
             
                  when Array
         | 
| 46 41 | 
             
                    # If element is an array,
         | 
| 47 | 
            -
                    is_list = context.container(active_property) | 
| 42 | 
            +
                    is_list = context.container(active_property).include?('@list')
         | 
| 48 43 | 
             
                    value = input.each_with_object([]) do |v, memo|
         | 
| 49 44 | 
             
                      # Initialize expanded item to the result of using this algorithm recursively, passing active context, active property, and item as element.
         | 
| 50 45 | 
             
                      v = expand(v, active_property, context, ordered: ordered, framing: framing, from_map: from_map)
         | 
| @@ -62,7 +57,7 @@ module JSON::LD | |
| 62 57 | 
             
                    value
         | 
| 63 58 | 
             
                  when Hash
         | 
| 64 59 | 
             
                    if context.previous_context
         | 
| 65 | 
            -
                      expanded_key_map = input.keys.inject({}) {|memo, key| memo.merge(key => context.expand_iri(key, vocab: true) | 
| 60 | 
            +
                      expanded_key_map = input.keys.inject({}) {|memo, key| memo.merge(key => context.expand_iri(key, vocab: true, as_string: true))}
         | 
| 66 61 | 
             
                      # Revert any previously type-scoped term definitions, unless this is from a map, a value object or a subject reference
         | 
| 67 62 | 
             
                      revert_context = !from_map &&
         | 
| 68 63 | 
             
                        !expanded_key_map.values.include?('@value') &&
         | 
| @@ -139,7 +134,7 @@ module JSON::LD | |
| 139 134 | 
             
                        raise JsonLdError::InvalidLanguageTaggedValue,
         | 
| 140 135 | 
             
                              "when @language is used, @value must be a string: #{output_object.inspect}"
         | 
| 141 136 | 
             
                      elsif !Array(output_object['@type']).all? {|t|
         | 
| 142 | 
            -
                              t.is_a?(String) && RDF::URI(t). | 
| 137 | 
            +
                              t.is_a?(String) && RDF::URI(t).valid? && !t.start_with?('_:') ||
         | 
| 143 138 | 
             
                              t.is_a?(Hash) && t.empty?}
         | 
| 144 139 | 
             
                        # Otherwise, if the result has a @type member and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
         | 
| 145 140 | 
             
                        raise JsonLdError::InvalidTypedValue,
         | 
| @@ -164,8 +159,8 @@ module JSON::LD | |
| 164 159 |  | 
| 165 160 | 
             
                    # If active property is null or @graph, drop free-floating values as follows:
         | 
| 166 161 | 
             
                    if (expanded_active_property || '@graph') == '@graph' &&
         | 
| 167 | 
            -
             | 
| 168 | 
            -
                       (output_object.keys -  | 
| 162 | 
            +
                       (output_object.key?('@value') || output_object.key?('@list') ||
         | 
| 163 | 
            +
                       (output_object.keys - KEY_ID).empty? && !framing)
         | 
| 169 164 | 
             
                      #log_debug(" =>") { "empty top-level: " + output_object.inspect}
         | 
| 170 165 | 
             
                      return nil
         | 
| 171 166 | 
             
                    end
         | 
| @@ -202,14 +197,14 @@ module JSON::LD | |
| 202 197 | 
             
                  nests = []
         | 
| 203 198 |  | 
| 204 199 | 
             
                  input_type = Array(input[type_key]).last
         | 
| 205 | 
            -
                  input_type = context.expand_iri(input_type, vocab: true,  | 
| 200 | 
            +
                  input_type = context.expand_iri(input_type, vocab: true, as_string: true) if input_type
         | 
| 206 201 |  | 
| 207 202 | 
             
                  # Then, proceed and process each property and value in element as follows:
         | 
| 208 203 | 
             
                  keys = ordered ? input.keys.sort : input.keys
         | 
| 209 204 | 
             
                  keys.each do |key|
         | 
| 210 205 | 
             
                    # For each key and value in element, ordered lexicographically by key:
         | 
| 211 206 | 
             
                    value = input[key]
         | 
| 212 | 
            -
                    expanded_property = context.expand_iri(key, vocab: true | 
| 207 | 
            +
                    expanded_property = context.expand_iri(key, vocab: true)
         | 
| 213 208 |  | 
| 214 209 | 
             
                    # If expanded property is null or it neither contains a colon (:) nor it is a keyword, drop key by continuing to the next key.
         | 
| 215 210 | 
             
                    next if expanded_property.is_a?(RDF::URI) && expanded_property.relative?
         | 
| @@ -241,16 +236,16 @@ module JSON::LD | |
| 241 236 | 
             
                        # If expanded property is @id and value is not a string, an invalid @id value error has been detected and processing is aborted
         | 
| 242 237 | 
             
                        e_id = case value
         | 
| 243 238 | 
             
                        when String
         | 
| 244 | 
            -
                          context.expand_iri(value, documentRelative: true,  | 
| 239 | 
            +
                          context.expand_iri(value, documentRelative: true, as_string: true)
         | 
| 245 240 | 
             
                        when Array
         | 
| 246 241 | 
             
                          # Framing allows an array of IRIs, and always puts values in an array
         | 
| 247 242 | 
             
                          raise JsonLdError::InvalidIdValue,
         | 
| 248 243 | 
             
                                "value of @id must be a string unless framing: #{value.inspect}" unless framing
         | 
| 249 | 
            -
                          context.expand_iri(value, documentRelative: true,  | 
| 244 | 
            +
                          context.expand_iri(value, documentRelative: true, as_string: true)
         | 
| 250 245 | 
             
                          value.map do |v|
         | 
| 251 246 | 
             
                            raise JsonLdError::InvalidTypeValue,
         | 
| 252 247 | 
             
                                  "@id value must be a string or array of strings for framing: #{v.inspect}" unless v.is_a?(String)
         | 
| 253 | 
            -
                            context.expand_iri(v, documentRelative: true,  | 
| 248 | 
            +
                            context.expand_iri(v, documentRelative: true, as_string: true)
         | 
| 254 249 | 
             
                          end
         | 
| 255 250 | 
             
                        when Hash
         | 
| 256 251 | 
             
                          raise JsonLdError::InvalidIdValue,
         | 
| @@ -287,21 +282,21 @@ module JSON::LD | |
| 287 282 | 
             
                          value.map do |v|
         | 
| 288 283 | 
             
                            raise JsonLdError::InvalidTypeValue,
         | 
| 289 284 | 
             
                                  "@type value must be a string or array of strings: #{v.inspect}" unless v.is_a?(String)
         | 
| 290 | 
            -
                            type_scoped_context.expand_iri(v, vocab: true, documentRelative: true,  | 
| 285 | 
            +
                            type_scoped_context.expand_iri(v, vocab: true, documentRelative: true, as_string: true)
         | 
| 291 286 | 
             
                          end
         | 
| 292 287 | 
             
                        when String
         | 
| 293 | 
            -
                          type_scoped_context.expand_iri(value, vocab: true, documentRelative: true,  | 
| 288 | 
            +
                          type_scoped_context.expand_iri(value, vocab: true, documentRelative: true, as_string: true)
         | 
| 294 289 | 
             
                        when Hash
         | 
| 295 290 | 
             
                          if !framing
         | 
| 296 291 | 
             
                            raise JsonLdError::InvalidTypeValue,
         | 
| 297 292 | 
             
                                  "@type value must be a string or array of strings: #{value.inspect}"
         | 
| 298 293 | 
             
                          elsif value.keys.length == 1 &&
         | 
| 299 | 
            -
                             type_scoped_context.expand_iri(value.keys.first, vocab: true | 
| 294 | 
            +
                             type_scoped_context.expand_iri(value.keys.first, vocab: true) == '@default'
         | 
| 300 295 | 
             
                            # Expand values of @default, which must be a string, or array of strings expanding to IRIs
         | 
| 301 296 | 
             
                            [{'@default' => Array(value['@default']).map do |v|
         | 
| 302 297 | 
             
                              raise JsonLdError::InvalidTypeValue,
         | 
| 303 298 | 
             
                                    "@type default value must be a string or array of strings: #{v.inspect}" unless v.is_a?(String)
         | 
| 304 | 
            -
                              type_scoped_context.expand_iri(v, vocab: true, documentRelative: true,  | 
| 299 | 
            +
                              type_scoped_context.expand_iri(v, vocab: true, documentRelative: true, as_string: true)
         | 
| 305 300 | 
             
                            end}]
         | 
| 306 301 | 
             
                          elsif !value.empty?
         | 
| 307 302 | 
             
                            raise JsonLdError::InvalidTypeValue,
         | 
| @@ -481,7 +476,7 @@ module JSON::LD | |
| 481 476 | 
             
                    expanded_value = if context.coerce(key) == '@json'
         | 
| 482 477 | 
             
                      # In JSON-LD 1.1, values can be native JSON
         | 
| 483 478 | 
             
                      {"@value" => value, "@type" => "@json"}
         | 
| 484 | 
            -
                    elsif container. | 
| 479 | 
            +
                    elsif container.include?('@language') && value.is_a?(Hash)
         | 
| 485 480 | 
             
                      # Otherwise, if key's container mapping in active context is @language and value is a JSON object then value is expanded from a language map as follows:
         | 
| 486 481 |  | 
| 487 482 | 
             
                      # Set multilingual array to an empty array.
         | 
| @@ -490,7 +485,7 @@ module JSON::LD | |
| 490 485 | 
             
                      # For each key-value pair language-language value in value, ordered lexicographically by language
         | 
| 491 486 | 
             
                      keys = ordered ? value.keys.sort : value.keys
         | 
| 492 487 | 
             
                      keys.each do |k|
         | 
| 493 | 
            -
                        expanded_k = context.expand_iri(k, vocab: true,  | 
| 488 | 
            +
                        expanded_k = context.expand_iri(k, vocab: true, as_string: true)
         | 
| 494 489 |  | 
| 495 490 | 
             
                        if k !~ /^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/ && expanded_k != '@none'
         | 
| 496 491 | 
             
                          warn "@language must be valid BCP47: #{k.inspect}"
         | 
| @@ -510,7 +505,7 @@ module JSON::LD | |
| 510 505 | 
             
                      end
         | 
| 511 506 |  | 
| 512 507 | 
             
                      ary
         | 
| 513 | 
            -
                    elsif container. | 
| 508 | 
            +
                    elsif container.intersect?(CONTAINER_INDEX_ID_TYPE) && value.is_a?(Hash)
         | 
| 514 509 | 
             
                      # Otherwise, if key's container mapping in active context contains @index, @id, @type and value is a JSON object then value is expanded from an index map as follows:
         | 
| 515 510 |  | 
| 516 511 | 
             
                      # Set ary to an empty array.
         | 
| @@ -535,13 +530,13 @@ module JSON::LD | |
| 535 530 | 
             
                        map_context = container_context.parse(map_context, propagate: false) if map_context
         | 
| 536 531 | 
             
                        map_context ||= container_context
         | 
| 537 532 |  | 
| 538 | 
            -
                        expanded_k = container_context.expand_iri(k, vocab: true,  | 
| 533 | 
            +
                        expanded_k = container_context.expand_iri(k, vocab: true, as_string: true)
         | 
| 539 534 |  | 
| 540 535 | 
             
                        # Initialize index value to the result of using this algorithm recursively, passing active context, key as active property, and index value as element.
         | 
| 541 536 | 
             
                        index_value = expand([value[k]].flatten, key, map_context, ordered: ordered, framing: framing, from_map: true)
         | 
| 542 537 | 
             
                        index_value.each do |item|
         | 
| 543 | 
            -
                          case | 
| 544 | 
            -
                          when  | 
| 538 | 
            +
                          case
         | 
| 539 | 
            +
                          when container.include?('@index')
         | 
| 545 540 | 
             
                            # Indexed graph by graph name
         | 
| 546 541 | 
             
                            if !graph?(item) && container.include?('@graph')
         | 
| 547 542 | 
             
                              item = {'@graph' => as_array(item)}
         | 
| @@ -553,18 +548,18 @@ module JSON::LD | |
| 553 548 | 
             
                            else
         | 
| 554 549 | 
             
                              # Expand key based on term
         | 
| 555 550 | 
             
                              expanded_k = k == '@none' ? '@none' : container_context.expand_value(index_key, k)
         | 
| 556 | 
            -
                              index_property = container_context.expand_iri(index_key, vocab: true,  | 
| 551 | 
            +
                              index_property = container_context.expand_iri(index_key, vocab: true, as_string: true)
         | 
| 557 552 | 
             
                              item[index_property] = [expanded_k].concat(Array(item[index_property])) unless expanded_k == '@none'
         | 
| 558 553 | 
             
                            end
         | 
| 559 | 
            -
                          when  | 
| 554 | 
            +
                          when container.include?('@id')
         | 
| 560 555 | 
             
                            # Indexed graph by graph name
         | 
| 561 556 | 
             
                            if !graph?(item) && container.include?('@graph')
         | 
| 562 557 | 
             
                              item = {'@graph' => as_array(item)}
         | 
| 563 558 | 
             
                            end
         | 
| 564 559 | 
             
                            # Expand k document relative
         | 
| 565 | 
            -
                            expanded_k = container_context.expand_iri(k, documentRelative: true,  | 
| 560 | 
            +
                            expanded_k = container_context.expand_iri(k, documentRelative: true, as_string: true) unless expanded_k == '@none'
         | 
| 566 561 | 
             
                            item['@id'] ||= expanded_k unless expanded_k == '@none'
         | 
| 567 | 
            -
                          when  | 
| 562 | 
            +
                          when container.include?('@type')
         | 
| 568 563 | 
             
                            item['@type'] = [expanded_k].concat(Array(item['@type'])) unless expanded_k == '@none'
         | 
| 569 564 | 
             
                          end
         | 
| 570 565 |  | 
    
        data/lib/json/ld/frame.rb
    CHANGED
    
    | @@ -119,7 +119,7 @@ module JSON::LD | |
| 119 119 | 
             
                      end
         | 
| 120 120 | 
             
                    end
         | 
| 121 121 |  | 
| 122 | 
            -
                    # If frame has `@included`, recurse over  | 
| 122 | 
            +
                    # If frame has `@included`, recurse over its sub-frame
         | 
| 123 123 | 
             
                    if frame['@included']
         | 
| 124 124 | 
             
                      frame(state.merge(embedded: false), subjects, frame['@included'], parent: output, property: '@included', **options)
         | 
| 125 125 | 
             
                    end
         | 
    
        data/lib/json/ld/from_rdf.rb
    CHANGED
    
    | @@ -42,7 +42,7 @@ module JSON::LD | |
| 42 42 |  | 
| 43 43 | 
             
                    default_graph[name] ||= {'@id' => name} unless name == '@default'
         | 
| 44 44 |  | 
| 45 | 
            -
                    subject = ec.expand_iri(statement.subject) | 
| 45 | 
            +
                    subject = ec.expand_iri(statement.subject, as_string: true)
         | 
| 46 46 | 
             
                    node = node_map[subject] ||= {'@id' => subject}
         | 
| 47 47 |  | 
| 48 48 | 
             
                    # If predicate is rdf:datatype, note subject in compound literal subjects map
         | 
    
        data/lib/json/ld/to_rdf.rb
    CHANGED
    
    | @@ -50,11 +50,11 @@ module JSON::LD | |
| 50 50 | 
             
                        # Either serialize using a datatype, or a compound-literal
         | 
| 51 51 | 
             
                        case @options[:rdfDirection]
         | 
| 52 52 | 
             
                        when 'i18n-datatype'
         | 
| 53 | 
            -
                          datatype = RDF::URI("https://www.w3.org/ns/i18n##{item.fetch('@language', '')}_#{item['@direction']}")
         | 
| 53 | 
            +
                          datatype = RDF::URI("https://www.w3.org/ns/i18n##{item.fetch('@language', '').downcase}_#{item['@direction']}")
         | 
| 54 54 | 
             
                        when 'compound-literal'
         | 
| 55 55 | 
             
                          cl = RDF::Node.new
         | 
| 56 56 | 
             
                          yield RDF::Statement(cl, RDF.value, item['@value'].to_s)
         | 
| 57 | 
            -
                          yield RDF::Statement(cl, RDF.to_uri + 'language', item['@language']) if item['@language']
         | 
| 57 | 
            +
                          yield RDF::Statement(cl, RDF.to_uri + 'language', item['@language'].downcase) if item['@language']
         | 
| 58 58 | 
             
                          yield RDF::Statement(cl, RDF.to_uri + 'direction', item['@direction'])
         | 
| 59 59 | 
             
                          return cl
         | 
| 60 60 | 
             
                        end
         | 
| @@ -76,7 +76,13 @@ module JSON::LD | |
| 76 76 | 
             
                    return parse_list(item['@list'], graph_name: graph_name, &block)
         | 
| 77 77 | 
             
                  end
         | 
| 78 78 |  | 
| 79 | 
            -
                   | 
| 79 | 
            +
                  # Skip if '@id' is nil
         | 
| 80 | 
            +
                  subject = if item.has_key?('@id')
         | 
| 81 | 
            +
                    item['@id'].nil? ? nil : as_resource(item['@id'])
         | 
| 82 | 
            +
                  else
         | 
| 83 | 
            +
                    node
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
             | 
| 80 86 | 
             
                  #log_debug("item_to_rdf")  {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
         | 
| 81 87 | 
             
                  item.each do |property, values|
         | 
| 82 88 | 
             
                    case property
         | 
    
        data/lib/json/ld/writer.rb
    CHANGED
    
    | @@ -143,8 +143,8 @@ module JSON::LD | |
| 143 143 | 
             
                      datatype: TrueClass,
         | 
| 144 144 | 
             
                      default: true,
         | 
| 145 145 | 
             
                      control: :checkbox,
         | 
| 146 | 
            -
                      on: ["--[no-] | 
| 147 | 
            -
                      description: "Require all properties to match (true). Default is `true` use --no- | 
| 146 | 
            +
                      on: ["--[no-]require-all"],
         | 
| 147 | 
            +
                      description: "Require all properties to match (true). Default is `true` use --no-require-all to disable.") {|arg| arg},
         | 
| 148 148 | 
             
                    RDF::CLI::Option.new(
         | 
| 149 149 | 
             
                      symbol: :stream,
         | 
| 150 150 | 
             
                      datatype: TrueClass,
         | 
    
        data/spec/context_spec.rb
    CHANGED
    
    | @@ -348,7 +348,7 @@ describe JSON::LD::Context do | |
| 348 348 | 
             
                    expect(subject.parse({
         | 
| 349 349 | 
             
                      "foo" => {"@id" => "http://example.com/", "@container" => "@list"}
         | 
| 350 350 | 
             
                    }).containers).to produce({
         | 
| 351 | 
            -
                      "foo" =>  | 
| 351 | 
            +
                      "foo" => Set["@list"]
         | 
| 352 352 | 
             
                    }, logger)
         | 
| 353 353 | 
             
                  end
         | 
| 354 354 |  | 
| @@ -356,7 +356,7 @@ describe JSON::LD::Context do | |
| 356 356 | 
             
                    expect(subject.parse({
         | 
| 357 357 | 
             
                      "foo" => {"@id" => "http://example.com/", "@container" => "@type"}
         | 
| 358 358 | 
             
                    }).containers).to produce({
         | 
| 359 | 
            -
                      "foo" =>  | 
| 359 | 
            +
                      "foo" => Set["@type"]
         | 
| 360 360 | 
             
                    }, logger)
         | 
| 361 361 | 
             
                  end
         | 
| 362 362 |  | 
| @@ -364,7 +364,7 @@ describe JSON::LD::Context do | |
| 364 364 | 
             
                    expect(subject.parse({
         | 
| 365 365 | 
             
                      "foo" => {"@id" => "http://example.com/", "@container" => "@id"}
         | 
| 366 366 | 
             
                    }).containers).to produce({
         | 
| 367 | 
            -
                      "foo" =>  | 
| 367 | 
            +
                      "foo" => Set["@id"]
         | 
| 368 368 | 
             
                    }, logger)
         | 
| 369 369 | 
             
                  end
         | 
| 370 370 |  | 
| @@ -553,12 +553,12 @@ describe JSON::LD::Context do | |
| 553 553 | 
             
                      end
         | 
| 554 554 | 
             
                    end
         | 
| 555 555 |  | 
| 556 | 
            -
                    it "generates  | 
| 557 | 
            -
                      expect {context.parse({'@propagate' => true})}.to raise_error(JSON::LD::JsonLdError:: | 
| 556 | 
            +
                    it "generates InvalidContextEntry if using @propagate" do
         | 
| 557 | 
            +
                      expect {context.parse({'@propagate' => true})}.to raise_error(JSON::LD::JsonLdError::InvalidContextEntry)
         | 
| 558 558 | 
             
                    end
         | 
| 559 559 |  | 
| 560 | 
            -
                    it "generates  | 
| 561 | 
            -
                      expect {context.parse({'@import' => "location"})}.to raise_error(JSON::LD::JsonLdError:: | 
| 560 | 
            +
                    it "generates InvalidContextEntry if using @import" do
         | 
| 561 | 
            +
                      expect {context.parse({'@import' => "location"})}.to raise_error(JSON::LD::JsonLdError::InvalidContextEntry)
         | 
| 562 562 | 
             
                    end
         | 
| 563 563 |  | 
| 564 564 | 
             
                    (JSON::LD::KEYWORDS - %w(@base @language @version @protected @propagate @vocab)).each do |kw|
         | 
| @@ -1796,23 +1796,23 @@ describe JSON::LD::Context do | |
| 1796 1796 |  | 
| 1797 1797 | 
             
                it "uses TermDefinition" do
         | 
| 1798 1798 | 
             
                  {
         | 
| 1799 | 
            -
                    "ex"          =>  | 
| 1800 | 
            -
                    "graph"       =>  | 
| 1801 | 
            -
                    "graphSet"    =>  | 
| 1802 | 
            -
                    "graphId"     =>  | 
| 1803 | 
            -
                    "graphIdSet"  =>  | 
| 1804 | 
            -
                    "graphNdx"    =>  | 
| 1805 | 
            -
                    "graphNdxSet" =>  | 
| 1806 | 
            -
                    "id"          =>  | 
| 1807 | 
            -
                    "idSet"       =>  | 
| 1808 | 
            -
                    "language"    =>  | 
| 1809 | 
            -
                    "langSet"     =>  | 
| 1810 | 
            -
                    "list"        =>  | 
| 1811 | 
            -
                    "ndx"         =>  | 
| 1812 | 
            -
                    "ndxSet"      =>  | 
| 1813 | 
            -
                    "set"         =>  | 
| 1814 | 
            -
                    "type"        =>  | 
| 1815 | 
            -
                    "typeSet"     =>  | 
| 1799 | 
            +
                    "ex"          => Set.new,
         | 
| 1800 | 
            +
                    "graph"       => Set["@graph"],
         | 
| 1801 | 
            +
                    "graphSet"    => Set["@graph"],
         | 
| 1802 | 
            +
                    "graphId"     => Set["@graph", "@id"],
         | 
| 1803 | 
            +
                    "graphIdSet"  => Set["@graph", "@id"],
         | 
| 1804 | 
            +
                    "graphNdx"    => Set["@graph", "@index"],
         | 
| 1805 | 
            +
                    "graphNdxSet" => Set["@graph", "@index"],
         | 
| 1806 | 
            +
                    "id"          => Set['@id'],
         | 
| 1807 | 
            +
                    "idSet"       => Set['@id'],
         | 
| 1808 | 
            +
                    "language"    => Set['@language'],
         | 
| 1809 | 
            +
                    "langSet"     => Set['@language'],
         | 
| 1810 | 
            +
                    "list"        => Set['@list'],
         | 
| 1811 | 
            +
                    "ndx"         => Set['@index'],
         | 
| 1812 | 
            +
                    "ndxSet"      => Set['@index'],
         | 
| 1813 | 
            +
                    "set"         => Set.new,
         | 
| 1814 | 
            +
                    "type"        => Set['@type'],
         | 
| 1815 | 
            +
                    "typeSet"     => Set['@type'],
         | 
| 1816 1816 | 
             
                  }.each do |defn, container|
         | 
| 1817 1817 | 
             
                    expect(subject.container(subject.term_definitions[defn])).to eq container
         | 
| 1818 1818 | 
             
                  end
         | 
| @@ -1844,23 +1844,23 @@ describe JSON::LD::Context do | |
| 1844 1844 |  | 
| 1845 1845 | 
             
                it "uses array" do
         | 
| 1846 1846 | 
             
                  {
         | 
| 1847 | 
            -
                    "ex"          =>  | 
| 1848 | 
            -
                    "graph"       =>  | 
| 1849 | 
            -
                    "graphSet"    =>  | 
| 1850 | 
            -
                    "graphId"     =>  | 
| 1851 | 
            -
                    "graphIdSet"  =>  | 
| 1852 | 
            -
                    "graphNdx"    =>  | 
| 1853 | 
            -
                    "graphNdxSet" =>  | 
| 1854 | 
            -
                    "id"          =>  | 
| 1855 | 
            -
                    "idSet"       =>  | 
| 1856 | 
            -
                    "language"    =>  | 
| 1857 | 
            -
                    "langSet"     =>  | 
| 1858 | 
            -
                    "list"        =>  | 
| 1859 | 
            -
                    "ndx"         =>  | 
| 1860 | 
            -
                    "ndxSet"      =>  | 
| 1861 | 
            -
                    "set"         =>  | 
| 1862 | 
            -
                    "type"        =>  | 
| 1863 | 
            -
                    "typeSet"     =>  | 
| 1847 | 
            +
                    "ex"          => Set.new,
         | 
| 1848 | 
            +
                    "graph"       => Set["@graph"],
         | 
| 1849 | 
            +
                    "graphSet"    => Set["@graph"],
         | 
| 1850 | 
            +
                    "graphId"     => Set["@graph", "@id"],
         | 
| 1851 | 
            +
                    "graphIdSet"  => Set["@graph", "@id"],
         | 
| 1852 | 
            +
                    "graphNdx"    => Set["@graph", "@index"],
         | 
| 1853 | 
            +
                    "graphNdxSet" => Set["@graph", "@index"],
         | 
| 1854 | 
            +
                    "id"          => Set['@id'],
         | 
| 1855 | 
            +
                    "idSet"       => Set['@id'],
         | 
| 1856 | 
            +
                    "language"    => Set['@language'],
         | 
| 1857 | 
            +
                    "langSet"     => Set['@language'],
         | 
| 1858 | 
            +
                    "list"        => Set['@list'],
         | 
| 1859 | 
            +
                    "ndx"         => Set['@index'],
         | 
| 1860 | 
            +
                    "ndxSet"      => Set['@index'],
         | 
| 1861 | 
            +
                    "set"         => Set.new,
         | 
| 1862 | 
            +
                    "type"        => Set['@type'],
         | 
| 1863 | 
            +
                    "typeSet"     => Set['@type'],
         | 
| 1864 1864 | 
             
                  }.each do |defn, container|
         | 
| 1865 1865 | 
             
                    expect(subject.container(defn)).to eq container
         | 
| 1866 1866 | 
             
                  end
         | 
| @@ -2053,13 +2053,13 @@ describe JSON::LD::Context do | |
| 2053 2053 |  | 
| 2054 2054 | 
             
                context "with container_mapping @id @set" do
         | 
| 2055 2055 | 
             
                  subject {described_class.new("term", container_mapping: %w(@id @set))}
         | 
| 2056 | 
            -
                  its(:container_mapping) {is_expected.to eq  | 
| 2056 | 
            +
                  its(:container_mapping) {is_expected.to eq Set['@id']}
         | 
| 2057 2057 | 
             
                  its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", container_mapping: ["@id", "@set"]))}
         | 
| 2058 2058 | 
             
                end
         | 
| 2059 2059 |  | 
| 2060 2060 | 
             
                context "with container_mapping @list" do
         | 
| 2061 2061 | 
             
                  subject {described_class.new("term", container_mapping: "@list")}
         | 
| 2062 | 
            -
                  its(:container_mapping) {is_expected.to eq  | 
| 2062 | 
            +
                  its(:container_mapping) {is_expected.to eq Set['@list']}
         | 
| 2063 2063 | 
             
                  its(:to_rb) {is_expected.to eq %(TermDefinition.new("term", container_mapping: "@list"))}
         | 
| 2064 2064 | 
             
                end
         | 
| 2065 2065 |  | 
    
        data/spec/suite_expand_spec.rb
    CHANGED
    
    | @@ -7,6 +7,8 @@ describe JSON::LD do | |
| 7 7 | 
             
                m = Fixtures::SuiteTest::Manifest.open("#{Fixtures::SuiteTest::SUITE}expand-manifest.jsonld")
         | 
| 8 8 | 
             
                describe m.name do
         | 
| 9 9 | 
             
                  m.entries.each do |t|
         | 
| 10 | 
            +
                    # MultiJson use OJ, by default, which doesn't handle native numbers the same as the JSON gem.
         | 
| 11 | 
            +
                    t.options[:adapter] = :json_gem if %w(#tjs12).include?(t.property('@id'))
         | 
| 10 12 | 
             
                    specify "#{t.property('@id')}: #{t.name} unordered#{' (negative test)' unless t.positiveTest?}" do
         | 
| 11 13 | 
             
                      t.options[:ordered] = false
         | 
| 12 14 | 
             
                      if %w(#t0068).include?(t.property('@id'))
         | 
    
        data/spec/suite_helper.rb
    CHANGED
    
    | @@ -132,6 +132,10 @@ module Fixtures | |
| 132 132 | 
             
                      {'specVersion' => "json-ld-1.1"}.merge(property('option') || {}).each do |k, v|
         | 
| 133 133 | 
             
                        opts[k.to_sym] = v
         | 
| 134 134 | 
             
                      end
         | 
| 135 | 
            +
                      if opts[:expandContext] && !RDF::URI(opts[:expandContext]).absolute?
         | 
| 136 | 
            +
                        # Resolve relative to manifest location
         | 
| 137 | 
            +
                        opts[:expandContext] = manifest_url.join(opts[:expandContext]).to_s
         | 
| 138 | 
            +
                      end
         | 
| 135 139 | 
             
                      opts
         | 
| 136 140 | 
             
                    end
         | 
| 137 141 | 
             
                  end
         | 
| @@ -144,6 +148,7 @@ module Fixtures | |
| 144 148 | 
             
                      file = self.send("#{m}_loc".to_sym)
         | 
| 145 149 |  | 
| 146 150 | 
             
                      dl_opts = {safe: true}
         | 
| 151 | 
            +
                      dl_opts[:contentType] = options[:contentType] if m == 'input' && options[:contentType]
         | 
| 147 152 | 
             
                      RDF::Util::File.open_file(file, **dl_opts) do |remote_doc|
         | 
| 148 153 | 
             
                        res = remote_doc.read
         | 
| 149 154 | 
             
                      end
         | 
    
        data/spec/to_rdf_spec.rb
    CHANGED
    
    | @@ -1133,7 +1133,7 @@ describe JSON::LD::API do | |
| 1133 1133 | 
             
                      ],
         | 
| 1134 1134 | 
             
                      "en-US rtl": [
         | 
| 1135 1135 | 
             
                        %q({"http://example.org/label": {"@value": "en-US", "@language": "en-US", "@direction": "rtl"}}),
         | 
| 1136 | 
            -
                        %q(_:a <http://example.org/label> "en-US"^^<https://www.w3.org/ns/i18n#en- | 
| 1136 | 
            +
                        %q(_:a <http://example.org/label> "en-US"^^<https://www.w3.org/ns/i18n#en-us_rtl> .)
         | 
| 1137 1137 | 
             
                      ]
         | 
| 1138 1138 | 
             
                    }.each do |title, (js, ttl)|
         | 
| 1139 1139 | 
             
                      it title do
         | 
| @@ -1161,7 +1161,7 @@ describe JSON::LD::API do | |
| 1161 1161 | 
             
                          @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
         | 
| 1162 1162 | 
             
                          _:a <http://example.org/label> [
         | 
| 1163 1163 | 
             
                            rdf:value "en-US";
         | 
| 1164 | 
            -
                            rdf:language "en- | 
| 1164 | 
            +
                            rdf:language "en-us";
         | 
| 1165 1165 | 
             
                            rdf:direction "rtl"
         | 
| 1166 1166 | 
             
                          ] .
         | 
| 1167 1167 | 
             
                        )
         | 
| @@ -1218,7 +1218,7 @@ describe JSON::LD::API do | |
| 1218 1218 | 
             
                        "@id": "http://example.com/foo",
         | 
| 1219 1219 | 
             
                        "http://example.com/bar": {"@value": "bar", "@type": "http://example.com/baz z"}
         | 
| 1220 1220 | 
             
                      }),
         | 
| 1221 | 
            -
                       | 
| 1221 | 
            +
                      exception: JSON::LD::JsonLdError::InvalidTypedValue
         | 
| 1222 1222 | 
             
                    },
         | 
| 1223 1223 | 
             
                    "Injected IRIs check" => {
         | 
| 1224 1224 | 
             
                      input: %({
         | 
    
        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.1. | 
| 4 | 
            +
              version: 3.1.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Gregg Kellogg
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2020-02-19 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rdf
         | 
| @@ -64,14 +64,14 @@ dependencies: | |
| 64 64 | 
             
                requirements:
         | 
| 65 65 | 
             
                - - "~>"
         | 
| 66 66 | 
             
                  - !ruby/object:Gem::Version
         | 
| 67 | 
            -
                    version: '0. | 
| 67 | 
            +
                    version: '0.2'
         | 
| 68 68 | 
             
              type: :runtime
         | 
| 69 69 | 
             
              prerelease: false
         | 
| 70 70 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 71 71 | 
             
                requirements:
         | 
| 72 72 | 
             
                - - "~>"
         | 
| 73 73 | 
             
                  - !ruby/object:Gem::Version
         | 
| 74 | 
            -
                    version: '0. | 
| 74 | 
            +
                    version: '0.2'
         | 
| 75 75 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 76 76 | 
             
              name: htmlentities
         | 
| 77 77 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -424,7 +424,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 424 424 | 
             
                - !ruby/object:Gem::Version
         | 
| 425 425 | 
             
                  version: '0'
         | 
| 426 426 | 
             
            requirements: []
         | 
| 427 | 
            -
            rubygems_version: 3. | 
| 427 | 
            +
            rubygems_version: 3.1.2
         | 
| 428 428 | 
             
            signing_key: 
         | 
| 429 429 | 
             
            specification_version: 4
         | 
| 430 430 | 
             
            summary: JSON-LD reader/writer for Ruby.
         |