diff --git a/History.md b/History.md
index 9576a40..f3d57cd 100644
--- a/History.md
+++ b/History.md
@@ -1,5 +1,30 @@
# Changelog
+## NEXT / YYYY-MM-DD
+
+- 1 deprecation:
+
+ - Deprecated `MIME::Type#priority_compare`. In a future release, this will be
+ will be renamed to `MIME::Type#<=>`. This method is used in tight loops, so
+ there is no warning message for either `MIME::Type#priority_compare` or
+ `MIME::Type#<=>`.
+
+- 1 enhancement:
+
+ - Improved the performance of sorting by eliminating the complex comparison
+ flow from `MIME::Type#priority_compare`. The old version shows under 600
+ i/s, and the new version shows over 900 i/s. In sorting the full set of MIME
+ data, there are three differences between the old and new versions; after
+ comparison, these differences are considered acceptable.
+
+- 1 bug fix:
+
+ - Simplified the default compare implementation (`MIME::Type#<=>`) to use the
+ new `MIME::Type#priority_compare` operation and simplify the fallback to
+ `String` comparison. This _may_ result in exceptions where there had been
+ none, as explicit support for several special values (which should have
+ caused errors in any case) have been removed.
+
## 3.6.0 / 2024-10-02
- 2 deprecations:
@@ -123,7 +148,7 @@ there are some validation changes and updated code with formatting.
## 3.3 / 2019-09-04
-- 1 minor enhancement
+- 1 minor enhancement:
- Jean Boussier reduced memory usage for Ruby versions 2.3 or higher by
interning various string values in each type. This is done with a
diff --git a/lib/mime/type.rb b/lib/mime/type.rb
index 983b64c..259af18 100644
--- a/lib/mime/type.rb
+++ b/lib/mime/type.rb
@@ -136,7 +136,9 @@ def to_s
def initialize(content_type) # :yields: self
@friendly = {}
@obsolete = @registered = @provisional = false
- @preferred_extension = @docs = @use_instead = nil
+ @preferred_extension = @docs = @use_instead = @__sort_priority = nil
+ __extension_priorities
+
self.extensions = []
case content_type
@@ -167,6 +169,8 @@ def initialize(content_type) # :yields: self
self.xrefs ||= {}
yield self if block_given?
+
+ update_sort_priority
end
# Indicates that a MIME type is like another type. This differs from
@@ -185,60 +189,28 @@ def like?(other)
# simplified type (the simplified type will be used if comparing against
# something that can be treated as a String with #to_s). In comparisons, this
# is done against the lowercase version of the MIME::Type.
+ #
+ # Note that this implementation of #<=> is deprecated and will be changed
+ # in the next major version to be the same as #priority_compare.
+ #
+ # Note that MIME::Types no longer compare against nil.
def <=>(other)
- if other.nil?
- -1
- elsif other.respond_to?(:simplified)
- simplified <=> other.simplified
- else
- filtered = "silent" if other == :silent
- filtered ||= "true" if other == true
- filtered ||= other.to_s
-
- simplified <=> MIME::Type.simplified(filtered)
- end
+ return priority_compare(other) if other.is_a?(MIME::Type)
+ simplified <=> other
end
- # Compares the +other+ MIME::Type based on how reliable it is before doing a
- # normal <=> comparison. Used by MIME::Types#[] to sort types. The
- # comparisons involved are:
- #
- # 1. self.simplified <=> other.simplified (ensures that we
- # do not try to compare different types)
- # 2. IANA-registered definitions < other definitions.
- # 3. Complete definitions < incomplete definitions.
- # 4. Current definitions < obsolete definitions.
- # 5. Obselete with use-instead names < obsolete without.
- # 6. Obsolete use-instead definitions are compared.
+ # Compares the +other+ MIME::Type using the simplified representation, then
+ # a pre-computed sort priority value. Used by MIME::Types#[] to sort types.
#
- # While this method is public, its use is strongly discouraged by consumers
- # of mime-types. In mime-types 3, this method is likely to see substantial
- # revision and simplification to ensure current registered content types sort
- # before unregistered or obsolete content types.
+ # While this method is public, its direct use is strongly discouraged by
+ # consumers of mime-types. For the next major version of MIME::Types, this
+ # method will become #<=> and #priority_compare will be removed.
def priority_compare(other)
- pc = simplified <=> other.simplified
- if pc.zero? || !(extensions & other.extensions).empty?
- pc =
- if (reg = registered?) != other.registered?
- reg ? -1 : 1 # registered < unregistered
- elsif (comp = complete?) != other.complete?
- comp ? -1 : 1 # complete < incomplete
- elsif (obs = obsolete?) != other.obsolete?
- obs ? 1 : -1 # current < obsolete
- elsif obs && ((ui = use_instead) != (oui = other.use_instead))
- if ui.nil?
- 1
- elsif oui.nil?
- -1
- else
- ui <=> oui
- end
- else
- 0
- end
+ if (cmp = __sort_priority <=> other.__sort_priority) == 0
+ simplified <=> other.simplified
+ else
+ cmp
end
-
- pc
end
# Returns +true+ if the +other+ object is a MIME::Type and the content types
@@ -273,6 +245,13 @@ def hash
simplified.hash
end
+ # The computed sort priority value. This is _not_ intended to be used by most
+ # callers.
+ def __sort_priority # :nodoc:
+ update_sort_priority if !instance_variable_defined?(:@__sort_priority) || @__sort_priority.nil?
+ @__sort_priority
+ end
+
# Returns the whole MIME content-type string.
#
# The content type is a presentation value from the MIME type registry and
@@ -327,6 +306,7 @@ def extensions
##
def extensions=(value) # :nodoc:
+ clear_sort_priority
@extensions = Set[*Array(value).flatten.compact].freeze
MIME::Types.send(:reindex_extensions, self)
end
@@ -355,10 +335,36 @@ def preferred_extension
def preferred_extension=(value) # :nodoc:
if value
add_extensions(value)
+ set_preferred_extension_priority(value)
+ elsif instance_variable_defined?(:@preferred_extension)
+ clear_extension_priority(@preferred_extension)
end
@preferred_extension = value
end
+ ##
+ # Optional extension priorities for this MIME type. This is a map of
+ # extensions to relative priority values (+-20..20+) similar to +nice(1)+.
+ # Unless otherwise specified in the data, an explicitly set
+ # +preferred_extension+ is automatically given a relative priority of +-10+.
+ #
+ # :attr_reader: extension_priorities
+ attr_accessor :extension_priorities
+
+ ##
+ # Returns the priority for the provided extension or extensions. If a priority
+ # is not set, the default priority is +0+. The range for priorities is
+ # +-20..20+, inclusive.
+ #
+ # Obsolete MIME types have a +3
penalty applied to their
+ # extension priority and unregistered MIME types have a +2
+ # penalty to their extension priority, meaning that the highest priority an
+ # obsolete, unregistered MIME type can have is +-15+. The lowest priority is
+ # always +20
.
+ def extension_priority(*exts)
+ exts.map { |ext| get_extension_priority(ext) }.min
+ end
+
##
# The encoding (+7bit+, +8bit+, quoted-printable, or +base64+)
# required to transport the data of this content type safely across a
@@ -408,9 +414,17 @@ def use_instead
attr_writer :use_instead
# Returns +true+ if the media type is obsolete.
- attr_accessor :obsolete
+ #
+ # :attr_accessor: obsolete
+ attr_reader :obsolete
alias_method :obsolete?, :obsolete
+ ##
+ def obsolete=(value)
+ clear_sort_priority
+ @obsolete = !!value
+ end
+
# The documentation for this MIME::Type.
attr_accessor :docs
@@ -468,11 +482,27 @@ def xref_urls
end
# Indicates whether the MIME type has been registered with IANA.
- attr_accessor :registered
+ #
+ # :attr_accessor: registered
+ attr_reader :registered
alias_method :registered?, :registered
+ ##
+ def registered=(value)
+ clear_sort_priority
+ @registered = !!value
+ end
+
# Indicates whether the MIME type's registration with IANA is provisional.
- attr_accessor :provisional
+ #
+ # :attr_accessor: provisional
+ attr_reader :provisional
+
+ ##
+ def provisional=(value)
+ clear_sort_priority
+ @provisional = !!value
+ end
# Indicates whether the MIME type's registration with IANA is provisional.
def provisional?
@@ -555,6 +585,8 @@ def encode_with(coder)
coder["registered"] = registered?
coder["provisional"] = provisional? if provisional?
coder["signature"] = signature? if signature?
+ coder["sort-priority"] = __sort_priority || 0b11111111
+ coder["extension-priorities"] = __extension_priorities unless __extension_priorities.empty?
coder
end
@@ -563,6 +595,7 @@ def encode_with(coder)
#
# This method should be considered a private implementation detail.
def init_with(coder)
+ @__sort_priority = 0
self.content_type = coder["content-type"]
self.docs = coder["docs"] || ""
self.encoding = coder["encoding"]
@@ -574,8 +607,11 @@ def init_with(coder)
self.signature = coder["signature"]
self.xrefs = coder["xrefs"] || {}
self.use_instead = coder["use-instead"]
+ self.extension_priorities = coder["extension-priorities"]
friendly(coder["friendly"] || {})
+
+ update_sort_priority
end
def inspect # :nodoc:
@@ -629,8 +665,62 @@ def simplify_matchdata(matchdata, remove_x = false, joiner: "/")
end
end
+ def __extension_priorities # :nodoc:
+ @extension_priorities ||= {}
+ end
+
private
+ def clear_extension_priority(ext)
+ __extension_priorities.delete(ext) if ext
+ end
+
+ def get_extension_priority(ext)
+ [[-20, (__extension_priorities[ext] || 0) + __priority_penalty].max, 20].min
+ end
+
+ def set_preferred_extension_priority(ext)
+ __extension_priorities[ext] = -10 unless __extension_priorities.has_key?(ext)
+ end
+
+ def clear_sort_priority
+ @__sort_priority = nil
+ end
+
+ # Update the __sort_priority value. Lower numbers sort better, so the
+ # bitmapping may seem a little odd. The _best_ sort priority is 0.
+ #
+ # | bit | meaning | details |
+ # | --- | --------------- | --------- |
+ # | 7 | obsolete | 1 if true |
+ # | 6 | provisional | 1 if true |
+ # | 5 | registered | 0 if true |
+ # | 4 | complete | 0 if true |
+ # | 3 | # of extensions | see below |
+ # | 2 | # of extensions | see below |
+ # | 1 | # of extensions | see below |
+ # | 0 | # of extensions | see below |
+ #
+ # The # of extensions is marked as the number of extensions subtracted from
+ # 16, to a minimum of 0.
+ def update_sort_priority
+ extension_count = @extensions.length
+ obsolete = (instance_variable_defined?(:@obsolete) && @obsolete) ? 1 << 7 : 0
+ provisional = (instance_variable_defined?(:@provisional) && @provisional) ? 1 << 6 : 0
+ registered = (instance_variable_defined?(:@registered) && @registered) ? 0 : 1 << 5
+ complete = extension_count.nonzero? ? 0 : 1 << 4
+ extension_count = [0, 16 - extension_count].max
+
+ @__sort_priority = obsolete | registered | provisional | complete | extension_count
+ @__priority_penalty = ((instance_variable_defined?(:@obsolete) && @obsolete) ? 3 : 0) +
+ ((instance_variable_defined?(:@registered) && @registered) ? 0 : 2)
+ end
+
+ def __priority_penalty
+ update_sort_priority if @__priority_penalty.nil?
+ @__priority_penalty
+ end
+
def content_type=(type_string)
match = MEDIA_TYPE_RE.match(type_string)
fail InvalidContentType, type_string if match.nil?
diff --git a/lib/mime/type/columnar.rb b/lib/mime/type/columnar.rb
index 1b7c3ca..11719d8 100644
--- a/lib/mime/type/columnar.rb
+++ b/lib/mime/type/columnar.rb
@@ -15,8 +15,10 @@
class MIME::Type::Columnar < MIME::Type
def initialize(container, content_type, extensions) # :nodoc:
@container = container
+ @__priority_penalty = nil
self.content_type = content_type
- self.extensions = extensions
+ @extensions = Set[*Array(extensions).flatten.compact].freeze
+ clear_sort_priority
end
def self.column(*methods, file: nil) # :nodoc:
@@ -39,6 +41,7 @@ def self.column(*methods, file: nil) # :nodoc:
:signature?, :provisional, :provisional=, :provisional?, file: "flags"
column :xrefs, :xrefs=, :xref_urls
column :use_instead, :use_instead=
+ column :extension_priorities, :extension_priorities=
def encode_with(coder) # :nodoc:
@container.send(:load_friendly)
@@ -48,9 +51,21 @@ def encode_with(coder) # :nodoc:
@container.send(:load_use_instead)
@container.send(:load_xrefs)
@container.send(:load_preferred_extension)
+ @container.send(:load_extension_priorities)
super
end
+ def update_sort_priority
+ if @container.__fully_loaded?
+ super
+ else
+ obsolete = (@__sort_priority & (1 << 7)) != 0
+ registered = (@__sort_priority & (1 << 5)) == 0
+
+ @__priority_penalty = (obsolete ? 3 : 0) + (registered ? 0 : 2)
+ end
+ end
+
class << self
undef column
end
diff --git a/lib/mime/types.rb b/lib/mime/types.rb
index 026be34..ab891f0 100644
--- a/lib/mime/types.rb
+++ b/lib/mime/types.rb
@@ -154,7 +154,13 @@ def type_for(filename)
Array(filename).flat_map { |fn|
@extension_index[fn.chomp.downcase[/\.?([^.]*?)\z/m, 1]]
}.compact.inject(Set.new, :+).sort { |a, b|
- a.priority_compare(b)
+ by_ext = a.extension_priority(*a.extensions) <=> b.extension_priority(*b.extensions)
+
+ if by_ext.zero?
+ a.priority_compare(b)
+ else
+ by_ext
+ end
}
end
alias_method :of, :type_for
@@ -196,6 +202,10 @@ def add_type(type, quiet = false)
index_extensions!(type)
end
+ def __fully_loaded? # :nodoc:
+ true
+ end
+
private
def add_type_variant!(mime_type)
diff --git a/lib/mime/types/_columnar.rb b/lib/mime/types/_columnar.rb
index 9f8c132..ab39df1 100644
--- a/lib/mime/types/_columnar.rb
+++ b/lib/mime/types/_columnar.rb
@@ -18,6 +18,10 @@ def self.extended(obj) # :nodoc:
obj.instance_variable_set(:@__files__, Set.new)
end
+ def __fully_loaded? # :nodoc:
+ @__files__.size == 10
+ end
+
# Load the first column data file (type and extensions).
def load_base_data(path) # :nodoc:
@__root__ = path
@@ -26,13 +30,16 @@ def load_base_data(path) # :nodoc:
line = line.split
content_type = line.shift
extensions = line
- # content_type, *extensions = line.split
type = MIME::Type::Columnar.new(self, content_type, extensions)
@__mime_data__ << type
add(type)
end
+ each_file_byte("spri") do |type, byte|
+ type.instance_variable_set(:@__sort_priority, byte)
+ end
+
self
end
@@ -60,6 +67,25 @@ def each_file_line(name, lookup = true)
end
end
+ def each_file_byte(name)
+ LOAD_MUTEX.synchronize do
+ next if @__files__.include?(name)
+
+ i = -1
+
+ filename = File.join(@__root__, "mime.#{name}.column")
+
+ next unless File.exist?(filename)
+
+ IO.binread(filename).unpack("C*").each do |byte|
+ (type = @__mime_data__[i += 1]) || next
+ yield type, byte
+ end
+
+ @__files__ << name
+ end
+ end
+
def load_encoding
each_file_line("encoding") do |type, line|
pool ||= {}
@@ -91,7 +117,7 @@ def load_flags
def load_xrefs
each_file_line("xrefs") { |type, line|
- type.instance_variable_set(:@xrefs, dict(line, array: true))
+ type.instance_variable_set(:@xrefs, dict(line, transform: :array))
}
end
@@ -107,18 +133,47 @@ def load_use_instead
end
end
- def dict(line, array: false)
+ def load_extension_priorities
+ each_file_line("extpri") do |type, line|
+ type.instance_variable_set(:@extension_priorities, dict(line, transform: :extension_priority))
+ end
+ rescue
+ # This path preserves backwards compatibility.
+ end
+
+ def dict(line, transform: nil)
if line == "-"
{}
else
line.split("|").each_with_object({}) { |l, h|
k, v = l.split("^")
v = nil if v.empty?
- h[k] = array ? Array(v) : v
+
+ if transform
+ send(:"dict_#{transform}", h, k, v)
+ else
+ h[k] = v
+ end
}
end
end
+ def dict_extension_priority(h, k, v)
+ return if v.nil?
+
+ v = v.to_i if v.is_a?(String)
+ v = v.trunc if v.is_a?(Float)
+ v = [[-20, v].max, 20].min
+
+ return if v.zero?
+
+ h[k] = v
+ end
+
+ def dict_array(h, k, v)
+ h[k] = Array(v)
+ end
+
def arr(line)
if line == "-"
[]
diff --git a/mime-types.gemspec b/mime-types.gemspec
index 8dc0a21..0cb7516 100644
--- a/mime-types.gemspec
+++ b/mime-types.gemspec
@@ -1,4 +1,3 @@
-# -*- encoding: utf-8 -*-
# stub: mime-types 3.6.0 ruby lib
Gem::Specification.new do |s|
@@ -6,10 +5,9 @@ Gem::Specification.new do |s|
s.version = "3.6.0".freeze
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
- s.metadata = { "bug_tracker_uri" => "https://github.com/mime-types/ruby-mime-types/issues", "changelog_uri" => "https://github.com/mime-types/ruby-mime-types/blob/master/History.md", "homepage_uri" => "https://github.com/mime-types/ruby-mime-types/", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/mime-types/ruby-mime-types/" } if s.respond_to? :metadata=
+ s.metadata = {"bug_tracker_uri" => "https://github.com/mime-types/ruby-mime-types/issues", "changelog_uri" => "https://github.com/mime-types/ruby-mime-types/blob/master/History.md", "homepage_uri" => "https://github.com/mime-types/ruby-mime-types/", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/mime-types/ruby-mime-types/"} if s.respond_to? :metadata=
s.require_paths = ["lib".freeze]
s.authors = ["Austin Ziegler".freeze]
- s.date = "2024-10-02"
s.description = "The mime-types library provides a library and registry for information about\nMIME content type definitions. It can be used to determine defined filename\nextensions for MIME types, or to use filename extensions to look up the likely\nMIME type definitions.\n\nVersion 3.0 is a major release that requires Ruby 2.0 compatibility and removes\ndeprecated functions. The columnar registry format introduced in 2.6 has been\nmade the primary format; the registry data has been extracted from this library\nand put into {mime-types-data}[https://github.com/mime-types/mime-types-data].\nAdditionally, mime-types is now licensed exclusively under the MIT licence and\nthere is a code of conduct in effect. There are a number of other smaller\nchanges described in the History file.".freeze
s.email = ["halostatue@gmail.com".freeze]
s.extra_rdoc_files = ["Code-of-Conduct.md".freeze, "Contributing.md".freeze, "History.md".freeze, "Licence.md".freeze, "Manifest.txt".freeze, "README.rdoc".freeze]
@@ -18,24 +16,21 @@ Gem::Specification.new do |s|
s.licenses = ["MIT".freeze]
s.rdoc_options = ["--main".freeze, "README.rdoc".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.0".freeze)
- s.rubygems_version = "3.5.16".freeze
s.summary = "The mime-types library provides a library and registry for information about MIME content type definitions".freeze
- s.specification_version = 4
-
- s.add_runtime_dependency(%q.freeze, ["~> 3.2015".freeze])
- s.add_runtime_dependency(%q.freeze, [">= 0".freeze])
- s.add_development_dependency(%q.freeze, ["~> 5.25".freeze])
- s.add_development_dependency(%q.freeze, [">= 3.0".freeze, "< 5".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.0".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.1".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.7".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.0".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.0".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.0".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.4".freeze])
- s.add_development_dependency(%q.freeze, [">= 10.0".freeze, "< 14.0".freeze])
- s.add_development_dependency(%q.freeze, ["~> 1.0".freeze])
- s.add_development_dependency(%q.freeze, [">= 4.0".freeze, "< 7".freeze])
- s.add_development_dependency(%q.freeze, ["~> 0.21".freeze])
+ s.add_runtime_dependency("mime-types-data".freeze, ["~> 3.2015".freeze])
+ s.add_runtime_dependency("logger".freeze, [">= 0".freeze])
+ s.add_development_dependency("minitest".freeze, ["~> 5.25".freeze])
+ s.add_development_dependency("hoe".freeze, [">= 3.0".freeze, "< 5".freeze])
+ s.add_development_dependency("hoe-doofus".freeze, ["~> 1.0".freeze])
+ s.add_development_dependency("hoe-gemspec2".freeze, ["~> 1.1".freeze])
+ s.add_development_dependency("hoe-git2".freeze, ["~> 1.7".freeze])
+ s.add_development_dependency("hoe-rubygems".freeze, ["~> 1.0".freeze])
+ s.add_development_dependency("minitest-autotest".freeze, ["~> 1.0".freeze])
+ s.add_development_dependency("minitest-focus".freeze, ["~> 1.0".freeze])
+ s.add_development_dependency("minitest-hooks".freeze, ["~> 1.4".freeze])
+ s.add_development_dependency("rake".freeze, [">= 10.0".freeze, "< 14.0".freeze])
+ s.add_development_dependency("standard".freeze, ["~> 1.0".freeze])
+ s.add_development_dependency("rdoc".freeze, [">= 4.0".freeze, "< 7".freeze])
+ s.add_development_dependency("simplecov".freeze, ["~> 0.21".freeze])
end
diff --git a/test/test_mime_type.rb b/test/test_mime_type.rb
index a2349ca..0a0666a 100644
--- a/test/test_mime_type.rb
+++ b/test/test_mime_type.rb
@@ -175,11 +175,6 @@ def mime_type(content_type)
refute_equal text_plain, "text/html"
assert_operator text_plain, :>, "text/html"
end
-
- it "correctly compares against nil" do
- refute_equal text_html, nil
- assert_operator text_plain, :<, nil
- end
end
describe "#ascii?" do
@@ -326,16 +321,20 @@ def mime_type(content_type)
end
describe "#priority_compare" do
+ def priority(type)
+ "#{type} (#{("%08b" % type.__sort_priority).chars.join(" ")})"
+ end
+
def assert_priority_less(left, right)
- assert_equal(-1, left.priority_compare(right))
+ assert_equal(-1, left.priority_compare(right), "#{priority(left)} is not less than #{priority(right)}")
end
def assert_priority_same(left, right)
- assert_equal 0, left.priority_compare(right)
+ assert_equal 0, left.priority_compare(right), "#{priority(left)} is not equal to #{priority(right)}"
end
def assert_priority_more(left, right)
- assert_equal 1, left.priority_compare(right)
+ assert_equal 1, left.priority_compare(right), "#{priority(left)} is not more than #{priority(right)}"
end
def assert_priority(left, middle, right)
@@ -348,19 +347,24 @@ def assert_priority(left, middle, right)
let(:text_1p) { mime_type("content-type" => "text/1") }
let(:text_2) { mime_type("content-type" => "text/2") }
- it "sorts (1) based on the simplified type" do
+ it "sorts based on the simplified type when the sort priorities are the same" do
assert_priority text_1, text_1p, text_2
end
- it "sorts (2) based on extensions" do
- text_1.extensions = ["foo", "bar"]
- text_2.extensions = ["foo"]
+ it "sorts obsolete types higher than non-obsolete types" do
+ text_1.obsolete = text_1p.obsolete = false
+ text_1b = mime_type(text_1) { |t| t.obsolete = true }
+
+ assert_priority_less text_1, text_1b
- assert_priority_same text_1, text_2
+ assert_priority text_1, text_1p, text_1b
+ end
- text_2.registered = true
+ it "sorts provisional types higher than non-provisional types" do
+ text_1.provisional = text_1p.provisional = true
+ text_1b = mime_type(text_1) { |t| t.provisional = false }
- assert_priority_more text_1, text_2
+ assert_priority text_1, text_1p, text_1b
end
it "sorts (3) based on the registration state" do
@@ -377,13 +381,6 @@ def assert_priority(left, middle, right)
assert_priority text_1, text_1p, text_1b
end
- it "sorts (5) based on obsolete status" do
- text_1.obsolete = text_1p.obsolete = false
- text_1b = mime_type(text_1) { |t| t.obsolete = true }
-
- assert_priority text_1, text_1p, text_1b
- end
-
it "sorts (5) based on the use-instead value" do
text_1.obsolete = text_1p.obsolete = true
text_1.use_instead = text_1p.use_instead = "abc/xyz"
@@ -395,6 +392,13 @@ def assert_priority(left, middle, right)
assert_priority text_1, text_1p, text_1b
end
+
+ it "sorts based on extensions (more extensions sort lower)" do
+ text_1.extensions = ["foo", "bar"]
+ text_2.extensions = ["foo"]
+
+ assert_priority_less text_1, text_2
+ end
end
describe "#raw_media_type" do
@@ -502,10 +506,10 @@ def assert_has_keys(wanted_keys, actual, msg = nil)
describe "#to_json" do
let(:expected_1) {
- '{"content-type":"a/b","encoding":"base64","registered":false}'
+ '{"content-type":"a/b","encoding":"base64","registered":false,"sort-priority":48}'
}
let(:expected_2) {
- '{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true}'
+ '{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true,"sort-priority":80}'
}
it "converts to JSON when requested" do
diff --git a/test/test_mime_types_class.rb b/test/test_mime_types_class.rb
index c4b8a33..66122f3 100644
--- a/test/test_mime_types_class.rb
+++ b/test/test_mime_types_class.rb
@@ -47,7 +47,7 @@ def setup
}
# This is this way because of a new type ending with gzip that only
# appears in some data files.
- assert_equal %w[application/gzip application/x-gzip multipart/x-gzip], types
+ assert_equal %w[application/gzip multipart/x-gzip application/x-gzip], types
assert_equal 3, types.size
end
@@ -86,9 +86,8 @@ def setup
assert_equal %w[image/jpeg], MIME::Types.of(["foo.jpeg", "bar.jpeg"])
end
- it "finds multiple extensions" do
- assert_equal %w[image/jpeg text/plain],
- MIME::Types.type_for(%w[foo.txt foo.jpeg])
+ it "finds multiple extensions ordered by the filename list" do
+ assert_equal %w[text/plain image/jpeg], MIME::Types.type_for(%w[foo.txt foo.jpeg])
end
it "does not find unknown extensions" do