epubforge 0.0.5

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