epubforge 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +26 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +26 -0
- data/Rakefile +71 -0
- data/VERSION +1 -0
- data/bin/epubforge +10 -0
- data/config/actions/book_to_epub.rb +20 -0
- data/config/actions/generate.rb +24 -0
- data/config/actions/generate_chapter.rb +26 -0
- data/config/actions/git_backup.rb +23 -0
- data/config/actions/gitify.rb +72 -0
- data/config/actions/globals.rb +77 -0
- data/config/actions/help.rb +21 -0
- data/config/actions/init.rb +137 -0
- data/config/actions/kindle.rb +68 -0
- data/config/actions/notes_to_epub.rb +20 -0
- data/config/actions/notes_to_kindle.rb +17 -0
- data/config/actions/word_count.rb +126 -0
- data/config/actions/wrap_scene_notes_in_hidden_div.rb +118 -0
- data/config/htmlizers.rb +62 -0
- data/lib/action/actions_lookup.rb +41 -0
- data/lib/action/cli_command.rb +72 -0
- data/lib/action/cli_sequence.rb +55 -0
- data/lib/action/file_transformer.rb +59 -0
- data/lib/action/run_description.rb +24 -0
- data/lib/action/runner.rb +122 -0
- data/lib/action/thor_action.rb +149 -0
- data/lib/core_extensions/array.rb +5 -0
- data/lib/core_extensions/kernel.rb +42 -0
- data/lib/core_extensions/nil_class.rb +5 -0
- data/lib/core_extensions/object.rb +5 -0
- data/lib/core_extensions/string.rb +37 -0
- data/lib/custom_helpers.rb +60 -0
- data/lib/epub/assets/asset.rb +11 -0
- data/lib/epub/assets/html.rb +8 -0
- data/lib/epub/assets/image.rb +18 -0
- data/lib/epub/assets/markdown.rb +8 -0
- data/lib/epub/assets/page.rb +32 -0
- data/lib/epub/assets/stylesheet.rb +22 -0
- data/lib/epub/assets/textile.rb +8 -0
- data/lib/epub/builder.rb +270 -0
- data/lib/epub/packager.rb +16 -0
- data/lib/epubforge.rb +97 -0
- data/lib/errors.rb +8 -0
- data/lib/project/project.rb +65 -0
- data/lib/utils/action_loader.rb +7 -0
- data/lib/utils/class_loader.rb +83 -0
- data/lib/utils/directory_builder.rb +181 -0
- data/lib/utils/downloader.rb +58 -0
- data/lib/utils/file_orderer.rb +45 -0
- data/lib/utils/file_path.rb +152 -0
- data/lib/utils/html_translator.rb +99 -0
- data/lib/utils/html_translator_queue.rb +70 -0
- data/lib/utils/htmlizer.rb +92 -0
- data/lib/utils/misc.rb +20 -0
- data/lib/utils/root_path.rb +20 -0
- data/lib/utils/settings.rb +146 -0
- data/lib/utils/template_evaluator.rb +20 -0
- data/templates/default/book/afterword.markdown.template +4 -0
- data/templates/default/book/chapter-%i%.markdown.sequence +4 -0
- data/templates/default/book/foreword.markdown.template +6 -0
- data/templates/default/book/images/cover.png +0 -0
- data/templates/default/book/stylesheets/stylesheet.css.template +2 -0
- data/templates/default/book/title_page.markdown.template +4 -0
- data/templates/default/notes/character.named.markdown.template +4 -0
- data/templates/default/notes/stylesheets/stylesheet.css.template +2 -0
- data/templates/default/payload.rb +65 -0
- data/templates/default/settings/actions/local_action.rb.example +14 -0
- data/templates/default/settings/config.rb.form +55 -0
- data/templates/default/settings/htmlizers.rb +0 -0
- data/templates/default/settings/wordcount.template +6 -0
- data/test/helper.rb +22 -0
- data/test/misc/config.rb +7 -0
- data/test/sample_text/sample.markdown +30 -0
- data/test/sample_text/sample.textile +24 -0
- data/test/test_custom_helpers.rb +22 -0
- data/test/test_directory_builder.rb +141 -0
- data/test/test_epf_root.rb +9 -0
- data/test/test_epubforge.rb +164 -0
- data/test/test_htmlizers.rb +24 -0
- data/test/test_runner.rb +15 -0
- data/test/test_utils.rb +39 -0
- metadata +328 -0
data/lib/epub/builder.rb
ADDED
@@ -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,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,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
|