epubforge 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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: