mime-types 2.99.3 → 3.0

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.autotest +35 -0
  3. data/.gemtest +0 -0
  4. data/.gitignore +17 -0
  5. data/.hoerc +20 -0
  6. data/Code-of-Conduct.rdoc +27 -60
  7. data/Contributing.rdoc +0 -1
  8. data/History.rdoc +75 -36
  9. data/Licence.rdoc +2 -16
  10. data/Manifest.txt +10 -18
  11. data/README.rdoc +46 -46
  12. data/Rakefile +112 -58
  13. data/lib/mime-types.rb +0 -2
  14. data/lib/mime/type.rb +183 -415
  15. data/lib/mime/type/columnar.rb +27 -62
  16. data/lib/mime/types.rb +37 -135
  17. data/lib/mime/types/cache.rb +49 -73
  18. data/lib/mime/types/columnar.rb +42 -48
  19. data/lib/mime/types/container.rb +30 -0
  20. data/lib/mime/types/deprecations.rb +1 -22
  21. data/lib/mime/types/full.rb +17 -0
  22. data/lib/mime/types/loader.rb +10 -137
  23. data/lib/mime/types/logger.rb +2 -0
  24. data/lib/mime/types/registry.rb +81 -0
  25. data/support/benchmarks/load.rb +27 -26
  26. data/support/benchmarks/load_allocations.rb +14 -7
  27. data/support/benchmarks/object_counts.rb +6 -4
  28. data/support/profile/columnar.rb +5 -0
  29. data/support/profile/columnar_full.rb +5 -0
  30. data/support/profile/full.rb +5 -0
  31. data/test/minitest_helper.rb +3 -12
  32. data/test/test_mime_type.rb +461 -454
  33. data/test/test_mime_types.rb +126 -86
  34. data/test/test_mime_types_cache.rb +55 -45
  35. data/test/test_mime_types_class.rb +113 -97
  36. data/test/test_mime_types_lazy.rb +19 -23
  37. data/test/test_mime_types_loader.rb +5 -32
  38. metadata +67 -44
  39. data/History-Types.rdoc +0 -454
  40. data/data/mime-types.json +0 -1
  41. data/data/mime.content_type.column +0 -1980
  42. data/data/mime.docs.column +0 -1980
  43. data/data/mime.encoding.column +0 -1980
  44. data/data/mime.friendly.column +0 -1980
  45. data/data/mime.obsolete.column +0 -1980
  46. data/data/mime.registered.column +0 -1980
  47. data/data/mime.signature.column +0 -1980
  48. data/data/mime.use_instead.column +0 -1980
  49. data/data/mime.xrefs.column +0 -1980
  50. data/docs/COPYING.txt +0 -339
  51. data/docs/artistic.txt +0 -127
  52. data/lib/mime/types/loader_path.rb +0 -15
  53. data/support/apache_mime_types.rb +0 -108
  54. data/support/convert.rb +0 -158
  55. data/support/convert/columnar.rb +0 -88
  56. data/support/iana_registry.rb +0 -172
@@ -1,15 +0,0 @@
1
- # -*- ruby encoding: utf-8 -*-
2
-
3
- class MIME::Types::Loader
4
- # The path that will be used for loading the MIME::Types data. The default
5
- # location is __FILE__/../../../../data, which is where the data lives
6
- # in the gem installation of the mime-types library.
7
- #
8
- # The MIME::Types::Loader will load all JSON or columnar files contained in
9
- # this path.
10
- #
11
- # System repackagers note: this is the constant that you would change if
12
- # you repackage mime-types for your system. It is recommended that the
13
- # path be something like /usr/share/ruby/mime-types/.
14
- PATH = File.expand_path('../../../../data', __FILE__)
15
- end
@@ -1,108 +0,0 @@
1
- # -*- ruby encoding: utf-8 -*-
2
-
3
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
-
5
- require 'open-uri'
6
- require 'nokogiri'
7
- require 'cgi'
8
- require 'pathname'
9
- require 'yaml'
10
-
11
- ENV['RUBY_MIME_TYPES_LAZY_LOAD'] = 'yes'
12
- require 'mime/types'
13
-
14
- class MIME::Type
15
- public_constant :UNREGISTERED_RE
16
- end
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
-
24
- class ApacheMIMETypes
25
- DEFAULTS = {
26
- url: %q(http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types),
27
- to: Pathname(__FILE__).join('../../type-lists')
28
- }.freeze.each_value(&:freeze)
29
-
30
- def self.download(options = {})
31
- dest = Pathname(options[:to] || DEFAULTS[:to]).expand_path
32
- url = options.fetch(:url, DEFAULTS[:url])
33
-
34
- puts 'Downloading Apache MIME type list.'
35
- puts "\t#{url}"
36
- data = open(url) { |f| f.read }.split($/)
37
- data.delete_if { |line| line =~ /\A#/ }
38
-
39
- conf = MIME::Types::Container.new
40
-
41
- data.each do |line|
42
- type = line.split(/\t+/)
43
- key = type.first.split(%r{/}).first.gsub(MIME::Type::UNREGISTERED_RE, '')
44
- conf[key] << type
45
- end
46
-
47
- conf.each do |type, types|
48
- next if type == 'example'
49
-
50
- new(type: type, registry: types, to: dest) do |parser|
51
- puts "Extracting #{parser.type}/*."
52
- parser.parse
53
- parser.save
54
- end
55
- end
56
- end
57
-
58
- attr_reader :type
59
-
60
- def initialize(options = {})
61
- @registry = options.fetch(:registry)
62
- @to = Pathname(options.fetch(:to)).expand_path
63
- @type = options.fetch(:type)
64
- @name = "#{@type}.yaml"
65
- @file = @to.join(@name)
66
- @types = mime_types_for(@file)
67
-
68
- yield self if block_given?
69
- end
70
-
71
- def parse
72
- @registry.each do |record|
73
- content_type = record.first
74
- extensions = record.last.split(/\s+/)
75
-
76
- types = @types.select { |t|
77
- (t.content_type.downcase == content_type.downcase)
78
- }
79
-
80
- if types.empty?
81
- MIME::Type.new(content_type) do |mt|
82
- mt.extensions = extensions
83
- mt.registered = false
84
- @types << mt
85
- end
86
- else
87
- types.each { |mt|
88
- mt.extensions = (mt.extensions + extensions)
89
- }
90
- end
91
- end
92
- end
93
-
94
- def save
95
- @to.mkpath
96
- File.open(@file, 'wb') { |f| f.puts @types.map.to_a.sort.to_yaml }
97
- end
98
-
99
- private
100
-
101
- def mime_types_for(file)
102
- if file.exist?
103
- MIME::Types::Loader.load_from_yaml(file)
104
- else
105
- MIME::Types.new
106
- end
107
- end
108
- end
@@ -1,158 +0,0 @@
1
- # -*- ruby encoding: utf-8 -*-
2
-
3
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
- ENV['RUBY_MIME_TYPES_LAZY_LOAD'] = 'true'
5
- require 'mime/types'
6
- require 'fileutils'
7
- require 'json'
8
-
9
- class MIME::Types
10
- def self.deprecated(*_args, &_block)
11
- # We are an internal tool. Silence deprecation warnings.
12
- end
13
- end
14
-
15
- class Convert
16
- class << self
17
- # Create a Convert instance that converts from YAML.
18
- def from_yaml(path = nil)
19
- new(path: path, from: :yaml)
20
- end
21
-
22
- # Create a Convert instance that converts from JSON.
23
- def from_json(path = nil)
24
- new(path: path, from: :json)
25
- end
26
-
27
- # Create a Convert instance that converts from the mime-types 1.x file
28
- # format.
29
- def from_v1(path = nil)
30
- new(path: path, from: :v1)
31
- end
32
-
33
- # Converts from YAML to JSON. Defaults to converting to a single file.
34
- def from_yaml_to_json(args)
35
- from_yaml(yaml_path(args.source)).
36
- to_json(
37
- destination: json_path(args.destination),
38
- multiple_files: multiple_files(args.multiple_files || 'single')
39
- )
40
- end
41
-
42
- # Converts from JSON to YAML. Defaults to converting to multiple files.
43
- def from_json_to_yaml(args)
44
- from_json(json_path(args.source)).
45
- to_yaml(
46
- destination: yaml_path(args.destination),
47
- multiple_files: multiple_files(args.multiple_files || 'multiple')
48
- )
49
- end
50
-
51
- private :new
52
-
53
- private
54
-
55
- def yaml_path(path)
56
- path_or_default(path, 'type-lists'.freeze)
57
- end
58
-
59
- def json_path(path)
60
- path_or_default(path, 'data'.freeze)
61
- end
62
-
63
- def path_or_default(path, default)
64
- if path.nil? or path.empty?
65
- default
66
- else
67
- path
68
- end
69
- end
70
-
71
- def multiple_files(flag)
72
- case flag.to_s.downcase
73
- when 'true', 'yes', 'multiple'
74
- true
75
- else
76
- false
77
- end
78
- end
79
- end
80
-
81
- def initialize(options = {})
82
- if options[:path].nil? or options[:path].empty?
83
- fail ArgumentError, ':path is required'
84
- elsif options[:from].nil? or options[:from].empty?
85
- fail ArgumentError, ':from is required'
86
- end
87
-
88
- @loader = MIME::Types::Loader.new(options[:path])
89
- load_from(options[:from])
90
- end
91
-
92
- # Convert the data to JSON.
93
- def to_json(options = {})
94
- options[:destination] or require_destination!
95
- write_types(options.merge(format: :json))
96
- end
97
-
98
- # Convert the data to YAML.
99
- def to_yaml(options = {})
100
- options[:destination] or require_destination!
101
- write_types(options.merge(format: :yaml))
102
- end
103
-
104
- private
105
-
106
- def load_from(source_type)
107
- method = :"load_#{source_type}"
108
- @loader.send(method)
109
- end
110
-
111
- def write_types(options)
112
- if options[:multiple_files]
113
- write_multiple_files(options)
114
- else
115
- write_one_file(options)
116
- end
117
- end
118
-
119
- def write_one_file(options)
120
- d = options[:destination]
121
- d = File.join(d, "mime-types.#{options[:format]}") if File.directory?(d)
122
-
123
- File.open(d, 'wb') { |f|
124
- f.puts convert(@loader.container.map.sort, options[:format])
125
- }
126
- end
127
-
128
- def write_multiple_files(options)
129
- d = options[:destination]
130
- must_be_directory!(d)
131
-
132
- media_types = MIME::Types.map(&:media_type).uniq
133
- media_types.each { |media_type|
134
- n = File.join(d, "#{media_type}.#{options[:format]}")
135
- t = @loader.container.select { |e| e.media_type == media_type }
136
- File.open(n, 'wb') { |f|
137
- f.puts convert(t.sort, options[:format])
138
- }
139
- }
140
- end
141
-
142
- def convert(data, format)
143
- data.send(:"to_#{format}")
144
- end
145
-
146
- def require_destination!
147
- fail ArgumentError, 'Destination path is required.'
148
- end
149
-
150
- def must_be_directory!(path)
151
- if File.exist?(path) and !File.directory?(path)
152
- fail ArgumentError, 'Cannot write multiple files to a file.'
153
- end
154
-
155
- FileUtils.mkdir_p(path) unless File.exist?(path)
156
- path
157
- end
158
- end
@@ -1,88 +0,0 @@
1
- require 'convert'
2
-
3
- class Convert::Columnar < Convert
4
- class << self
5
- # Converts from YAML to Columnar format. This *always* converts to multiple
6
- # files.
7
- def from_yaml_to_columnar(args)
8
- from_yaml(yaml_path(args.source)).
9
- to_columnar(destination: columnar_path(args.destination))
10
- end
11
-
12
- private
13
-
14
- def columnar_path(path)
15
- path_or_default(path, 'data')
16
- end
17
- end
18
-
19
- # Convert the data to multiple text files.
20
- def to_columnar(options = {})
21
- root = options[:destination] or require_destination!
22
- @root = must_be_directory!(root)
23
- @data = @loader.container.sort.map(&:to_h)
24
-
25
- column_file('content_type') do |type|
26
- [ type['content-type'], Array(type['extensions']).join(' ') ].
27
- flatten.join(' ').strip
28
- end
29
-
30
- required_file('encoding')
31
- optional_file('docs')
32
- bool_file('obsolete')
33
- bool_file('registered')
34
- bool_file('signature')
35
- dict_file('xrefs')
36
- dict_file('friendly')
37
- optional_file('use_instead', 'use-instead')
38
- end
39
-
40
- def column_file(name, &block)
41
- File.open(File.join(@root, "mime.#{name}.column"), 'wb') do |f|
42
- f.puts @data.map(&block)
43
- end
44
- end
45
-
46
- def bool_file(name, *fields)
47
- fields = [ name ] if fields.empty?
48
- column_file(name) do |type|
49
- fields.map { |field|
50
- type[field] ? 1 : 0
51
- }.join(' ')
52
- end
53
- end
54
-
55
- def required_file(name, field = name)
56
- column_file(name) { |type| type[field] }
57
- end
58
-
59
- def optional_file(name, field = name)
60
- column_file(name) { |type| opt(type[field]) }
61
- end
62
-
63
- def array_file(name, field = name)
64
- column_file(name) { |type| arr(type[field]) }
65
- end
66
-
67
- def dict_file(name, field = name)
68
- column_file(name) { |type| dict(type[field]) }
69
- end
70
-
71
- def opt(value)
72
- value || '-'
73
- end
74
-
75
- def arr(value)
76
- Array(opt(value)).join('|')
77
- end
78
-
79
- def dict(value)
80
- if value
81
- value.sort.map { |k, v|
82
- [ k, Array(v).compact.join('^') ].join('^')
83
- }.join('|')
84
- else
85
- '-'
86
- end
87
- end
88
- end
@@ -1,172 +0,0 @@
1
- # -*- ruby encoding: utf-8 -*-
2
-
3
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
-
5
- require 'open-uri'
6
- require 'nokogiri'
7
- require 'cgi'
8
- require 'pathname'
9
- require 'yaml'
10
-
11
- ENV['RUBY_MIME_TYPES_LAZY_LOAD'] = 'yes'
12
- require 'mime/types'
13
-
14
- class MIME::Types
15
- def self.deprecated(*_args, &_block)
16
- # We are an internal tool. Silence deprecation warnings.
17
- end
18
- end
19
-
20
- class MIME::Type
21
- public_constant :MEDIA_TYPE_RE if respond_to? :public_constant
22
- end
23
-
24
- class IANARegistry
25
- DEFAULTS = {
26
- url: %q(https://www.iana.org/assignments/media-types/media-types.xml),
27
- to: Pathname(__FILE__).join('../../type-lists')
28
- }.freeze.each_value(&:freeze)
29
-
30
- def self.download(options = {})
31
- dest = Pathname(options[:to] || DEFAULTS[:to]).expand_path
32
- url = options.fetch(:url, DEFAULTS[:url])
33
-
34
- puts 'Downloading IANA MIME type assignments.'
35
- puts "\t#{url}"
36
- xml = Nokogiri::XML(open(url) { |f| f.read })
37
-
38
- xml.css('registry registry').each do |registry|
39
- next if registry.at_css('title').text == 'example'
40
- new(registry: registry, to: dest) do |parser|
41
- puts "Extracting #{parser.type}/*."
42
- parser.parse
43
- parser.save
44
- end
45
- end
46
- end
47
-
48
- attr_reader :type
49
-
50
- def initialize(options = {})
51
- @registry = options.fetch(:registry)
52
- @to = Pathname(options.fetch(:to)).expand_path
53
- @type = @registry.at_css('title').text
54
- @name = "#{@type}.yaml"
55
- @file = @to.join(@name)
56
- @types = mime_types_for(@file)
57
-
58
- yield self if block_given?
59
- end
60
-
61
- ASSIGNMENT_FILE_REF = '{%s=http://www.iana.org/assignments/media-types/%s}'
62
-
63
- def parse
64
- @registry.css('record').each do |record|
65
- subtype = record.at_css('name').text
66
- obsolete = record.at_css('obsolete').text rescue nil
67
- use_instead = record.at_css('deprecated').text rescue nil
68
-
69
- if subtype =~ /OBSOLETE|DEPRECATE/i
70
- use_instead ||= $1 if subtype =~ /in favou?r of (#{MIME::Type::MEDIA_TYPE_RE})/
71
- obsolete = true
72
- end
73
-
74
- subtype, notes = subtype.split(/ /, 2)
75
-
76
- refs, xrefs = parse_refs_and_files(
77
- record.css('xref'),
78
- record.css('file'),
79
- subtype
80
- )
81
-
82
- xrefs['notes'] << notes if notes
83
-
84
- content_type = [ @type, subtype ].join('/')
85
-
86
- types = @types.select { |t|
87
- (t.content_type.downcase == content_type.downcase)
88
- }
89
-
90
- if types.empty?
91
- MIME::Type.new(content_type) do |mt|
92
- mt.xrefs = xrefs
93
- mt.registered = true
94
- mt.obsolete = obsolete if obsolete
95
- mt.use_instead = use_instead if use_instead
96
- @types << mt
97
- end
98
- else
99
- types.each { |mt|
100
- mt.registered = true
101
- mt.xrefs = xrefs
102
- mt.obsolete = obsolete if obsolete
103
- mt.use_instead = use_instead if use_instead
104
- }
105
- end
106
- end
107
- end
108
-
109
- def save
110
- @to.mkpath
111
- File.open(@file, 'wb') { |f| f.puts @types.map.to_a.sort.uniq.to_yaml }
112
- end
113
-
114
- private
115
-
116
- def mime_types_for(file)
117
- if file.exist?
118
- MIME::Types::Loader.load_from_yaml(file)
119
- else
120
- MIME::Types.new
121
- end
122
- end
123
-
124
- def parse_refs_and_files(refs, files, subtype)
125
- xr = MIME::Types::Container.new
126
- r = []
127
-
128
- refs.each do |xref|
129
- type = xref['type']
130
- data = xref['data']
131
-
132
- next if data.nil? || data.empty?
133
-
134
- r << ref_from_type(type, data)
135
-
136
- xr[type] << data
137
- end
138
-
139
- files.each do |file|
140
- file_name = if file.text == subtype
141
- [ @type, subtype ].join('/')
142
- else
143
- file.text
144
- end
145
-
146
- if file['type'] == 'template'
147
- r << (ASSIGNMENT_FILE_REF % [ file_name, file_name ])
148
- end
149
-
150
- xr[file['type']] << file_name
151
- end
152
-
153
- [ r, xr ]
154
- end
155
-
156
- def ref_from_type(type, data)
157
- case type
158
- when 'person'
159
- "[#{data}]"
160
- when 'rfc'
161
- data.upcase
162
- when 'draft'
163
- "DRAFT:#{data.sub(/^RFC-/, 'draft-')}"
164
- when 'rfc-errata'
165
- "{RFC Errata #{data}=http://www.rfc-editor.org/errata_search.php?eid=#{data}}"
166
- when 'uri'
167
- "{#{data}}"
168
- else # 'text' or something else
169
- data
170
- end
171
- end
172
- end