mime-types 2.99.3 → 3.3.1

Sign up to get free protection for your applications and to get access to all the features.
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,80 +1,58 @@
1
- # -*- ruby encoding: utf-8 -*-
2
-
3
- class MIME::Types
4
- Cache = Struct.new(:version, :data) # :nodoc:
5
-
6
- # Caching of MIME::Types registries is advisable if you will be loading
7
- # the default registry relatively frequently. With the class methods on
8
- # MIME::Types::Cache, any MIME::Types registry can be marshaled quickly
9
- # and easily.
10
- #
11
- # The cache is invalidated on a per-version basis; a cache file for
12
- # version 2.0 will not be reused with version 2.0.1.
13
- class Cache
14
- class << self
15
- # Attempts to load the cache from the file provided as a parameter or in
16
- # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the
17
- # file does not exist, if the file cannot be loaded, or if the data in
18
- # the cache version is different than this version.
19
- def load(cache_file = nil)
20
- cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
21
- return nil unless cache_file and File.exist?(cache_file)
22
-
23
- cache = Marshal.load(File.binread(cache_file))
24
- if cache.version == MIME::Types::VERSION
25
- Marshal.load(cache.data)
26
- else
27
- MIME::Types.logger.warn <<-warning.chomp
1
+ # frozen_string_literal: true
2
+
3
+ MIME::Types::Cache = Struct.new(:version, :data) # :nodoc:
4
+
5
+ # Caching of MIME::Types registries is advisable if you will be loading
6
+ # the default registry relatively frequently. With the class methods on
7
+ # MIME::Types::Cache, any MIME::Types registry can be marshaled quickly
8
+ # and easily.
9
+ #
10
+ # The cache is invalidated on a per-data-version basis; a cache file for
11
+ # version 3.2015.1118 will not be reused with version 3.2015.1201.
12
+ class << MIME::Types::Cache
13
+ # Attempts to load the cache from the file provided as a parameter or in
14
+ # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the
15
+ # file does not exist, if the file cannot be loaded, or if the data in
16
+ # the cache version is different than this version.
17
+ def load(cache_file = nil)
18
+ cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
19
+ return nil unless cache_file and File.exist?(cache_file)
20
+
21
+ cache = Marshal.load(File.binread(cache_file))
22
+ if cache.version == MIME::Types::Data::VERSION
23
+ Marshal.load(cache.data)
24
+ else
25
+ MIME::Types.logger.warn <<-WARNING.chomp
28
26
  Could not load MIME::Types cache: invalid version
29
- warning
30
- nil
31
- end
32
- rescue => e
33
- MIME::Types.logger.warn <<-warning.chomp
34
- Could not load MIME::Types cache: #{e}
35
- warning
36
- return nil
37
- end
38
-
39
- # Attempts to save the types provided to the cache file provided.
40
- #
41
- # If +types+ is not provided or is +nil+, the cache will contain the
42
- # current MIME::Types default registry.
43
- #
44
- # If +cache_file+ is not provided or is +nil+, the cache will be written
45
- # to the file specified in the environment variable
46
- # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
47
- # directly or through the environment, this method will return +nil+
48
- def save(types = nil, cache_file = nil)
49
- cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
50
- return nil unless cache_file
51
-
52
- types ||= MIME::Types.send(:__types__)
53
-
54
- File.open(cache_file, 'wb') do |f|
55
- f.write(Marshal.dump(new(types.data_version, Marshal.dump(types))))
56
- end
57
- end
27
+ WARNING
28
+ nil
58
29
  end
30
+ rescue => e
31
+ MIME::Types.logger.warn <<-WARNING.chomp
32
+ Could not load MIME::Types cache: #{e}
33
+ WARNING
34
+ nil
59
35
  end
60
36
 
61
- # MIME::Types requires a container Hash with a default values for keys
62
- # resulting in an empty array (<tt>[]</tt>), but this cannot be dumped
63
- # through Marshal because of the presence of that default Proc. This class
64
- # exists solely to satisfy that need.
65
- class Container < Hash # :nodoc:
66
- def initialize
67
- super
68
- self.default_proc = ->(h, k) { h[k] = [] }
69
- end
70
-
71
- def marshal_dump
72
- {}.merge(self)
73
- end
74
-
75
- def marshal_load(hash)
76
- self.default_proc = ->(h, k) { h[k] = [] }
77
- self.merge!(hash)
37
+ # Attempts to save the types provided to the cache file provided.
38
+ #
39
+ # If +types+ is not provided or is +nil+, the cache will contain the
40
+ # current MIME::Types default registry.
41
+ #
42
+ # If +cache_file+ is not provided or is +nil+, the cache will be written
43
+ # to the file specified in the environment variable
44
+ # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
45
+ # directly or through the environment, this method will return +nil+
46
+ def save(types = nil, cache_file = nil)
47
+ cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
48
+ return nil unless cache_file
49
+
50
+ types ||= MIME::Types.send(:__types__)
51
+
52
+ File.open(cache_file, 'wb') do |f|
53
+ f.write(
54
+ Marshal.dump(new(MIME::Types::Data::VERSION, Marshal.dump(types)))
55
+ )
78
56
  end
79
57
  end
80
58
  end
@@ -1,148 +1,3 @@
1
- module MIME
2
- class Types
3
- end
4
- end
1
+ # frozen_string_literal: true
5
2
 
6
- require 'mime/type/columnar'
7
-
8
- # MIME::Types::Columnar is used to extend a MIME::Types container to load data
9
- # by columns instead of from JSON or YAML. Column loads of MIME types loaded
10
- # through the columnar store are synchronized with a Mutex.
11
- #
12
- # MIME::Types::Columnar is not intended to be used directly, but will be added
13
- # to an instance of MIME::Types when it is loaded with
14
- # MIME::Types::Loader#load_columnar.
15
- module MIME::Types::Columnar
16
- LOAD_MUTEX = Mutex.new # :nodoc:
17
-
18
- def self.extended(obj) # :nodoc:
19
- super
20
- obj.instance_variable_set(:@__mime_data__, [])
21
- obj.instance_variable_set(:@__attributes__, [])
22
- end
23
-
24
- # Load the first column data file (type and extensions).
25
- def load_base_data(path) #:nodoc:
26
- @__root__ = path
27
-
28
- each_file_line('content_type', false) do |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 @__attributes__.include?(name)
44
-
45
- File.open(File.join(@__root__, "mime.#{name}.column"), 'r:UTF-8') do |f|
46
- i = -1
47
-
48
- f.each_line 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
- end
59
-
60
- @__attributes__ << name
61
- end
62
- end
63
-
64
- def load_encoding
65
- pool = {}
66
- each_file_line('encoding') do |type, line|
67
- line.freeze
68
- type.encoding = (pool[line] ||= line)
69
- end
70
- end
71
-
72
- def load_docs
73
- each_file_line('docs') do |type, line|
74
- type.docs = arr(line)
75
- end
76
- end
77
-
78
- def load_obsolete
79
- each_file_line('obsolete') do |type, line|
80
- type.obsolete = bool(line)
81
- end
82
- end
83
-
84
- def load_registered
85
- each_file_line('registered') do |type, line|
86
- type.registered = bool(line)
87
- end
88
- end
89
-
90
- def load_signature
91
- each_file_line('signature') do |type, line|
92
- type.signature = bool(line)
93
- end
94
- end
95
-
96
- def load_xrefs
97
- each_file_line('xrefs') { |type, line| type.xrefs = dict(line) }
98
- end
99
-
100
- def load_friendly
101
- each_file_line('friendly') { |type, line|
102
- v = dict(line)
103
- type.friendly = v.empty? ? nil : v
104
- }
105
- end
106
-
107
- def load_use_instead
108
- each_file_line('use_instead') do |type, line|
109
- type.use_instead = (line unless line == '-'.freeze)
110
- end
111
- end
112
-
113
- def dict(line)
114
- if line == '-'.freeze
115
- {}
116
- else
117
- line.split('|'.freeze).each_with_object({}) { |l, h|
118
- k, v = l.split('^'.freeze)
119
- v = [ nil ] if v.empty?
120
- h[k] = v
121
- }
122
- end
123
- end
124
-
125
- def arr(line)
126
- if line == '-'.freeze
127
- []
128
- else
129
- line.split('|'.freeze).flatten.compact.uniq
130
- end
131
- end
132
-
133
- def bool(line)
134
- line == '1'.freeze ? true : false
135
- end
136
- end
137
-
138
- unless MIME::Types.private_method_defined?(:load_mode)
139
- class << MIME::Types
140
- private
141
-
142
- def load_mode
143
- { columnar: true }
144
- end
145
- end
146
-
147
- require 'mime/types'
148
- end
3
+ require 'mime/types'
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+ require 'forwardable'
5
+
6
+ # MIME::Types requires a serializable keyed container that returns an empty Set
7
+ # on a key miss. Hash#default_value cannot be used because, while it traverses
8
+ # the Marshal format correctly, it won't survive any other serialization
9
+ # format (plus, a default of a mutable object resuls in a shared mess).
10
+ # Hash#default_proc cannot be used without a wrapper because it prevents
11
+ # Marshal serialization (and doesn't survive the round-trip).
12
+ class MIME::Types::Container #:nodoc:
13
+ extend Forwardable
14
+
15
+ def initialize(hash = {})
16
+ @container = {}
17
+ merge!(hash)
18
+ end
19
+
20
+ def [](key)
21
+ container[key] || EMPTY_SET
22
+ end
23
+
24
+ def []=(key, value)
25
+ container[key] =
26
+ case value
27
+ when Set
28
+ value
29
+ else
30
+ Set[*value]
31
+ end
32
+ end
33
+
34
+ def merge(other)
35
+ self.class.new(other)
36
+ end
37
+
38
+ def merge!(other)
39
+ tap {
40
+ other = other.kind_of?(MIME::Types::Container) ? other.container : other
41
+ container.merge!(other)
42
+ normalize
43
+ }
44
+ end
45
+
46
+ def to_hash
47
+ container
48
+ end
49
+
50
+ def_delegators :@container,
51
+ :==,
52
+ :count,
53
+ :each,
54
+ :each_value,
55
+ :empty?,
56
+ :flat_map,
57
+ :keys,
58
+ :select,
59
+ :values
60
+
61
+ def add(key, value)
62
+ (container[key] ||= Set.new).add(value)
63
+ end
64
+
65
+ def marshal_dump
66
+ {}.merge(container)
67
+ end
68
+
69
+ def marshal_load(hash)
70
+ @container = hash
71
+ end
72
+
73
+ def encode_with(coder)
74
+ container.each { |k, v| coder[k] = v.to_a }
75
+ end
76
+
77
+ def init_with(coder)
78
+ @container = {}
79
+ coder.map.each { |k, v| container[k] = Set[*v] }
80
+ end
81
+
82
+ protected
83
+
84
+ attr_accessor :container
85
+
86
+ def normalize
87
+ container.each do |k, v|
88
+ next if v.kind_of?(Set)
89
+
90
+ container[k] = Set[*v]
91
+ end
92
+ end
93
+
94
+ EMPTY_SET = Set.new.freeze
95
+ private_constant :EMPTY_SET
96
+ end
@@ -1,9 +1,10 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'mime/types/logger'
4
4
 
5
5
  # The namespace for MIME applications, tools, and libraries.
6
6
  module MIME
7
+ ##
7
8
  class Types
8
9
  # Used to mark a method as deprecated in the mime-types interface.
9
10
  def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
@@ -22,32 +23,10 @@ module MIME
22
23
  else
23
24
  message
24
25
  end
25
- MIME::Types.logger.warn <<-warning.chomp
26
+ MIME::Types.logger.warn <<-WARNING.chomp
26
27
  #{caller[1]}: #{klass}#{level}#{sym} is deprecated #{message}.
27
- warning
28
+ WARNING
28
29
  block.call if block
29
30
  end
30
31
  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
32
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ module MIME
5
+ ##
6
+ class Types
7
+ unless private_method_defined?(:load_mode)
8
+ class << self
9
+ private
10
+
11
+ def load_mode
12
+ { columnar: false }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ require 'mime/types'
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # -*- ruby encoding: utf-8 -*-
2
4
 
5
+ ##
3
6
  module MIME; end
7
+ ##
4
8
  class MIME::Types; end
5
9
 
6
- require 'mime/types/loader_path'
10
+ require 'mime/types/data'
7
11
 
8
12
  # This class is responsible for initializing the MIME::Types registry from
9
13
  # the data files supplied with the mime-types library.
@@ -11,7 +15,7 @@ require 'mime/types/loader_path'
11
15
  # The Loader will use one of the following paths:
12
16
  # 1. The +path+ provided in its constructor argument;
13
17
  # 2. The value of ENV['RUBY_MIME_TYPES_DATA']; or
14
- # 3. The value of MIME::Types::Loader::PATH.
18
+ # 3. The value of MIME::Types::Data::PATH.
15
19
  #
16
20
  # When #load is called, the +path+ will be searched recursively for all YAML
17
21
  # (.yml or .yaml) files. By convention, there is one file for each media
@@ -24,15 +28,11 @@ class MIME::Types::Loader
24
28
  attr_reader :container
25
29
 
26
30
  # Creates a Loader object that can be used to load MIME::Types registries
27
- # into memory, using YAML, JSON, or v1 registry format loaders.
31
+ # into memory, using YAML, JSON, or Columnar registry format loaders.
28
32
  def initialize(path = nil, container = nil)
29
- path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Loader::PATH
33
+ path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Data::PATH
30
34
  @container = container || MIME::Types.new
31
35
  @path = File.expand_path(path)
32
- # begin
33
- # require 'mime/lazy_types'
34
- # @container.extend(MIME::LazyTypes)
35
- # end
36
36
  end
37
37
 
38
38
  # Loads a MIME::Types registry from YAML files (<tt>*.yml</tt> or
@@ -41,8 +41,7 @@ class MIME::Types::Loader
41
41
  # It is expected that the YAML objects contained within the registry array
42
42
  # will be tagged as <tt>!ruby/object:MIME::Type</tt>.
43
43
  #
44
- # Note that the YAML format is about 2½ times *slower* than either the v1
45
- # format or the JSON format.
44
+ # Note that the YAML format is about 2½ times *slower* than the JSON format.
46
45
  #
47
46
  # NOTE: The purpose of this format is purely for maintenance reasons.
48
47
  def load_yaml
@@ -89,122 +88,19 @@ class MIME::Types::Loader
89
88
  end
90
89
  end
91
90
 
92
- # Loads a MIME::Types registry from files found in +path+ that are in the
93
- # v1 data format. The file search for this will exclude both JSON
94
- # (<tt>*.json</tt>) and YAML (<tt>*.yml</tt> or <tt>*.yaml</tt>) files.
95
- #
96
- # This method has been deprecated and will be removed from mime-types 3.0.
97
- def load_v1
98
- MIME::Types.deprecated(self.class, __method__)
99
- Dir[v1_path].sort.each do |f|
100
- next if f =~ /\.(?:ya?ml|json|column)$/
101
- container.add(self.class.load_from_v1(f, true), true)
102
- end
103
- container
104
- end
105
-
106
- # Raised when a V1 format file is discovered. This exception will be removed
107
- # for mime-types 3.0.
108
- BadV1Format = Class.new(Exception)
109
-
110
91
  class << self
111
92
  # Loads the default MIME::Type registry.
112
93
  def load(options = { columnar: false })
113
94
  new.load(options)
114
95
  end
115
96
 
116
- # Build the type list from a file in the format:
117
- #
118
- # [*][!][os:]mt/st[<ws>@ext][<ws>:enc][<ws>'url-list][<ws>=docs]
119
- #
120
- # == *
121
- # An unofficial MIME type. This should be used if and only if the MIME type
122
- # is not properly specified (that is, not under either x-type or
123
- # vnd.name.type).
124
- #
125
- # == !
126
- # An obsolete MIME type. May be used with an unofficial MIME type.
127
- #
128
- # == os:
129
- # Platform-specific MIME type definition.
130
- #
131
- # == mt
132
- # The media type.
133
- #
134
- # == st
135
- # The media subtype.
136
- #
137
- # == <ws>@ext
138
- # The list of comma-separated extensions.
139
- #
140
- # == <ws>:enc
141
- # The encoding.
142
- #
143
- # == <ws>'url-list
144
- # The list of comma-separated URLs.
145
- #
146
- # == <ws>=docs
147
- # The documentation string.
148
- #
149
- # That is, everything except the media type and the subtype is optional. The
150
- # more information that's available, though, the richer the values that can
151
- # be provided.
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__
156
- data = read_file(filename).split($/)
157
- mime = MIME::Types.new
158
- data.each_with_index { |line, index|
159
- item = line.chomp.strip
160
- next if item.empty?
161
-
162
- m = V1_FORMAT.match(item)
163
-
164
- unless m
165
- MIME::Types.logger.warn <<-EOS
166
- #{filename}:#{index + 1}: Parsing error in v1 MIME type definition.
167
- => #{line}
168
- EOS
169
- fail BadV1Format, line
170
- end
171
-
172
- unregistered, obsolete, _, mediatype, subtype, extensions, encoding,
173
- urls, docs, _ = *m.captures
174
-
175
- next if mediatype.nil?
176
-
177
- extensions &&= extensions.split(/,/)
178
- urls &&= urls.split(/,/)
179
-
180
- if docs.nil?
181
- use_instead = nil
182
- else
183
- use_instead = docs.scan(%r{use-instead:(\S+)}).flatten.first
184
- docs = docs.gsub(%r{use-instead:\S+}, '').squeeze(' \t')
185
- end
186
-
187
- mime_type = MIME::Type.new("#{mediatype}/#{subtype}") do |t|
188
- t.extensions = extensions
189
- t.encoding = encoding
190
- t.obsolete = obsolete
191
- t.registered = false if unregistered
192
- t.use_instead = use_instead
193
- t.docs = docs
194
- end
195
-
196
- mime.add_type(mime_type, true)
197
- }
198
- mime
199
- end
200
-
201
97
  # Loads MIME::Types from a single YAML file.
202
98
  #
203
99
  # It is expected that the YAML objects contained within the registry
204
100
  # array will be tagged as <tt>!ruby/object:MIME::Type</tt>.
205
101
  #
206
- # Note that the YAML format is about 2½ times *slower* than either the v1
207
- # format or the JSON format.
102
+ # Note that the YAML format is about 2½ times *slower* than the JSON
103
+ # format.
208
104
  #
209
105
  # NOTE: The purpose of this format is purely for maintenance reasons.
210
106
  def load_from_yaml(filename)
@@ -230,7 +126,7 @@ class MIME::Types::Loader
230
126
  private
231
127
 
232
128
  def read_file(filename)
233
- File.open(filename, 'r:UTF-8:-') { |f| f.read }
129
+ File.open(filename, 'r:UTF-8:-', &:read)
234
130
  end
235
131
  end
236
132
 
@@ -247,29 +143,4 @@ class MIME::Types::Loader
247
143
  def columnar_path
248
144
  File.join(path, '*.column')
249
145
  end
250
-
251
- def v1_path
252
- File.join(path, '*')
253
- end
254
-
255
- # The regular expression used to match a v1-format file-based MIME type
256
- # definition.
257
- #
258
- # This constant has been deprecated and will be removed in mime-types 3.0.
259
- V1_FORMAT = # :nodoc:
260
- %r{\A\s*
261
- ([*])? # 0: Unregistered?
262
- (!)? # 1: Obsolete?
263
- (?:(\w+):)? # 2: Platform marker
264
- ([-\w.+]+)/([-\w.+]*) # 3, 4: Media Type
265
- (?:\s+@(\S+))? # 5: Extensions
266
- (?:\s+:(base64|7bit|8bit|quoted\-printable))? # 6: Encoding
267
- (?:\s+'(\S+))? # 7: URL list
268
- (?:\s+=(.+))? # 8: Documentation
269
- (?:\s*([#].*)?)? # Comments
270
- \s*
271
- \z
272
- }x
273
-
274
- private_constant :V1_FORMAT if respond_to? :private_constant
275
146
  end