mime-types 2.5 → 2.6
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/.gitignore +1 -0
- data/Contributing.rdoc +72 -20
- data/History-Types.rdoc +11 -0
- data/History.rdoc +31 -1
- data/Manifest.txt +18 -1
- data/README.rdoc +142 -61
- data/Rakefile +59 -91
- data/data/mime-types.json +1 -1
- data/data/mime.content_type.column +1907 -0
- data/data/mime.docs.column +1907 -0
- data/data/mime.encoding.column +1907 -0
- data/data/mime.friendly.column +1907 -0
- data/data/mime.obsolete.column +1907 -0
- data/data/mime.references.column +1907 -0
- data/data/mime.registered.column +1907 -0
- data/data/mime.signature.column +1907 -0
- data/data/mime.system.column +1907 -0
- data/data/mime.use_instead.column +1907 -0
- data/data/mime.xrefs.column +1907 -0
- data/lib/mime/type.rb +192 -119
- data/lib/mime/type/columnar.rb +112 -0
- data/lib/mime/types.rb +39 -25
- data/lib/mime/types/cache.rb +41 -35
- data/lib/mime/types/columnar.rb +160 -0
- data/lib/mime/types/deprecations.rb +53 -0
- data/lib/mime/types/loader.rb +60 -20
- data/lib/mime/types/loader_path.rb +2 -3
- data/lib/mime/types/logger.rb +35 -0
- data/support/apache_mime_types.rb +8 -1
- data/support/benchmarks/load.rb +17 -8
- data/support/benchmarks/load_allocations.rb +83 -0
- data/support/benchmarks/object_counts.rb +41 -0
- data/support/convert.rb +44 -24
- data/support/convert/columnar.rb +90 -0
- data/support/iana_registry.rb +18 -8
- data/test/fixture/json.json +1 -1
- data/test/fixture/yaml.yaml +3 -6
- data/test/minitest_helper.rb +9 -10
- data/test/test_mime_type.rb +126 -62
- data/test/test_mime_types.rb +15 -11
- data/test/test_mime_types_class.rb +16 -14
- data/test/test_mime_types_lazy.rb +7 -1
- data/test/test_mime_types_loader.rb +17 -8
- metadata +54 -12
- data/lib/mime.rb +0 -51
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'mime/types/logger'
|
4
|
+
|
5
|
+
# The namespace for MIME applications, tools, and libraries.
|
6
|
+
module MIME
|
7
|
+
class Types
|
8
|
+
# Used to mark a method as deprecated in the mime-types interface.
|
9
|
+
def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
|
10
|
+
level = case klass
|
11
|
+
when Class, Module
|
12
|
+
'.'
|
13
|
+
else
|
14
|
+
klass = klass.class
|
15
|
+
'#'
|
16
|
+
end
|
17
|
+
message = case message
|
18
|
+
when :private, :protected
|
19
|
+
"and will be #{message}"
|
20
|
+
when nil
|
21
|
+
'and will be removed'
|
22
|
+
else
|
23
|
+
message
|
24
|
+
end
|
25
|
+
MIME::Types.logger.warn <<-warning.chomp
|
26
|
+
#{caller[1]}: #{klass}#{level}#{sym} is deprecated #{message}.
|
27
|
+
warning
|
28
|
+
block.call if block
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
# MIME::InvalidContentType was moved to MIME::Type::InvalidContentType.
|
34
|
+
# Provide a single warning about this fact in the interim.
|
35
|
+
def const_missing(name) # :nodoc:
|
36
|
+
case name.to_s
|
37
|
+
when 'InvalidContentType'
|
38
|
+
warn_about_moved_constants(name)
|
39
|
+
MIME::Type.const_get(name.to_sym)
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def warn_about_moved_constants(name)
|
48
|
+
MIME::Types.logger.warn <<-warning.chomp
|
49
|
+
#{caller[1]}: MIME::#{name} is deprecated. Use MIME::Type::#{name} instead.
|
50
|
+
warning
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/mime/types/loader.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# -*- ruby encoding: utf-8 -*-
|
2
2
|
|
3
|
+
module MIME; end
|
4
|
+
class MIME::Types; end
|
5
|
+
|
3
6
|
require 'mime/types/loader_path'
|
4
7
|
|
5
8
|
# This class is responsible for initializing the MIME::Types registry from
|
@@ -23,10 +26,13 @@ class MIME::Types::Loader
|
|
23
26
|
# Creates a Loader object that can be used to load MIME::Types registries
|
24
27
|
# into memory, using YAML, JSON, or v1 registry format loaders.
|
25
28
|
def initialize(path = nil, container = nil)
|
26
|
-
path
|
27
|
-
MIME::Types::Loader::PATH
|
28
|
-
@path = File.expand_path(File.join(path, '**'))
|
29
|
+
path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Loader::PATH
|
29
30
|
@container = container || MIME::Types.new
|
31
|
+
@path = File.expand_path(path)
|
32
|
+
# begin
|
33
|
+
# require 'mime/lazy_types'
|
34
|
+
# @container.extend(MIME::LazyTypes)
|
35
|
+
# end
|
30
36
|
end
|
31
37
|
|
32
38
|
# Loads a MIME::Types registry from YAML files (<tt>*.yml</tt> or
|
@@ -52,8 +58,6 @@ class MIME::Types::Loader
|
|
52
58
|
# It is expected that the JSON objects will be an array of hash objects.
|
53
59
|
# The JSON format is the registry format for the MIME types registry
|
54
60
|
# shipped with the mime-types library.
|
55
|
-
#
|
56
|
-
# This method is aliased to #load.
|
57
61
|
def load_json
|
58
62
|
Dir[json_path].sort.each do |f|
|
59
63
|
types = self.class.load_from_json(f)
|
@@ -61,29 +65,52 @@ class MIME::Types::Loader
|
|
61
65
|
end
|
62
66
|
container
|
63
67
|
end
|
64
|
-
|
68
|
+
|
69
|
+
# Loads a MIME::Types registry from columnar files recursively found in
|
70
|
+
# +path+.
|
71
|
+
def load_columnar
|
72
|
+
require 'mime/types/columnar'
|
73
|
+
container.extend(MIME::Types::Columnar)
|
74
|
+
container.load_base_data(path)
|
75
|
+
|
76
|
+
container
|
77
|
+
end
|
78
|
+
|
79
|
+
# Loads a MIME::Types registry. Loads from JSON files by default
|
80
|
+
# (#load_json).
|
81
|
+
#
|
82
|
+
# This will load from columnar files (#load_columnar) if <tt>columnar:
|
83
|
+
# true</tt> is provided in +options+ and there are columnar files in +path+.
|
84
|
+
def load(options = { columnar: false })
|
85
|
+
if options[:columnar] && !Dir[columnar_path].empty?
|
86
|
+
load_columnar
|
87
|
+
else
|
88
|
+
load_json
|
89
|
+
end
|
90
|
+
end
|
65
91
|
|
66
92
|
# Loads a MIME::Types registry from files found in +path+ that are in the
|
67
93
|
# v1 data format. The file search for this will exclude both JSON
|
68
94
|
# (<tt>*.json</tt>) and YAML (<tt>*.yml</tt> or <tt>*.yaml</tt>) files.
|
69
95
|
#
|
70
|
-
# This method has been deprecated.
|
96
|
+
# This method has been deprecated and will be removed from mime-types 3.0.
|
71
97
|
def load_v1
|
72
|
-
MIME.deprecated(self.class, __method__)
|
98
|
+
MIME::Types.deprecated(self.class, __method__)
|
73
99
|
Dir[v1_path].sort.each do |f|
|
74
|
-
next if f =~ /\.ya?ml
|
75
|
-
container.add(self.class.load_from_v1(f), true)
|
100
|
+
next if f =~ /\.(?:ya?ml|json|column)$/
|
101
|
+
container.add(self.class.load_from_v1(f, true), true)
|
76
102
|
end
|
77
103
|
container
|
78
104
|
end
|
79
105
|
|
80
|
-
# Raised when a V1 format file is discovered.
|
106
|
+
# Raised when a V1 format file is discovered. This exception will be removed
|
107
|
+
# for mime-types 3.0.
|
81
108
|
BadV1Format = Class.new(Exception)
|
82
109
|
|
83
110
|
class << self
|
84
111
|
# Loads the default MIME::Type registry.
|
85
|
-
def load
|
86
|
-
new.load
|
112
|
+
def load(options = { columnar: false })
|
113
|
+
new.load(options)
|
87
114
|
end
|
88
115
|
|
89
116
|
# Build the type list from a file in the format:
|
@@ -122,8 +149,10 @@ class MIME::Types::Loader
|
|
122
149
|
# That is, everything except the media type and the subtype is optional. The
|
123
150
|
# more information that's available, though, the richer the values that can
|
124
151
|
# be provided.
|
125
|
-
|
126
|
-
|
152
|
+
#
|
153
|
+
# This method has been deprecated and will be removed in mime-types 3.0.
|
154
|
+
def load_from_v1(filename, __internal__ = false)
|
155
|
+
MIME::Types.deprecated(self.class, __method__) unless __internal__
|
127
156
|
data = read_file(filename).split($/)
|
128
157
|
mime = MIME::Types.new
|
129
158
|
data.each_with_index { |line, index|
|
@@ -133,11 +162,11 @@ class MIME::Types::Loader
|
|
133
162
|
m = V1_FORMAT.match(item)
|
134
163
|
|
135
164
|
unless m
|
136
|
-
warn <<-EOS
|
165
|
+
MIME::Types.logger.warn <<-EOS
|
137
166
|
#{filename}:#{index + 1}: Parsing error in v1 MIME type definition.
|
138
167
|
=> #{line}
|
139
168
|
EOS
|
140
|
-
|
169
|
+
fail BadV1Format, line
|
141
170
|
end
|
142
171
|
|
143
172
|
unregistered, obsolete, platform, mediatype, subtype, extensions,
|
@@ -151,8 +180,8 @@ class MIME::Types::Loader
|
|
151
180
|
if docs.nil?
|
152
181
|
use_instead = nil
|
153
182
|
else
|
154
|
-
use_instead = docs.scan(%r{use-instead:(\S+)}).flatten
|
155
|
-
docs = docs.gsub(%r{use-instead:\S+},
|
183
|
+
use_instead = docs.scan(%r{use-instead:(\S+)}).flatten.first
|
184
|
+
docs = docs.gsub(%r{use-instead:\S+}, '').squeeze(' \t')
|
156
185
|
end
|
157
186
|
|
158
187
|
mime_type = MIME::Type.new("#{mediatype}/#{subtype}") do |t|
|
@@ -163,7 +192,10 @@ class MIME::Types::Loader
|
|
163
192
|
t.registered = false if unregistered
|
164
193
|
t.use_instead = use_instead
|
165
194
|
t.docs = docs
|
166
|
-
|
195
|
+
|
196
|
+
# This is being removed. Cheat to silence it for now.
|
197
|
+
t.instance_variable_set :@references,
|
198
|
+
Array(urls).flatten.compact.uniq
|
167
199
|
end
|
168
200
|
|
169
201
|
mime.add_type(mime_type, true)
|
@@ -201,12 +233,14 @@ class MIME::Types::Loader
|
|
201
233
|
end
|
202
234
|
|
203
235
|
private
|
236
|
+
|
204
237
|
def read_file(filename)
|
205
238
|
File.open(filename, 'r:UTF-8:-') { |f| f.read }
|
206
239
|
end
|
207
240
|
end
|
208
241
|
|
209
242
|
private
|
243
|
+
|
210
244
|
def yaml_path
|
211
245
|
File.join(path, '*.y{,a}ml')
|
212
246
|
end
|
@@ -215,12 +249,18 @@ class MIME::Types::Loader
|
|
215
249
|
File.join(path, '*.json')
|
216
250
|
end
|
217
251
|
|
252
|
+
def columnar_path
|
253
|
+
File.join(path, '*.column')
|
254
|
+
end
|
255
|
+
|
218
256
|
def v1_path
|
219
257
|
File.join(path, '*')
|
220
258
|
end
|
221
259
|
|
222
260
|
# The regular expression used to match a v1-format file-based MIME type
|
223
261
|
# definition.
|
262
|
+
#
|
263
|
+
# This constant has been deprecated and will be removed in mime-types 3.0.
|
224
264
|
V1_FORMAT = # :nodoc:
|
225
265
|
%r{\A\s*
|
226
266
|
([*])? # 0: Unregistered?
|
@@ -5,9 +5,8 @@ class MIME::Types::Loader
|
|
5
5
|
# location is __FILE__/../../../../data, which is where the data lives
|
6
6
|
# in the gem installation of the mime-types library.
|
7
7
|
#
|
8
|
-
# The MIME::Types::Loader will load all
|
9
|
-
#
|
10
|
-
# application.yml, audio.yml, etc.).
|
8
|
+
# The MIME::Types::Loader will load all JSON or columnar files contained in
|
9
|
+
# this path.
|
11
10
|
#
|
12
11
|
# System repackagers note: this is the constant that you would change if
|
13
12
|
# you repackage mime-types for your system. It is recommended that the
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module MIME
|
6
|
+
class Types
|
7
|
+
class << self
|
8
|
+
# Configure the MIME::Types logger. This defaults to an instance of a
|
9
|
+
# logger that passes messages (unformatted) through to Kernel#warn.
|
10
|
+
attr_accessor :logger
|
11
|
+
end
|
12
|
+
|
13
|
+
class WarnLogger < ::Logger #:nodoc:
|
14
|
+
class WarnLogDevice < ::Logger::LogDevice #:nodoc:
|
15
|
+
def initialize(*)
|
16
|
+
end
|
17
|
+
|
18
|
+
def write(m)
|
19
|
+
Kernel.warn(m)
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(_1, _2 = nil, _3 = nil)
|
27
|
+
super nil
|
28
|
+
@logdev = WarnLogDevice.new
|
29
|
+
@formatter = ->(_s, _d, _p, m) { m }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
self.logger = WarnLogger.new(nil)
|
34
|
+
end
|
35
|
+
end
|
@@ -15,6 +15,12 @@ class MIME::Type
|
|
15
15
|
public_constant :UNREGISTERED_RE
|
16
16
|
end
|
17
17
|
|
18
|
+
class MIME::Types
|
19
|
+
def self.deprecated(*_args, &_block)
|
20
|
+
# We are an internal tool. Silence deprecation warnings.
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
18
24
|
class ApacheMIMETypes
|
19
25
|
DEFAULTS = {
|
20
26
|
url: %q(http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types),
|
@@ -25,7 +31,7 @@ class ApacheMIMETypes
|
|
25
31
|
dest = Pathname(options[:to] || DEFAULTS[:to]).expand_path
|
26
32
|
url = options.fetch(:url, DEFAULTS[:url])
|
27
33
|
|
28
|
-
puts
|
34
|
+
puts 'Downloading Apache MIME type list.'
|
29
35
|
puts "\t#{url}"
|
30
36
|
data = open(url) { |f| f.read }.split($/)
|
31
37
|
data.delete_if { |line| line =~ /\A#/ }
|
@@ -91,6 +97,7 @@ class ApacheMIMETypes
|
|
91
97
|
end
|
92
98
|
|
93
99
|
private
|
100
|
+
|
94
101
|
def mime_types_for(file)
|
95
102
|
if file.exist?
|
96
103
|
MIME::Types::Loader.load_from_yaml(file)
|
data/support/benchmarks/load.rb
CHANGED
@@ -15,11 +15,19 @@ module Benchmarks
|
|
15
15
|
@load_path = load_path
|
16
16
|
end
|
17
17
|
|
18
|
-
def reload_mime_types(repeats = 1,
|
18
|
+
def reload_mime_types(repeats = 1, options = {})
|
19
|
+
force_load = options.fetch(:force_load, false)
|
20
|
+
columnar = options.fetch(:columnar, false)
|
21
|
+
|
19
22
|
repeats.times {
|
20
23
|
Object.send(:remove_const, :MIME) if defined? ::MIME
|
21
24
|
$LOADED_FEATURES.delete_if { |n| n =~ /#{@load_path}/ }
|
22
|
-
|
25
|
+
|
26
|
+
if columnar
|
27
|
+
require 'mime/types/columnar'
|
28
|
+
else
|
29
|
+
require 'mime/types'
|
30
|
+
end
|
23
31
|
::MIME::Types.send(:__types__) if force_load
|
24
32
|
}
|
25
33
|
end
|
@@ -28,21 +36,22 @@ module Benchmarks
|
|
28
36
|
remove_cache
|
29
37
|
|
30
38
|
Benchmark.bm(17) do |mark|
|
31
|
-
mark.report(
|
39
|
+
mark.report('Normal:') { reload_mime_types(@repeats) }
|
40
|
+
mark.report('Columnar:') { reload_mime_types(@repeats, columnar: true) }
|
32
41
|
|
33
42
|
ENV['RUBY_MIME_TYPES_LAZY_LOAD'] = 'yes'
|
34
|
-
mark.report(
|
35
|
-
mark.report(
|
43
|
+
mark.report('Lazy:') { reload_mime_types(@repeats) }
|
44
|
+
mark.report('Lazy+Load:') { reload_mime_types(@repeats, force_load: true) }
|
36
45
|
|
37
46
|
ENV.delete('RUBY_MIME_TYPES_LAZY_LOAD')
|
38
47
|
|
39
48
|
ENV['RUBY_MIME_TYPES_CACHE'] = @cache_file
|
40
49
|
reload_mime_types
|
41
50
|
|
42
|
-
mark.report(
|
51
|
+
mark.report('Cached:') { reload_mime_types(@repeats) }
|
43
52
|
ENV['RUBY_MIME_TYPES_LAZY_LOAD'] = 'yes'
|
44
|
-
mark.report(
|
45
|
-
mark.report(
|
53
|
+
mark.report('Lazy Cached:') { reload_mime_types(@repeats) }
|
54
|
+
mark.report('Lazy Cached Load:') { reload_mime_types(@repeats, force_load: true) }
|
46
55
|
end
|
47
56
|
ensure
|
48
57
|
remove_cache
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
|
3
|
+
if RUBY_VERSION < '2.1'
|
4
|
+
$stderr.puts "Cannot count allocations on #{RUBY_VERSION}."
|
5
|
+
exit 1
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'allocation_tracer'
|
10
|
+
rescue LoadError
|
11
|
+
$stderr.puts "Allocation tracking requires the gem 'allocation_tracer'."
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
|
15
|
+
module Benchmarks
|
16
|
+
class LoadAllocations
|
17
|
+
def self.report(columnar: false, top_x: nil, mime_types_only: false)
|
18
|
+
new(columnar: columnar, top_x: top_x, mime_types_only: mime_types_only).
|
19
|
+
report
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(columnar: false, top_x: nil, mime_types_only: false)
|
23
|
+
@columnar = columnar
|
24
|
+
@mime_types_only = !!mime_types_only
|
25
|
+
|
26
|
+
@top_x = top_x
|
27
|
+
|
28
|
+
return unless @top_x
|
29
|
+
@top_x = top_x.to_i
|
30
|
+
@top_x = 10 if @top_x <= 0
|
31
|
+
end
|
32
|
+
|
33
|
+
def report
|
34
|
+
collect
|
35
|
+
report_top_x if @top_x
|
36
|
+
puts "TOTAL Allocations: #{@count}"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def report_top_x
|
42
|
+
table = @allocations.sort_by { |_, v| v.first }.reverse.first(@top_x)
|
43
|
+
table.map! { |(location, allocs)|
|
44
|
+
next if @mime_types_only and location.first !~ %r{mime-types/lib}
|
45
|
+
[ location.join(':').gsub(%r{^#{Dir.pwd}/}, ''), *allocs ]
|
46
|
+
}.compact!
|
47
|
+
|
48
|
+
head = (ObjectSpace::AllocationTracer.header - [ :line ]).map {|h|
|
49
|
+
h.to_s.split(/_/).map(&:capitalize).join(' ')
|
50
|
+
}
|
51
|
+
table.unshift head
|
52
|
+
|
53
|
+
max_widths = [].tap do |mw|
|
54
|
+
table.map { |row| row.lazy.map(&:to_s).map(&:length).to_a }.tap do |w|
|
55
|
+
w.first.each_index do |i|
|
56
|
+
mw << w.lazy.map { |r| r[i] }.max
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
pattern = [ '%%-%ds' ]
|
62
|
+
pattern << ([ '%% %ds' ] * (max_widths.length - 1))
|
63
|
+
pattern = pattern.join("\t") % max_widths
|
64
|
+
table.each { |row| puts pattern % row }
|
65
|
+
puts
|
66
|
+
end
|
67
|
+
|
68
|
+
def collect
|
69
|
+
if @columnar
|
70
|
+
@allocations = ObjectSpace::AllocationTracer.trace do
|
71
|
+
require 'mime/types/columnar'
|
72
|
+
end
|
73
|
+
else
|
74
|
+
@allocations = ObjectSpace::AllocationTracer.trace do
|
75
|
+
require 'mime/types'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@count = ObjectSpace::AllocationTracer.allocated_count_table.values.
|
80
|
+
inject(:+)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Benchmarks
|
4
|
+
class ObjectCounts
|
5
|
+
def self.report(columnar: false)
|
6
|
+
new(columnar: columnar).report
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(columnar: false)
|
10
|
+
@columnar = columnar
|
11
|
+
end
|
12
|
+
|
13
|
+
def report
|
14
|
+
collect
|
15
|
+
@before.keys.grep(/T_/).map { |key|
|
16
|
+
[ key, @after[key] - @before[key] ]
|
17
|
+
}.sort_by { |_, delta| -delta }.each { |key, delta|
|
18
|
+
puts '%10s +%6d' % [ key, delta ]
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def collect
|
25
|
+
@before = count_objects
|
26
|
+
|
27
|
+
if @columnar
|
28
|
+
require 'mime/types/columnar'
|
29
|
+
else
|
30
|
+
require 'mime/types'
|
31
|
+
end
|
32
|
+
|
33
|
+
@after = count_objects
|
34
|
+
end
|
35
|
+
|
36
|
+
def count_objects
|
37
|
+
GC.start
|
38
|
+
ObjectSpace.count_objects
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|