epub_tools 0.3.1 → 0.4.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +41 -0
  4. data/Gemfile +13 -9
  5. data/Gemfile.lock +49 -0
  6. data/README.md +16 -0
  7. data/bin/epub-tools +3 -109
  8. data/epub_tools.gemspec +6 -8
  9. data/lib/epub_tools/add_chapters.rb +41 -19
  10. data/lib/epub_tools/cli/command_registry.rb +47 -0
  11. data/lib/epub_tools/cli/option_builder.rb +164 -0
  12. data/lib/epub_tools/cli/runner.rb +164 -0
  13. data/lib/epub_tools/cli.rb +45 -0
  14. data/lib/epub_tools/compile_book.rb +60 -28
  15. data/lib/epub_tools/epub_initializer.rb +38 -28
  16. data/lib/epub_tools/loggable.rb +11 -0
  17. data/lib/epub_tools/pack_ebook.rb +18 -12
  18. data/lib/epub_tools/split_chapters.rb +31 -21
  19. data/lib/epub_tools/{text_style_class_finder.rb → style_finder.rb} +21 -17
  20. data/lib/epub_tools/unpack_ebook.rb +17 -12
  21. data/lib/epub_tools/version.rb +1 -1
  22. data/lib/epub_tools/xhtml_cleaner.rb +17 -13
  23. data/lib/epub_tools/xhtml_extractor.rb +20 -11
  24. data/lib/epub_tools.rb +2 -1
  25. data/test/add_chapters_test.rb +12 -5
  26. data/test/cli/command_registry_test.rb +66 -0
  27. data/test/cli/option_builder_test.rb +173 -0
  28. data/test/cli/runner_test.rb +91 -0
  29. data/test/cli_commands_test.rb +100 -0
  30. data/test/cli_test.rb +4 -0
  31. data/test/cli_version_test.rb +5 -3
  32. data/test/compile_book_test.rb +11 -2
  33. data/test/epub_initializer_test.rb +51 -31
  34. data/test/pack_ebook_test.rb +14 -8
  35. data/test/split_chapters_test.rb +22 -1
  36. data/test/{text_style_class_finder_test.rb → style_finder_test.rb} +7 -6
  37. data/test/test_helper.rb +4 -5
  38. data/test/unpack_ebook_test.rb +21 -5
  39. data/test/xhtml_cleaner_test.rb +13 -7
  40. data/test/xhtml_extractor_test.rb +17 -1
  41. metadata +19 -36
  42. data/lib/epub_tools/cli_helper.rb +0 -31
@@ -0,0 +1,164 @@
1
+ require_relative 'command_registry'
2
+ require_relative 'option_builder'
3
+
4
+ module EpubTools
5
+ module CLI
6
+ # Main runner for the CLI application
7
+ class Runner
8
+ attr_reader :registry, :program_name
9
+
10
+ # Initialize a new CLI Runner
11
+ # @param program_name [String] Name of the program
12
+ def initialize(program_name = nil)
13
+ @registry = CommandRegistry.new
14
+ @program_name = program_name || File.basename($PROGRAM_NAME)
15
+ end
16
+
17
+ # Run the CLI application
18
+ # @param args [Array<String>] Command line arguments
19
+ # @return [Boolean] true if the command was run successfully
20
+ def run(args = ARGV)
21
+ # Handle global version flag
22
+ if ['-v', '--version'].include?(args[0])
23
+ puts EpubTools::VERSION
24
+ exit 0
25
+ end
26
+
27
+ commands = registry.available_commands
28
+
29
+ if args.empty? || !commands.include?(args[0])
30
+ print_usage(commands)
31
+ exit 1
32
+ end
33
+
34
+ cmd = args.shift
35
+ handle_command(cmd, args)
36
+ end
37
+
38
+ # Handle a specific command
39
+ # @param cmd [String] Command name
40
+ # @param args [Array<String>] Command line arguments
41
+ # @return [Boolean] true if the command was run successfully
42
+ def handle_command(cmd, args = ARGV)
43
+ command_config = registry.get(cmd)
44
+ return false unless command_config
45
+
46
+ options = command_config[:default_options].dup
47
+ required_keys = command_config[:required_keys]
48
+
49
+ builder = OptionBuilder.new(options, required_keys)
50
+ .with_banner("Usage: #{program_name} #{cmd} [options]")
51
+ .with_help_option
52
+
53
+ # Configure command-specific options
54
+ configure_command_options(cmd, builder)
55
+
56
+ # Parse arguments and run the command
57
+ options = builder.parse(args)
58
+ command_class = command_config[:class]
59
+ command_class.new(options).run
60
+ true
61
+ end
62
+
63
+ private
64
+
65
+ # Print usage information
66
+ # @param commands [Array<String>] Available commands
67
+ def print_usage(_commands)
68
+ puts <<~USAGE
69
+ Usage: #{program_name} COMMAND [options]
70
+ Commands:
71
+ init Initialize a bare-bones EPUB
72
+ extract Extract XHTML files from EPUBs
73
+ split Split XHTML into separate XHTMLs per chapter
74
+ add Add chapter XHTML files into an EPUB
75
+ pack Package an EPUB directory into a .epub file
76
+ unpack Unpack an EPUB file into a directory
77
+ compile Takes EPUBs in a dir and splits, cleans, and compiles into a single EPUB.
78
+ USAGE
79
+ end
80
+
81
+ # Configure command-specific options
82
+ # @param cmd [String] Command name
83
+ # @param builder [OptionBuilder] Option builder instance
84
+ def configure_command_options(cmd, builder)
85
+ case cmd
86
+ when 'add'
87
+ builder.with_custom_options do |opts, options|
88
+ opts.on('-c DIR', '--chapters-dir DIR', 'Chapters directory (required)') { |v| options[:chapters_dir] = v }
89
+ opts.on('-e DIR', '--epub-oebps-dir DIR', 'EPUB OEBPS directory (required)') do |v|
90
+ options[:epub_oebps_dir] = v
91
+ end
92
+ end
93
+
94
+ when 'extract'
95
+ builder.with_custom_options do |opts, options|
96
+ opts.on('-s DIR', '--source-dir DIR', 'Directory with EPUBs to extract XHTMLs from (required)') do |v|
97
+ options[:source_dir] = v
98
+ end
99
+ opts.on('-t DIR', '--target-dir DIR',
100
+ 'Directory where the XHTML files will be extracted to (required)') do |v|
101
+ options[:target_dir] = v
102
+ end
103
+ end
104
+ .with_verbose_option
105
+
106
+ when 'split'
107
+ builder.with_custom_options do |opts, options|
108
+ opts.on('-i FILE', '--input FILE', 'Source XHTML file (required)') { |v| options[:input_file] = v }
109
+ opts.on('-t TITLE', '--title TITLE', 'Book title for HTML <title> tags (required)') do |v|
110
+ options[:book_title] = v
111
+ end
112
+ opts.on('-o DIR', '--output-dir DIR',
113
+ "Output directory for chapter files (default: #{options[:output_dir]})") do |v|
114
+ options[:output_dir] = v
115
+ end
116
+ opts.on('-p PREFIX', '--prefix PREFIX',
117
+ "Filename prefix for chapters (default: #{options[:prefix]})") do |v|
118
+ options[:prefix] = v
119
+ end
120
+ end
121
+ .with_verbose_option
122
+
123
+ when 'init'
124
+ builder.with_title_option
125
+ .with_author_option
126
+ .with_custom_options do |opts, options|
127
+ opts.on('-o DIR', '--output-dir DIR', 'Destination EPUB directory (required)') do |v|
128
+ options[:destination] = v
129
+ end
130
+ end
131
+ .with_cover_option
132
+
133
+ when 'pack'
134
+ builder.with_input_dir('EPUB directory to package')
135
+ .with_output_file('Output EPUB file path')
136
+ .with_verbose_option
137
+
138
+ when 'unpack'
139
+ builder.with_custom_options do |opts, options|
140
+ opts.on('-i FILE', '--input-file FILE', 'EPUB file to unpack (required)') { |v| options[:epub_file] = v }
141
+ opts.on('-o DIR', '--output-dir DIR', 'Output directory to extract into (default: basename of epub)') do |v|
142
+ options[:output_dir] = v
143
+ end
144
+ end
145
+ .with_verbose_option
146
+
147
+ when 'compile'
148
+ builder.with_title_option
149
+ .with_author_option
150
+ .with_custom_options do |opts, options|
151
+ opts.on('-s DIR', '--source-dir DIR', 'Directory with EPUBs to extract XHTMLs from (required)') do |v|
152
+ options[:source_dir] = v
153
+ end
154
+ opts.on('-o FILE', '--output FILE', 'EPUB to create (default: book title in source dir)') do |v|
155
+ options[:output_file] = v
156
+ end
157
+ end
158
+ .with_cover_option
159
+ .with_verbose_option
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,45 @@
1
+ require_relative 'cli/command_registry'
2
+ require_relative 'cli/option_builder'
3
+ require_relative 'cli/runner'
4
+
5
+ module EpubTools
6
+ # CLI module - houses the object-oriented command line interface components
7
+ module CLI
8
+ # Create a new Runner instance configured with all available commands
9
+ # @param program_name [String] Name of the program
10
+ # @return [CLI::Runner] A configured runner instance
11
+ def self.create_runner(program_name = nil)
12
+ runner = Runner.new(program_name)
13
+
14
+ # Register all commands
15
+ runner.registry.register('add', EpubTools::AddChapters,
16
+ %i[chapters_dir epub_oebps_dir])
17
+
18
+ runner.registry.register('extract', EpubTools::XHTMLExtractor,
19
+ %i[source_dir target_dir],
20
+ { verbose: true })
21
+
22
+ runner.registry.register('split', EpubTools::SplitChapters,
23
+ %i[input_file book_title],
24
+ { output_dir: './chapters', prefix: 'chapter', verbose: true })
25
+
26
+ runner.registry.register('init', EpubTools::EpubInitializer,
27
+ %i[title author destination],
28
+ { verbose: true })
29
+
30
+ runner.registry.register('pack', EpubTools::PackEbook,
31
+ %i[input_dir output_file],
32
+ { verbose: true })
33
+
34
+ runner.registry.register('unpack', EpubTools::UnpackEbook,
35
+ [:epub_file],
36
+ { verbose: true })
37
+
38
+ runner.registry.register('compile', EpubTools::CompileBook,
39
+ %i[title author source_dir],
40
+ { verbose: true })
41
+
42
+ runner
43
+ end
44
+ end
45
+ end
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'fileutils'
3
+ require_relative 'loggable'
3
4
  require_relative 'xhtml_extractor'
4
5
  require_relative 'split_chapters'
5
6
  require_relative 'epub_initializer'
@@ -9,6 +10,7 @@ require_relative 'pack_ebook'
9
10
  module EpubTools
10
11
  # Orchestrates extraction, splitting, validation, and packaging of book EPUBs
11
12
  class CompileBook
13
+ include Loggable
12
14
  # Book title
13
15
  attr_reader :title
14
16
  # Book author
@@ -25,14 +27,22 @@ module EpubTools
25
27
  attr_reader :verbose
26
28
 
27
29
  # Initializes the class
28
- def initialize(title:, author:, source_dir:, cover_image: nil, output_file: nil, build_dir: nil, verbose: false)
29
- @title = title
30
- @author = author
31
- @source_dir = source_dir
32
- @cover_image = cover_image
33
- @output_file = output_file || default_output_file
34
- @build_dir = build_dir || File.join(Dir.pwd, '.epub_tools_build')
35
- @verbose = verbose
30
+ # @param options [Hash] Configuration options
31
+ # @option options [String] :title Book title (required)
32
+ # @option options [String] :author Book author (required)
33
+ # @option options [String] :source_dir Path of the input epubs (required)
34
+ # @option options [String] :cover_image Optional path to the cover image
35
+ # @option options [String] :output_file Filename for the final epub (default: [title].epub)
36
+ # @option options [String] :build_dir Optional working directory for intermediate files
37
+ # @option options [Boolean] :verbose Whether to print progress to STDOUT (default: false)
38
+ def initialize(options = {})
39
+ @title = options.fetch(:title)
40
+ @author = options.fetch(:author)
41
+ @source_dir = options.fetch(:source_dir)
42
+ @cover_image = options[:cover_image]
43
+ @output_file = options[:output_file] || default_output_file
44
+ @build_dir = options[:build_dir] || File.join(Dir.pwd, '.epub_tools_build')
45
+ @verbose = options[:verbose] || false
36
46
  end
37
47
 
38
48
  # Run the full compile workflow
@@ -51,10 +61,6 @@ module EpubTools
51
61
 
52
62
  private
53
63
 
54
- def log(message)
55
- puts message if verbose
56
- end
57
-
58
64
  def default_output_file
59
65
  "#{title.gsub(' ', '_')}.epub"
60
66
  end
@@ -65,7 +71,7 @@ module EpubTools
65
71
  end
66
72
 
67
73
  def prepare_dirs
68
- log "Preparing build directories..."
74
+ log 'Preparing build directories...'
69
75
  FileUtils.mkdir_p(xhtml_dir)
70
76
  FileUtils.mkdir_p(chapters_dir)
71
77
  end
@@ -84,52 +90,78 @@ module EpubTools
84
90
 
85
91
  def extract_xhtmls
86
92
  log "Extracting XHTML files from epubs in '#{source_dir}'..."
87
- XHTMLExtractor.new(source_dir: source_dir, target_dir: xhtml_dir, verbose: verbose).extract_all
93
+ XHTMLExtractor.new({
94
+ source_dir: source_dir,
95
+ target_dir: xhtml_dir,
96
+ verbose: verbose
97
+ }).run
88
98
  end
89
99
 
90
100
  def split_xhtmls
91
- log "Splitting XHTML files into chapters..."
101
+ log 'Splitting XHTML files into chapters...'
92
102
  Dir.glob(File.join(xhtml_dir, '*.xhtml')).each do |xhtml_file|
93
103
  base = File.basename(xhtml_file, '.xhtml')
94
104
  log "Splitting '#{base}'..."
95
- SplitChapters.new(xhtml_file, title, chapters_dir, 'chapter', verbose).run
105
+ SplitChapters.new({
106
+ input_file: xhtml_file,
107
+ book_title: title,
108
+ output_dir: chapters_dir,
109
+ output_prefix: 'chapter',
110
+ verbose: verbose
111
+ }).run
96
112
  end
97
113
  end
98
114
 
99
115
  def validate_sequence
100
- log "Validating chapter sequence..."
116
+ log 'Validating chapter sequence...'
101
117
  nums = Dir.glob(File.join(chapters_dir, '*.xhtml')).map do |file|
102
118
  if (m = File.basename(file, '.xhtml').match(/_(\d+)\z/))
103
119
  m[1].to_i
104
120
  end
105
121
  end.compact
106
122
  raise "No chapter files found in #{chapters_dir}" if nums.empty?
123
+
107
124
  sorted = nums.sort.uniq
108
125
  missing = (sorted.first..sorted.last).to_a - sorted
109
- if missing.any?
110
- raise "Missing chapter numbers: #{missing.join(' ')}"
111
- else
112
- log "Chapter sequence is complete: #{sorted.first} to #{sorted.last}."
113
- end
126
+ raise "Missing chapter numbers: #{missing.join(' ')}" if missing.any?
127
+
128
+ log "Chapter sequence is complete: #{sorted.first} to #{sorted.last}."
114
129
  end
115
130
 
116
131
  def initialize_epub
117
- log "Initializing new EPUB..."
132
+ log 'Initializing new EPUB...'
118
133
  if cover_image
119
- EpubInitializer.new(title, author, epub_dir, cover_image).run
134
+ EpubInitializer.new({
135
+ title: title,
136
+ author: author,
137
+ destination: epub_dir,
138
+ cover_image: cover_image
139
+ }).run
120
140
  else
121
- EpubInitializer.new(title, author, epub_dir).run
141
+ EpubInitializer.new({
142
+ title: title,
143
+ author: author,
144
+ destination: epub_dir
145
+ }).run
122
146
  end
123
147
  end
124
148
 
125
149
  def add_chapters
126
- log "Adding chapters to EPUB..."
127
- AddChapters.new(chapters_dir, File.join(epub_dir, 'OEBPS'), verbose).run
150
+ log 'Adding chapters to EPUB...'
151
+ AddChapters.new({
152
+ chapters_dir: chapters_dir,
153
+ epub_dir: File.join(epub_dir, 'OEBPS'),
154
+ verbose: verbose
155
+ }).run
128
156
  end
129
157
 
130
158
  def pack_epub
131
159
  log "Building final EPUB '#{output_file}'..."
132
- PackEbook.new(epub_dir, output_file, verbose: verbose).run
160
+ PackEbook.new({
161
+ input_dir: epub_dir,
162
+ output_file: output_file,
163
+ verbose: verbose
164
+ }).run
133
165
  end
134
166
  end
135
167
  end
@@ -2,6 +2,7 @@
2
2
  require 'fileutils'
3
3
  require 'time'
4
4
  require 'securerandom'
5
+ require_relative 'loggable'
5
6
 
6
7
  module EpubTools
7
8
  # Sets up a basic empty EPUB directory structure with the basic files created:
@@ -13,19 +14,24 @@ module EpubTools
13
14
  # - +style.css+ a basic style inherited from the repo
14
15
  # - cover image (optionally)
15
16
  class EpubInitializer
16
- # [title] Book title
17
- # [author] Book Author
18
- # [destination] Target directory
19
- # [cover_image] Optional image path to use as a cover for the book
20
- def initialize(title, author, destination, cover_image = nil)
21
- @title = title
22
- @author = author
23
- @destination = File.expand_path(destination)
17
+ include Loggable
18
+ # Initializes the class
19
+ # @param options [Hash] Configuration options
20
+ # @option options [String] :title Book title (required)
21
+ # @option options [String] :author Book author (required)
22
+ # @option options [String] :destination Target directory for the EPUB files (required)
23
+ # @option options [String] :cover_image Optional path to the cover image
24
+ # @option options [Boolean] :verbose Whether to print progress to STDOUT (default: false)
25
+ def initialize(options = {})
26
+ @title = options.fetch(:title)
27
+ @author = options.fetch(:author)
28
+ @destination = File.expand_path(options.fetch(:destination))
24
29
  @uuid = "urn:uuid:#{SecureRandom.uuid}"
25
30
  @modified = Time.now.utc.iso8601
26
- @cover_image_path = cover_image
31
+ @cover_image_path = options[:cover_image]
27
32
  @cover_image_fname = nil
28
33
  @cover_image_media_type = nil
34
+ @verbose = options[:verbose] || false
29
35
  end
30
36
 
31
37
  # Creates the empty ebook and returns the directory
@@ -38,6 +44,7 @@ module EpubTools
38
44
  write_package_opf
39
45
  write_nav
40
46
  write_style
47
+ log "Created empty ebook structure at: #{@destination}"
41
48
  @destination
42
49
  end
43
50
 
@@ -49,7 +56,7 @@ module EpubTools
49
56
  end
50
57
 
51
58
  def write_mimetype
52
- File.write("#{@destination}/mimetype", "application/epub+zip")
59
+ File.write("#{@destination}/mimetype", 'application/epub+zip')
53
60
  end
54
61
 
55
62
  def write_title_page
@@ -126,36 +133,39 @@ module EpubTools
126
133
  File.write(File.join(@destination, 'OEBPS', 'cover.xhtml'), content)
127
134
  end
128
135
 
136
+ def mitem(id, href, type, properties = nil)
137
+ xml = "<item id=\"#{id}\" href=\"#{href}\" media-type=\"#{type}\""
138
+ xml += " properties=\"#{properties}\"" if properties
139
+ "#{xml}/>"
140
+ end
141
+
129
142
  # Generates the package.opf with optional cover image entries
130
143
  def write_package_opf
131
144
  manifest_items = []
132
145
  spine_items = []
133
-
134
- manifest_items << '<item id="style" href="style.css" media-type="text/css"/>'
135
- manifest_items << '<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>'
146
+ manifest_items << mitem('style', 'style.css', 'text/css')
147
+ manifest_items << mitem('nav', 'nav.xhtml', 'application/xhtml+xml', 'nav')
136
148
 
137
149
  if @cover_image_fname
138
- manifest_items << %Q{<item id="cover-image" href="#{@cover_image_fname}" media-type="#{@cover_image_media_type}" properties="cover-image"/>}
139
- manifest_items << '<item id="cover-page" href="cover.xhtml" media-type="application/xhtml+xml"/>'
150
+ manifest_items << mitem('cover-image', @cover_image_fname, @cover_image_media_type, 'cover-image')
151
+ manifest_items << mitem('cover-page', 'cover.xhtml', 'application/xhtml+xml')
140
152
  spine_items << '<itemref idref="cover-page"/>'
141
153
  end
142
154
 
143
- manifest_items << '<item id="title" href="title.xhtml" media-type="application/xhtml+xml"/>'
155
+ manifest_items << mitem('title', 'title.xhtml', 'application/xhtml+xml')
144
156
  spine_items << '<itemref idref="title"/>'
145
157
 
146
158
  metadata = []
147
- metadata << %Q{<dc:identifier id="pub-id">#{@uuid}</dc:identifier>}
148
- metadata << %Q{<dc:title>#{@title}</dc:title>}
149
- metadata << %Q{<dc:creator>#{@author}</dc:creator>}
150
- metadata << "<dc:language>en</dc:language>"
151
- metadata << %Q{<meta property="dcterms:modified">#{@modified}</meta>}
152
- metadata << %Q{<meta property="schema:accessMode">textual</meta>}
153
- metadata << %Q{<meta property="schema:accessibilityFeature">unknown</meta>}
154
- metadata << %Q{<meta property="schema:accessibilityHazard">none</meta>}
155
- metadata << %Q{<meta property="schema:accessModeSufficient">textual</meta>}
156
- if @cover_image_fname
157
- metadata << %Q{<meta name="cover" content="cover-image"/>}
158
- end
159
+ metadata << %(<dc:identifier id="pub-id">#{@uuid}</dc:identifier>)
160
+ metadata << %(<dc:title>#{@title}</dc:title>)
161
+ metadata << %(<dc:creator>#{@author}</dc:creator>)
162
+ metadata << '<dc:language>en</dc:language>'
163
+ metadata << %(<meta property="dcterms:modified">#{@modified}</meta>)
164
+ metadata << %(<meta property="schema:accessMode">textual</meta>)
165
+ metadata << %(<meta property="schema:accessibilityFeature">unknown</meta>)
166
+ metadata << %(<meta property="schema:accessibilityHazard">none</meta>)
167
+ metadata << %(<meta property="schema:accessModeSufficient">textual</meta>)
168
+ metadata << %(<meta name="cover" content="cover-image"/>) if @cover_image_fname
159
169
 
160
170
  content = <<~XML
161
171
  <?xml version="1.0" encoding="utf-8"?>
@@ -0,0 +1,11 @@
1
+ module EpubTools
2
+ # Provides logging capability to classes that include it
3
+ module Loggable
4
+ # Logs a message if verbose mode is enabled
5
+ # @param message [String] The message to log
6
+ # @return [nil]
7
+ def log(message)
8
+ puts message if @verbose
9
+ end
10
+ end
11
+ end
@@ -1,21 +1,27 @@
1
1
  require 'zip'
2
2
  require 'fileutils'
3
3
  require 'pathname'
4
+ require_relative 'loggable'
4
5
 
5
6
  module EpubTools
6
7
  # Packages an EPUB directory into a .epub file
7
8
  class PackEbook
8
- # [input_dir] Path to the EPUB directory (containing mimetype, META-INF, OEBPS)
9
- # [output_file] Path to resulting .epub file; if +nil+, defaults to <tt><input_dir>.epub</tt>
10
- def initialize(input_dir, output_file = nil, verbose: false)
11
- @input_dir = File.expand_path(input_dir)
9
+ include Loggable
10
+ # Initializes the class
11
+ # @param options [Hash] Configuration options
12
+ # @option options [String] :input_dir Path to the EPUB directory (containing mimetype, META-INF, OEBPS) (required)
13
+ # @option options [String] :output_file Path to resulting .epub file (default: <input_dir>.epub)
14
+ # @option options [Boolean] :verbose Whether to print progress to STDOUT (default: false)
15
+ def initialize(options = {})
16
+ @input_dir = File.expand_path(options.fetch(:input_dir))
12
17
  default_name = "#{File.basename(@input_dir)}.epub"
18
+ output_file = options[:output_file]
13
19
  @output_file = if output_file.nil? || output_file.empty?
14
20
  default_name
15
21
  else
16
22
  output_file
17
23
  end
18
- @verbose = verbose
24
+ @verbose = options[:verbose] || false
19
25
  end
20
26
 
21
27
  # Runs the packaging process and returns the resulting file path
@@ -33,24 +39,24 @@ module EpubTools
33
39
  Dir.glob('**/*', File::FNM_DOTMATCH).sort.each do |entry|
34
40
  next if ['.', '..', 'mimetype'].include?(entry)
35
41
  next if File.directory?(entry)
42
+
36
43
  zip.add(entry, entry)
37
44
  end
38
45
  end
39
46
  end
40
- puts "EPUB created: #{@output_file}" if @verbose
47
+ log "EPUB created: #{@output_file}"
41
48
  @output_file
42
49
  end
43
50
 
44
51
  private
45
52
 
46
53
  def validate_input!
47
- unless Dir.exist?(@input_dir)
48
- raise ArgumentError, "Directory '#{@input_dir}' does not exist."
49
- end
54
+ raise ArgumentError, "Directory '#{@input_dir}' does not exist." unless Dir.exist?(@input_dir)
55
+
50
56
  mimetype = File.join(@input_dir, 'mimetype')
51
- unless File.file?(mimetype)
52
- raise ArgumentError, "Error: 'mimetype' file missing in #{@input_dir}"
53
- end
57
+ return if File.file?(mimetype)
58
+
59
+ raise ArgumentError, "Error: 'mimetype' file missing in #{@input_dir}"
54
60
  end
55
61
 
56
62
  def add_mimetype(zip)