class CHECKING::YOU
Public Class Methods
IN(wanted_type_or_types)
click to toggle source
Returns a Set
of MIME::Type
objects matching a String
search key of the format MEDIA_TYPE/SUB_TYPE. This can return multiple Types, e.g. 'font/collection' TTC/OTC variations:
- #<MIME::Type: font/collection>, #<MIME::Type: font/collection>
# File lib/distorted/checking_you_out.rb, line 158 def self.IN(wanted_type_or_types) if wanted_type_or_types.is_a?(Enumerable) # Support taking a list of String types for Molecules whose Type support # isn't easily expressable as a single Regexp. types.select{ |type| wanted_type_or_types.include?(type.to_s) } else # Might be a single String or Regexp types[wanted_type_or_types, :complete => wanted_type_or_types.is_a?(Regexp)].to_set end end
OUT(path, so_deep: false, only_one_test: false)
click to toggle source
Returns a Set
of MIME::Type
for a given file path, by default only based on the file extension. If the file extension is unavailable— or if `so_deep` is enabled—the `path` will be used as an actual path to look at the magic bytes with ruby-filemagic.
# File lib/distorted/checking_you_out.rb, line 112 def self.OUT(path, so_deep: false, only_one_test: false) return Set[] if path.nil? if not (only_one_test || types.type_for(path).empty?) # NOTE: `type_for`'s return order is supposed to be deterministic: # https://github.com/mime-types/ruby-mime-types/issues/148 # My use case so far has never required order but has required # many Set comparisons, so I am going to return a Set here # and possibly throw the order away. # In my experience the order is usually preserved anyway: # irb(main)> MIME::Types.type_for(File.expand_path('lol.ttf')) # => [#<MIME::Type: font/ttf>, #<MIME::Type: application/font-sfnt>, #<MIME::Type: application/x-font-truetype>, #<MIME::Type: application/x-font-ttf>] # irb(main)> MIME::Types.type_for('lol.ttf')).to_set # => #<Set: {#<MIME::Type: font/ttf>, #<MIME::Type: application/font-sfnt>, #<MIME::Type: application/x-font-truetype>, #<MIME::Type: application/x-font-ttf>}> return types.type_for(path).to_set elsif (so_deep && path[0] != '.'.freeze) # Support taking hypothetical file extensions (e.g. '.jpg') without stat()ing anything. # Did we fail to guess any MIME::Types from the given filename? # We're going to have to look at the actual file # (or at least its first four bytes). FileMagic.open(:mime) do |fm| # The second argument makes fm.file return just the simple # MIME::Type String, e.g.: # # irb(main)> fm.file('/home/okeeblow/IIDX-turntable.svg') # => "image/svg+xml; charset=us-ascii" # irb(main)> fm.file('/home/okeeblow/IIDX-turntable.svg', true) # => "image/svg" # # However MIME::Types won't take short variants like 'image/svg', # so explicitly have FM return long types and split it ourself # on the semicolon: # # irb(main)> "image/svg+xml; charset=us-ascii".split(';').first # => "image/svg+xml" mime = types[fm.file(path, false).split(';'.freeze).first].to_set end # FileMagic.open else # TODO: Warn here that we may need a custom type! #p "NO MATCH FOR #{path}" Set[] end # if end
Protected Class Methods
types()
click to toggle source
Returns the MIME::Types container or loads one
# File lib/distorted/checking_you_out.rb, line 172 def self.types @@types ||= types_loader end
types_loader()
click to toggle source
Returns a loaded MIME::Types container containing both the upstream mime-types-data and our own local data.
# File lib/distorted/checking_you_out.rb, line 178 def self.types_loader container = MIME::Types.new # Load the upstream mime-types-data by providing a nil `path`: # path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Data::PATH loader = MIME::Types::Loader.new(nil, container) # TODO: Log this once I figure out a nice way to wrap Jekyll logger too. # irb> loader.load_columnar => #<MIME::Types: 2277 variants, 1195 extensions> loader.load_columnar # Change default JPEG file extension from .jpeg to .jpg # because it pisses me off lol container['image/jpeg'].last.preferred_extension = 'jpg' # Add a missing extension to MPEG-DASH manifests: # irb> MIME::Types['application/dash+xml'].first # => #<MIME::Type: application/dash+xml> # irb> MIME::Types['application/dash+xml'].first.preferred_extension # => nil # https://www.iana.org/assignments/media-types/application/dash+xml container['application/dash+xml'].last.preferred_extension = 'mpd' # Override the loader's path with the path to our local data directory # after we've loaded the upstream data. # :@path is set up in Loader::initialize and only has an attr_reader # but we can reach in and change it. loader.instance_variable_set(:@path, File.join(__dir__, 'checking_you_out'.freeze)) # Load our local types data. The YAML files are separated by type, # and :load_yaml will load all of them in the :@path we just set. # MAYBE: Integrate MIME::Types YAML conversion scripts and commit # JSON/Columnar artifacts for SPEEEEEED, but YAML is probably fine # since we will have so few custom types compared to upstream. # Convert.from_yaml_to_json # Convert::Columnar.from_yaml_to_columnar loader.load_yaml container end