mime-types 3.6.2 → 3.7.0.pre1
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/CHANGELOG.md +24 -1
- data/CONTRIBUTORS.md +1 -0
- data/Rakefile +10 -1
- data/lib/mime/type/columnar.rb +16 -1
- data/lib/mime/type.rb +142 -52
- data/lib/mime/types/_columnar.rb +59 -4
- data/lib/mime/types/version.rb +1 -1
- data/lib/mime/types.rb +11 -1
- data/test/minitest_helper.rb +2 -0
- data/test/test_mime_type.rb +32 -34
- data/test/test_mime_types_class.rb +3 -4
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbc8ea5f8e0271da1f1b5ad79011d66be1ab6eaf2e51ccefb7a6b1744ab7a60c
|
4
|
+
data.tar.gz: c8bef17d139d55505852440b1f8103d0ed218093e7e6f0b999c58cfaa6a7f302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a30479ab4fd1589bcdf9dd21b145786038799fb4f3e0b8bc0ba4ad14fd23c38e88265323752faca4750de2d5e23f30ecbbb4e9bc33fca2dd93ddf45032a5f40
|
7
|
+
data.tar.gz: 3b5dd2e2a4628096ab7b44a3a5cb43d1c2c0c5404fa8e16909f8e20481ad0521bbe957fc5e0410b807c6e834d5e086dd5bbe40ffbb13a289c41efc9e3f5585be
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,32 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 3.7.0.pre1 / YYYY-MM-DD
|
4
|
+
|
5
|
+
- Deprecated `MIME::Type#priority_compare`. In a future release, this will be
|
6
|
+
will be renamed to `MIME::Type#<=>`. This method is used in tight loops, so
|
7
|
+
there is no warning message for either `MIME::Type#priority_compare` or
|
8
|
+
`MIME::Type#<=>`.
|
9
|
+
|
10
|
+
- Improved the performance of sorting by eliminating the complex comparison flow
|
11
|
+
from `MIME::Type#priority_compare`. The old version shows under 600 i/s, and
|
12
|
+
the new version shows over 900 i/s. In sorting the full set of MIME data,
|
13
|
+
there are three differences between the old and new versions; after
|
14
|
+
comparison, these differences are considered acceptable.
|
15
|
+
|
16
|
+
- Simplified the default compare implementation (`MIME::Type#<=>`) to use the
|
17
|
+
new `MIME::Type#priority_compare` operation and simplify the fallback to
|
18
|
+
`String` comparison. This _may_ result in exceptions where there had been
|
19
|
+
none, as explicit support for several special values (which should have caused
|
20
|
+
errors in any case) have been removed.
|
21
|
+
|
3
22
|
## 3.6.2 / 2025-03-25
|
4
23
|
|
5
24
|
- Updated the reference to the changelog in the README, fixing RubyGems metadata
|
6
25
|
on the next release. Fixed in [#189][pull-189] by nna774.
|
7
26
|
|
27
|
+
- Daniel Watkins fixed an error in the repo tag for this release because the
|
28
|
+
modified gemspec was not included in the release. Fixed in [#196][pull-196].
|
29
|
+
|
8
30
|
## 3.6.1 / 2025-03-15
|
9
31
|
|
10
32
|
- Restructure project structure to be more consistent with mime-types-data.
|
@@ -148,7 +170,7 @@ there are some validation changes and updated code with formatting.
|
|
148
170
|
|
149
171
|
## 3.3 / 2019-09-04
|
150
172
|
|
151
|
-
- 1 minor enhancement
|
173
|
+
- 1 minor enhancement:
|
152
174
|
|
153
175
|
- Jean Boussier reduced memory usage for Ruby versions 2.3 or higher by
|
154
176
|
interning various string values in each type. This is done with a
|
@@ -373,6 +395,7 @@ there are some validation changes and updated code with formatting.
|
|
373
395
|
[pull-179]: https://github.com/mime-types/ruby-mime-types/pull/179
|
374
396
|
[pull-180]: https://github.com/mime-types/ruby-mime-types/pull/180
|
375
397
|
[pull-189]: https://github.com/mime-types/ruby-mime-types/pull/189
|
398
|
+
[pull-196]: https://github.com/mime-types/ruby-mime-types/pull/196
|
376
399
|
[pull-79]: https://github.com/mime-types/ruby-mime-types/pull/79
|
377
400
|
[pull-84]: https://github.com/mime-types/ruby-mime-types/pull/84
|
378
401
|
[pull-85]: https://github.com/mime-types/ruby-mime-types/pull/85
|
data/CONTRIBUTORS.md
CHANGED
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@ require "rubygems"
|
|
2
2
|
require "hoe"
|
3
3
|
require "rake/clean"
|
4
4
|
require "minitest"
|
5
|
+
require "minitest/test_task"
|
5
6
|
|
6
7
|
Hoe.plugin :halostatue
|
7
8
|
Hoe.plugin :rubygems
|
@@ -10,6 +11,7 @@ Hoe.plugins.delete :debug
|
|
10
11
|
Hoe.plugins.delete :newb
|
11
12
|
Hoe.plugins.delete :publish
|
12
13
|
Hoe.plugins.delete :signing
|
14
|
+
Hoe.plugins.delete :test
|
13
15
|
|
14
16
|
spec = Hoe.spec "mime-types" do
|
15
17
|
developer("Austin Ziegler", "halostatue@gmail.com")
|
@@ -24,7 +26,7 @@ spec = Hoe.spec "mime-types" do
|
|
24
26
|
val.merge!({"rubygems_mfa_required" => "true"})
|
25
27
|
}
|
26
28
|
|
27
|
-
extra_deps << ["mime-types-data", "~> 3.
|
29
|
+
extra_deps << ["mime-types-data", "~> 3.2025", ">= 3.2025.0506.pre1"]
|
28
30
|
extra_deps << ["logger", ">= 0"]
|
29
31
|
|
30
32
|
extra_dev_deps << ["hoe", "~> 4.0"]
|
@@ -65,6 +67,8 @@ Minitest::TestTask.create :coverage do |t|
|
|
65
67
|
RUBY
|
66
68
|
end
|
67
69
|
|
70
|
+
task default: :test
|
71
|
+
|
68
72
|
namespace :benchmark do
|
69
73
|
task :support do
|
70
74
|
%w[lib support].each { |path|
|
@@ -174,6 +178,11 @@ namespace :convert do
|
|
174
178
|
task docs: "convert:docs:run"
|
175
179
|
end
|
176
180
|
|
181
|
+
task :version do
|
182
|
+
require "mime/types/version"
|
183
|
+
puts MIME::Types::VERSION
|
184
|
+
end
|
185
|
+
|
177
186
|
namespace :deps do
|
178
187
|
task :top, [:number] => "benchmark:support" do |_, args|
|
179
188
|
require "deps"
|
data/lib/mime/type/columnar.rb
CHANGED
@@ -15,8 +15,10 @@ require "mime/type"
|
|
15
15
|
class MIME::Type::Columnar < MIME::Type
|
16
16
|
def initialize(container, content_type, extensions) # :nodoc:
|
17
17
|
@container = container
|
18
|
+
@__priority_penalty = nil
|
18
19
|
self.content_type = content_type
|
19
|
-
|
20
|
+
@extensions = Set[*Array(extensions).flatten.compact].freeze
|
21
|
+
clear_sort_priority
|
20
22
|
end
|
21
23
|
|
22
24
|
def self.column(*methods, file: nil) # :nodoc:
|
@@ -39,6 +41,7 @@ class MIME::Type::Columnar < MIME::Type
|
|
39
41
|
:signature?, :provisional, :provisional=, :provisional?, file: "flags"
|
40
42
|
column :xrefs, :xrefs=, :xref_urls
|
41
43
|
column :use_instead, :use_instead=
|
44
|
+
column :extension_priorities, :extension_priorities=
|
42
45
|
|
43
46
|
def encode_with(coder) # :nodoc:
|
44
47
|
@container.send(:load_friendly)
|
@@ -48,9 +51,21 @@ class MIME::Type::Columnar < MIME::Type
|
|
48
51
|
@container.send(:load_use_instead)
|
49
52
|
@container.send(:load_xrefs)
|
50
53
|
@container.send(:load_preferred_extension)
|
54
|
+
@container.send(:load_extension_priorities)
|
51
55
|
super
|
52
56
|
end
|
53
57
|
|
58
|
+
def update_sort_priority
|
59
|
+
if @container.__fully_loaded?
|
60
|
+
super
|
61
|
+
else
|
62
|
+
obsolete = (@__sort_priority & (1 << 7)) != 0
|
63
|
+
registered = (@__sort_priority & (1 << 5)) == 0
|
64
|
+
|
65
|
+
@__priority_penalty = (obsolete ? 3 : 0) + (registered ? 0 : 2)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
54
69
|
class << self
|
55
70
|
undef column
|
56
71
|
end
|
data/lib/mime/type.rb
CHANGED
@@ -133,7 +133,9 @@ class MIME::Type
|
|
133
133
|
def initialize(content_type) # :yields: self
|
134
134
|
@friendly = {}
|
135
135
|
@obsolete = @registered = @provisional = false
|
136
|
-
@preferred_extension = @docs = @use_instead = nil
|
136
|
+
@preferred_extension = @docs = @use_instead = @__sort_priority = nil
|
137
|
+
__extension_priorities
|
138
|
+
|
137
139
|
self.extensions = []
|
138
140
|
|
139
141
|
case content_type
|
@@ -164,6 +166,8 @@ class MIME::Type
|
|
164
166
|
self.xrefs ||= {}
|
165
167
|
|
166
168
|
yield self if block_given?
|
169
|
+
|
170
|
+
update_sort_priority
|
167
171
|
end
|
168
172
|
|
169
173
|
# Indicates that a MIME type is like another type. This differs from
|
@@ -182,60 +186,28 @@ class MIME::Type
|
|
182
186
|
# simplified type (the simplified type will be used if comparing against
|
183
187
|
# something that can be treated as a String with #to_s). In comparisons, this
|
184
188
|
# is done against the lowercase version of the MIME::Type.
|
189
|
+
#
|
190
|
+
# Note that this implementation of #<=> is deprecated and will be changed
|
191
|
+
# in the next major version to be the same as #priority_compare.
|
192
|
+
#
|
193
|
+
# Note that MIME::Types no longer compare against nil.
|
185
194
|
def <=>(other)
|
186
|
-
if other.
|
187
|
-
|
188
|
-
elsif other.respond_to?(:simplified)
|
189
|
-
simplified <=> other.simplified
|
190
|
-
else
|
191
|
-
filtered = "silent" if other == :silent
|
192
|
-
filtered ||= "true" if other == true
|
193
|
-
filtered ||= other.to_s
|
194
|
-
|
195
|
-
simplified <=> MIME::Type.simplified(filtered)
|
196
|
-
end
|
195
|
+
return priority_compare(other) if other.is_a?(MIME::Type)
|
196
|
+
simplified <=> other
|
197
197
|
end
|
198
198
|
|
199
|
-
# Compares the +other+ MIME::Type
|
200
|
-
#
|
201
|
-
# comparisons involved are:
|
202
|
-
#
|
203
|
-
# 1. self.simplified <=> other.simplified (ensures that we
|
204
|
-
# do not try to compare different types)
|
205
|
-
# 2. IANA-registered definitions < other definitions.
|
206
|
-
# 3. Complete definitions < incomplete definitions.
|
207
|
-
# 4. Current definitions < obsolete definitions.
|
208
|
-
# 5. Obselete with use-instead names < obsolete without.
|
209
|
-
# 6. Obsolete use-instead definitions are compared.
|
199
|
+
# Compares the +other+ MIME::Type using the simplified representation, then
|
200
|
+
# a pre-computed sort priority value. Used by MIME::Types#[] to sort types.
|
210
201
|
#
|
211
|
-
# While this method is public, its use is strongly discouraged by
|
212
|
-
# of mime-types.
|
213
|
-
#
|
214
|
-
# before unregistered or obsolete content types.
|
202
|
+
# While this method is public, its direct use is strongly discouraged by
|
203
|
+
# consumers of mime-types. For the next major version of MIME::Types, this
|
204
|
+
# method will become #<=> and #priority_compare will be removed.
|
215
205
|
def priority_compare(other)
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
reg ? -1 : 1 # registered < unregistered
|
221
|
-
elsif (comp = complete?) != other.complete?
|
222
|
-
comp ? -1 : 1 # complete < incomplete
|
223
|
-
elsif (obs = obsolete?) != other.obsolete?
|
224
|
-
obs ? 1 : -1 # current < obsolete
|
225
|
-
elsif obs && ((ui = use_instead) != (oui = other.use_instead))
|
226
|
-
if ui.nil?
|
227
|
-
1
|
228
|
-
elsif oui.nil?
|
229
|
-
-1
|
230
|
-
else
|
231
|
-
ui <=> oui
|
232
|
-
end
|
233
|
-
else
|
234
|
-
0
|
235
|
-
end
|
206
|
+
if (cmp = __sort_priority <=> other.__sort_priority) == 0
|
207
|
+
simplified <=> other.simplified
|
208
|
+
else
|
209
|
+
cmp
|
236
210
|
end
|
237
|
-
|
238
|
-
pc
|
239
211
|
end
|
240
212
|
|
241
213
|
# Returns +true+ if the +other+ object is a MIME::Type and the content types
|
@@ -270,6 +242,13 @@ class MIME::Type
|
|
270
242
|
simplified.hash
|
271
243
|
end
|
272
244
|
|
245
|
+
# The computed sort priority value. This is _not_ intended to be used by most
|
246
|
+
# callers.
|
247
|
+
def __sort_priority # :nodoc:
|
248
|
+
update_sort_priority if !instance_variable_defined?(:@__sort_priority) || @__sort_priority.nil?
|
249
|
+
@__sort_priority
|
250
|
+
end
|
251
|
+
|
273
252
|
# Returns the whole MIME content-type string.
|
274
253
|
#
|
275
254
|
# The content type is a presentation value from the MIME type registry and
|
@@ -324,6 +303,7 @@ class MIME::Type
|
|
324
303
|
|
325
304
|
##
|
326
305
|
def extensions=(value) # :nodoc:
|
306
|
+
clear_sort_priority
|
327
307
|
@extensions = Set[*Array(value).flatten.compact].freeze
|
328
308
|
MIME::Types.send(:reindex_extensions, self)
|
329
309
|
end
|
@@ -352,10 +332,36 @@ class MIME::Type
|
|
352
332
|
def preferred_extension=(value) # :nodoc:
|
353
333
|
if value
|
354
334
|
add_extensions(value)
|
335
|
+
set_preferred_extension_priority(value)
|
336
|
+
elsif instance_variable_defined?(:@preferred_extension)
|
337
|
+
clear_extension_priority(@preferred_extension)
|
355
338
|
end
|
356
339
|
@preferred_extension = value
|
357
340
|
end
|
358
341
|
|
342
|
+
##
|
343
|
+
# Optional extension priorities for this MIME type. This is a map of
|
344
|
+
# extensions to relative priority values (+-20..20+) similar to +nice(1)+.
|
345
|
+
# Unless otherwise specified in the data, an explicitly set
|
346
|
+
# +preferred_extension+ is automatically given a relative priority of +-10+.
|
347
|
+
#
|
348
|
+
# :attr_reader: extension_priorities
|
349
|
+
attr_accessor :extension_priorities
|
350
|
+
|
351
|
+
##
|
352
|
+
# Returns the priority for the provided extension or extensions. If a priority
|
353
|
+
# is not set, the default priority is +0+. The range for priorities is
|
354
|
+
# +-20..20+, inclusive.
|
355
|
+
#
|
356
|
+
# Obsolete MIME types have a <code>+3</code> penalty applied to their
|
357
|
+
# extension priority and unregistered MIME types have a <code>+2</code>
|
358
|
+
# penalty to their extension priority, meaning that the highest priority an
|
359
|
+
# obsolete, unregistered MIME type can have is +-15+. The lowest priority is
|
360
|
+
# always <code>+20</code>.
|
361
|
+
def extension_priority(*exts)
|
362
|
+
exts.map { |ext| get_extension_priority(ext) }.min
|
363
|
+
end
|
364
|
+
|
359
365
|
##
|
360
366
|
# The encoding (+7bit+, +8bit+, <tt>quoted-printable</tt>, or +base64+)
|
361
367
|
# required to transport the data of this content type safely across a
|
@@ -405,9 +411,17 @@ class MIME::Type
|
|
405
411
|
attr_writer :use_instead
|
406
412
|
|
407
413
|
# Returns +true+ if the media type is obsolete.
|
408
|
-
|
414
|
+
#
|
415
|
+
# :attr_accessor: obsolete
|
416
|
+
attr_reader :obsolete
|
409
417
|
alias_method :obsolete?, :obsolete
|
410
418
|
|
419
|
+
##
|
420
|
+
def obsolete=(value)
|
421
|
+
clear_sort_priority
|
422
|
+
@obsolete = !!value
|
423
|
+
end
|
424
|
+
|
411
425
|
# The documentation for this MIME::Type.
|
412
426
|
attr_accessor :docs
|
413
427
|
|
@@ -465,11 +479,27 @@ class MIME::Type
|
|
465
479
|
end
|
466
480
|
|
467
481
|
# Indicates whether the MIME type has been registered with IANA.
|
468
|
-
|
482
|
+
#
|
483
|
+
# :attr_accessor: registered
|
484
|
+
attr_reader :registered
|
469
485
|
alias_method :registered?, :registered
|
470
486
|
|
487
|
+
##
|
488
|
+
def registered=(value)
|
489
|
+
clear_sort_priority
|
490
|
+
@registered = !!value
|
491
|
+
end
|
492
|
+
|
471
493
|
# Indicates whether the MIME type's registration with IANA is provisional.
|
472
|
-
|
494
|
+
#
|
495
|
+
# :attr_accessor: provisional
|
496
|
+
attr_reader :provisional
|
497
|
+
|
498
|
+
##
|
499
|
+
def provisional=(value)
|
500
|
+
clear_sort_priority
|
501
|
+
@provisional = !!value
|
502
|
+
end
|
473
503
|
|
474
504
|
# Indicates whether the MIME type's registration with IANA is provisional.
|
475
505
|
def provisional?
|
@@ -552,6 +582,8 @@ class MIME::Type
|
|
552
582
|
coder["registered"] = registered?
|
553
583
|
coder["provisional"] = provisional? if provisional?
|
554
584
|
coder["signature"] = signature? if signature?
|
585
|
+
coder["sort-priority"] = __sort_priority || 0b11111111
|
586
|
+
coder["extension-priorities"] = __extension_priorities unless __extension_priorities.empty?
|
555
587
|
coder
|
556
588
|
end
|
557
589
|
|
@@ -560,6 +592,7 @@ class MIME::Type
|
|
560
592
|
#
|
561
593
|
# This method should be considered a private implementation detail.
|
562
594
|
def init_with(coder)
|
595
|
+
@__sort_priority = 0
|
563
596
|
self.content_type = coder["content-type"]
|
564
597
|
self.docs = coder["docs"] || ""
|
565
598
|
self.encoding = coder["encoding"]
|
@@ -571,8 +604,11 @@ class MIME::Type
|
|
571
604
|
self.signature = coder["signature"]
|
572
605
|
self.xrefs = coder["xrefs"] || {}
|
573
606
|
self.use_instead = coder["use-instead"]
|
607
|
+
self.extension_priorities = coder["extension-priorities"]
|
574
608
|
|
575
609
|
friendly(coder["friendly"] || {})
|
610
|
+
|
611
|
+
update_sort_priority
|
576
612
|
end
|
577
613
|
|
578
614
|
def inspect # :nodoc:
|
@@ -626,8 +662,62 @@ class MIME::Type
|
|
626
662
|
end
|
627
663
|
end
|
628
664
|
|
665
|
+
def __extension_priorities # :nodoc:
|
666
|
+
@extension_priorities ||= {}
|
667
|
+
end
|
668
|
+
|
629
669
|
private
|
630
670
|
|
671
|
+
def clear_extension_priority(ext)
|
672
|
+
__extension_priorities.delete(ext) if ext
|
673
|
+
end
|
674
|
+
|
675
|
+
def get_extension_priority(ext)
|
676
|
+
[[-20, (__extension_priorities[ext] || 0) + __priority_penalty].max, 20].min
|
677
|
+
end
|
678
|
+
|
679
|
+
def set_preferred_extension_priority(ext)
|
680
|
+
__extension_priorities[ext] = -10 unless __extension_priorities.has_key?(ext)
|
681
|
+
end
|
682
|
+
|
683
|
+
def clear_sort_priority
|
684
|
+
@__sort_priority = nil
|
685
|
+
end
|
686
|
+
|
687
|
+
# Update the __sort_priority value. Lower numbers sort better, so the
|
688
|
+
# bitmapping may seem a little odd. The _best_ sort priority is 0.
|
689
|
+
#
|
690
|
+
# | bit | meaning | details |
|
691
|
+
# | --- | --------------- | --------- |
|
692
|
+
# | 7 | obsolete | 1 if true |
|
693
|
+
# | 6 | provisional | 1 if true |
|
694
|
+
# | 5 | registered | 0 if true |
|
695
|
+
# | 4 | complete | 0 if true |
|
696
|
+
# | 3 | # of extensions | see below |
|
697
|
+
# | 2 | # of extensions | see below |
|
698
|
+
# | 1 | # of extensions | see below |
|
699
|
+
# | 0 | # of extensions | see below |
|
700
|
+
#
|
701
|
+
# The # of extensions is marked as the number of extensions subtracted from
|
702
|
+
# 16, to a minimum of 0.
|
703
|
+
def update_sort_priority
|
704
|
+
extension_count = @extensions.length
|
705
|
+
obsolete = (instance_variable_defined?(:@obsolete) && @obsolete) ? 1 << 7 : 0
|
706
|
+
provisional = (instance_variable_defined?(:@provisional) && @provisional) ? 1 << 6 : 0
|
707
|
+
registered = (instance_variable_defined?(:@registered) && @registered) ? 0 : 1 << 5
|
708
|
+
complete = extension_count.nonzero? ? 0 : 1 << 4
|
709
|
+
extension_count = [0, 16 - extension_count].max
|
710
|
+
|
711
|
+
@__sort_priority = obsolete | registered | provisional | complete | extension_count
|
712
|
+
@__priority_penalty = ((instance_variable_defined?(:@obsolete) && @obsolete) ? 3 : 0) +
|
713
|
+
((instance_variable_defined?(:@registered) && @registered) ? 0 : 2)
|
714
|
+
end
|
715
|
+
|
716
|
+
def __priority_penalty
|
717
|
+
update_sort_priority if @__priority_penalty.nil?
|
718
|
+
@__priority_penalty
|
719
|
+
end
|
720
|
+
|
631
721
|
def content_type=(type_string)
|
632
722
|
match = MEDIA_TYPE_RE.match(type_string)
|
633
723
|
fail InvalidContentType, type_string if match.nil?
|
data/lib/mime/types/_columnar.rb
CHANGED
@@ -18,6 +18,10 @@ module MIME::Types::Columnar
|
|
18
18
|
obj.instance_variable_set(:@__files__, Set.new)
|
19
19
|
end
|
20
20
|
|
21
|
+
def __fully_loaded? # :nodoc:
|
22
|
+
@__files__.size == 10
|
23
|
+
end
|
24
|
+
|
21
25
|
# Load the first column data file (type and extensions).
|
22
26
|
def load_base_data(path) # :nodoc:
|
23
27
|
@__root__ = path
|
@@ -26,13 +30,16 @@ module MIME::Types::Columnar
|
|
26
30
|
line = line.split
|
27
31
|
content_type = line.shift
|
28
32
|
extensions = line
|
29
|
-
# content_type, *extensions = line.split
|
30
33
|
|
31
34
|
type = MIME::Type::Columnar.new(self, content_type, extensions)
|
32
35
|
@__mime_data__ << type
|
33
36
|
add(type)
|
34
37
|
end
|
35
38
|
|
39
|
+
each_file_byte("spri") do |type, byte|
|
40
|
+
type.instance_variable_set(:@__sort_priority, byte)
|
41
|
+
end
|
42
|
+
|
36
43
|
self
|
37
44
|
end
|
38
45
|
|
@@ -60,6 +67,25 @@ module MIME::Types::Columnar
|
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
70
|
+
def each_file_byte(name)
|
71
|
+
LOAD_MUTEX.synchronize do
|
72
|
+
next if @__files__.include?(name)
|
73
|
+
|
74
|
+
i = -1
|
75
|
+
|
76
|
+
filename = File.join(@__root__, "mime.#{name}.column")
|
77
|
+
|
78
|
+
next unless File.exist?(filename)
|
79
|
+
|
80
|
+
IO.binread(filename).unpack("C*").each do |byte|
|
81
|
+
(type = @__mime_data__[i += 1]) || next
|
82
|
+
yield type, byte
|
83
|
+
end
|
84
|
+
|
85
|
+
@__files__ << name
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
63
89
|
def load_encoding
|
64
90
|
each_file_line("encoding") do |type, line|
|
65
91
|
pool ||= {}
|
@@ -91,7 +117,7 @@ module MIME::Types::Columnar
|
|
91
117
|
|
92
118
|
def load_xrefs
|
93
119
|
each_file_line("xrefs") { |type, line|
|
94
|
-
type.instance_variable_set(:@xrefs, dict(line,
|
120
|
+
type.instance_variable_set(:@xrefs, dict(line, transform: :array))
|
95
121
|
}
|
96
122
|
end
|
97
123
|
|
@@ -107,18 +133,47 @@ module MIME::Types::Columnar
|
|
107
133
|
end
|
108
134
|
end
|
109
135
|
|
110
|
-
def
|
136
|
+
def load_extension_priorities
|
137
|
+
each_file_line("extpri") do |type, line|
|
138
|
+
type.instance_variable_set(:@extension_priorities, dict(line, transform: :extension_priority))
|
139
|
+
end
|
140
|
+
rescue
|
141
|
+
# This path preserves backwards compatibility.
|
142
|
+
end
|
143
|
+
|
144
|
+
def dict(line, transform: nil)
|
111
145
|
if line == "-"
|
112
146
|
{}
|
113
147
|
else
|
114
148
|
line.split("|").each_with_object({}) { |l, h|
|
115
149
|
k, v = l.split("^")
|
116
150
|
v = nil if v.empty?
|
117
|
-
|
151
|
+
|
152
|
+
if transform
|
153
|
+
send(:"dict_#{transform}", h, k, v)
|
154
|
+
else
|
155
|
+
h[k] = v
|
156
|
+
end
|
118
157
|
}
|
119
158
|
end
|
120
159
|
end
|
121
160
|
|
161
|
+
def dict_extension_priority(h, k, v)
|
162
|
+
return if v.nil?
|
163
|
+
|
164
|
+
v = v.to_i if v.is_a?(String)
|
165
|
+
v = v.trunc if v.is_a?(Float)
|
166
|
+
v = [[-20, v].max, 20].min
|
167
|
+
|
168
|
+
return if v.zero?
|
169
|
+
|
170
|
+
h[k] = v
|
171
|
+
end
|
172
|
+
|
173
|
+
def dict_array(h, k, v)
|
174
|
+
h[k] = Array(v)
|
175
|
+
end
|
176
|
+
|
122
177
|
def arr(line)
|
123
178
|
if line == "-"
|
124
179
|
[]
|
data/lib/mime/types/version.rb
CHANGED
data/lib/mime/types.rb
CHANGED
@@ -151,7 +151,13 @@ class MIME::Types
|
|
151
151
|
Array(filename).flat_map { |fn|
|
152
152
|
@extension_index[fn.chomp.downcase[/\.?([^.]*?)\z/m, 1]]
|
153
153
|
}.compact.inject(Set.new, :+).sort { |a, b|
|
154
|
-
a.
|
154
|
+
by_ext = a.extension_priority(*a.extensions) <=> b.extension_priority(*b.extensions)
|
155
|
+
|
156
|
+
if by_ext.zero?
|
157
|
+
a.priority_compare(b)
|
158
|
+
else
|
159
|
+
by_ext
|
160
|
+
end
|
155
161
|
}
|
156
162
|
end
|
157
163
|
alias_method :of, :type_for
|
@@ -193,6 +199,10 @@ class MIME::Types
|
|
193
199
|
index_extensions!(type)
|
194
200
|
end
|
195
201
|
|
202
|
+
def __fully_loaded? # :nodoc:
|
203
|
+
true
|
204
|
+
end
|
205
|
+
|
196
206
|
private
|
197
207
|
|
198
208
|
def add_type_variant!(mime_type)
|
data/test/minitest_helper.rb
CHANGED
data/test/test_mime_type.rb
CHANGED
@@ -175,11 +175,6 @@ describe MIME::Type do
|
|
175
175
|
refute_equal text_plain, "text/html"
|
176
176
|
assert_operator text_plain, :>, "text/html"
|
177
177
|
end
|
178
|
-
|
179
|
-
it "correctly compares against nil" do
|
180
|
-
refute_equal text_html, nil
|
181
|
-
assert_operator text_plain, :<, nil
|
182
|
-
end
|
183
178
|
end
|
184
179
|
|
185
180
|
describe "#ascii?" do
|
@@ -326,41 +321,56 @@ describe MIME::Type do
|
|
326
321
|
end
|
327
322
|
|
328
323
|
describe "#priority_compare" do
|
324
|
+
def priority(type)
|
325
|
+
priority = "OpRceXtN"
|
326
|
+
.chars
|
327
|
+
.zip(("%08b" % type.__sort_priority).chars)
|
328
|
+
.map { |e| e.join(":") }
|
329
|
+
.join(" ")
|
330
|
+
|
331
|
+
"#{type} (#{priority} / #{type.__sort_priority})"
|
332
|
+
end
|
333
|
+
|
329
334
|
def assert_priority_less(left, right)
|
330
|
-
assert_equal(-1, left.priority_compare(right))
|
335
|
+
assert_equal(-1, left.priority_compare(right), "#{priority(left)} is not less than #{priority(right)}")
|
331
336
|
end
|
332
337
|
|
333
338
|
def assert_priority_same(left, right)
|
334
|
-
assert_equal 0, left.priority_compare(right)
|
339
|
+
assert_equal 0, left.priority_compare(right), "#{priority(left)} is not equal to #{priority(right)}"
|
335
340
|
end
|
336
341
|
|
337
342
|
def assert_priority_more(left, right)
|
338
|
-
assert_equal 1, left.priority_compare(right)
|
343
|
+
assert_equal 1, left.priority_compare(right), "#{priority(left)} is not more than #{priority(right)}"
|
339
344
|
end
|
340
345
|
|
341
346
|
def assert_priority(left, middle, right)
|
342
347
|
assert_priority_less left, right
|
343
348
|
assert_priority_same left, middle
|
344
|
-
assert_priority_more right,
|
349
|
+
assert_priority_more right, middle
|
345
350
|
end
|
346
351
|
|
347
352
|
let(:text_1) { mime_type("content-type" => "text/1") }
|
348
353
|
let(:text_1p) { mime_type("content-type" => "text/1") }
|
349
354
|
let(:text_2) { mime_type("content-type" => "text/2") }
|
350
355
|
|
351
|
-
it "sorts
|
356
|
+
it "sorts based on the simplified type when the sort priorities are the same" do
|
352
357
|
assert_priority text_1, text_1p, text_2
|
353
358
|
end
|
354
359
|
|
355
|
-
it "sorts
|
356
|
-
text_1.
|
357
|
-
|
360
|
+
it "sorts obsolete types higher than non-obsolete types" do
|
361
|
+
text_1.obsolete = text_1p.obsolete = false
|
362
|
+
text_1b = mime_type(text_1) { |t| t.obsolete = true }
|
363
|
+
|
364
|
+
assert_priority_less text_1, text_1b
|
358
365
|
|
359
|
-
|
366
|
+
assert_priority text_1, text_1p, text_1b
|
367
|
+
end
|
360
368
|
|
361
|
-
|
369
|
+
it "sorts provisional types higher than non-provisional types" do
|
370
|
+
text_1.provisional = text_1p.provisional = false
|
371
|
+
text_1b = mime_type(text_1) { |t| t.provisional = true }
|
362
372
|
|
363
|
-
|
373
|
+
assert_priority text_1, text_1p, text_1b
|
364
374
|
end
|
365
375
|
|
366
376
|
it "sorts (3) based on the registration state" do
|
@@ -377,23 +387,11 @@ describe MIME::Type do
|
|
377
387
|
assert_priority text_1, text_1p, text_1b
|
378
388
|
end
|
379
389
|
|
380
|
-
it "sorts
|
381
|
-
text_1.
|
382
|
-
|
383
|
-
|
384
|
-
assert_priority text_1, text_1p, text_1b
|
385
|
-
end
|
386
|
-
|
387
|
-
it "sorts (5) based on the use-instead value" do
|
388
|
-
text_1.obsolete = text_1p.obsolete = true
|
389
|
-
text_1.use_instead = text_1p.use_instead = "abc/xyz"
|
390
|
-
text_1b = mime_type(text_1) { |t| t.use_instead = nil }
|
391
|
-
|
392
|
-
assert_priority text_1, text_1p, text_1b
|
393
|
-
|
394
|
-
text_1b.use_instead = "abc/zzz"
|
390
|
+
it "sorts based on extensions (more extensions sort lower)" do
|
391
|
+
text_1.extensions = ["foo", "bar"]
|
392
|
+
text_2.extensions = ["foo"]
|
395
393
|
|
396
|
-
|
394
|
+
assert_priority_less text_1, text_2
|
397
395
|
end
|
398
396
|
end
|
399
397
|
|
@@ -502,10 +500,10 @@ describe MIME::Type do
|
|
502
500
|
|
503
501
|
describe "#to_json" do
|
504
502
|
let(:expected_1) {
|
505
|
-
'{"content-type":"a/b","encoding":"base64","registered":false}'
|
503
|
+
'{"content-type":"a/b","encoding":"base64","registered":false,"sort-priority":48}'
|
506
504
|
}
|
507
505
|
let(:expected_2) {
|
508
|
-
'{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true}'
|
506
|
+
'{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true,"sort-priority":80}'
|
509
507
|
}
|
510
508
|
|
511
509
|
it "converts to JSON when requested" do
|
@@ -47,7 +47,7 @@ describe MIME::Types, "registry" do
|
|
47
47
|
}
|
48
48
|
# This is this way because of a new type ending with gzip that only
|
49
49
|
# appears in some data files.
|
50
|
-
assert_equal %w[application/gzip
|
50
|
+
assert_equal %w[application/gzip multipart/x-gzip application/x-gzip], types
|
51
51
|
assert_equal 3, types.size
|
52
52
|
end
|
53
53
|
|
@@ -86,9 +86,8 @@ describe MIME::Types, "registry" do
|
|
86
86
|
assert_equal %w[image/jpeg], MIME::Types.of(["foo.jpeg", "bar.jpeg"])
|
87
87
|
end
|
88
88
|
|
89
|
-
it "finds multiple extensions" do
|
90
|
-
assert_equal %w[image/jpeg
|
91
|
-
MIME::Types.type_for(%w[foo.txt foo.jpeg])
|
89
|
+
it "finds multiple extensions ordered by the filename list" do
|
90
|
+
assert_equal %w[text/plain image/jpeg], MIME::Types.type_for(%w[foo.txt foo.jpeg])
|
92
91
|
end
|
93
92
|
|
94
93
|
it "does not find unknown extensions" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mime-types
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.7.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Austin Ziegler
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-04 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: mime-types-data
|
@@ -15,14 +15,20 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: '3.
|
18
|
+
version: '3.2025'
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2025.0506.pre1
|
19
22
|
type: :runtime
|
20
23
|
prerelease: false
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
22
25
|
requirements:
|
23
26
|
- - "~>"
|
24
27
|
- !ruby/object:Gem::Version
|
25
|
-
version: '3.
|
28
|
+
version: '3.2025'
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 3.2025.0506.pre1
|
26
32
|
- !ruby/object:Gem::Dependency
|
27
33
|
name: logger
|
28
34
|
requirement: !ruby/object:Gem::Requirement
|
@@ -269,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
269
275
|
- !ruby/object:Gem::Version
|
270
276
|
version: '0'
|
271
277
|
requirements: []
|
272
|
-
rubygems_version: 3.6.
|
278
|
+
rubygems_version: 3.6.6
|
273
279
|
specification_version: 4
|
274
280
|
summary: The mime-types library provides a library and registry for information about
|
275
281
|
MIME content type definitions
|