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.
- 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
|