mime-types 2.99.3 → 3.3.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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/{Code-of-Conduct.rdoc → Code-of-Conduct.md} +19 -20
  3. data/Contributing.md +143 -0
  4. data/History.md +240 -0
  5. data/{Licence.rdoc → Licence.md} +4 -18
  6. data/Manifest.txt +8 -25
  7. data/README.rdoc +62 -73
  8. data/Rakefile +175 -58
  9. data/lib/mime-types.rb +1 -1
  10. data/lib/mime/type.rb +213 -424
  11. data/lib/mime/type/columnar.rb +29 -62
  12. data/lib/mime/types.rb +46 -141
  13. data/lib/mime/types/_columnar.rb +136 -0
  14. data/lib/mime/types/cache.rb +51 -73
  15. data/lib/mime/types/columnar.rb +2 -147
  16. data/lib/mime/types/container.rb +96 -0
  17. data/lib/mime/types/deprecations.rb +4 -25
  18. data/lib/mime/types/full.rb +19 -0
  19. data/lib/mime/types/loader.rb +12 -141
  20. data/lib/mime/types/logger.rb +5 -1
  21. data/lib/mime/types/registry.rb +90 -0
  22. data/test/minitest_helper.rb +5 -13
  23. data/test/test_mime_type.rb +470 -456
  24. data/test/test_mime_types.rb +135 -87
  25. data/test/test_mime_types_cache.rb +82 -54
  26. data/test/test_mime_types_class.rb +118 -98
  27. data/test/test_mime_types_lazy.rb +26 -24
  28. data/test/test_mime_types_loader.rb +6 -33
  29. metadata +107 -64
  30. data/Contributing.rdoc +0 -170
  31. data/History-Types.rdoc +0 -454
  32. data/History.rdoc +0 -590
  33. data/data/mime-types.json +0 -1
  34. data/data/mime.content_type.column +0 -1980
  35. data/data/mime.docs.column +0 -1980
  36. data/data/mime.encoding.column +0 -1980
  37. data/data/mime.friendly.column +0 -1980
  38. data/data/mime.obsolete.column +0 -1980
  39. data/data/mime.registered.column +0 -1980
  40. data/data/mime.signature.column +0 -1980
  41. data/data/mime.use_instead.column +0 -1980
  42. data/data/mime.xrefs.column +0 -1980
  43. data/docs/COPYING.txt +0 -339
  44. data/docs/artistic.txt +0 -127
  45. data/lib/mime/types/loader_path.rb +0 -15
  46. data/support/apache_mime_types.rb +0 -108
  47. data/support/benchmarks/load.rb +0 -64
  48. data/support/benchmarks/load_allocations.rb +0 -83
  49. data/support/benchmarks/object_counts.rb +0 -41
  50. data/support/convert.rb +0 -158
  51. data/support/convert/columnar.rb +0 -88
  52. data/support/iana_registry.rb +0 -172
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mime/type'
2
4
 
3
5
  # A version of MIME::Type that works hand-in-hand with a MIME::Types::Columnar
@@ -11,80 +13,45 @@ require 'mime/type'
11
13
  # MIME::Type::Columnar is *not* intended to be created except by
12
14
  # MIME::Types::Columnar containers.
13
15
  class MIME::Type::Columnar < MIME::Type
14
- attr_writer :friendly # :nodoc:
15
-
16
16
  def initialize(container, content_type, extensions) # :nodoc:
17
17
  @container = container
18
18
  self.content_type = content_type
19
19
  self.extensions = extensions
20
20
  end
21
21
 
22
- def friendly(*) # :nodoc:
23
- @container.send(:load_friendly) unless defined?(@friendly)
24
- super if @friendly
25
- end
26
-
27
- def encoding # :nodoc:
28
- @container.send(:load_encoding) unless defined?(@encoding)
29
- @encoding
30
- end
31
-
32
- def docs # :nodoc:
33
- @container.send(:load_docs) unless defined?(@docs)
34
- @docs
35
- end
36
-
37
- def obsolete? # :nodoc:
38
- @container.send(:load_obsolete) unless defined?(@obsolete)
39
- super
40
- end
41
-
42
- def registered? # :nodoc:
43
- @container.send(:load_registered) unless defined?(@registered)
44
- super
45
- end
46
-
47
- def signature? # :nodoc:
48
- @container.send(:load_signature) unless defined?(@signature)
49
- super
50
- end
22
+ def self.column(*methods, file: nil) # :nodoc:
23
+ file ||= methods.first
51
24
 
52
- def xrefs # :nodoc:
53
- @container.send(:load_xrefs) unless defined?(@xrefs)
54
- @xrefs
25
+ file_method = :"load_#{file}"
26
+ methods.each do |m|
27
+ define_method m do |*args|
28
+ @container.send(file_method)
29
+ super(*args)
30
+ end
31
+ end
55
32
  end
56
33
 
57
- def use_instead # :nodoc:
58
- @container.send(:load_use_instead) unless defined?(@use_instead)
59
- @use_instead
60
- end
61
-
62
- def binary? # :nodoc:
63
- @container.send(:load_encoding) unless defined?(@encoding)
64
- super
65
- end
34
+ column :friendly
35
+ column :encoding, :encoding=
36
+ column :docs, :docs=
37
+ column :preferred_extension, :preferred_extension=
38
+ column :obsolete, :obsolete=, :obsolete?, :registered, :registered=,
39
+ :registered?, :signature, :signature=, :signature?, file: 'flags'
40
+ column :xrefs, :xrefs=, :xref_urls
41
+ column :use_instead, :use_instead=
66
42
 
67
- def to_a # :nodoc:
68
- @container.send(:load_encoding) unless defined?(@encoding)
69
- @container.send(:load_docs) unless defined?(@docs)
70
- super
71
- end
72
-
73
- def to_hash # :nodoc:
74
- @container.send(:load_encoding) unless defined?(@encoding)
75
- @container.send(:load_docs) unless defined?(@docs)
43
+ def encode_with(coder) # :nodoc:
44
+ @container.send(:load_friendly)
45
+ @container.send(:load_encoding)
46
+ @container.send(:load_docs)
47
+ @container.send(:load_flags)
48
+ @container.send(:load_use_instead)
49
+ @container.send(:load_xrefs)
50
+ @container.send(:load_preferred_extension)
76
51
  super
77
52
  end
78
53
 
79
- def encode_with(coder) # :nodoc:
80
- @container.send(:load_friendly) unless defined?(@friendly)
81
- @container.send(:load_encoding) unless defined?(@encoding)
82
- @container.send(:load_docs) unless defined?(@docs)
83
- @container.send(:load_obsolete) unless defined?(@obsolete)
84
- @container.send(:load_use_instead) unless defined?(@use_instead)
85
- @container.send(:load_xrefs) unless defined?(@xrefs)
86
- @container.send(:load_registered) unless defined?(@registered)
87
- @container.send(:load_signature) unless defined?(@signature)
88
- super
54
+ class << self
55
+ undef column
89
56
  end
90
57
  end
@@ -1,9 +1,13 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ module MIME
5
+ ##
6
+ class Types
7
+ end
8
+ end
2
9
 
3
- require 'mime/types/deprecations'
4
10
  require 'mime/type'
5
- require 'mime/types/cache'
6
- require 'mime/types/loader'
7
11
 
8
12
  # MIME::Types is a registry of MIME types. It is both a class (created with
9
13
  # MIME::Types.new) and a default registry (loaded automatically or through
@@ -66,37 +70,19 @@ class MIME::Types
66
70
 
67
71
  include Enumerable
68
72
 
69
- # The data version.
70
- attr_reader :data_version
71
-
72
73
  # Creates a new MIME::Types registry.
73
74
  def initialize
74
75
  @type_variants = Container.new
75
76
  @extension_index = Container.new
76
- @data_version = VERSION.dup.freeze
77
- end
78
-
79
- # This method is deprecated and will be removed in mime-types 3.0.
80
- def add_type_variant(mime_type) # :nodoc:
81
- MIME::Types.deprecated(self, __method__, :private)
82
- add_type_variant!(mime_type)
83
- end
84
-
85
- # This method is deprecated and will be removed in mime-types 3.0.
86
- def index_extensions(mime_type) # :nodoc:
87
- MIME::Types.deprecated(self, __method__, :private)
88
- index_extensions!(mime_type)
89
- end
90
-
91
- # This method is deprecated and will be removed in mime-types 3.0.
92
- def defined_types # :nodoc:
93
- MIME::Types.deprecated(self, __method__)
94
- @type_variants.values.flatten
95
77
  end
96
78
 
97
79
  # Returns the number of known type variants.
98
80
  def count
99
- @type_variants.values.reduce(0) { |m, o| m + o.size }
81
+ @type_variants.values.inject(0) { |a, e| a + e.size }
82
+ end
83
+
84
+ def inspect # :nodoc:
85
+ "#<#{self.class}: #{count} variants, #{@extension_index.count} extensions>"
100
86
  end
101
87
 
102
88
  # Iterates through the type variants.
@@ -108,7 +94,7 @@ class MIME::Types
108
94
  end
109
95
  end
110
96
 
111
- @__types__ = nil
97
+ @__types__ = nil
112
98
 
113
99
  # Returns a list of MIME::Type objects, which may be empty. The optional
114
100
  # flag parameters are <tt>:complete</tt> (finds only complete MIME::Type
@@ -135,13 +121,7 @@ class MIME::Types
135
121
  # without;
136
122
  # 5. Obsolete definitions use-instead clauses are compared.
137
123
  # 6. Sort on name.
138
- #
139
- # The previously supported (but deprecated) <tt>:platform</tt> flag is now ignored.
140
- def [](type_id, flags = {})
141
- if flags.key?(:platform)
142
- MIME::Types.deprecated(self, __method__, 'using the :platform flag')
143
- end
144
-
124
+ def [](type_id, complete: false, registered: false)
145
125
  matches = case type_id
146
126
  when MIME::Type
147
127
  @type_variants[type_id.simplified]
@@ -151,7 +131,9 @@ class MIME::Types
151
131
  @type_variants[MIME::Type.simplified(type_id)]
152
132
  end
153
133
 
154
- prune_matches(matches, flags).sort { |a, b| a.priority_compare(b) }
134
+ prune_matches(matches, complete, registered).sort { |a, b|
135
+ a.priority_compare(b)
136
+ }
155
137
  end
156
138
 
157
139
  # Return the list of MIME::Types which belongs to the file based on its
@@ -166,19 +148,14 @@ class MIME::Types
166
148
  # => [image/gif]
167
149
  # puts MIME::Types.type_for(%w(citydesk.xml citydesk.gif))
168
150
  # => [application/xml, image/gif, text/xml]
169
- #
170
- # The deprecated +platform+ flag is ignored.
171
- def type_for(filename, platform = :deprecated)
172
- types = Array(filename).flat_map { |fn|
151
+ def type_for(filename)
152
+ Array(filename).flat_map { |fn|
173
153
  @extension_index[fn.chomp.downcase[/\.?([^.]*?)$/, 1]]
174
- }.compact.sort { |a, b| a.priority_compare(b) }.uniq
175
-
176
- unless platform == :deprecated
177
- MIME::Types.deprecated(self, __method__, 'using the platform parameter')
178
- end
179
- types
154
+ }.compact.inject(Set.new, :+).sort { |a, b|
155
+ a.priority_compare(b)
156
+ }
180
157
  end
181
- alias_method :of, :type_for
158
+ alias of type_for
182
159
 
183
160
  # Add one or more MIME::Type objects to the set of known types. If the
184
161
  # type is already known, a warning will be displayed.
@@ -194,7 +171,7 @@ class MIME::Types
194
171
  nil
195
172
  when MIME::Types
196
173
  variants = mime_type.instance_variable_get(:@type_variants)
197
- add(*variants.values.flatten, quiet)
174
+ add(*variants.values.inject(Set.new, :+).to_a, quiet)
198
175
  when Array
199
176
  add(*mime_type, quiet)
200
177
  else
@@ -208,119 +185,47 @@ class MIME::Types
208
185
  # truthy value to suppress that warning.
209
186
  def add_type(type, quiet = false)
210
187
  if !quiet and @type_variants[type.simplified].include?(type)
211
- MIME::Types.logger.warn <<-warning
188
+ MIME::Types.logger.warn <<-WARNING
212
189
  Type #{type} is already registered as a variant of #{type.simplified}.
213
- warning
190
+ WARNING
214
191
  end
215
192
 
216
193
  add_type_variant!(type)
217
194
  index_extensions!(type)
218
195
  end
219
196
 
220
- class << self
221
- include Enumerable
222
-
223
- # Load MIME::Types from a v1 file registry.
224
- #
225
- # This method has been deprecated and will be removed in mime-types 3.0.
226
- def load_from_file(filename)
227
- MIME::Types.deprecated(self, __method__)
228
- MIME::Types::Loader.load_from_v1(filename)
229
- end
230
-
231
- # MIME::Types#[] against the default MIME::Types registry.
232
- def [](type_id, flags = {})
233
- __types__[type_id, flags]
234
- end
235
-
236
- # MIME::Types#count against the default MIME::Types registry.
237
- def count
238
- __types__.count
239
- end
240
-
241
- # MIME::Types#each against the default MIME::Types registry.
242
- def each
243
- if block_given?
244
- __types__.each { |t| yield t }
245
- else
246
- enum_for(:each)
247
- end
248
- end
249
-
250
- # MIME::Types#type_for against the default MIME::Types registry.
251
- def type_for(filename, platform = :deprecated)
252
- __types__.type_for(filename, platform)
253
- end
254
- alias_method :of, :type_for
255
-
256
- # MIME::Types#add against the default MIME::Types registry.
257
- def add(*types)
258
- __types__.add(*types)
259
- end
260
-
261
- # Returns the currently defined cache file, if any.
262
- #
263
- # This method has been deprecated and will be removed in mime-types 3.0.
264
- def cache_file
265
- MIME::Types.deprecated(self, __method__)
266
- ENV['RUBY_MIME_TYPES_CACHE']
267
- end
268
-
269
- def add_type_variant(mime_type) # :nodoc:
270
- __types__.add_type_variant(mime_type)
271
- end
272
-
273
- def index_extensions(mime_type) # :nodoc:
274
- __types__.index_extensions(mime_type)
275
- end
276
-
277
- private
278
-
279
- def lazy_load?
280
- (lazy = ENV['RUBY_MIME_TYPES_LAZY_LOAD']) && (lazy != 'false')
281
- end
282
-
283
- def __types__
284
- (defined?(@__types__) and @__types__) or load_default_mime_types
285
- end
286
-
287
- unless private_method_defined?(:load_mode)
288
- def load_mode
289
- {}
290
- end
291
- end
197
+ private
292
198
 
293
- def load_default_mime_types(mode = load_mode())
294
- @__types__ = MIME::Types::Cache.load
295
- unless @__types__
296
- @__types__ = MIME::Types::Loader.load(mode)
297
- MIME::Types::Cache.save(@__types__)
298
- end
299
- @__types__
300
- end
199
+ def add_type_variant!(mime_type)
200
+ @type_variants.add(mime_type.simplified, mime_type)
301
201
  end
302
202
 
303
- private
203
+ def reindex_extensions!(mime_type)
204
+ return unless @type_variants[mime_type.simplified].include?(mime_type)
304
205
 
305
- def add_type_variant!(mime_type)
306
- @type_variants[mime_type.simplified] << mime_type
206
+ index_extensions!(mime_type)
307
207
  end
308
208
 
309
209
  def index_extensions!(mime_type)
310
- mime_type.extensions.each { |ext| @extension_index[ext] << mime_type }
210
+ mime_type.extensions.each { |ext| @extension_index.add(ext, mime_type) }
311
211
  end
312
212
 
313
- def prune_matches(matches, flags)
314
- matches.delete_if { |e| !e.complete? } if flags[:complete]
315
- matches.delete_if { |e| !e.registered? } if flags[:registered]
213
+ def prune_matches(matches, complete, registered)
214
+ matches.delete_if { |e| !e.complete? } if complete
215
+ matches.delete_if { |e| !e.registered? } if registered
316
216
  matches
317
217
  end
318
218
 
319
219
  def match(pattern)
320
- @type_variants.select { |k, _| k =~ pattern }.values.flatten
220
+ @type_variants.select { |k, _|
221
+ k =~ pattern
222
+ }.values.inject(Set.new, :+)
321
223
  end
322
-
323
- load_default_mime_types(load_mode) unless lazy_load?
324
224
  end
325
225
 
326
- # vim: ft=ruby
226
+ require 'mime/types/cache'
227
+ require 'mime/types/container'
228
+ require 'mime/types/loader'
229
+ require 'mime/types/logger'
230
+ require 'mime/types/_columnar'
231
+ require 'mime/types/registry'
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mime/type/columnar'
4
+
5
+ # MIME::Types::Columnar is used to extend a MIME::Types container to load data
6
+ # by columns instead of from JSON or YAML. Column loads of MIME types loaded
7
+ # through the columnar store are synchronized with a Mutex.
8
+ #
9
+ # MIME::Types::Columnar is not intended to be used directly, but will be added
10
+ # to an instance of MIME::Types when it is loaded with
11
+ # MIME::Types::Loader#load_columnar.
12
+ module MIME::Types::Columnar
13
+ LOAD_MUTEX = Mutex.new # :nodoc:
14
+
15
+ def self.extended(obj) # :nodoc:
16
+ super
17
+ obj.instance_variable_set(:@__mime_data__, [])
18
+ obj.instance_variable_set(:@__files__, Set.new)
19
+ end
20
+
21
+ # Load the first column data file (type and extensions).
22
+ def load_base_data(path) #:nodoc:
23
+ @__root__ = path
24
+
25
+ each_file_line('content_type', false) do |line|
26
+ line = line.split
27
+ content_type = line.shift
28
+ extensions = line
29
+ # content_type, *extensions = line.split
30
+
31
+ type = MIME::Type::Columnar.new(self, content_type, extensions)
32
+ @__mime_data__ << type
33
+ add(type)
34
+ end
35
+
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def each_file_line(name, lookup = true)
42
+ LOAD_MUTEX.synchronize do
43
+ next if @__files__.include?(name)
44
+
45
+ i = -1
46
+ column = File.join(@__root__, "mime.#{name}.column")
47
+
48
+ IO.readlines(column, encoding: 'UTF-8').each do |line|
49
+ line.chomp!
50
+
51
+ if lookup
52
+ type = @__mime_data__[i += 1] or next
53
+ yield type, line
54
+ else
55
+ yield line
56
+ end
57
+ end
58
+
59
+ @__files__ << name
60
+ end
61
+ end
62
+
63
+ def load_encoding
64
+ each_file_line('encoding') do |type, line|
65
+ pool ||= {}
66
+ type.instance_variable_set(:@encoding, (pool[line] ||= line))
67
+ end
68
+ end
69
+
70
+ def load_docs
71
+ each_file_line('docs') do |type, line|
72
+ type.instance_variable_set(:@docs, opt(line))
73
+ end
74
+ end
75
+
76
+ def load_preferred_extension
77
+ each_file_line('pext') do |type, line|
78
+ type.instance_variable_set(:@preferred_extension, opt(line))
79
+ end
80
+ end
81
+
82
+ def load_flags
83
+ each_file_line('flags') do |type, line|
84
+ line = line.split
85
+ type.instance_variable_set(:@obsolete, flag(line.shift))
86
+ type.instance_variable_set(:@registered, flag(line.shift))
87
+ type.instance_variable_set(:@signature, flag(line.shift))
88
+ end
89
+ end
90
+
91
+ def load_xrefs
92
+ each_file_line('xrefs') { |type, line|
93
+ type.instance_variable_set(:@xrefs, dict(line, array: true))
94
+ }
95
+ end
96
+
97
+ def load_friendly
98
+ each_file_line('friendly') { |type, line|
99
+ type.instance_variable_set(:@friendly, dict(line))
100
+ }
101
+ end
102
+
103
+ def load_use_instead
104
+ each_file_line('use_instead') do |type, line|
105
+ type.instance_variable_set(:@use_instead, opt(line))
106
+ end
107
+ end
108
+
109
+ def dict(line, array: false)
110
+ if line == '-'
111
+ {}
112
+ else
113
+ line.split('|').each_with_object({}) { |l, h|
114
+ k, v = l.split('^')
115
+ v = nil if v.empty?
116
+ h[k] = array ? Array(v) : v
117
+ }
118
+ end
119
+ end
120
+
121
+ def arr(line)
122
+ if line == '-'
123
+ []
124
+ else
125
+ line.split('|').flatten.compact.uniq
126
+ end
127
+ end
128
+
129
+ def opt(line)
130
+ line unless line == '-'
131
+ end
132
+
133
+ def flag(line)
134
+ line == '1'
135
+ end
136
+ end