epubforge 0.0.5

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 (83) hide show
  1. data/Gemfile +26 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +26 -0
  4. data/Rakefile +71 -0
  5. data/VERSION +1 -0
  6. data/bin/epubforge +10 -0
  7. data/config/actions/book_to_epub.rb +20 -0
  8. data/config/actions/generate.rb +24 -0
  9. data/config/actions/generate_chapter.rb +26 -0
  10. data/config/actions/git_backup.rb +23 -0
  11. data/config/actions/gitify.rb +72 -0
  12. data/config/actions/globals.rb +77 -0
  13. data/config/actions/help.rb +21 -0
  14. data/config/actions/init.rb +137 -0
  15. data/config/actions/kindle.rb +68 -0
  16. data/config/actions/notes_to_epub.rb +20 -0
  17. data/config/actions/notes_to_kindle.rb +17 -0
  18. data/config/actions/word_count.rb +126 -0
  19. data/config/actions/wrap_scene_notes_in_hidden_div.rb +118 -0
  20. data/config/htmlizers.rb +62 -0
  21. data/lib/action/actions_lookup.rb +41 -0
  22. data/lib/action/cli_command.rb +72 -0
  23. data/lib/action/cli_sequence.rb +55 -0
  24. data/lib/action/file_transformer.rb +59 -0
  25. data/lib/action/run_description.rb +24 -0
  26. data/lib/action/runner.rb +122 -0
  27. data/lib/action/thor_action.rb +149 -0
  28. data/lib/core_extensions/array.rb +5 -0
  29. data/lib/core_extensions/kernel.rb +42 -0
  30. data/lib/core_extensions/nil_class.rb +5 -0
  31. data/lib/core_extensions/object.rb +5 -0
  32. data/lib/core_extensions/string.rb +37 -0
  33. data/lib/custom_helpers.rb +60 -0
  34. data/lib/epub/assets/asset.rb +11 -0
  35. data/lib/epub/assets/html.rb +8 -0
  36. data/lib/epub/assets/image.rb +18 -0
  37. data/lib/epub/assets/markdown.rb +8 -0
  38. data/lib/epub/assets/page.rb +32 -0
  39. data/lib/epub/assets/stylesheet.rb +22 -0
  40. data/lib/epub/assets/textile.rb +8 -0
  41. data/lib/epub/builder.rb +270 -0
  42. data/lib/epub/packager.rb +16 -0
  43. data/lib/epubforge.rb +97 -0
  44. data/lib/errors.rb +8 -0
  45. data/lib/project/project.rb +65 -0
  46. data/lib/utils/action_loader.rb +7 -0
  47. data/lib/utils/class_loader.rb +83 -0
  48. data/lib/utils/directory_builder.rb +181 -0
  49. data/lib/utils/downloader.rb +58 -0
  50. data/lib/utils/file_orderer.rb +45 -0
  51. data/lib/utils/file_path.rb +152 -0
  52. data/lib/utils/html_translator.rb +99 -0
  53. data/lib/utils/html_translator_queue.rb +70 -0
  54. data/lib/utils/htmlizer.rb +92 -0
  55. data/lib/utils/misc.rb +20 -0
  56. data/lib/utils/root_path.rb +20 -0
  57. data/lib/utils/settings.rb +146 -0
  58. data/lib/utils/template_evaluator.rb +20 -0
  59. data/templates/default/book/afterword.markdown.template +4 -0
  60. data/templates/default/book/chapter-%i%.markdown.sequence +4 -0
  61. data/templates/default/book/foreword.markdown.template +6 -0
  62. data/templates/default/book/images/cover.png +0 -0
  63. data/templates/default/book/stylesheets/stylesheet.css.template +2 -0
  64. data/templates/default/book/title_page.markdown.template +4 -0
  65. data/templates/default/notes/character.named.markdown.template +4 -0
  66. data/templates/default/notes/stylesheets/stylesheet.css.template +2 -0
  67. data/templates/default/payload.rb +65 -0
  68. data/templates/default/settings/actions/local_action.rb.example +14 -0
  69. data/templates/default/settings/config.rb.form +55 -0
  70. data/templates/default/settings/htmlizers.rb +0 -0
  71. data/templates/default/settings/wordcount.template +6 -0
  72. data/test/helper.rb +22 -0
  73. data/test/misc/config.rb +7 -0
  74. data/test/sample_text/sample.markdown +30 -0
  75. data/test/sample_text/sample.textile +24 -0
  76. data/test/test_custom_helpers.rb +22 -0
  77. data/test/test_directory_builder.rb +141 -0
  78. data/test/test_epf_root.rb +9 -0
  79. data/test/test_epubforge.rb +164 -0
  80. data/test/test_htmlizers.rb +24 -0
  81. data/test/test_runner.rb +15 -0
  82. data/test/test_utils.rb +39 -0
  83. metadata +328 -0
@@ -0,0 +1,270 @@
1
+ # Avoiding namespace collision.
2
+ XmlBuilder = Builder
3
+
4
+ module EpubForge
5
+ module Epub
6
+ PAGE_FILE_EXTENSIONS = %w(html markdown textile)
7
+ IMAGE_FILE_EXTENSIONS = %w(jpg png gif)
8
+
9
+ MEDIA_TYPES = { "gif" => "image/gif", "jpg" => "image/jpeg", "png" => "image/png",
10
+ "css" => "text/css", "js" => "application/javascript", "pdf" => "application/pdf",
11
+ "txt" => "text/plain", "xhtml" => "application/xhtml+xml"
12
+ }
13
+
14
+ IMAGES_DIR = "".fwf_filepath.join( "/", "OEBPS", "Images" )
15
+ STYLE_DIR = "".fwf_filepath.join( "/", "OEBPS", "Styles" )
16
+ TEXT_DIR = "".fwf_filepath.join( "/", "OEBPS", "Text" )
17
+
18
+ class Builder
19
+ attr_reader :stylesheets
20
+
21
+ def initialize project, opts = {}
22
+ puts "--------------- forgin' #{project.filename_for_epub_book} ------------------"
23
+ @project = project
24
+ @config = project.config
25
+ @book_dir_short = opts[:book_dir] ? opts[:book_dir].split.last.to_s : "book"
26
+ @book_dir = @project.target_dir.join( @book_dir_short ).fwf_filepath
27
+ @config = @project.config
28
+
29
+ @config["page_orderer"] = Utils::FileOrderer.new( opts[:page_order] || @config["pages"][@book_dir_short] )
30
+
31
+ @metadata = @config["metadata"] || {}
32
+
33
+ page_files = @book_dir.glob( ext: PAGE_FILE_EXTENSIONS )
34
+ @section_files = @config["page_orderer"].reorder( page_files )
35
+
36
+ @sections = @section_files.map do |section|
37
+ case section.to_s.split(".").last
38
+ when "markdown"
39
+ Assets::Markdown.new( section, @metadata, self )
40
+ when "html"
41
+ Assets::HTML.new( section, @metadata, self )
42
+ when "textile"
43
+ Assets::Textile.new( section, @metadata, self )
44
+ else
45
+ raise "UNKNOWN EXTENSION TYPE"
46
+ end
47
+ end
48
+
49
+ @sections.each_with_index{ |sec, i| sec.section_number = i }
50
+
51
+ images = @book_dir.glob( "images", ext: IMAGE_FILE_EXTENSIONS )
52
+ @images = images.map{ |img| Assets::Image.new(img) }
53
+
54
+ @stylesheets = @book_dir.glob( "stylesheets", "*.css" ).map do |sheet|
55
+ Assets::Stylesheet.new( sheet )
56
+ end
57
+
58
+ @scratch_dir = Dir.mktmpdir.fwf_filepath.join( "ebookdir" )
59
+ end
60
+
61
+ def toc
62
+ b = XmlBuilder::XmlMarkup.new(:indent => 2)
63
+ b.instruct! # <?xml version="1.0" encoding="UTF-8"?>
64
+ b.declare! :DOCTYPE, :ncx, :PUBLIC, "-//NISO//DTD ncx 2005-1//EN", "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd" # <!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"
65
+
66
+ # <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
67
+ b.ncx :xmlns => "http://www.daisy.org/z3986/2005/ncx/", :version => "2005-1" do
68
+ # <head>
69
+ # <meta name="dtb:uid" content="58cf98c8-e5be-416d-8ce8-ceae573d5ac5"/>
70
+ # <meta name="dtb:depth" content="1"/>
71
+ # <meta name="dtb:totalPageCount" content="0"/>
72
+ # <meta name="dtb:maxPageNumber" content="0"/>
73
+ # </head>
74
+ b.head do
75
+ b.meta :name => "dtb:uid", :content => "58cf98c8-e5be-416d-8ce8-ceae573d5ac5"
76
+ b.meta :name => "dtb:depth", :content => "1"
77
+ b.meta :name => "dtb:totalPageCount", :content => "0"
78
+ b.meta :name => "dtb:maxPageNumber", :content=> "0"
79
+ end
80
+
81
+ # <docTitle>
82
+ # <text>#{PROJECT_NAME}</text>
83
+ # </docTitle>
84
+ b.docTitle do
85
+ b.text @metadata["name"]
86
+ end
87
+
88
+ # <navMap>
89
+ b.navMap do
90
+ @sections.each_with_index do |section,i|
91
+ # <navPoint id="navPoint-#{i}" playOrder="#{i}">
92
+ # <navLabel>
93
+ # <text>#{section.title}</text>
94
+ # </navLabel>
95
+ # <content src="Text/section#{sprintf("%04i",i)}.xhtml"/>
96
+ # </navPoint>
97
+ b.navPoint :id => "navPoint-#{i}", :playOrder => "#{i}" do
98
+ b.navLabel do
99
+ b.text section.title
100
+ end
101
+ b.content :src => section.link
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+
108
+ b.target!.to_s
109
+ end
110
+
111
+ def mimetype
112
+ "application/epub+zip"
113
+ end
114
+
115
+ def container
116
+ b = XmlBuilder::XmlMarkup.new(:indent => 2)
117
+
118
+ # <?xml version="1.0"?>
119
+ b.instruct!
120
+ # <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
121
+ # <rootfiles>
122
+ # <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
123
+ # </rootfiles>
124
+ # </container>
125
+ b.container :version => "1.0", :xmlns => "urn:oasis:names:tc:opendocument:xmlns:container" do
126
+ b.rootfiles do
127
+ b.rootfile :"full-path" => "OEBPS/content.opf", :"media-type" => "application/oebps-package+xml"
128
+ end
129
+ end
130
+ end
131
+
132
+ def content_opf
133
+ b = XmlBuilder::XmlMarkup.new(:indent => 2)
134
+
135
+ # <?xml version="1.0" encoding="UTF-8"?>
136
+ b.instruct!
137
+
138
+ # <package xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookID" version="2.0">
139
+ b.package :xmlns => "http://www.idpf.org/2007/opf", "unique-identifier" => "BookID", :version => "2.0" do
140
+ # <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
141
+ b.metadata :"xmlns:dc" => "http://purl.org/dc/elements/1.1/", :"xmlns:opf" => "http://www.idpf.org/2007/opf" do
142
+ # <dc:title>#{PROJECT_NAME}</dc:title>
143
+ # <dc:creator opf:role="aut">#{PROJECT_AUTHOR}</dc:creator>
144
+ # <dc:language>en-US</dc:language>
145
+ # <dc:identifier id="BookID" opf:scheme="UUID">urn:uuid:58cf98c8-e5be-416d-8ce8-ceae573d5ac5</dc:identifier>
146
+ #
147
+ # <dc:rights>Creative Commons Non-commercial No Derivatives</dc:rights>
148
+ # <dc:publisher>Lulu.com</dc:publisher>
149
+ # <dc:date opf:event="original-publication">2012</dc:date>
150
+ # <dc:date opf:event="epub-publication">2012</dc:date>
151
+ #
152
+ b.dc :title, @metadata["name"]
153
+ b.dc :creator, {:"opf:role" => "aut"}, @metadata["author"]
154
+ b.dc :language, "en-US"
155
+ b.dc :identifier, {:id => "BookID", "opf:scheme" => "UUID"}, "urn:uuid:58cf98c8-e5be-416d-8ce8-ceae573d5ac5" #TODO Unique id generator
156
+ b.dc :rights, @metadata["license"]
157
+ b.dc :publisher, @metadata["publisher"] || "A Pack of Orangutans"
158
+ b.dc :date, {:"opf:event" => "original-publication"}, @metadata["original-publication"] || Time.now.year
159
+ b.dc :date, {:"opf:event" => "epub-publication"}, @metadata["epub-publication"] || Time.now.year
160
+ end
161
+
162
+ # <manifest>
163
+ b.manifest do
164
+ # <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
165
+ b.item :id => "ncx", :href => "toc.ncx", :"media-type" => "application/x-dtbncx+xml"
166
+
167
+ @sections.each_with_index do |section, i|
168
+ b.item :id => section.link, :href => section.link, :"media-type" => section.media_type
169
+ end
170
+
171
+ @images.each do |image|
172
+ b.item :id => image.name, :href => image.link, :"media-type" => image.media_type
173
+ end
174
+
175
+ @stylesheets.each do |sheet|
176
+ b.item :id => sheet.name, :href => sheet.link, :"media-type" => sheet.media_type
177
+ end
178
+ end
179
+
180
+ # <spine toc="ncx">
181
+ b.spine :toc => "ncx" do
182
+ @sections.each_with_index do |section, i|
183
+ b.itemref :idref => "section#{sprintf("%04i",i)}.xhtml"
184
+ end
185
+ end
186
+
187
+ # TODO: <guide> section
188
+ # <guide>
189
+ # <reference type="title-page" title="Title Page"
190
+ # href="Text/title_page.xhtml" />
191
+ # <reference type="cover" title="Cover" href="Text/cover.xhtml"/>
192
+ # <reference type="text" title="Text"
193
+ # href="Text/chapter0001.xhtml" />
194
+ # </guide>
195
+ end
196
+
197
+ b.target!.to_s
198
+ end
199
+
200
+ # zips up contents
201
+ def build
202
+ Utils::DirectoryBuilder.create( @scratch_dir ) do |build|
203
+
204
+ build.file( "mimetype", mimetype )
205
+
206
+ build.dir( "META-INF" ) do
207
+ build.file("container.xml", container)
208
+ end
209
+
210
+ build.dir( "OEBPS" ) do
211
+ build.file( "toc.ncx", toc )
212
+ build.file( "content.opf", content_opf )
213
+
214
+ build.dir( "Text" ) do
215
+ @sections.each_with_index do |section, i|
216
+ build.file( "section#{sprintf("%04i",i)}.xhtml", wrap_page( section.html ) )
217
+ end
218
+ end
219
+
220
+ if @images.length > 0
221
+ build.dir "Images" do
222
+ for img in @images
223
+ build.copy( img.filename )
224
+ end
225
+ end
226
+ end
227
+
228
+ unless @stylesheets.epf_blank?
229
+ build.dir "Styles" do
230
+ for sheet in @stylesheets
231
+ build.file( sheet.name, sheet.contents )
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ def package epub_filename
240
+ Packager.new( @scratch_dir, epub_filename ).package
241
+ end
242
+
243
+ def clean
244
+ # `rm -r #{@scratch_dir}`
245
+ end
246
+
247
+ protected
248
+ def wrap_page content
249
+ b = XmlBuilder::XmlMarkup.new( :indent => 2)
250
+ b.instruct! :xml, :encoding => "utf-8", :standalone => "no"
251
+ b.declare! :DOCTYPE, :html, :PUBLIC, "-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
252
+
253
+ b.html :xmlns => "http://www.w3.org/1999/xhtml" do
254
+ b.head do
255
+ b.title( @metadata["name"] )
256
+ for sheet in @stylesheets
257
+ b.link :href => sheet.link, :media => "screen", :rel => "stylesheet", :type => "text/css"
258
+ end
259
+ end
260
+
261
+ b.body do
262
+ b << content
263
+ end
264
+ end
265
+
266
+ b.target!.to_s
267
+ end
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,16 @@
1
+ module EpubForge
2
+ module Epub
3
+ class Packager
4
+ def initialize( src_dir, dst_filename )
5
+ @src_dir = src_dir
6
+ @dst_filename = dst_filename
7
+ end
8
+
9
+ def package
10
+ @dst_filename = @dst_filename.expand
11
+ FileUtils.rm( @dst_filename ) if @dst_filename.exist?
12
+ `cd #{@src_dir} && zip -Xr #{@dst_filename.to_s.epf_backhashed_filename} mimetype META-INF OEBPS`
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/epubforge.rb ADDED
@@ -0,0 +1,97 @@
1
+ # I don't know if mentioning them in the Gemfile automatically requires them.
2
+ # Let's find out.
3
+ # require 'readline'
4
+ # require 'singleton'
5
+ # require 'builder'
6
+ require 'thor'
7
+ require 'xdg' # keep configuration files in sane places
8
+ require 'debugger'
9
+ require 'erb'
10
+ require 'singleton'
11
+ require 'builder'
12
+ require 'pathname'
13
+ require 'tmpdir' # Dir.mktmpdir
14
+ require 'net/http'
15
+ require 'open-uri' # needed by Utils::Downloader
16
+ require 'yaml'
17
+ require 'rbconfig'
18
+ # require 'configurator'
19
+ require 'fun_with_files'
20
+ require 'fun_with_configurations'
21
+
22
+
23
+
24
+ EpubForge = Module.new
25
+ EpubForge::DEBUG = false
26
+
27
+ # EpubForge.root responds with the gem directory
28
+ FunWith::Files::RootPath.rootify( EpubForge, __FILE__.fwf_filepath.dirname.up )
29
+
30
+ def debugger?
31
+ debugger if debugging?
32
+ end
33
+
34
+ def debugging?
35
+ EpubForge::DEBUG
36
+ end
37
+
38
+
39
+ require_relative 'core_extensions/array'
40
+ require_relative 'core_extensions/kernel'
41
+ require_relative 'core_extensions/nil_class'
42
+ require_relative 'core_extensions/object'
43
+ require_relative 'core_extensions/string'
44
+
45
+
46
+ require_relative 'utils/directory_builder'
47
+ require_relative 'utils/downloader'
48
+ require_relative 'utils/file_orderer'
49
+ require_relative 'utils/misc'
50
+ require_relative 'utils/class_loader'
51
+ require_relative 'utils/action_loader'
52
+ require_relative 'utils/template_evaluator'
53
+
54
+
55
+
56
+ module EpubForge
57
+ ACTIONS_DIR = EpubForge.root.join( "config", "actions" )
58
+ TEMPLATES_DIR = EpubForge.root.join( "templates" )
59
+ USER_SETTINGS = XDG['CONFIG_HOME'].to_s.fwf_filepath.join( "epubforge" )
60
+ USER_GLOBALS_FILE = USER_SETTINGS.join( "globals.rb" )
61
+ USER_ACTIONS_DIR = USER_SETTINGS.join( "actions" )
62
+
63
+ puts "Warning: Cannot create user settings folder." unless USER_ACTIONS_DIR.touch_dir
64
+ puts "Warning: Cannot create globals file." unless USER_GLOBALS_FILE.touch
65
+ end
66
+
67
+ EpubForge.install_fwc_config_from_file( EpubForge::USER_GLOBALS_FILE )
68
+
69
+ EpubForge.config.activation_key = rand(20**32).to_s(16).gsub(/(.{5})/, '\1-')[0..-2]
70
+ puts "Thank you for registering your copy of the epubforge gem. Please write down your activation key (#{EpubForge.config.activation_key}) in case you need to call customer service."
71
+
72
+ require_relative 'utils/html_translator'
73
+ require_relative 'utils/html_translator_queue'
74
+ require_relative 'utils/htmlizer'
75
+
76
+ require_relative 'action/file_transformer'
77
+ require_relative 'action/run_description'
78
+ require_relative 'action/thor_action'
79
+ require_relative 'action/actions_lookup'
80
+ require_relative 'action/runner'
81
+ require_relative 'action/cli_command'
82
+ require_relative 'action/cli_sequence'
83
+ require_relative 'custom_helpers'
84
+ require_relative 'epub/builder'
85
+ require_relative 'epub/packager'
86
+ require_relative 'epub/assets/asset'
87
+ require_relative 'epub/assets/page'
88
+ require_relative 'epub/assets/html'
89
+ require_relative 'epub/assets/markdown'
90
+ require_relative 'epub/assets/textile'
91
+ require_relative 'epub/assets/image'
92
+ require_relative 'epub/assets/stylesheet'
93
+ require_relative 'project/project'
94
+
95
+ puts "Requirements loaded" if debugging?
96
+
97
+ puts "Done with tests inside epubforge.rb" if debugging?
data/lib/errors.rb ADDED
@@ -0,0 +1,8 @@
1
+ module EpubForge
2
+ module Exceptions
3
+ class NotAProject < Exception; end
4
+ class FileError < Exception; end
5
+ class FileDoesNotExist < FileError; end
6
+ class FileMustNotExist < FileError; end
7
+ end
8
+ end
@@ -0,0 +1,65 @@
1
+ module EpubForge
2
+ class Project
3
+ SETTINGS_FOLDER = "settings"
4
+ CONFIG_FILE_NAME = "config.rb"
5
+ PROJECT_ACTIONS_DIRECTORY = "actions"
6
+
7
+ attr_reader :target_dir, :config_file, :config, :book_dir,
8
+ :notes_dir, :project_basename, :filename_for_epub_book,
9
+ :filename_for_mobi_book, :filename_for_epub_notes,
10
+ :filename_for_mobi_notes, :actions_dir
11
+
12
+ def initialize( target_dir )
13
+ @target_dir = FunWith::Files::FilePath.new( target_dir ).expand
14
+
15
+ load_configuration
16
+
17
+ @notes_dir = config.notes_dir || @target_dir.join( "notes" )
18
+ @book_dir = config.book_dir || @target_dir.join( "book" )
19
+
20
+ @project_basename = default_project_basename
21
+ @filename_for_epub_book = @target_dir.join( "#{default_project_basename}.epub" )
22
+ @filename_for_mobi_book = @target_dir.join( "#{default_project_basename}.mobi" )
23
+ @filename_for_epub_notes = @target_dir.join( "#{default_project_basename}.notes.epub" )
24
+ @filename_for_mobi_notes = @target_dir.join( "#{default_project_basename}.notes.mobi" )
25
+ end
26
+
27
+ # shorthand string that 'names' the project, like the_vampire_of_the_leeky_hills. Variable-ish, used within filenames
28
+ def default_project_basename
29
+ config.filename || @target_dir.basename.to_s.gsub( /\.epubforge$/ , '' )
30
+ end
31
+
32
+ # TODO: should test be more definitive?
33
+ def self.is_project_dir?( dir )
34
+ dir = dir && (dir.is_a?(String) || dir.is_a?(FunWith::Files::FilePath)) ? dir.fwf_filepath : nil
35
+ return false if dir.nil?
36
+
37
+ ( dir.exist? && dir.join( SETTINGS_FOLDER, CONFIG_FILE_NAME ).exist? && dir.join( "book" ).directory? ) ? dir : false
38
+ end
39
+
40
+ def project_exists?
41
+ @target_dir.exist? && config_file.exist?
42
+ end
43
+
44
+ def settings_folder(*args)
45
+ @settings_folder ||= @target_dir.join( SETTINGS_FOLDER )
46
+ @settings_folder.join( *args )
47
+ end
48
+
49
+ def config_file
50
+ settings_folder( CONFIG_FILE_NAME )
51
+ end
52
+
53
+ def actions_directory
54
+ settings_folder( ACTIONS_DIRECTORY )
55
+ end
56
+
57
+ def chapters
58
+ @book_dir.glob("chapter-????.*")
59
+ end
60
+
61
+ def load_configuration
62
+ self.install_fwc_config_from_file( config_file )
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ module EpubForge
2
+ module Utils
3
+ class ActionLoader < ClassLoader
4
+ namespace( "EpubForge::Action" )
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,83 @@
1
+ module EpubForge
2
+ module Utils
3
+ # filepath string with metadata, representing a class
4
+ # file that can be loaded.
5
+ class ClassLoader < FunWith::Files::FilePath
6
+ def self.loaded_classes
7
+ @loaded_classes ||= []
8
+ end
9
+
10
+ def self.loaded_directories
11
+ @loaded_directories ||= []
12
+ end
13
+
14
+ def self.namespace( nsp = nil )
15
+ @namespace = nsp unless nsp.nil?
16
+ @namespace
17
+ end
18
+
19
+ def class_name
20
+ unless @class_name
21
+ base = self.basename.to_s.split(".")[0].epf_camelize
22
+ @class_name = "#{self.class.namespace}::#{base}"
23
+ end
24
+ @class_name
25
+ end
26
+
27
+ # Returns true if an error was raised when trying to require the file,
28
+ # or if the expected class is not loaded after the file was required.
29
+ # Proper naming is very important here.
30
+ def require_me
31
+ begin
32
+ require self.to_s
33
+ rescue NameError => e
34
+ puts "Error encounterd while trying to load #{self.class_name} from #{self}"
35
+ puts e.message
36
+ puts e.backtrace.map{|line| "\t#{line}" }
37
+ return false
38
+ end
39
+
40
+ return self.class_loaded?
41
+ end
42
+
43
+ def class_loaded?
44
+ begin
45
+ self.to_class
46
+ return true
47
+ rescue NameError # There's gotta be another way I should be doing this.
48
+ return false
49
+ end
50
+ end
51
+
52
+ def to_class
53
+ return @klass unless @klass.nil?
54
+ @klass = Utils::Misc.constantize( self.class_name )
55
+ end
56
+
57
+ def self.require_me( *loadables )
58
+ @loaded_classes ||= []
59
+ @loaded_directories ||= []
60
+
61
+ for loadable in loadables
62
+ loadable = self.new( loadable )
63
+
64
+ if loadable.file?
65
+ if loadable.require_me
66
+ @loaded_classes << loadable.to_class
67
+ else
68
+ puts "Warning: Failed to load #{loadable.class_name} from file #{loadable}"
69
+ end
70
+ elsif loadable.directory?
71
+ @loaded_directories << loadable
72
+ loadable.glob( "**", "*.rb" ).each do |entry|
73
+ self.require_me( entry )
74
+ end
75
+ else
76
+ puts "Warning: Could not find file #{loadable} to load htmlizers from."
77
+ raise "AAAH"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end