libis-format 1.3.4 → 2.0.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +20 -0
  4. data/.travis.yml +70 -0
  5. data/Gemfile +0 -12
  6. data/README.md +2 -2
  7. data/Rakefile +8 -0
  8. data/base/Dockerfile +35 -0
  9. data/base/Dockerfile.alpine +20 -0
  10. data/base/Dockerfile.rvm +56 -0
  11. data/base/rework_path +20 -0
  12. data/bin/{pdf_tool → pdf_copy} +2 -3
  13. data/data/PDFA_def.ps +3 -3
  14. data/data/eciRGB_v2.icc +0 -0
  15. data/data/types.yml +4 -17
  16. data/docker_cfg.yml +1 -0
  17. data/lib/libis/format/cli/convert.rb +4 -4
  18. data/lib/libis/format/cli/prompt_helper.rb +24 -32
  19. data/lib/libis/format/command_line.rb +3 -2
  20. data/lib/libis/format/config.rb +23 -19
  21. data/lib/libis/format/converter/audio_converter.rb +31 -56
  22. data/lib/libis/format/converter/base.rb +36 -16
  23. data/lib/libis/format/converter/chain.rb +32 -52
  24. data/lib/libis/format/converter/fop_pdf_converter.rb +8 -4
  25. data/lib/libis/format/converter/image_assembler.rb +82 -0
  26. data/lib/libis/format/converter/image_converter.rb +45 -250
  27. data/lib/libis/format/converter/image_splitter.rb +80 -0
  28. data/lib/libis/format/converter/image_watermarker.rb +261 -0
  29. data/lib/libis/format/converter/jp2_converter.rb +38 -36
  30. data/lib/libis/format/converter/office_converter.rb +28 -22
  31. data/lib/libis/format/converter/pdf_assembler.rb +66 -0
  32. data/lib/libis/format/converter/pdf_converter.rb +52 -200
  33. data/lib/libis/format/converter/pdf_optimizer.rb +70 -0
  34. data/lib/libis/format/converter/pdf_splitter.rb +65 -0
  35. data/lib/libis/format/converter/pdf_watermarker.rb +110 -0
  36. data/lib/libis/format/converter/repository.rb +13 -7
  37. data/lib/libis/format/converter/spreadsheet_converter.rb +16 -10
  38. data/lib/libis/format/converter/video_converter.rb +58 -47
  39. data/lib/libis/format/converter/xslt_converter.rb +11 -13
  40. data/lib/libis/format/converter.rb +1 -1
  41. data/lib/libis/format/identifier.rb +46 -44
  42. data/lib/libis/format/info.rb +27 -0
  43. data/lib/libis/format/library.rb +147 -0
  44. data/lib/libis/format/tool/droid.rb +30 -29
  45. data/lib/libis/format/tool/extension_identification.rb +26 -24
  46. data/lib/libis/format/tool/{ff_mpeg.rb → ffmpeg.rb} +10 -17
  47. data/lib/libis/format/tool/fido.rb +27 -22
  48. data/lib/libis/format/tool/file_tool.rb +24 -11
  49. data/lib/libis/format/tool/fop_pdf.rb +14 -25
  50. data/lib/libis/format/tool/identification_tool.rb +40 -38
  51. data/lib/libis/format/tool/office_to_pdf.rb +18 -30
  52. data/lib/libis/format/tool/pdf_copy.rb +47 -0
  53. data/lib/libis/format/tool/pdf_merge.rb +19 -25
  54. data/lib/libis/format/tool/pdf_optimizer.rb +19 -22
  55. data/lib/libis/format/tool/pdf_split.rb +33 -6
  56. data/lib/libis/format/tool/pdf_to_pdfa.rb +31 -45
  57. data/lib/libis/format/tool/pdfa_validator.rb +30 -24
  58. data/lib/libis/format/tool/spreadsheet_to_ods.rb +18 -29
  59. data/lib/libis/format/tool.rb +3 -4
  60. data/lib/libis/format/version.rb +1 -3
  61. data/lib/libis/format/yaml_loader.rb +71 -0
  62. data/lib/libis/format.rb +7 -5
  63. data/lib/libis-format.rb +0 -2
  64. data/libis-format.gemspec +18 -24
  65. data/tools/PdfTool.jar +0 -0
  66. data/tools/pdfbox/pdfbox-app-2.0.13.jar +0 -0
  67. data/tools/pdfbox/{preflight-app-3.0.3.jar → preflight-app-2.0.13.jar} +0 -0
  68. metadata +86 -128
  69. data/data/AdobeRGB1998.icc +0 -0
  70. data/lib/libis/format/converter/email_converter.rb +0 -35
  71. data/lib/libis/format/tool/msg_to_pdf.rb +0 -270
  72. data/lib/libis/format/tool/pdf_tool.rb +0 -52
  73. data/lib/libis/format/type_database.rb +0 -156
  74. data/lib/libis/format/type_database_impl.rb +0 -153
  75. data/tools/pdf2pdfa +0 -395
  76. data/tools/pdfbox/pdfbox-app-3.0.3.jar +0 -0
  77. /data/bin/{droid_tool → droid} +0 -0
  78. /data/bin/{fido_tool → fido} +0 -0
@@ -1,270 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'mapi/msg'
4
- require 'rfc_2047'
5
- require 'cgi'
6
- require 'pdfkit'
7
- require 'time'
8
- require 'fileutils'
9
- require 'pathname'
10
- require 'libis/format/config'
11
-
12
- module Libis
13
- module Format
14
- module Tool
15
- class MsgToPdf
16
- include ::Libis::Tools::Logger
17
-
18
- HEADER_STYLE = '<style>.header-table {margin: 0 0 20 0;padding: 0;font-family: Arial, Helvetica, sans-serif;}.header-name {padding-right: 5px;color: #9E9E9E;text-align: right;vertical-align: top;font-size: 12px;}.header-value {font-size: 12px;}#header_fields {#background: white;#margin: 0;#border: 1px solid #DDD;#border-radius: 3px;#padding: 8px;#width: 100%%;#box-sizing: border-box;#}</style><script type="text/javascript">function timer() {try {parent.postMessage(Math.max(document.body.offsetHeight, document.body.scrollHeight), \'*\');} catch (r) {}setTimeout(timer, 10);};timer();</script>' # rubocop:disable Layout/LineLength
19
- HEADER_TABLE_TEMPLATE = '<div class="header-table"><table id="header_fields"><tbody>%s</tbody></table></div>'
20
- HEADER_FIELD_TEMPLATE = '<tr><td class="header-name">%s</td><td class="header-value">%s</td></tr>'
21
- HTML_WRAPPER_TEMPLATE = '<!DOCTYPE html><html><head><style>body {font-size: 0.5cm;}</style><title>title</title></head><body>%s</body></html>' # rubocop:disable Layout/LineLength
22
-
23
- IMG_CID_PLAIN_REGEX = /\[cid:(.*?)\]/m
24
- IMG_CID_HTML_REGEX = /cid:([^"]*)/m
25
-
26
- def self.installed?
27
- File.exist?(Libis::Format::Config[:wkhtmltopdf])
28
- end
29
-
30
- def self.run(source, target, **options)
31
- new.run source, target, **options
32
- end
33
-
34
- def run(source, target, **options)
35
- # Preliminary checks
36
- # ------------------
37
-
38
- @warnings = []
39
-
40
- # Check if source file exists
41
- raise "File #{source} does not exist" unless File.exist?(source)
42
-
43
- # Retrieving the message
44
- # ----------------------
45
-
46
- # Open the message
47
- msg = Mapi::Msg.open(source)
48
-
49
- target_format = options.delete(:to_html) ? :HTML : :PDF
50
- result = msg_to_pdf(msg, target, target_format, options)
51
- msg.close
52
- result
53
- end
54
-
55
- def msg_to_pdf(msg, target, target_format, pdf_options, root_msg: true)
56
- # Make sure the target directory exists
57
- outdir = File.dirname(target)
58
- FileUtils.mkdir_p(outdir)
59
-
60
- # Get the body of the message in HTML
61
- body = msg.properties.body_html
62
-
63
- # Embed plain body in HTML as a fallback
64
- body ||= HTML_WRAPPER_TEMPLATE % msg.properties.body
65
-
66
- # Check and fix the character encoding
67
- begin
68
- # Try to encode into UTF-8
69
- body.encode!('UTF-8', universal_newline: true)
70
- rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
71
- begin
72
- # If it fails, the text may be in Windows' Latin1 (ISO-8859-1)
73
- body.force_encoding('ISO-8859-1').encode!('UTF-8', universal_newline: true)
74
- rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError => e
75
- # If that fails too, log a warning and replace the invalid/unknown with a ? character.
76
- @warnings << "#{e.class}: #{e.message}"
77
- body.encode!('UTF-8', universal_newline: true, invalid: :replace, undef: :replace)
78
- end
79
- end
80
-
81
- # Process headers
82
- # ---------------
83
- headers = {}
84
- hdr_html = ''
85
-
86
- %w[From To Cc Subject Date].each do |key|
87
- value = find_hdr(msg.headers, key)
88
- if value
89
- headers[key.downcase.to_sym] = value
90
- hdr_html += hdr_html(key, value)
91
- end
92
- end
93
-
94
- [:date].each do |key|
95
- next unless headers[key]
96
-
97
- headers[key] = DateTime.parse(headers[key]).to_time.localtime.iso8601
98
- end
99
-
100
- # Add header section to the HTML body
101
- unless hdr_html.empty?
102
- # Insert header block styles
103
- if body =~ %r{</head>}
104
- # if head exists, append the style block
105
- body.gsub!(%r{</head>}, "#{HEADER_STYLE}</head>")
106
- elsif body =~ %r{<head/>}
107
- # empty head, replace with the style block
108
- body.gsub!(%r{<head/>}, "<head>#{HEADER_STYLE}</head>")
109
- else
110
- # otherwise insert a head section before the body tag
111
- body.gsub!(/<body/, "<head>#{HEADER_STYLE}</head><body")
112
- end
113
- # Add the headers html table as first element in the body section
114
- body.gsub!(/<body[^>]*>/) { |m| "#{m}#{HEADER_TABLE_TEMPLATE % hdr_html}" }
115
- end
116
-
117
- # Embed inline images
118
- # -------------------
119
- attachments = msg.attachments
120
- used_files = []
121
-
122
- # First process plaintext cid entries
123
- body.gsub!(IMG_CID_PLAIN_REGEX) do |_match|
124
- data = get_attachment_data(attachments, ::Regexp.last_match(1))
125
- if data
126
- used_files << ::Regexp.last_match(1)
127
- "<img src=\"data:#{data[:mime_type]};base64,#{data[:base64]}\"/>"
128
- else
129
- '<img src=""/>'
130
- end
131
- end
132
-
133
- # Then process HTML img tags with CID entries
134
- body.gsub!(IMG_CID_HTML_REGEX) do |_match|
135
- data = get_attachment_data(attachments, ::Regexp.last_match(1))
136
- if data
137
- used_files << ::Regexp.last_match(1)
138
- "data:#{data[:mime_type]};base64,#{data[:base64]}"
139
- else
140
- ''
141
- end
142
- end
143
-
144
- # Create PDF
145
- # ----------
146
- files = []
147
-
148
- if target_format == :PDF
149
- # PDF creation options
150
- pdf_options = {
151
- page_size: 'A4',
152
- margin_top: '10mm',
153
- margin_bottom: '10mm',
154
- margin_left: '10mm',
155
- margin_right: '10mm',
156
- # image_quality: 100,
157
- # viewport_size: '2480x3508',
158
- dpi: 300
159
- }.merge pdf_options
160
-
161
- subject = find_hdr(msg.headers, 'Subject')
162
- kit = PDFKit.new(body, title: (subject || 'message'), **pdf_options)
163
- pdf = kit.to_pdf
164
- File.open(target, 'wb') { |f| f.write(pdf) }
165
- else
166
- File.open(target, 'wb') { |f| f.write(body) }
167
- end
168
- files << target if File.exist?(target)
169
-
170
- # Save attachments
171
- # ----------------
172
- outdir = File.join(outdir, "#{File.basename(target)}.attachments")
173
- digits = ((attachments.count + 1) / 10) + 1
174
- i = 1
175
- attachments.delete_if { |a| a.properties.attachment_hidden }.each do |a|
176
- prefix = "#{format('%0*d', digits, i)}-"
177
- if (sub_msg = a.instance_variable_get(:@embedded_msg))
178
- subject = a.properties[:display_name] || sub_msg.subject || ''
179
- file = File.join(outdir, "#{prefix}#{subject}.msg.#{target_format.to_s.downcase}")
180
- result = msg_to_pdf(sub_msg, file, target_format, pdf_options, root_msg: false)
181
- if (e = result[:error])
182
- raise e
183
- end
184
-
185
- files += result[:files]
186
- elsif a.filename
187
- next if used_files.include?(a.filename)
188
-
189
- file = File.join(outdir, "#{prefix}#{a.filename}")
190
- FileUtils.mkdir_p(File.dirname(file))
191
- File.open(file, 'wb') { |f| a.save(f) }
192
- files << file
193
- else
194
- @warnings << "Attachment #{a.properties[:display_name]} cannot be extracted"
195
- next
196
- end
197
- i += 1
198
- end
199
-
200
- if root_msg
201
- p = Pathname(File.dirname(files.first))
202
- files[1..].each do |f|
203
- (headers[:attachments] ||= []) << Pathname.new(f).relative_path_from(p).to_s
204
- end
205
- end
206
-
207
- {
208
- command: { status: 0 },
209
- files:,
210
- headers:,
211
- warnings: @warnings
212
- }
213
- rescue Exception => e
214
- raise unless root_msg
215
-
216
- msg.close
217
- {
218
- command: { status: -1 },
219
- files: [],
220
- headers: {},
221
- errors: [
222
- {
223
- error: e.message,
224
- error_class: e.class.name,
225
- error_trace: e.backtrace
226
- }
227
- ],
228
- warnings: @warnings
229
- }
230
- end
231
-
232
- protected
233
-
234
- def eml_to_html; end
235
-
236
- private
237
-
238
- def find_hdr(list, key)
239
- keys = list.keys
240
- if (k = keys.find { |x| x.to_s =~ /^#{key}$/i })
241
- v = list[k]
242
- v = v.first if v.is_a? Array
243
- v = Rfc2047.decode(v).strip if v.is_a? String
244
- return v
245
- end
246
- nil
247
- end
248
-
249
- def hdr_html(key, value)
250
- return format(HEADER_FIELD_TEMPLATE, key, CGI.escapeHTML(value)) if key.is_a?(String) && value.is_a?(String) && !value.empty?
251
-
252
- ''
253
- end
254
-
255
- def get_attachment_data(attachments, cid)
256
- attachments.each do |attachment|
257
- next unless attachment.properties.attach_content_id == cid
258
-
259
- attachment.data.rewind
260
- return {
261
- mime_type: attachment.properties.attach_mime_tag,
262
- base64: Base64.encode64(attachment.data.read).gsub(/[\r\n]/, '')
263
- }
264
- end
265
- nil
266
- end
267
- end
268
- end
269
- end
270
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'os'
4
-
5
- require 'libis/tools/extend/string'
6
- require 'libis/tools/logger'
7
- require 'libis/tools/command'
8
-
9
- require 'libis/format/config'
10
-
11
- module Libis
12
- module Format
13
- module Tool
14
- class PdfTool
15
- include ::Libis::Tools::Logger
16
-
17
- def self.installed?
18
- result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd], '-version')
19
- return false unless (result[:status]).zero?
20
-
21
- File.exist?(Libis::Format::Config[:pdf_tool])
22
- end
23
-
24
- def self.run(command, source, target, *options)
25
- new.run command, source, target, *options
26
- end
27
-
28
- def run(command, source, target, *options)
29
- if OS.java?
30
- # TODO: import library and execute in current VM. For now do exactly as in MRI.
31
- end
32
-
33
- timeout = Libis::Format::Config[:timeouts][:pdf_tool]
34
- args = [
35
- Libis::Format::Config[:java_cmd],
36
- '-jar', Libis::Format::Config[:pdf_tool],
37
- [command],
38
- '-i', source,
39
- '-o', target,
40
- options,
41
- ].flatten
42
-
43
- result = Libis::Tools::Command.run(*args, timeout: , kill_after: timeout * 2)
44
-
45
- result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
46
-
47
- result
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,156 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
- require 'libis/tools/extend/hash'
5
-
6
- module Libis
7
- module Format
8
- # noinspection RubyClassVariableUsageInspection
9
- class TypeDatabase
10
- @implementation = Libis::Format::TypeDatabaseImpl.instance
11
-
12
- def self.implementation(impl)
13
- @implementation = impl
14
- end
15
-
16
- def self.enrich(info, map_keys = {})
17
- return {} unless info.is_a? Hash
18
-
19
- mapper = Hash.new { |hash, key| hash[key] = key }
20
- mapper.merge! map_keys
21
- unless (puid = info[mapper[:PUID]]).blank?
22
- info[mapper[:TYPE]] ||= begin
23
- puid_infos(puid).first[:TYPE]
24
- rescue StandardError
25
- nil
26
- end
27
- end
28
- unless (mime = info[mapper[:MIME]]).blank?
29
- info[mapper[:TYPE]] ||= begin
30
- mime_infos(mime).first[:TYPE]
31
- rescue StandardError
32
- nil
33
- end
34
- end
35
- unless (type_name = info[mapper[:TYPE]]).nil?
36
- mapper.each_key do |key|
37
- info[mapper[key]] = get(type_name, key) || info[mapper[key]]
38
- end
39
- info[mapper[:GROUP]] = type_group(type_name)
40
- end
41
- info
42
- end
43
-
44
- def self.normalize(info, map_keys = {})
45
- return {} unless info.is_a? Hash
46
-
47
- mapper = Hash.new { |hash, key| hash[key] = key }
48
- mapper.merge! map_keys
49
- unless (puid = info[mapper[:PUID]]).blank?
50
- info[mapper[:TYPE]] ||= begin
51
- puid_infos(puid).first[:TYPE]
52
- rescue StandardError
53
- nil
54
- end
55
- end
56
- unless (mime = info[mapper[:MIME]]).blank?
57
- info[mapper[:TYPE]] ||= begin
58
- mime_infos(mime).first[:TYPE]
59
- rescue StandardError
60
- nil
61
- end
62
- end
63
- unless (type_name = info[mapper[:TYPE]]).nil?
64
- info[mapper[:MIME]] = type_mimetypes(type_name).first if type_mimetypes(type_name).first
65
- info[mapper[:GROUP]] = type_group(type_name)
66
- end
67
- info
68
- end
69
-
70
- def self.get(type_name, key)
71
- case key
72
- when :MIME
73
- type_mimetypes(type_name).first
74
- when :PUID
75
- type_puids(type_name).first
76
- when :EXTENSION
77
- type_extentions(type_name).first
78
- else
79
- typeinfo(type_name)[key]
80
- end
81
- end
82
-
83
- def self.type_group(ftype)
84
- typeinfo(ftype)[:GROUP]
85
- end
86
-
87
- def self.type_mimetypes(ftype)
88
- typeinfo(ftype)[:MIME] || []
89
- end
90
-
91
- def self.type_puids(ftype)
92
- typeinfo(ftype)[:PUID] || []
93
- end
94
-
95
- def self.type_extentions(ftype)
96
- typeinfo(ftype)[:EXTENSIONS] || []
97
- end
98
-
99
- def self.typeinfo(ftype)
100
- @implementation.typeinfo(ftype)
101
- end
102
-
103
- def self.group_types(group)
104
- @implementation.group_types(group)
105
- end
106
-
107
- def self.puid_infos(puid)
108
- @implementation.puid_infos(puid)
109
- end
110
-
111
- def self.puid_types(puid)
112
- @implementation.puid_types(puid)
113
- end
114
-
115
- def self.puid_groups(puid)
116
- puid_types(puid).map(&method(:type_group))
117
- end
118
-
119
- def self.mime_infos(mime)
120
- @implementation.mime_infos(mime)
121
- end
122
-
123
- def self.mime_types(mime)
124
- @implementation.mime_types(mime)
125
- end
126
-
127
- def self.mime_groups(mime)
128
- mime_types(mime).map(&method(:type_group))
129
- end
130
-
131
- def self.ext_infos(ext)
132
- @implementation.ext_infos(ext)
133
- end
134
-
135
- def self.ext_types(ext)
136
- @implementation.ext_types(ext)
137
- end
138
-
139
- def self.puid_typeinfo(puid)
140
- @implementation.puid_typeinfo(puid)
141
- end
142
-
143
- def self.known_mime?(mime)
144
- @implementation.known_mime?(mime)
145
- end
146
-
147
- def self.groups
148
- @implementation.groups
149
- end
150
-
151
- def self.export_csv(filename, **options)
152
- @implementation.export_csv(filename, **options)
153
- end
154
- end
155
- end
156
- end
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
- require 'yaml'
5
- require 'csv'
6
-
7
- require 'libis/tools/logger'
8
- require 'libis/tools/extend/hash'
9
- require 'libis/tools/extend/string'
10
- require 'libis/tools/extend/symbol'
11
-
12
- module Libis
13
- module Format
14
- class TypeDatabaseImpl
15
- include Singleton
16
- include ::Libis::Tools::Logger
17
-
18
- def typeinfo(ftype)
19
- @types[ftype.to_sym] || {}
20
- end
21
-
22
- def group_types(group)
23
- @types.select do |_, v|
24
- v[:GROUP] == group.to_sym
25
- end.keys
26
- end
27
-
28
- def puid_infos(puid)
29
- @types.select do |_, v|
30
- v[:PUID].include? puid
31
- rescue StandardError
32
- false
33
- end.values
34
- end
35
-
36
- def puid_types(puid)
37
- @types.select do |_, v|
38
- v[:PUID].include? puid
39
- rescue StandardError
40
- false
41
- end.keys
42
- end
43
-
44
- def mime_infos(mime)
45
- @types.select do |_, v|
46
- v[:MIME].include? mime
47
- rescue StandardError
48
- false
49
- end.values
50
- end
51
-
52
- def mime_types(mime)
53
- @types.select do |_, v|
54
- v[:MIME].include? mime
55
- rescue StandardError
56
- false
57
- end.keys
58
- end
59
-
60
- def ext_infos(ext)
61
- ext = ext.gsub(/^\./, '')
62
- @types.select do |_, v|
63
- v[:EXTENSIONS].include?(ext)
64
- rescue StandardError
65
- false
66
- end.values
67
- end
68
-
69
- def ext_types(ext)
70
- ext = ext.gsub(/^\./, '')
71
- @types.select do |_, v|
72
- v[:EXTENSIONS].include?(ext)
73
- rescue StandardError
74
- false
75
- end.keys
76
- end
77
-
78
- def puid_typeinfo(puid)
79
- @types.each do |_, v|
80
- return v if v[:PUID]&.include?(puid)
81
- end
82
- nil
83
- end
84
-
85
- def known_mime?(mime)
86
- @types.each do |_, v|
87
- return true if v[:MIME]&.include? mime
88
- end
89
- false
90
- end
91
-
92
- def groups
93
- @types.values.map(&:dig.with(:GROUP)).uniq
94
- end
95
-
96
- def export_csv(filename, **options)
97
- headers = @types.values.each_with_object(Set.new) { |v, s| v.each_key { |k| s << k.to_s } }
98
- options[:headers] = headers.to_a
99
- CSV.open(filename, 'w', **options) do |csv|
100
- @types.each_value do |v|
101
- csv << CSV::Row.new(v.keys, v.values.map { |x| x.is_a?(Array) ? x.join(', ') : x })
102
- end
103
- end
104
- end
105
-
106
- def load_types(file_or_hash = {}, append = true)
107
- hash = file_or_hash.is_a?(Hash) ? file_or_hash : YAML.load_file(file_or_hash)
108
- # noinspection RubyResolve
109
- hash.each do |group, type_info|
110
- type_info.each do |type_name, info|
111
- type_key = type_name.to_sym
112
- info.symbolize_keys!
113
- info[:TYPE] = type_key
114
- info[:GROUP] = group.to_sym
115
- info[:MIME] = begin
116
- info[:MIME].strip.split(/[\s,]+/).map(&:strip)
117
- rescue StandardError
118
- []
119
- end
120
- info[:EXTENSIONS] = begin
121
- info[:EXTENSIONS].strip.split(/[\s,]+/).map(&:strip)
122
- rescue StandardError
123
- []
124
- end
125
- info[:PUID] = info[:PUID].strip.split(/[\s,]+/).map(&:strip) if info[:PUID]
126
- if @types.key?(type_key)
127
- warn 'Type %s already defined; merging with info from %s.', type_name, file_or_hash
128
- info.merge!(@types[type_key]) do |_, v_new, v_old|
129
- case v_old
130
- when Array
131
- append ? v_old + v_new : v_new + v_old
132
- when Hash
133
- append ? v_new.merge(v_old) : v_old.merge(v_new)
134
- else
135
- append ? v_old : v_new
136
- end
137
- end
138
- end
139
- @types[type_key] = info
140
- end
141
- end
142
- end
143
-
144
- protected
145
-
146
- def initialize
147
- @types = {}
148
- type_database = Libis::Format::Config[:type_database]
149
- load_types(type_database)
150
- end
151
- end
152
- end
153
- end