epubforge 0.0.5 → 0.0.6

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
@@ -15,7 +15,7 @@ module EpubForge
15
15
 
16
16
  @template_dir = EpubForge.root.join( "templates", @template_to_use )
17
17
  src_entries = @template_dir.glob( "**", "*" ).map{ |entry|
18
- entry.relative_to( @template_dir )
18
+ entry.relative_path_from( @template_dir )
19
19
  }
20
20
 
21
21
  self.source_paths.push( @template_dir )
@@ -74,7 +74,7 @@ module EpubForge
74
74
  configure_git( opts[:git] || {} )
75
75
  end
76
76
  else
77
- say_in_warning("The program 'git' must be installed and locatable if you want epubforge to back up your project.")
77
+ warn("The program 'git' must be installed and locatable if you want epubforge to back up your project.")
78
78
  end
79
79
  end
80
80
 
@@ -121,7 +121,6 @@ module EpubForge
121
121
  end
122
122
 
123
123
  self.destination_root_filepath = root.fwf_filepath
124
- debugger if self.destination_root_filepath != root.fwf_filepath.expand
125
124
 
126
125
  if self.destination_root_filepath.exist? &&
127
126
  (!(self.destination_root_filepath.empty?) || !(self.destination_root_filepath.directory?))
@@ -4,6 +4,7 @@ module EpubForge
4
4
  description "Create a .mobi book and try to push it to your Kindle (conversion requires Calibre)"
5
5
  keywords :kindle, :push, :b2k
6
6
  usage "#{$PROGRAM_NAME} b2k <project_directory>"
7
+ # requires_executable "ebook-convert"
7
8
 
8
9
  # TODO: Hard-coded. Need a global settings file?
9
10
  KINDLE_DEVICE_DIR = "/".fwf_filepath.join( "Volumes", "Kindle" )
@@ -15,7 +16,6 @@ module EpubForge
15
16
  @src_epub = @project.filename_for_epub_book.fwf_filepath
16
17
  @dst_mobi = @project.filename_for_mobi_book.fwf_filepath
17
18
 
18
- mobify
19
19
  end
20
20
 
21
21
  protected
@@ -31,8 +31,8 @@ module EpubForge
31
31
  say_all_is_well "Formatted for Kindle (.mobi file). File at #{@dst_mobi}."
32
32
  push_to_device @dst_mobi
33
33
  else
34
- say_warning( "Something went wrong during the conversion process." )
35
- say_warning( "#{@dst_mobi} exists, but may not be complete or correct." ) if @dst_mobi.exist?
34
+ warn( "Something went wrong during the conversion process." )
35
+ warn( "#{@dst_mobi} exists, but may not be complete or correct." ) if @dst_mobi.exist?
36
36
  false
37
37
  end
38
38
  end
@@ -0,0 +1,69 @@
1
+ module EpubForge
2
+ module Action
3
+ class Mobify < ThorAction
4
+ description "Create a .mobi book and try to push it to your Kindle (conversion requires Calibre)"
5
+ keywords :mobify
6
+ usage "#{$PROGRAM_NAME} mobify <project_directory(optional)>"
7
+ # requires_executable "ebook-convert", "ebook-convert is included as part of the Calibre ebook management software."
8
+
9
+ desc( "do:kindle", "Turn your .epub file into a .mobi file. Check to see if your Kindle is connected, then pushes it." )
10
+ def do( project, *args )
11
+ @project = project
12
+ @src_epub = @project.filename_for_epub_book.fwf_filepath
13
+ @dst_mobi = @project.filename_for_mobi_book.fwf_filepath
14
+
15
+ @args = args
16
+
17
+ mobify
18
+
19
+
20
+ end
21
+
22
+ protected
23
+ def mobify
24
+ return false unless fulfill_requirements
25
+
26
+ say "converting from #{@src_epub} to #{@dst_mobi}"
27
+ cmd = "ebook-convert #{@src_epub} #{@dst_mobi}"
28
+ say "executing: #{cmd}"
29
+ `#{cmd}`
30
+
31
+ if $?.success? && @dst_mobi.exist?
32
+ say_all_is_well "Formatted for Kindle (.mobi file). File at #{@dst_mobi}."
33
+ push_to_device @dst_mobi
34
+ else
35
+ warn( "Something went wrong during the conversion process." )
36
+ warn( "#{@dst_mobi} exists, but may not be complete or correct." ) if @dst_mobi.exist?
37
+ false
38
+ end
39
+ end
40
+
41
+ def push_to_device mobi_file
42
+ if KINDLE_DEVICE_DIR.directory? && KINDLE_PUSH_DIR.directory?
43
+ FileUtils.copy( mobi_file, KINDLE_PUSH_DIR )
44
+ say_all_is_well "File pushed to Kindle."
45
+ true
46
+ else
47
+ say_error "NOT installed on Kindle. It may not be plugged in."
48
+ false
49
+ end
50
+ end
51
+
52
+ def fulfill_requirements
53
+ unless ebook_convert_installed?
54
+ say_error( "ebook-convert is not installed. Quitting." )
55
+ return false
56
+ end
57
+
58
+ BookToEpub.new.do( @project )
59
+
60
+ unless @src_epub.exist?
61
+ say_error( "Cannot find source .epub #{src_epub}" )
62
+ return false
63
+ end
64
+
65
+ true
66
+ end
67
+ end
68
+ end
69
+ end
data/config/htmlizers.rb CHANGED
@@ -1,3 +1,11 @@
1
+ EpubForge::Utils::Htmlizer.define do |html|
2
+ html.format :xhtml
3
+ html.group :default
4
+ html.executable "false"
5
+ html.cmd "cat {{f}}"
6
+ end
7
+
8
+
1
9
  EpubForge::Utils::Htmlizer.define do |html|
2
10
  html.format :markdown
3
11
  html.group :default # the default is :user, so user-defined ones don't have to set it
@@ -1,11 +1,13 @@
1
1
  module EpubForge
2
2
  module Action
3
3
  class RunDescription
4
- attr_accessor :args
5
- attr_accessor :project
6
- attr_accessor :keyword
7
- attr_accessor :klass
8
- attr_accessor :errors
4
+ attr_accessor :args,
5
+ :project,
6
+ :keyword,
7
+ :klass,
8
+ :errors,
9
+ :state,
10
+ :execution_returned
9
11
 
10
12
  def initialize
11
13
  @args = nil
@@ -13,10 +15,58 @@ module EpubForge
13
15
  @keyword = nil
14
16
  @klass = nil
15
17
  @errors = []
18
+ @state = :initialized
16
19
  end
20
+
21
+ def run
22
+ if self.runnable?
23
+ handle_errors do
24
+ @execution_returned = self.klass.new.do( self.project, *(self.args) )
25
+ end
26
+ else
27
+ puts "Error(s) trying to complete the requested action:"
28
+ puts self.errors.join("\n")
29
+ end
30
+
31
+ self.finish
32
+ self
33
+ end
34
+
35
+ def handle_errors &block
36
+ yield
37
+ rescue Exception => e
38
+ @errors << "#{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
39
+ self
40
+ end
41
+
17
42
 
18
43
  def runnable?
19
- @errors.epf_blank?
44
+ ! errors?
45
+ end
46
+
47
+ def errors?
48
+ !@errors.epf_blank?
49
+ end
50
+
51
+ def success?
52
+ finished? && ! errors?
53
+ end
54
+
55
+ def finished?
56
+ @state == :finished
57
+ end
58
+
59
+ def finish
60
+ @state = :finished
61
+ end
62
+
63
+ def to_s
64
+ str = "RunDescription:\n"
65
+ [ :args, :project, :keyword, :klass, :errors, :state ].each do |data|
66
+ str << "#{data} : #{self.send(data)}\n"
67
+ end
68
+
69
+ str
20
70
  end
21
71
  end
22
72
  end
data/lib/action/runner.rb CHANGED
@@ -17,12 +17,9 @@ module EpubForge
17
17
  end
18
18
 
19
19
  def run
20
- if @run_description.runnable?
21
- @run_description.klass.new.do( @run_description.project, *(@run_description.args) )
22
- else
23
- puts "Error(s) trying to complete the requested action:"
24
- puts @run_description.errors.join("\n")
25
- end
20
+ @run_description.run
21
+ puts @run_description
22
+ @run_description
26
23
  end
27
24
 
28
25
  # order: project_dir(optional), keyword, args
@@ -36,9 +33,6 @@ module EpubForge
36
33
  # print help message if no keywords given
37
34
  parse_args
38
35
 
39
- # finish setting up run_description
40
- @run_description.args = @args
41
-
42
36
  run
43
37
  end
44
38
 
@@ -86,6 +80,8 @@ module EpubForge
86
80
 
87
81
  if !existing_project && @run_description.klass.project_required?
88
82
  @run_description.errors << "Could not find a project directory, but the action #{@run_description.klass} requires one. Current directory is not an epubforge project."
83
+ else
84
+ @run_description.args = @args
89
85
  end
90
86
  end
91
87
 
@@ -40,6 +40,9 @@ module EpubForge
40
40
  include Thor::Actions
41
41
  extend SharedActionInterface
42
42
 
43
+ method_option :verbose, :type => :boolean, :default => false, :aliases => "-v"
44
+ method_option :debug, :type => :boolean, :default => false, :aliases => "--dbg"
45
+
43
46
 
44
47
  CLEAR = Thor::Shell::Color::CLEAR
45
48
  RED = Thor::Shell::Color::RED
@@ -52,6 +55,14 @@ module EpubForge
52
55
 
53
56
 
54
57
  protected
58
+ def say_when_verbose( *args )
59
+ say( *args ) if @verbose
60
+ end
61
+
62
+ def say_when_debugging( *args )
63
+ say( *args ) if @debug
64
+ end
65
+
55
66
  def say_error( statement )
56
67
  say( "ERROR : #{statement}", RED + ON_BLUE )
57
68
  end
@@ -64,10 +75,6 @@ module EpubForge
64
75
  say( statement, GREEN )
65
76
  end
66
77
 
67
- def say_in_warning( statement )
68
- warn( statement, RED )
69
- end
70
-
71
78
  def say_subtly( statement )
72
79
  say( statement, MAGENTA )
73
80
  end
@@ -133,6 +140,27 @@ module EpubForge
133
140
  @executables[name]
134
141
  end
135
142
 
143
+ def requirements
144
+ @requirements ||= []
145
+ end
146
+
147
+ def add_requirement( *args, &block )
148
+ @requirements ||= []
149
+ @requirements.push( [args, block] )
150
+ end
151
+
152
+ def requires_executable( ex, fail_msg )
153
+ add_requirement( ex, fail_msg ) do
154
+ executable_installed?( ex, fail_msg )
155
+ end
156
+ end
157
+
158
+ def must_target_a_project( project_dir )
159
+ add_requirement( project_dir ) do
160
+ Project.is_project_dir?( project_dir )
161
+ end
162
+ end
163
+
136
164
  def git_installed?
137
165
  executable_installed?('git')
138
166
  end
@@ -1,24 +1,4 @@
1
1
  module Kernel
2
- # def puts_nowhere( &block )
3
- # collect_stdout( "/dev/null", &block )
4
- # end
5
- #
6
- # def collect_stdout( dest, &block )
7
- # @puts_nowhere_keep_old_stdout ||= []
8
- # @puts_nowhere_keep_old_stdout << $stdout
9
- # if dest.is_a?(String)
10
- # $stdout = File.open( dest, "w" )
11
- # else
12
- # $stdout = dest
13
- # end
14
- #
15
- # $stdout.sync = true
16
- #
17
- # yield
18
- #
19
- # $stdout = @puts_nowhere_keep_old_stdout.pop
20
- # end
21
-
22
2
  # yields an alternate reality block where instance methods
23
3
  # are different from what they were. At the end of the block
24
4
  # it resets the initial values of the instance variables.
@@ -27,33 +27,34 @@ module EpubForge
27
27
  end
28
28
 
29
29
  def collect_stdout( dest = StringIO.new, &block )
30
- raise ArgumentError.new("No block given.") unless block_given?
31
-
32
- prior_stdout = $stdout
33
- # @epf_prior_stdout_stack ||= []
34
- # @epf_prior_stdout_stack << $stdout
35
-
36
- $stdout = begin
37
- if dest.is_a?( String ) || dest.is_a?( Pathname )
38
- File.open( dest, "a" )
39
- elsif dest.is_a?( IO ) || dest.is_a?( StringIO )
40
- dest
41
- else
42
- raise ArgumentError.new("collect_stdout cannot take a <#{dest.class.name}> as an argument.")
43
- end
44
- end
45
-
46
- $stdout.sync = true
47
- yield
48
-
49
- $stdout = prior_stdout
50
-
51
- dest.is_a?( StringIO ) ? dest.string : nil
52
- end
53
- #
54
- # def collect_stdout( *args, &block )
55
- # yield
56
- # end
30
+ raise ArgumentError.new("No block given.") unless block_given?
31
+
32
+ prior_stdout = $stdout
33
+ # @epf_prior_stdout_stack ||= []
34
+ # @epf_prior_stdout_stack << $stdout
35
+
36
+ $stdout = begin
37
+ if dest.is_a?( String ) || dest.is_a?( Pathname )
38
+ File.open( dest, "a" )
39
+ elsif dest.is_a?( IO ) || dest.is_a?( StringIO )
40
+ dest
41
+ else
42
+ raise ArgumentError.new("collect_stdout cannot take a <#{dest.class.name}> as an argument.")
43
+ end
44
+ end
45
+
46
+ $stdout.sync = true
47
+ yield
48
+
49
+ $stdout = prior_stdout
50
+
51
+ dest.is_a?( StringIO ) ? dest.string : nil
52
+ end
53
+
54
+ # def collect_stdout( *args, &block )
55
+ # yield
56
+ # ""
57
+ # end
57
58
  end
58
59
  end
59
60
 
@@ -5,12 +5,11 @@ module EpubForge
5
5
  attr_reader :ext, :filename, :name
6
6
  def initialize( filename, options = {} )
7
7
  @filename = filename.fwf_filepath
8
- @name = @filename.basename.to_s.split(".")[0..-2].join(".")
9
- @ext = @filename.extname.gsub( /^\./, "" )
8
+ @name, @ext = @filename.basename_and_ext
10
9
  end
11
10
 
12
11
  def link
13
- IMAGES_DIR.join( @name )
12
+ IMAGES_DIR.join( "#{@name}.#{@ext}" )
14
13
  end
15
14
  end
16
15
  end
@@ -2,30 +2,57 @@ module EpubForge
2
2
  module Epub
3
3
  module Assets
4
4
  class Page < Asset
5
- attr_reader :html, :original_file, :title, :project, :media_type, :dest_extension
6
- attr_accessor :section_id, :section_number
5
+ attr_reader :html, :original_file, :title, :project, :media_type, :dest_extension, :dest_filename
6
+ attr_reader :section_id
7
7
 
8
8
  def initialize file, metadata, project
9
9
  raise "NIL" if project.nil?
10
+
11
+ @original_file = file.fwf_filepath
10
12
 
11
13
  @metadata = metadata
12
14
  @project = project
13
- @original_file = file
14
15
  @dest_extension = "xhtml"
16
+ @section_id = @original_file.basename_no_ext
17
+ @dest_filename = "#{@section_id}.#{@dest_extension}"
15
18
 
16
- @html = Utils::Htmlizer.instance.translate( file )
17
- @title = File.basename( file ).split(".")[0..-2].map(&:capitalize).join(" : ")
19
+ get_html
20
+ get_title
21
+
18
22
  @content = ""
23
+ @cover = false
19
24
  puts "Initialized #{file} with title [#{@title}]"
20
25
  end
21
26
 
27
+ def get_html
28
+ @html = Utils::Htmlizer.instance.translate( @original_file )
29
+ end
30
+
31
+ def get_title
32
+ @title = @original_file.basename.to_s.split(".")[0..-2].map(&:capitalize).join(" : ")
33
+ end
34
+
22
35
  def link
23
- TEXT_DIR.join( "section#{ sprintf("%04i", @section_number) }.#{@dest_extension}" )
36
+ TEXT_DIR.join( "#{@section_id}.#{@dest_extension}" )
24
37
  end
25
38
 
26
39
  def media_type
27
40
  MEDIA_TYPES[@dest_extension]
28
41
  end
42
+
43
+ def cover( val = nil )
44
+ unless val.nil?
45
+ @cover = val
46
+ end
47
+ @cover
48
+ end
49
+
50
+ def cover_asset( val = nil )
51
+ unless val.nil?
52
+ @cover = val
53
+ end
54
+ @cover
55
+ end
29
56
  end
30
57
  end
31
58
  end
@@ -0,0 +1,8 @@
1
+ module EpubForge
2
+ module Epub
3
+ module Assets
4
+ class XHTML < Page
5
+ end
6
+ end
7
+ end
8
+ end
data/lib/epub/builder.rb CHANGED
@@ -3,7 +3,7 @@ XmlBuilder = Builder
3
3
 
4
4
  module EpubForge
5
5
  module Epub
6
- PAGE_FILE_EXTENSIONS = %w(html markdown textile)
6
+ PAGE_FILE_EXTENSIONS = %w(html markdown textile xhtml)
7
7
  IMAGE_FILE_EXTENSIONS = %w(jpg png gif)
8
8
 
9
9
  MEDIA_TYPES = { "gif" => "image/gif", "jpg" => "image/jpeg", "png" => "image/png",
@@ -26,12 +26,12 @@ module EpubForge
26
26
  @book_dir = @project.target_dir.join( @book_dir_short ).fwf_filepath
27
27
  @config = @project.config
28
28
 
29
- @config["page_orderer"] = Utils::FileOrderer.new( opts[:page_order] || @config["pages"][@book_dir_short] )
29
+ @config.page_orderer = Utils::FileOrderer.new( opts[:page_order] || @config.pages[@book_dir_short] )
30
30
 
31
- @metadata = @config["metadata"] || {}
31
+ @metadata = @config.metadata || {}
32
32
 
33
33
  page_files = @book_dir.glob( ext: PAGE_FILE_EXTENSIONS )
34
- @section_files = @config["page_orderer"].reorder( page_files )
34
+ @section_files = @config.page_orderer.reorder( page_files )
35
35
 
36
36
  @sections = @section_files.map do |section|
37
37
  case section.to_s.split(".").last
@@ -41,21 +41,42 @@ module EpubForge
41
41
  Assets::HTML.new( section, @metadata, self )
42
42
  when "textile"
43
43
  Assets::Textile.new( section, @metadata, self )
44
+ when "xhtml"
45
+ Assets::XHTML.new( section, @metadata, self ) # These files are inserted into the book unaltered
44
46
  else
45
47
  raise "UNKNOWN EXTENSION TYPE"
46
48
  end
47
49
  end
48
50
 
49
- @sections.each_with_index{ |sec, i| sec.section_number = i }
51
+ # @sections.each_with_index{ |sec, i| sec.section_number = i }
50
52
 
51
53
  images = @book_dir.glob( "images", ext: IMAGE_FILE_EXTENSIONS )
52
54
  @images = images.map{ |img| Assets::Image.new(img) }
53
-
55
+
54
56
  @stylesheets = @book_dir.glob( "stylesheets", "*.css" ).map do |sheet|
55
57
  Assets::Stylesheet.new( sheet )
56
58
  end
57
59
 
58
- @scratch_dir = Dir.mktmpdir.fwf_filepath.join( "ebookdir" )
60
+ install_cover
61
+
62
+ @scratch_dir = FunWith::Files::FilePath.tmpdir.join( "ebookdir" )
63
+ end
64
+
65
+ def install_cover
66
+ # Existing cover is moved to the very front
67
+ if cover_section = @sections.detect{|sec| sec.original_file.basename_no_ext.match( /^cover$/ ) }
68
+ cover_section.cover( true )
69
+ elsif cover_image = @images.find{ |img| img.name == "cover" }
70
+ # actually install cover
71
+ contents = "<div id='cover'><img class='cover' src='#{cover_image.link.relative_path_from(TEXT_DIR)}' alt='#{@metadata.name}, by #{@metadata.author}'/></div>"
72
+ cover_file = @project.book_dir.join( "cover.xhtml" )
73
+ cover_file.write( wrap_page( contents ) )
74
+ cover_section = Assets::Page.new( cover_file, @metadata, @project )
75
+ @sections.unshift( cover_section )
76
+ puts "cover page generated"
77
+ else
78
+ return false
79
+ end
59
80
  end
60
81
 
61
82
  def toc
@@ -76,6 +97,7 @@ module EpubForge
76
97
  b.meta :name => "dtb:depth", :content => "1"
77
98
  b.meta :name => "dtb:totalPageCount", :content => "0"
78
99
  b.meta :name => "dtb:maxPageNumber", :content=> "0"
100
+
79
101
  end
80
102
 
81
103
  # <docTitle>
@@ -98,7 +120,7 @@ module EpubForge
98
120
  b.navLabel do
99
121
  b.text section.title
100
122
  end
101
- b.content :src => section.link
123
+ b.content :src => section.link.relative_path_from( "/OEBPS" )
102
124
  end
103
125
  end
104
126
  end
@@ -157,6 +179,11 @@ module EpubForge
157
179
  b.dc :publisher, @metadata["publisher"] || "A Pack of Orangutans"
158
180
  b.dc :date, {:"opf:event" => "original-publication"}, @metadata["original-publication"] || Time.now.year
159
181
  b.dc :date, {:"opf:event" => "epub-publication"}, @metadata["epub-publication"] || Time.now.year
182
+
183
+
184
+ if @sections.first.cover
185
+ b.meta :name => "cover", :content => @sections.first.cover
186
+ end
160
187
  end
161
188
 
162
189
  # <manifest>
@@ -165,22 +192,22 @@ module EpubForge
165
192
  b.item :id => "ncx", :href => "toc.ncx", :"media-type" => "application/x-dtbncx+xml"
166
193
 
167
194
  @sections.each_with_index do |section, i|
168
- b.item :id => section.link, :href => section.link, :"media-type" => section.media_type
195
+ b.item :id => section.link.basename, :href => section.link.relative_path_from("/OEBPS"), :"media-type" => section.media_type
169
196
  end
170
197
 
171
198
  @images.each do |image|
172
- b.item :id => image.name, :href => image.link, :"media-type" => image.media_type
199
+ b.item :id => image.filename.basename, :href => image.link.relative_path_from("/OEBPS"), :"media-type" => image.media_type
173
200
  end
174
201
 
175
202
  @stylesheets.each do |sheet|
176
- b.item :id => sheet.name, :href => sheet.link, :"media-type" => sheet.media_type
203
+ b.item :id => sheet.name, :href => sheet.link.relative_path_from("/OEBPS"), :"media-type" => sheet.media_type
177
204
  end
178
205
  end
179
206
 
180
207
  # <spine toc="ncx">
181
208
  b.spine :toc => "ncx" do
182
- @sections.each_with_index do |section, i|
183
- b.itemref :idref => "section#{sprintf("%04i",i)}.xhtml"
209
+ @sections.each do |section|
210
+ b.itemref :idref => section.dest_filename
184
211
  end
185
212
  end
186
213
 
@@ -196,7 +223,7 @@ module EpubForge
196
223
 
197
224
  b.target!.to_s
198
225
  end
199
-
226
+
200
227
  # zips up contents
201
228
  def build
202
229
  Utils::DirectoryBuilder.create( @scratch_dir ) do |build|
@@ -212,8 +239,10 @@ module EpubForge
212
239
  build.file( "content.opf", content_opf )
213
240
 
214
241
  build.dir( "Text" ) do
215
- @sections.each_with_index do |section, i|
216
- build.file( "section#{sprintf("%04i",i)}.xhtml", wrap_page( section.html ) )
242
+ @sections.each do |section|
243
+ build.file( section.dest_filename,
244
+ section.is_a?( Assets::XHTML ) ? section.html : wrap_page( section.html )
245
+ )
217
246
  end
218
247
  end
219
248
 
@@ -245,7 +274,7 @@ module EpubForge
245
274
  end
246
275
 
247
276
  protected
248
- def wrap_page content
277
+ def wrap_page content = ""
249
278
  b = XmlBuilder::XmlMarkup.new( :indent => 2)
250
279
  b.instruct! :xml, :encoding => "utf-8", :standalone => "no"
251
280
  b.declare! :DOCTYPE, :html, :PUBLIC, "-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
@@ -254,7 +283,7 @@ module EpubForge
254
283
  b.head do
255
284
  b.title( @metadata["name"] )
256
285
  for sheet in @stylesheets
257
- b.link :href => sheet.link, :media => "screen", :rel => "stylesheet", :type => "text/css"
286
+ b.link :href => sheet.link.relative_path_from("/OEBPS/Text"), :media => "screen", :rel => "stylesheet", :type => "text/css"
258
287
  end
259
288
  end
260
289
 
data/lib/epubforge.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  # require 'singleton'
5
5
  # require 'builder'
6
6
  require 'thor'
7
+ require 'optparse'
7
8
  require 'xdg' # keep configuration files in sane places
8
9
  require 'debugger'
9
10
  require 'erb'
@@ -15,7 +16,6 @@ require 'net/http'
15
16
  require 'open-uri' # needed by Utils::Downloader
16
17
  require 'yaml'
17
18
  require 'rbconfig'
18
- # require 'configurator'
19
19
  require 'fun_with_files'
20
20
  require 'fun_with_configurations'
21
21
 
@@ -90,6 +90,7 @@ require_relative 'epub/assets/markdown'
90
90
  require_relative 'epub/assets/textile'
91
91
  require_relative 'epub/assets/image'
92
92
  require_relative 'epub/assets/stylesheet'
93
+ require_relative 'epub/assets/xhtml'
93
94
  require_relative 'project/project'
94
95
 
95
96
  puts "Requirements loaded" if debugging?
@@ -73,8 +73,7 @@ module EpubForge
73
73
  self.require_me( entry )
74
74
  end
75
75
  else
76
- puts "Warning: Could not find file #{loadable} to load htmlizers from."
77
- raise "AAAH"
76
+ puts "Warning: Could not find file #{loadable} to load classes from."
78
77
  end
79
78
  end
80
79
  end
@@ -5,7 +5,7 @@ module EpubForge
5
5
  # by matching the filenames against one regex after another. Allows you to say,
6
6
  # "I want the title page, the foreward, then all the chapters, then all the appendixes, then the afterword."
7
7
  # Ex: FileOrderer( ["title_page", "forward", "chapter-.*", "afterword", "appendix.*" ).reorder( pages )
8
- # Only compares the basename minus extension. Files should come from the same directory
8
+ # Only compares the basename minus extension. Files should come from the same directory. cover.extension always comes first.
9
9
  class FileOrderer
10
10
  def initialize( matchers )
11
11
  @matchers = matchers.map do |m|
@@ -17,26 +17,26 @@ module EpubForge
17
17
  end
18
18
  end
19
19
 
20
+ @matchers.unshift( /^cover$/ )
20
21
  @matchers.push( /^.*$/ )
21
22
  end
22
23
 
23
24
  def reorder( files )
24
25
  files = files.map(&:fwf_filepath)
25
26
 
26
- files.sort_by!{ |f|
27
- f.basename_no_ext.to_s
28
- }
29
-
30
-
31
27
  ordered_files = @matchers.inject( [] ) do |collector, matcher|
32
28
  matched_files = files.select do |f|
33
29
  name = f.basename_no_ext.to_s
34
30
  matcher.match( name )
35
31
  end
36
-
37
- collector += matched_files
32
+
33
+ matched_files.sort_by! do |filename|
34
+ filename.basename_no_ext.to_s
35
+ end
36
+
37
+ collector += matched_files.sort
38
38
  files -= matched_files
39
-
39
+
40
40
  collector
41
41
  end
42
42
  end
@@ -129,7 +129,7 @@ module EpubForge
129
129
  self.basename.to_s.split(".").last || ""
130
130
  end
131
131
 
132
- def relative_to( ancestor_dir )
132
+ def relative_path_from( ancestor_dir )
133
133
  depth = ancestor_dir.to_s.split(File::SEPARATOR).length
134
134
  relative_path = self.to_s.split(File::SEPARATOR)
135
135
  relative_path[(depth)..-1].join(File::SEPARATOR).fwf_filepath
@@ -74,7 +74,7 @@ module EpubForge
74
74
  def translate( filename, opts = "" )
75
75
  return false unless can_do_job?( filename )
76
76
 
77
- result = "<!-- generated from #{@format} by htmlizer #{@name} -->\n\n"
77
+ result = ""
78
78
  if @custom_proc
79
79
  result += @custom_proc.call( filename, *opts )
80
80
  elsif @cmd
@@ -88,6 +88,7 @@ module EpubForge
88
88
  return false
89
89
  end
90
90
 
91
+ result += "\n\n<!-- generated from #{@format} by htmlizer #{@name} -->\n"
91
92
  result
92
93
  end
93
94
 
@@ -81,7 +81,7 @@ module EpubForge
81
81
  end
82
82
 
83
83
  def self.format_from_filename( filename )
84
- ext = filename.fwf_filepath.extname.gsub(/^\./, "")
84
+ ext = filename.fwf_filepath.ext
85
85
  ext.epf_blank? ? :unknown : ext.to_sym
86
86
  end
87
87
  end
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="no"?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
3
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4
+
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title></title>
8
+ </head>
9
+
10
+ <body>
11
+ <p><img class="cover" alt="The Improbable Rise of Singularity Girl, by Bryce Anderson" src="../Images/cover.jpg" /></p>
12
+ </body>
13
+ </html>
@@ -42,7 +42,7 @@ FunWith::Configurations::Config.new do
42
42
  # chapter_summary that comes after, you might want to define the matcher more
43
43
  # specifically, for example 'chapter-\d+' (chapter followed by dash followed by any number of numbers).
44
44
  #
45
- "chapter-*",
45
+ "chapter-.*",
46
46
  "afterword"
47
47
  ]
48
48
 
@@ -7,7 +7,7 @@ class TestEpubforge < Test::Unit::TestCase #
7
7
  printout = EpubForge.collect_stdout do
8
8
  EpubForge::Action::Runner.new.exec # empty args, should append --help
9
9
  end
10
-
10
+
11
11
  assert_match /\( wc \| count \)/, printout
12
12
  assert_match /epubforge \[action\] \[folder\]/, printout
13
13
  end
@@ -27,10 +27,10 @@ class TestEpubforge < Test::Unit::TestCase #
27
27
  should "successfully count ALL THE WORDS!" do
28
28
  create_project do
29
29
  EpubForge.collect_stdout do
30
- report = EpubForge::Action::Runner.new.exec( "wc", @project_dir )
30
+ report = EpubForge::Action::Runner.new.exec( "wc", @project_dir ).execution_returned
31
31
  assert_kind_of Hash, report
32
- assert_equal 87, report["Book"]
33
- assert_equal 94, report["Today"]
32
+ assert_equal 119, report["Book"]
33
+ assert_equal 126, report["Today"]
34
34
  assert @project_dir.join( EpubForge::Project::SETTINGS_FOLDER, EpubForge::Action::WordCount::WORD_COUNT_FILE ).exist?
35
35
  end
36
36
  end
@@ -39,7 +39,9 @@ class TestEpubforge < Test::Unit::TestCase #
39
39
  should "fail to count words when no project is given and cwd is not a project" do
40
40
  create_project do
41
41
  printout = EpubForge.collect_stdout do
42
- assert !EpubForge::Action::Runner.new.exec( "wc" )
42
+ run_description = EpubForge::Action::Runner.new.exec( "wc" )
43
+ assert_equal nil, run_description.execution_returned
44
+ assert_equal false, run_description.success?
43
45
  end
44
46
 
45
47
  assert_match /Error\(s\) trying to complete the requested action/, printout
@@ -74,8 +76,8 @@ class TestEpubforge < Test::Unit::TestCase #
74
76
  end
75
77
 
76
78
  d.join("Text") do |d|
77
- d.join( "section0002.xhtml" ) do |section|
78
- assert section.file?
79
+ d.join( "afterword.xhtml" ) do |section|
80
+ assert section.file?, "file should exist: chapter-0002.xhtml"
79
81
  section_text = section.read
80
82
  assert_match /DOCTYPE/, section_text
81
83
  assert_match /<title>#{@book_title}<\/title>/, section_text
@@ -90,7 +92,7 @@ class TestEpubforge < Test::Unit::TestCase #
90
92
  d.join( "content.opf" ) do |content|
91
93
  content_text = content.read
92
94
  assert_match /<dc:title>#{@book_title}<\/dc:title>/, content_text
93
- assert_match /Text\/section0003/, content_text
95
+ assert_match /Text\/chapter-0003/, content_text
94
96
  end
95
97
 
96
98
  d.join( "toc.ncx" ) do |toc|
@@ -128,7 +130,6 @@ class TestEpubforge < Test::Unit::TestCase #
128
130
 
129
131
  assert @project_dir.directory?, "Project directory doesn't exist. Cannot proceed."
130
132
 
131
-
132
133
  @book_title = fill_in_project_options[:answers][:title]
133
134
  @chapter_count = fill_in_project_options[:answers][:chapter_count].to_i
134
135
  @ebook_file = @project_dir.join( @book_title.epf_underscorize + ".epub" )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epubforge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-30 00:00:00.000000000 Z
12
+ date: 2013-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: xdg
@@ -223,6 +223,7 @@ files:
223
223
  - ./config/actions/help.rb
224
224
  - ./config/actions/init.rb
225
225
  - ./config/actions/kindle.rb
226
+ - ./config/actions/mobify.rb
226
227
  - ./config/actions/notes_to_epub.rb
227
228
  - ./config/actions/notes_to_kindle.rb
228
229
  - ./config/actions/word_count.rb
@@ -248,6 +249,7 @@ files:
248
249
  - ./lib/epub/assets/page.rb
249
250
  - ./lib/epub/assets/stylesheet.rb
250
251
  - ./lib/epub/assets/textile.rb
252
+ - ./lib/epub/assets/xhtml.rb
251
253
  - ./lib/epub/builder.rb
252
254
  - ./lib/epub/packager.rb
253
255
  - ./lib/epubforge.rb
@@ -268,11 +270,13 @@ files:
268
270
  - ./lib/utils/template_evaluator.rb
269
271
  - ./templates/default/book/afterword.markdown.template
270
272
  - ./templates/default/book/chapter-%i%.markdown.sequence
273
+ - ./templates/default/book/cover.xhtml.template
271
274
  - ./templates/default/book/foreword.markdown.template
272
275
  - ./templates/default/book/images/cover.png
273
276
  - ./templates/default/book/stylesheets/stylesheet.css.template
274
277
  - ./templates/default/book/title_page.markdown.template
275
278
  - ./templates/default/notes/character.named.markdown.template
279
+ - ./templates/default/notes/images/cover.png
276
280
  - ./templates/default/notes/stylesheets/stylesheet.css.template
277
281
  - ./templates/default/payload.rb
278
282
  - ./templates/default/settings/actions/local_action.rb.example
@@ -311,7 +315,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
311
315
  version: '0'
312
316
  segments:
313
317
  - 0
314
- hash: 4298602007966861026
318
+ hash: 243230996870064853
315
319
  required_rubygems_version: !ruby/object:Gem::Requirement
316
320
  none: false
317
321
  requirements: