libis-format 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21f527308cef3b9865c24c956f5a76cf67973400
4
- data.tar.gz: 19c867aef5d28da24a3354025b11fc718b885a7f
3
+ metadata.gz: a96a71d90952cf5d8be62d9b82ac6fc22c4f080a
4
+ data.tar.gz: 79bda271ae8b628e96c7a3d19b65884a3fe1eee0
5
5
  SHA512:
6
- metadata.gz: 3af22a3b301bc89a0839215a96a571d729478c61f3d414ee144e7f011d16443f4e604efd8f6afb0b40d2dd02dc77ca65878dfba7b29a6f4bc186beec8373b437
7
- data.tar.gz: 81bebc7836625f251e9365100bfdb4a13d3ec4424a26a536521bb1776a11d96472645af1e360077ff64d5ef4e6f08671e0c87330d8fa32f5230b390509a016ce
6
+ metadata.gz: 303f4353c79d988110668ddc1c4bb5867d4e644b30d1a6f60e24da13a2f8f99703ab1b8f5afba73ed11aee0cfdd8bad6e759e857350a97d734d021fcfca31c32
7
+ data.tar.gz: 612a76df7a9907900aa292e68065f3c13d1362edffa01cbf2425edb8c8f41040d17871680ad7bab430a49790da96bba323ce2706ab13dfa39494ca8795e7d639
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+
6
+ require 'libis/format/command_line'
7
+
8
+ Libis::Format::CommandLine.start(ARGV)
@@ -4,6 +4,7 @@ module Libis
4
4
  module Format
5
5
  autoload :Config, 'libis/format/config'
6
6
  autoload :TypeDatabase, 'libis/format/type_database'
7
+ autoload :TypeDatabaseImpl, 'libis/format/type_database_impl'
7
8
  autoload :Identifier, 'libis/format/identifier'
8
9
 
9
10
  autoload :Tool, 'libis/format/tool'
@@ -0,0 +1,310 @@
1
+ require 'awesome_print'
2
+ require 'libis-format'
3
+ require 'libis-tools'
4
+ require 'libis/tools/extend/hash'
5
+ require 'fileutils'
6
+ require 'tmpdir'
7
+ require 'yaml'
8
+
9
+ require 'libis/format/converter/image_converter'
10
+
11
+ require_relative 'sub_command'
12
+
13
+ module Libis
14
+ module Format
15
+ module Cli
16
+ class Convert < SubCommand
17
+
18
+ no_commands do
19
+ def self.description(field)
20
+ "#{STRING_CONFIG[field]}." + (DEFAULT_CONFIG[field].nil? ? '' : " default: #{DEFAULT_CONFIG[field]}")
21
+ end
22
+ end
23
+
24
+ DEFAULT_CONFIG = {
25
+ scale: '100%',
26
+ resize: '100%',
27
+ wm_tiles: 4,
28
+ wm_resize: 1.0,
29
+ wm_gap: 0.2,
30
+ wm_rotation: 30,
31
+ wm_opacity: 0.1,
32
+ wm_gravity: 'center',
33
+ wm_composition: 'modulate'
34
+ }
35
+
36
+ STRING_CONFIG = {
37
+ page: 'Page number to select for multipage documents',
38
+ quiet: 'suppress all warning messages. Error messages are still reported',
39
+ scale: 'minify / magnify the image with pixel block averaging and pixel replication, respectively',
40
+ resize: 'Resize the image',
41
+ resample: 'Resize the image so that its rendered size remains the same as the original at the specified target resolution',
42
+ flatten: 'Create a canvas the size of the first images virtual canvas using the current -background color, and -compose each image in turn onto that canvas. Images falling outside that canvas is clipped',
43
+ delete_date: 'Remove modified date and created date metadata from the target image',
44
+ colorspace: 'Set the image colorspace',
45
+ profile: 'Specify color profile used for the image',
46
+ wm_text: 'Create watermark with given text',
47
+ wm_file: 'Create watermark from given file',
48
+ wm_tiles: 'Number of tiles of the watermark to distribute over the image. 0: no tiling, 1: watermark image scaled to fit image, n>1: at least n tiles horizontally/vertically, n<0: tile without recaling',
49
+ wm_resize: 'Resize the watermark image (fraction 0.0 - 1.0)',
50
+ wm_gap: 'Leave n % of whitespace between the watermark images. Similar effect can be achieved with wm_resize',
51
+ wm_rotation: 'Rotate the watermark text n degrees counterclockwise (0-360)',
52
+ wm_opacity: 'Opacity of the watermark (fraction 0.0 - 1.0)',
53
+ wm_gravity: 'Center point of the watermark overlay',
54
+ wm_composition: 'Set the type of image composition'
55
+ }
56
+
57
+ desc 'auto SOURCE TARGET [options]', 'Convert SOURCE file to TARGET file using auto algorithm'
58
+ long_desc <<-DESC
59
+
60
+ 'auto SOURCE TARGET [options]' will convert a file according to the best conversion chain algorithm.
61
+
62
+ A source file name and target file name should be supplied. The source file should exist and be readable.
63
+ The target file should be writable, but should not exist.
64
+
65
+ Optionally an options file name can be added to the command line. The options file should be a valid YAML
66
+ file that contains either a Hash or an Array of Hashes. The content should contain the required methods and
67
+ arguments that any of the targetted converters support.
68
+
69
+ The source file's format will be identified by the Libis::Format::Identifier and the target file's format
70
+ will be derived from the file's extension. The Libis::Format::TypeDatabase is used to relate extensions
71
+ with formats.
72
+
73
+ DESC
74
+
75
+ method_option :options, aliases: '-o', desc: 'Options file'
76
+
77
+ def auto(source_file, target_file)
78
+ options_file = options[:options]
79
+ opts = check_input(source_file, target_file, options_file)
80
+ output, converter = do_convert(source_file, target_file, opts)
81
+ prompt.ok "Output file '#{output}' created with converter #{converter}."
82
+ end
83
+
84
+ desc 'image SOURCE TARGET [options]', 'Convert SOURCE image to TARGET image using ImageConverter'
85
+ long_desc <<-DESC
86
+
87
+ 'image SOURCE TARGET [options]' will convert a SOURCE image to TARGET image using the ImageConverter.
88
+
89
+ A source file name and target file name should be supplied. The source file should exist and be readable.
90
+ The target file should be writable, but should not exist.
91
+
92
+ The target file's format will be derived from the file's extension. The Libis::Format::TypeDatabase is used
93
+ to relate extensions with formats.
94
+
95
+ DESC
96
+
97
+ method_option :page, type: :numeric, aliases: '-p', desc: description(:page)
98
+ method_option :quiet, type: :boolean, aliases: '-q', desc: description(:quiet)
99
+ method_option :scale, type: :numeric, aliases: '-c', desc: description(:scale)
100
+ method_option :resize, type: :numeric, aliases: '-r', desc: description(:resize)
101
+ method_option :resample, type: :numeric, aliases: '-m', desc: description(:resample)
102
+ method_option :flatten, type: :boolean, aliases: '-f', desc: description(:flatten)
103
+ method_option :delete_date, type: :boolean, aliases: '-dd', desc: description(:delete_date)
104
+ method_option :colorspace, aliases: '-cs', desc: description(:colorspace)
105
+ method_option :profile, aliases: '-prof', desc: description(:profile)
106
+ method_option :wm_text, desc: description(:wm_text)
107
+ method_option :wm_file, desc: description(:wm_file)
108
+ method_option :wm_tiles, type: :numeric, desc: description(:wm_tiles)
109
+ method_option :wm_resize, type: :numeric, desc: description(:wm_resize)
110
+ method_option :wm_gap, type: :numeric, desc: description(:wm_gap)
111
+ method_option :wm_rotation, type: :numeric, desc: description(:wm_rotation)
112
+ method_option :wm_opacity, type: :numeric, desc: description(:wm_opacity)
113
+ method_option :wm_gravity, desc: description(:wm_gravity)
114
+ method_option :wm_composition, desc: description(:wm_composition)
115
+
116
+ def image(source_file, target_file)
117
+ check_input(source_file, target_file)
118
+ convert_image(source_file, target_file)
119
+ prompt.ok "Output file '#{target_file}' created with image converter."
120
+ end
121
+
122
+ protected
123
+
124
+ def do_convert(source_file, target_file, opts)
125
+ format_info = format_identifier(source_file)
126
+ src_mime = format_info[:mimetype]
127
+ source_format = format_info[:TYPE]
128
+ unless source_format
129
+ prompt.error "File item %s format (#{src_mime}) is not supported."
130
+ exit
131
+ end
132
+ target_format = get_format(target_file)
133
+ converterlist = []
134
+ temp_files = []
135
+ opts.each do |o|
136
+ o = o.dup
137
+ tgt_format = o.delete(:target_format) || target_format
138
+ tgt_file = tempname(source_file, tgt_format)
139
+ temp_files << tgt_file
140
+ begin
141
+ source_file, converter = convert_file(source_file, tgt_file, source_format, tgt_format, o)
142
+ rescue Exception => e
143
+ prompt.error "File conversion of '%s' from '%s' to '%s' failed: %s @ %s" %
144
+ [source_file, source_format, tgt_format, e.message, e.backtrace.first]
145
+ exit
146
+ end
147
+ source_format = tgt_format
148
+ converterlist << converter
149
+ end
150
+ converter = converterlist.join(' + ')
151
+ if target_file
152
+ FileUtils.mkpath(File.dirname(target_file))
153
+ FileUtils.copy(source_file, target_file)
154
+ else
155
+ target_file = temp_files.pop
156
+ end
157
+ temp_files.each {|tmp_file| FileUtils.rm_f tmp_file}
158
+ [target_file, converter]
159
+ end
160
+
161
+ def convert_file(src_file, tgt_file, src_format, tgt_format, opts)
162
+ converter = Libis::Format::Converter::Repository.get_converter_chain(src_format, tgt_format, opts)
163
+
164
+ unless converter
165
+ prompt.error "Could not find converter for #{src_format} -> #{tgt_format} with #{opts}"
166
+ exit
167
+ end
168
+
169
+ converter_name = converter.to_s
170
+ prompt.say 'Converting file %s to %s with %s ' % [src_file, tgt_file, converter_name]
171
+ converted = converter.convert(src_file, tgt_file)
172
+
173
+ unless converted && converted == tgt_file
174
+ prompt.error 'File conversion failed (%s).', converter_name
175
+ return [nil, converter_name]
176
+ end
177
+
178
+ [tgt_file, converter_name]
179
+ end
180
+
181
+ def convert_image(source_file, target_file)
182
+ target_format = get_format(target_file)
183
+ converter = Libis::Format::Converter::ImageConverter.new
184
+ converter.page options[:page] if options[:page]
185
+ converter.quiet options[:quiet] if options[:quiet]
186
+ converter.scale options[:scale] if options[:scale]
187
+ converter.resize options[:resize] if options[:resize]
188
+ converter.resample options[:resample] if options[:resample]
189
+ converter.flatten if options[:flatten]
190
+ converter.delete_date if options[:delete_date]
191
+ converter.colorspace options[:colorspace] if options[:colorspace]
192
+ converter.profile options[:profile] if options[:profile]
193
+ if options[:wm_text] || options[:wm_file]
194
+ wm_options = {}
195
+ wm_options[:text] = options[:wm_text] if options[:wm_text]
196
+ wm_options[:file] = options[:wm_file] if options[:wm_file]
197
+ wm_options[:tiles] = options[:wm_tiles] if options[:wm_tiles]
198
+ wm_options[:resize] = options[:wm_resize] if options[:wm_resize]
199
+ wm_options[:gap] = options[:wm_gap] if options[:wm_gap]
200
+ wm_options[:rotation] = options[:wm_rotation] if options[:wm_rotation]
201
+ wm_options[:opacity] = options[:wm_opacity] if options[:wm_opacity]
202
+ wm_options[:gravity] = options[:wm_gravity] if options[:wm_gravity]
203
+ wm_options[:composition] = options[:wm_composition] if options[:wm_composition]
204
+ converter.watermark(wm_options)
205
+ end
206
+ converter.convert source_file, target_file, target_format
207
+ end
208
+
209
+ private
210
+
211
+ def check_input(source_file, target_file, options_file = nil)
212
+ # Check if source file exists and can be read
213
+ unless source_file && File.exist?(source_file) && File.readable?(source_file)
214
+ prompt.error "Fatal error trying to access source file '#{source_file}'."
215
+ exit
216
+ end
217
+ # Check if target file argument is supplied
218
+ unless target_file
219
+ prompt.error "Fatal error: no target file name supplied."
220
+ exit
221
+ end
222
+ # Check if target file directory can be created
223
+ begin
224
+ FileUtils.mkdir_p(File.dirname(target_file))
225
+ rescue SystemCallError => e
226
+ prompt.error "Fatal error trying to create folder for target file: #{e.message}"
227
+ exit
228
+ end
229
+
230
+ return [{}] unless options_file
231
+
232
+ # Check if options file exists and can be read
233
+ unless File.exist?(options_file) && File.readable?(options_file)
234
+ prompt.error "Fatal error trying to access options file '#{options_file}'."
235
+ exit
236
+ end
237
+
238
+ begin
239
+ opts = ::YAML.load_file(options_file)
240
+ opts = case opts
241
+ when Hash
242
+ [opts]
243
+ when Array
244
+ opts
245
+ when NilClass
246
+ [{}]
247
+ else
248
+ prompt.error "Options file contents should be a Hash or an Array of Hashes."
249
+ exit
250
+ end
251
+ opts.each {|h| h.key_strings_to_symbols!(recursive: true)}
252
+ opts
253
+ rescue Exception => e
254
+ prompt.error "Fatal error trying to parse options file: #{e.message}"
255
+ exit
256
+ end
257
+
258
+ end
259
+
260
+ def tempname(source_file, target_format)
261
+ # noinspection RubyResolve
262
+ Dir::Tmpname.create(
263
+ [File.basename(source_file, '.*'), ".#{extname(target_format)}"]
264
+ ) {}
265
+ end
266
+
267
+ def extname(format)
268
+ Libis::Format::TypeDatabase.type_extentions(format).first
269
+ end
270
+
271
+ def get_format(file_name)
272
+ Libis::Format::TypeDatabase.ext_types(File.extname(file_name)).first
273
+ end
274
+
275
+ def format_identifier(file)
276
+ prompt.say "Identifying format of file '#{file}'"
277
+ result = Libis::Format::Identifier.get(file) || {}
278
+ process_messages(result)
279
+ format = result[:formats][file]
280
+ unless format[:mimetype]
281
+ prompt.warn "Could not determine MIME type. Using default 'application/octet-stream'."
282
+ result[:puid] ||= 'fmt/unknown'
283
+ end
284
+ prompt.say "#{file} format: #{format[:GROUP]}, #{format[:TYPE]} (puid: #{format[:puid]}) mimetype: #{format[:mimetype]}"
285
+ format
286
+ end
287
+
288
+ def process_messages(format_result)
289
+ format_result[:messages].each do |msg|
290
+ case msg[0]
291
+ when :debug
292
+ prompt.say msg[1]
293
+ when :info
294
+ prompt.say msg[1]
295
+ when :warn
296
+ prompt.warn msg[1]
297
+ when :error
298
+ prompt.error msg[1]
299
+ when :fatal
300
+ prompt.error msg[1]
301
+ else
302
+ prompt.say "#{msg[0]}: #{msg[1]}"
303
+ end
304
+ end
305
+ end
306
+
307
+ end
308
+ end
309
+ end
310
+ end
@@ -0,0 +1,77 @@
1
+ require 'awesome_print'
2
+ require 'libis-format'
3
+ require 'libis-tools'
4
+
5
+ require_relative 'sub_command'
6
+
7
+ module Libis
8
+ module Format
9
+ module Cli
10
+ class Format < SubCommand
11
+
12
+ no_commands do
13
+ def self.description(field)
14
+ "#{STRING_CONFIG[field]}." + (DEFAULT_CONFIG[field].nil? ? '' : " default: #{DEFAULT_CONFIG[field]}")
15
+ end
16
+ end
17
+
18
+ DEFAULT_CONFIG = {
19
+ droid: true,
20
+ fido: true,
21
+ file: true,
22
+ xml_validation: true
23
+ }
24
+
25
+ STRING_CONFIG = {
26
+ droid: 'Use Droid to identify the format',
27
+ fido: 'Use Fido to identify the format',
28
+ file: 'Use File to identify the format',
29
+ xml_validation: 'When XML file found, validate the file against known XML schemas',
30
+ }
31
+
32
+ desc 'identify FILE [options]', 'Identify the FILE using a combination of the tools.'
33
+ long_desc <<-DESC
34
+
35
+ 'identify FILE [options]' will idnetify a file using a combination of tools.
36
+
37
+ The file will be identified by each of the selected tools in turn and the format with best score will be
38
+ selected to give the final result. The score is determined by the identification method and will be lowered if
39
+ a known weak format (e.g. zip file) is detected.
40
+
41
+ The tool will display as much information about the format as possible, including the format candidates that
42
+ were not selected.
43
+
44
+ DESC
45
+
46
+ method_option :droid, default: DEFAULT_CONFIG[:droid], type: :boolean, desc: STRING_CONFIG[:droid]
47
+ method_option :fido, default: DEFAULT_CONFIG[:fido], type: :boolean, desc: STRING_CONFIG[:fido]
48
+ method_option :file, default: DEFAULT_CONFIG[:file], type: :boolean, desc: STRING_CONFIG[:file]
49
+ method_option :xml_validation, default: DEFAULT_CONFIG[:xml_validation], type: :boolean, desc: STRING_CONFIG[:xml_validation]
50
+
51
+ def identify(source_file)
52
+ ::Libis::Tools::Config.logger.level = :WARN
53
+ opts = options.inject({}) { |h, x| h[x.first.to_sym] = x.last; h}
54
+ opts[:keep_output] = true
55
+ result = ::Libis::Format::Identifier.get source_file, opts
56
+ puts '--- messages ---'
57
+ result[:messages].each do |message|
58
+ puts "#{message[0]} : #{message[1]}"
59
+ end
60
+
61
+ puts '--- formats ---'
62
+ result[:formats].each do |file, info|
63
+ puts "#{file}:"
64
+ ap info
65
+ end
66
+
67
+ puts '--- tool results ---'
68
+ result[:output].each do |file, info|
69
+ puts "#{file}:"
70
+ ap info
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,87 @@
1
+ require 'tty-prompt'
2
+ require 'pastel'
3
+
4
+ module Libis
5
+ module Format
6
+ module Cli
7
+ module PromptHelper
8
+
9
+ attr_reader :prompt, :pastel
10
+
11
+ def initialize(*args)
12
+ @prompt = TTY::Prompt.new
13
+ @pastel = Pastel.new
14
+ super
15
+ end
16
+
17
+ protected
18
+
19
+ private
20
+
21
+ def index_of(list, value)
22
+ i = list.index(value)
23
+ i += 1 if i
24
+ i || 1
25
+ end
26
+
27
+ def ask(question, bool: false, enum: nil, default: nil, mask: false)
28
+ cmd, args, opts = :ask, [question], {}
29
+ if enum
30
+ cmd = :select
31
+ args << enum
32
+ # Change default to its index in the enum
33
+ default = index_of(enum, default)
34
+ end
35
+ cmd = :mask if mask
36
+ opts[:default] = default if default
37
+ cmd = (opts[:default] ? :yes? : :no?) if bool
38
+ prompt.send(cmd, *args, opts)
39
+ end
40
+
41
+ def tree_select(path, question: nil, file: false, page_size: 22, filter: true, cycle: false, create: false,
42
+ default_choices: nil)
43
+ path = Pathname.new(path) unless path.is_a? Pathname
44
+
45
+ return path unless path.exist?
46
+ path = path.realpath
47
+
48
+ dirs = path.children.select(&:directory?).sort
49
+ files = file ? path.children.select(&:file?).sort : []
50
+
51
+ choices = []
52
+ choices << {name: "Folder: #{path}", value: path, disabled: file ? '' : false}
53
+ choices += default_choices if default_choices
54
+ choices << {name: '-- new directory --', value: -> do
55
+ new_name = prompt.ask('new directory name:', modify: :trim, required: true)
56
+ new_path = path + new_name
57
+ FileUtils.mkdir(new_path.to_path)
58
+ new_path
59
+ end
60
+ } if create
61
+
62
+ choices << {name: "-- new file --", value: -> do
63
+ new_name = prompt.ask('new file name:', modify: :trim, required: true)
64
+ path + new_name
65
+ end
66
+ } if file && create
67
+
68
+ choices << {name: '[..]', value: path.parent}
69
+
70
+ dirs.each {|d| choices << {name: "[#{d.basename}]", value: d}}
71
+ files.each {|f| choices << {name: f.basename.to_path, value: f}}
72
+
73
+ question ||= "Select #{'file or ' if files}directory"
74
+ selection = prompt.select question, choices,
75
+ per_page: page_size, filter: filter, cycle: cycle, default: file ? 2 : 1
76
+
77
+ return selection unless selection.is_a? Pathname
78
+ return selection.to_path if selection == path || selection.file?
79
+
80
+ tree_select selection, question: question, file: file, page_size: page_size, filter: filter,
81
+ cycle: cycle, create: create, default_choices: default_choices
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,22 @@
1
+ require 'thor'
2
+ require_relative 'prompt_helper'
3
+
4
+ module Libis
5
+ module Format
6
+ module Cli
7
+ class SubCommand < Thor
8
+
9
+ include PromptHelper
10
+
11
+ def self.banner(command, namespace = nil, subcommand = false)
12
+ "#{basename} #{subcommand_prefix} #{command.usage}"
13
+ end
14
+
15
+ def self.subcommand_prefix
16
+ self.name.gsub(%r{.*::}, '').gsub(%r{^[A-Z]}) { |match| match[0].downcase }.gsub(%r{[A-Z]}) { |match| "-#{match[0].downcase}" }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ require 'thor'
2
+ require 'tty-prompt'
3
+ require 'tty-config'
4
+
5
+ require 'libis/format/cli/convert'
6
+ require 'libis/format/cli/format'
7
+
8
+ module Libis
9
+ module Format
10
+
11
+ class CommandLine < Thor
12
+
13
+ def self.exit_on_failure?
14
+ true
15
+ end
16
+
17
+ desc 'convert', 'perform format conversion on a given file'
18
+ subcommand 'convert', Cli::Convert
19
+
20
+ desc 'format', 'perform format identification on a given file or directory'
21
+ subcommand 'format', Cli::Format
22
+ end
23
+
24
+ end
25
+ end
@@ -6,18 +6,20 @@ require 'libis/format/identifier'
6
6
  require 'mini_magick'
7
7
  require 'fileutils'
8
8
 
9
- MiniMagick.logger.level = ::Logger::ERROR
9
+ MiniMagick.logger.level = ::Logger::UNKNOWN
10
10
 
11
11
  MiniMagick.configure do |config|
12
12
  # config.cli = :graphicsmagick
13
13
  config.validate_on_create = false
14
14
  config.validate_on_write = false
15
+ config.whiny = false
15
16
  end
16
17
 
17
18
  module Libis
18
19
  module Format
19
20
  module Converter
20
21
 
22
+ # noinspection RubyTooManyInstanceVariablesInspection
21
23
  class ImageConverter < Libis::Format::Converter::Base
22
24
 
23
25
  def self.input_types
@@ -43,7 +45,7 @@ module Libis
43
45
  end
44
46
 
45
47
  def quiet(v)
46
- @flags[:quiet] = !!v
48
+ @quiet = !!v
47
49
  end
48
50
 
49
51
  def page(nr)
@@ -70,16 +72,16 @@ module Libis
70
72
  @options[:resample] = value
71
73
  end
72
74
 
73
- def flatten
74
- @flags[:flatten] = true
75
+ def flatten(value = true)
76
+ @options[:flatten] = !!value
75
77
  end
76
78
 
77
79
  def colorspace(value)
78
80
  @options[:colorspace] = value
79
81
  end
80
82
 
81
- def delete_date
82
- @delete_date = true
83
+ def delete_date(value = true)
84
+ @delete_date = !!value
83
85
  end
84
86
 
85
87
  def profile(icc)
@@ -92,9 +94,16 @@ module Libis
92
94
  # - file: watermark image to use
93
95
  # - text: text to create a watermark from
94
96
  # - rotation: rotation of the watermark text (counter clockwise in degrees; integer number) - default 30
95
- # - size: size of the watermark (integer > 0, 1/n of image size) - default 4
96
- # - opacity: opacity of the watermark (fraction 0.0 - 1.0) - default 0.3
97
+ # - tiles: number of tiles of the watermark - default 4
98
+ # - 0: no tiling, so only 1 watermark will be placed with the original size
99
+ # - 1: 1 tile, so the watermark will be scaled up to fill the image
100
+ # - n > 1: minimum n tiles in both directions
101
+ # - n < 0: tile without scaling the watermark
102
+ # - size: same as tiles - for backwards compatibility
103
+ # - resize: fraction 0.0 - 1.0
97
104
  # - gap: size of the gap between watermark instances. Fractions as percentage of widht/height. - default 0.2
105
+ # - opacity: opacity of the watermark (fraction 0.0 - 1.0) - default 0.1
106
+ # - gravity: center point of the overlay - default 'center'
98
107
  # If both options are given, the file will be used as-is if it exists and is a valid image file. Otherwise the
99
108
  # file will be created or overwritten with a newly created watermark image.
100
109
  #
@@ -104,14 +113,17 @@ module Libis
104
113
  # @param [Hash] options Hash of options for watermark creation.
105
114
  def watermark(options = {})
106
115
  text = options[:text] || '© LIBIS'
107
- @wm_size = (options[:size] || '4').to_i
116
+ @wm_tiles = (options[:tiles] || '4').to_i
117
+ @wm_tiles ||= (options[:size] || '4').to_i
118
+ @wm_resize = ((options[:resize]).to_f * 100).to_i if options[:resize]
108
119
  @wm_opacity = ((options[:opacity] || 0.1).to_f * 100).to_i
109
120
  @wm_composition = options[:composition] || 'modulate'
110
- gap = ((options[:gap] || 0.2).to_f * 100).to_i
121
+ @wm_gravity = options[:gravity] || 'center'
122
+ @wm_gap = ((options[:gap] || 0.2).to_f * 100).to_i
111
123
  rotation = 360 - (options[:rotation] || 30).to_i
112
124
  @wm_image = MiniMagick::Image.new(options[:file]) if options[:file]
113
125
  unless @wm_image && @wm_image.valid?
114
- image = options[:file] || (Dir::Tmpname.create(%w(wm_image .png)) { |_|})
126
+ image = options[:file] || (Dir::Tmpname.create(%w(wm_image .png)) {|_|})
115
127
  # noinspection RubyResolve
116
128
  MiniMagick::Tool::Convert.new do |convert|
117
129
  # noinspection RubyLiteralArrayInspection
@@ -123,7 +135,6 @@ module Libis
123
135
  convert << "label:#{text}"
124
136
  convert.rotate rotation
125
137
  convert.trim.repage.+
126
- convert.bordercolor('transparent').border("#{gap}%")
127
138
  convert << image
128
139
  end
129
140
  if options[:file]
@@ -150,19 +161,20 @@ module Libis
150
161
  assemble_and_convert(source, target, format)
151
162
 
152
163
  elsif File.directory?(source)
153
- source_list = Dir[File.join(source, '**', '*')].reject { |p| File.directory? p }
164
+ source_list = Dir[File.join(source, '**', '*')].reject {|p| File.directory? p}
154
165
 
155
166
  assemble_and_convert(source_list, target, format)
156
167
 
157
168
  else
158
169
 
159
- image = MiniMagick::Image.new(source)
170
+ image = MiniMagick::Image.new(source) { |b| b.quiet }
160
171
 
161
172
  if image.pages.size > 1
162
173
  if @page
163
174
  convert_image(image.pages[@page].path, target, format)
164
175
  else
165
- assemble_and_convert(image.pages.map { |page| page.path }, target, format)
176
+ # noinspection RubyBlockToMethodReference
177
+ assemble_and_convert(image.pages.map {|page| page.path}, target, format)
166
178
  end
167
179
  else
168
180
  convert_image(source, target, format)
@@ -177,13 +189,14 @@ module Libis
177
189
 
178
190
  warn 'Received multiple images as input and single page format as target.' unless self.class.multipage?(format)
179
191
  converted_pages = sources.inject([]) do |list, path|
192
+ # noinspection RubyArgCount
180
193
  converted = Tempfile.new(['page-', ".#{Libis::Format::TypeDatabase.type_extentions(format).first}"])
181
194
  convert_image(path, converted.path, format)
182
195
  list << converted
183
196
  end
184
197
  MiniMagick::Tool::Convert.new do |b|
185
198
  b.append unless self.class.multipage?(format)
186
- converted_pages.each { |page| b << page.path }
199
+ converted_pages.each {|page| b << page.path}
187
200
  b << target
188
201
  end
189
202
  converted_pages.each do |temp_file|
@@ -197,29 +210,37 @@ module Libis
197
210
  def convert_image(source, target, format)
198
211
 
199
212
  image_info = nil
200
- image_info = MiniMagick::Image::Info.new(source) if @wm_image
213
+ image_info = MiniMagick::Image::Info.new(source) {|b| b.quiet} if @wm_image
201
214
 
202
215
  MiniMagick::Tool::Convert.new do |convert|
216
+ convert.quiet if @quiet
203
217
  if @wm_image
204
218
  convert << @wm_image.path
219
+ convert.bordercolor('transparent').border("#{@wm_gap}%") if @wm_gap > 0
205
220
  convert.filter('Lagrange')
206
- convert.resize("#{image_info['width'] / @wm_size}x#{image_info['height'] / @wm_size}").write('mpr:watermark').delete.+
221
+ convert.resize("#{image_info['width'] / @wm_tiles}x#{image_info['height'] / @wm_tiles}") if @wm_tiles > 0
222
+ convert.resize("#{@wm_resize}%") if @wm_resize
223
+ convert.write('mpr:watermark').delete.+
207
224
  end
208
225
 
226
+ convert.quiet if @quiet
209
227
  convert << source
210
- convert.flatten if format == :JPG
228
+ convert.flatten if @options[:flatten].nil? && format == :JPG
211
229
  if @wm_image
212
- # noinspection RubyResolve
213
- convert.stack do |stack|
214
- stack.size("#{image_info['width']}x#{image_info['height']}")
215
- stack << 'xc:transparent'
216
- stack.tile('mpr:watermark')
217
- stack.draw "rectangle 0,0,#{image_info['width']},#{image_info['height']}"
230
+ if @wm_tiles >= 0 and @wm_tiles <= 1
231
+ convert << 'mpr:watermark'
232
+ else
233
+ convert.stack do |stack|
234
+ stack.size("#{image_info['width']}x#{image_info['height']}")
235
+ stack << 'xc:transparent'
236
+ stack.tile('mpr:watermark')
237
+ stack.draw "rectangle 0,0,#{image_info['width']},#{image_info['height']}"
238
+ end
218
239
  end
219
- convert.compose(@wm_composition).define("compose:args=#{@wm_opacity}").composite
240
+ convert.compose(@wm_composition).gravity(@wm_gravity).define("compose:args=#{@wm_opacity}%").composite
220
241
  end
221
242
 
222
- @flags.each { |f, v| v.is_a?(FalseClass) ? convert.send(f).+ : convert.send(f) }
243
+ @flags.each {|f, v| v.is_a?(TrueClass) ? convert.send(f).+ : convert.send(f)}
223
244
  if @delete_date
224
245
  convert << '+set' << 'modify-date' << '+set' << 'create-date'
225
246
  end
@@ -227,13 +248,15 @@ module Libis
227
248
  colorspace = @options.delete(:colorspace) || 'sRGB'
228
249
  unless @options.empty?
229
250
  convert.colorspace('RGB')
230
- @options.each { |o, v| convert.send(o, v) }
251
+ @options.each {|o, v| convert.send(o, v)}
231
252
  end
232
253
  convert.colorspace(colorspace)
233
254
  convert.profile @profile if @profile
234
255
 
235
256
  convert.format(format)
236
257
  convert << target
258
+
259
+ debug "ImageMagick command: '#{convert.command.join(' ')}'"
237
260
  end
238
261
 
239
262
  target
@@ -42,10 +42,10 @@ module Libis
42
42
 
43
43
  def get(file, options = {})
44
44
 
45
- options[:droid] = true unless options.keys.include?(:droid) and options[:tool] and options[:tool] != :droid
46
- options[:fido] = true unless options.keys.include?(:fido) and options[:tool] and options[:tool] != :fido
47
- options[:file] = true unless options.keys.include?(:file) and options[:tool] and options[:tool] != :file
48
- options[:xml_validation] = true unless options.keys.include?(:xml_validation) and !options[:xml_validation]
45
+ options[:droid] = true unless options.keys.include?(:droid) or (options[:tool] and options[:tool] != :droid)
46
+ options[:fido] = true unless options.keys.include?(:fido) or (options[:tool] and options[:tool] != :fido)
47
+ options[:file] = true unless options.keys.include?(:file) or (options[:tool] and options[:tool] != :file)
48
+ options[:xml_validation] = true if options[:xml_validation].nil?
49
49
 
50
50
  result = {messages: [], output: {}, formats: {}}
51
51
 
@@ -1,23 +1,18 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'singleton'
4
3
  require 'yaml'
5
4
 
6
5
  require 'backports/rails/hash'
7
- require 'libis/tools/logger'
8
- require 'libis/tools/extend/string'
9
-
10
- require_relative 'config'
11
6
 
12
7
  module Libis
13
8
  module Format
14
9
 
10
+ # noinspection RubyClassVariableUsageInspection
15
11
  class TypeDatabase
16
- include Singleton
17
- include ::Libis::Tools::Logger
12
+ @implementation = Libis::Format::TypeDatabaseImpl.instance
18
13
 
19
- def self.typeinfo(t)
20
- self.instance.types[t.to_sym] || {}
14
+ def self.implementation(impl)
15
+ @implementation = impl
21
16
  end
22
17
 
23
18
  def self.enrich(info, map_keys = {})
@@ -34,7 +29,7 @@ module Libis
34
29
  mapper.keys.each do |key|
35
30
  info[mapper[key]] = get(type_name, key) || info[mapper[key]]
36
31
  end
37
- info[mapper[:GROUP]] = self.type_group(type_name)
32
+ info[mapper[:GROUP]] = type_group(type_name)
38
33
  end
39
34
  info
40
35
  end
@@ -44,14 +39,14 @@ module Libis
44
39
  mapper = Hash.new {|hash,key| hash[key] = key}
45
40
  mapper.merge! map_keys
46
41
  unless (puid = info[mapper[:PUID]]).blank?
47
- info[mapper[:TYPE]] ||= self.puid_infos(puid).first[:TYPE] rescue nil
42
+ info[mapper[:TYPE]] ||= puid_infos(puid).first[:TYPE] rescue nil
48
43
  end
49
44
  unless (mime = info[mapper[:MIME]]).blank?
50
- info[mapper[:TYPE]] ||= self.mime_infos(mime).first[:TYPE] rescue nil
45
+ info[mapper[:TYPE]] ||= mime_infos(mime).first[:TYPE] rescue nil
51
46
  end
52
47
  unless (type_name = info[mapper[:TYPE]]).nil?
53
- info[mapper[:MIME]] = self.type_mimetypes(type_name).first if self.type_mimetypes(type_name).first
54
- info[mapper[:GROUP]] = self.type_group(type_name)
48
+ info[mapper[:MIME]] = type_mimetypes(type_name).first if type_mimetypes(type_name).first
49
+ info[mapper[:GROUP]] = type_group(type_name)
55
50
  end
56
51
  info
57
52
  end
@@ -65,7 +60,7 @@ module Libis
65
60
  when :EXTENSION
66
61
  type_extentions(type_name).first
67
62
  else
68
- self.typeinfo(type_name)[key]
63
+ typeinfo(type_name)[key]
69
64
  end
70
65
  end
71
66
 
@@ -85,114 +80,52 @@ module Libis
85
80
  typeinfo(t)[:EXTENSIONS] || []
86
81
  end
87
82
 
83
+ def self.typeinfo(t)
84
+ @implementation.typeinfo(t)
85
+ end
86
+
88
87
  def self.group_types(group)
89
- self.instance.types.select do |_, v|
90
- v[:GROUP] == group.to_sym
91
- end.keys
88
+ @implementation.group_types(group)
92
89
  end
93
90
 
94
91
  def self.puid_infos(puid)
95
- self.instance.types.select do |_, v|
96
- v[:PUID].include? puid rescue false
97
- end.values
92
+ @implementation.puid_infos(puid)
98
93
  end
99
94
 
100
95
  def self.puid_types(puid)
101
- self.instance.types.select do |_, v|
102
- v[:PUID].include? puid rescue false
103
- end.keys
96
+ @implementation.puid_types(puid)
104
97
  end
105
98
 
106
99
  def self.puid_groups(puid)
107
- puid_types(puid).map do |t|
108
- type_group t
109
- end
100
+ puid_types(puid).map(&method(:type_group))
110
101
  end
111
102
 
112
103
  def self.mime_infos(mime)
113
- self.instance.types.select do |_, v|
114
- v[:MIME].include? mime rescue false
115
- end.values
104
+ @implementation.mime_infos(mime)
116
105
  end
117
106
 
118
107
  def self.mime_types(mime)
119
- self.instance.types.select do |_, v|
120
- v[:MIME].include? mime rescue false
121
- end.keys
108
+ @implementation.mime_types(mime)
122
109
  end
123
110
 
124
111
  def self.mime_groups(mime)
125
- mime_types(mime).map do |t|
126
- type_group t
127
- end
112
+ mime_types(mime).map(&method(:type_group))
128
113
  end
129
114
 
130
115
  def self.ext_infos(ext)
131
- ext = ext.gsub /^\./, ''
132
- self.instance.types.select do |_, v|
133
- v[:EXTENSIONS].include?(ext) rescue false
134
- end.values
116
+ @implementation.ext_infos(ext)
135
117
  end
136
118
 
137
119
  def self.ext_types(ext)
138
- ext = ext.gsub /^\./, ''
139
- self.instance.types.select do |_, v|
140
- v[:EXTENSIONS].include?(ext) rescue false
141
- end.keys
120
+ @implementation.ext_types(ext)
142
121
  end
143
122
 
144
123
  def self.puid_typeinfo(puid)
145
- self.instance.types.each do |_, v|
146
- return v if v[:PUID] and v[:PUID].include?(puid)
147
- end
148
- nil
124
+ @implementation.puid_typeinfo(puid)
149
125
  end
150
126
 
151
127
  def self.known_mime?(mime)
152
- self.instance.types.each do |_, v|
153
- return true if v[:MIME].include? mime
154
- end
155
- false
156
- end
157
-
158
- attr_reader :types
159
-
160
- def load_types(file_or_hash = {}, append = true)
161
- hash = file_or_hash.is_a?(Hash) ? file_or_hash : YAML::load_file(file_or_hash)
162
- # noinspection RubyResolve
163
- hash.each do |group, type_info|
164
- type_info.each do |type_name, info|
165
- type_key = type_name.to_sym
166
- info.symbolize_keys!
167
- info[:TYPE] = type_key
168
- info[:GROUP] = group.to_sym
169
- info[:MIME] = info[:MIME].strip.split(/[\s,]+/).map { |v| v.strip } rescue []
170
- info[:EXTENSIONS] = info[:EXTENSIONS].strip.split(/[\s,]+/).map { |v| v.strip } rescue []
171
- info[:PUID] = info[:PUID].strip.split(/[\s,]+/).map { |v| v.strip } if info[:PUID]
172
- if @types.has_key?(type_key)
173
- warn 'Type %s already defined; merging with info from %s.', type_name.to_s, file_or_hash
174
- info.merge!(@types[type_key]) do |_,v_new,v_old|
175
- case v_old
176
- when Array
177
- append ? v_old + v_new : v_new + v_old
178
- when Hash
179
- append ? v_new.merge(v_old) : v_old.merge(v_new)
180
- else
181
- append ? v_old : v_new
182
- end
183
- end
184
- end
185
- @types[type_key] = info
186
- end
187
- end
188
- end
189
-
190
- protected
191
-
192
- def initialize
193
- @types = Hash.new
194
- type_database = Libis::Format::Config[:type_database]
195
- load_types(type_database)
128
+ @implementation.known_mime?(mime)
196
129
  end
197
130
 
198
131
  end
@@ -0,0 +1,120 @@
1
+ # coding: utf-8
2
+
3
+ require 'singleton'
4
+ require 'yaml'
5
+
6
+ require 'backports/rails/hash'
7
+ require 'libis/tools/logger'
8
+ require 'libis/tools/extend/string'
9
+
10
+ module Libis
11
+ module Format
12
+
13
+ class TypeDatabaseImpl
14
+ include Singleton
15
+ include ::Libis::Tools::Logger
16
+
17
+ def typeinfo(t)
18
+ @types[t.to_sym] || {}
19
+ end
20
+
21
+ def group_types(group)
22
+ @types.select do |_, v|
23
+ v[:GROUP] == group.to_sym
24
+ end.keys
25
+ end
26
+
27
+ def puid_infos(puid)
28
+ @types.select do |_, v|
29
+ v[:PUID].include? puid rescue false
30
+ end.values
31
+ end
32
+
33
+ def puid_types(puid)
34
+ @types.select do |_, v|
35
+ v[:PUID].include? puid rescue false
36
+ end.keys
37
+ end
38
+
39
+ def mime_infos(mime)
40
+ @types.select do |_, v|
41
+ v[:MIME].include? mime rescue false
42
+ end.values
43
+ end
44
+
45
+ def mime_types(mime)
46
+ @types.select do |_, v|
47
+ v[:MIME].include? mime rescue false
48
+ end.keys
49
+ end
50
+
51
+ def ext_infos(ext)
52
+ ext = ext.gsub /^\./, ''
53
+ @types.select do |_, v|
54
+ v[:EXTENSIONS].include?(ext) rescue false
55
+ end.values
56
+ end
57
+
58
+ def ext_types(ext)
59
+ ext = ext.gsub /^\./, ''
60
+ @types.select do |_, v|
61
+ v[:EXTENSIONS].include?(ext) rescue false
62
+ end.keys
63
+ end
64
+
65
+ def puid_typeinfo(puid)
66
+ @types.each do |_, v|
67
+ return v if v[:PUID] and v[:PUID].include?(puid)
68
+ end
69
+ nil
70
+ end
71
+
72
+ def known_mime?(mime)
73
+ @types.each do |_, v|
74
+ return true if v[:MIME].include? mime
75
+ end
76
+ false
77
+ end
78
+
79
+ def load_types(file_or_hash = {}, append = true)
80
+ hash = file_or_hash.is_a?(Hash) ? file_or_hash : YAML::load_file(file_or_hash)
81
+ # noinspection RubyResolve
82
+ hash.each do |group, type_info|
83
+ type_info.each do |type_name, info|
84
+ type_key = type_name.to_sym
85
+ info.symbolize_keys!
86
+ info[:TYPE] = type_key
87
+ info[:GROUP] = group.to_sym
88
+ info[:MIME] = info[:MIME].strip.split(/[\s,]+/).map(&:strip) rescue []
89
+ info[:EXTENSIONS] = info[:EXTENSIONS].strip.split(/[\s,]+/).map { |v| v.strip } rescue []
90
+ info[:PUID] = info[:PUID].strip.split(/[\s,]+/).map { |v| v.strip } if info[:PUID]
91
+ if @types.has_key?(type_key)
92
+ warn 'Type %s already defined; merging with info from %s.', type_name.to_s, file_or_hash
93
+ info.merge!(@types[type_key]) do |_,v_new,v_old|
94
+ case v_old
95
+ when Array
96
+ append ? v_old + v_new : v_new + v_old
97
+ when Hash
98
+ append ? v_new.merge(v_old) : v_old.merge(v_new)
99
+ else
100
+ append ? v_old : v_new
101
+ end
102
+ end
103
+ end
104
+ @types[type_key] = info
105
+ end
106
+ end
107
+ end
108
+
109
+ protected
110
+
111
+ def initialize
112
+ @types = Hash.new
113
+ type_database = Libis::Format::Config[:type_database]
114
+ load_types(type_database)
115
+ end
116
+
117
+ end
118
+
119
+ end
120
+ end
@@ -1,5 +1,5 @@
1
1
  module Libis
2
2
  module Format
3
- VERSION = '1.0.2'
3
+ VERSION = '1.0.4'
4
4
  end
5
5
  end
@@ -22,7 +22,6 @@ Gem::Specification.new do |spec|
22
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.6'
26
25
  spec.add_development_dependency 'rake', '~> 10.3'
27
26
  spec.add_development_dependency 'rspec', '~> 3.1'
28
27
  spec.add_development_dependency 'awesome_print'
Binary file
Binary file
Binary file
@@ -12,7 +12,7 @@ formatlist =
12
12
  'test.odt' => {mimetype: 'application/vnd.oasis.opendocument.text', puid: 'fmt/291'},
13
13
  'test.doc' => {mimetype: 'application/msword', puid: 'fmt/40'},
14
14
  'test.docx' => {mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', puid: 'fmt/412'},
15
- 'test.pdf' => {mimetype: 'application/pdf', puid: 'fmt/18'},
15
+ 'test.pdf' => {mimetype: 'application/pdf', puid: 'fmt/276'},
16
16
  'test.rtf' => {mimetype: 'application/rtf', puid: 'fmt/45'},
17
17
  'test.txt' => {mimetype: 'text/plain', puid: 'x-fmt/111'},
18
18
  'test.ods' => {mimetype: 'application/vnd.oasis.opendocument.spreadsheet', puid: 'fmt/295'},
@@ -42,7 +42,7 @@ fidolist =
42
42
  'test.odt' => {mimetype: 'application/vnd.oasis.opendocument.text', puid: 'fmt/290'},
43
43
  'test.doc' => {mimetype: nil, puid: 'fmt/111'},
44
44
  'test.docx' => {mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', puid: 'fmt/412'},
45
- 'test.pdf' => {mimetype: 'application/pdf', puid: 'fmt/18'},
45
+ 'test.pdf' => {mimetype: 'application/pdf', puid: 'fmt/276'},
46
46
  'test.rtf' => {mimetype: 'application/rtf', puid: 'fmt/45'},
47
47
  'test.txt' => {mimetype: 'text/plain', puid: 'x-fmt/111'},
48
48
  'test.ods' => {mimetype: 'application/vnd.oasis.opendocument.spreadsheet', puid: 'fmt/294'},
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  describe 'Type Databse' do
5
5
 
6
6
  before :all do
7
- ::Libis::Format::TypeDatabase.instance.load_types File.join(File.dirname(__FILE__), 'test_types.yml')
7
+ ::Libis::Format::TypeDatabaseImpl.instance.load_types File.join(File.dirname(__FILE__), 'test_types.yml')
8
8
  end
9
9
 
10
10
  it 'should load types from file' do
@@ -93,7 +93,7 @@ describe 'Type Databse' do
93
93
 
94
94
  it 'should load types from hash' do
95
95
 
96
- ::Libis::Format::TypeDatabase.instance.load_types TESTMEDIUM: {
96
+ ::Libis::Format::TypeDatabaseImpl.instance.load_types TESTMEDIUM: {
97
97
  TESTREPORT: {
98
98
  NAME: 'Test report format',
99
99
  MIME: 'test/report application/test/report',
@@ -111,7 +111,7 @@ describe 'Type Databse' do
111
111
 
112
112
  it 'should merge types from hash' do
113
113
 
114
- ::Libis::Format::TypeDatabase.instance.load_types TESTMEDIUM: {
114
+ ::Libis::Format::TypeDatabaseImpl.instance.load_types TESTMEDIUM: {
115
115
  TESTREPORT: {
116
116
  EXTENSIONS: 'rpt'
117
117
  }
@@ -123,7 +123,7 @@ describe 'Type Databse' do
123
123
  MIME: %w'test/report application/test/report',
124
124
  EXTENSIONS: %w'rep rpt'
125
125
 
126
- ::Libis::Format::TypeDatabase.instance.load_types({TESTMEDIUM: {
126
+ ::Libis::Format::TypeDatabaseImpl.instance.load_types({TESTMEDIUM: {
127
127
  TESTREPORT: {
128
128
  EXTENSIONS: 'report'
129
129
  }
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libis-format
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kris Dekeyser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-15 00:00:00.000000000 Z
11
+ date: 2019-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.6'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.6'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -186,6 +172,7 @@ executables:
186
172
  - droid
187
173
  - fido
188
174
  - formatinfo
175
+ - libis_format
189
176
  - pdf_copy
190
177
  extensions: []
191
178
  extra_rdoc_files: []
@@ -200,6 +187,7 @@ files:
200
187
  - bin/droid
201
188
  - bin/fido
202
189
  - bin/formatinfo
190
+ - bin/libis_format
203
191
  - bin/pdf_copy
204
192
  - data/ISOcoated_v2_eci.icc
205
193
  - data/PDFA_def.ps
@@ -210,6 +198,11 @@ files:
210
198
  - data/xlink.xsd
211
199
  - lib/libis-format.rb
212
200
  - lib/libis/format.rb
201
+ - lib/libis/format/cli/convert.rb
202
+ - lib/libis/format/cli/format.rb
203
+ - lib/libis/format/cli/prompt_helper.rb
204
+ - lib/libis/format/cli/sub_command.rb
205
+ - lib/libis/format/command_line.rb
213
206
  - lib/libis/format/config.rb
214
207
  - lib/libis/format/converter.rb
215
208
  - lib/libis/format/converter/audio_converter.rb
@@ -242,6 +235,7 @@ files:
242
235
  - lib/libis/format/tool/pdfa_validator.rb
243
236
  - lib/libis/format/tool/spreadsheet_to_ods.rb
244
237
  - lib/libis/format/type_database.rb
238
+ - lib/libis/format/type_database_impl.rb
245
239
  - lib/libis/format/version.rb
246
240
  - libis-format.gemspec
247
241
  - spec/converter_audio_spec.rb