epubforge 0.0.10 → 0.0.11
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.
- checksums.yaml +7 -0
- data/Gemfile +17 -10
- data/VERSION +1 -1
- data/bin/epubforge +1 -1
- data/config/actions/epub.rb +50 -0
- data/config/actions/forge.rb +34 -13
- data/config/actions/git.rb +106 -0
- data/config/actions/help.rb +13 -13
- data/config/actions/html.rb +33 -0
- data/config/actions/mobi.rb +60 -0
- data/config/actions/new.rb +182 -0
- data/config/actions/word_count.rb +26 -24
- data/config/{actions → actions_to_ignore}/generate.rb +1 -1
- data/config/{actions → actions_to_ignore}/generate_chapter.rb +0 -0
- data/config/{actions → actions_to_ignore}/git_backup.rb +2 -2
- data/config/{actions → actions_to_ignore}/globals.rb +1 -1
- data/config/{actions → actions_to_ignore}/kindle.rb +3 -3
- data/config/{actions → actions_to_ignore}/local_action.rb +1 -1
- data/config/{actions → actions_to_ignore}/mobify.rb +3 -3
- data/config/actions_to_ignore/notes_to_epub.rb +19 -0
- data/config/actions_to_ignore/notes_to_kindle.rb +18 -0
- data/config/{actions → actions_to_ignore}/spell.rb +1 -1
- data/config/{actions → actions_to_ignore}/version.rb +3 -3
- data/config/{actions → actions_to_ignore}/wrap_scene_notes_in_hidden_div.rb +1 -1
- data/config/converters/epub_to_mobi.calibre.rb +8 -0
- data/config/converters/epub_to_mobi.kindlegen.rb +11 -0
- data/config/html_translators/default_kramdown.html_translator.rb +9 -0
- data/config/html_translators/default_markdown.html_translator.rb +10 -0
- data/config/html_translators/default_markdown_pandoc.html_translator.rb +10 -0
- data/config/html_translators/default_textile_pandoc.html_translator.rb +8 -0
- data/config/html_translators/default_xhtml.html_translator.rb +7 -0
- data/config/html_translators/fallback_html.html_translator.rb +9 -0
- data/config/html_translators/fallback_markdown.html_translator.rb +8 -0
- data/config/html_translators/fallback_textile.html_translator.rb +7 -0
- data/config/html_translators/fallback_txt.html_translator.rb +8 -0
- data/config/html_translators/fallback_unknown.html_translator.rb +7 -0
- data/lib/epubforge.rb +37 -82
- data/lib/{action/thor_action.rb → epubforge/action/action.rb} +89 -69
- data/lib/epubforge/action/action2.rb +109 -0
- data/lib/epubforge/action/action_definition.rb +62 -0
- data/lib/epubforge/action/actions_lookup.rb +45 -0
- data/lib/epubforge/action/chatterbox.rb +93 -0
- data/lib/{action → epubforge/action}/cli_command.rb +2 -2
- data/lib/{action → epubforge/action}/cli_sequence.rb +0 -0
- data/lib/{action → epubforge/action}/file_transformer.rb +0 -0
- data/lib/{action → epubforge/action}/hooks_interface.rb +2 -2
- data/lib/{action → epubforge/action}/run_description.rb +12 -9
- data/lib/{action → epubforge/action}/runner.rb +23 -24
- data/lib/{epub → epubforge/builder}/assets/asset.rb +1 -1
- data/lib/{epub → epubforge/builder}/assets/font.rb +1 -1
- data/lib/epubforge/builder/assets/html.rb +9 -0
- data/lib/{epub → epubforge/builder}/assets/image.rb +1 -1
- data/lib/epubforge/builder/assets/markdown.rb +9 -0
- data/lib/{epub → epubforge/builder}/assets/page.rb +12 -4
- data/lib/{epub → epubforge/builder}/assets/stylesheet.rb +1 -1
- data/lib/epubforge/builder/assets/textile.rb +9 -0
- data/lib/epubforge/builder/assets/xhtml.rb +9 -0
- data/lib/epubforge/builder/builder.rb +134 -0
- data/lib/{epub/builder.rb → epubforge/builder/epub.rb} +58 -161
- data/lib/epubforge/builder/html.rb +22 -0
- data/lib/epubforge/builder/packager.rb +16 -0
- data/lib/epubforge/core_extensions/array.rb +2 -0
- data/lib/{core_extensions → epubforge/core_extensions}/kernel.rb +0 -0
- data/lib/epubforge/core_extensions/nil_class.rb +2 -0
- data/lib/epubforge/core_extensions/object.rb +24 -0
- data/lib/{core_extensions → epubforge/core_extensions}/string.rb +1 -5
- data/lib/{custom_helpers.rb → epubforge/custom_helpers.rb} +0 -1
- data/lib/{errors.rb → epubforge/exceptions/errors.rb} +0 -0
- data/lib/{project → epubforge/project}/project.rb +23 -17
- data/lib/epubforge/utils/action_loader.rb +8 -0
- data/lib/epubforge/utils/class_loader.rb +102 -0
- data/lib/epubforge/utils/converter.rb +94 -0
- data/lib/{utils → epubforge/utils}/downloader.rb +0 -0
- data/lib/{utils → epubforge/utils}/file_orderer.rb +0 -0
- data/lib/epubforge/utils/file_path.rb +8 -0
- data/lib/epubforge/utils/html_translator.rb +126 -0
- data/lib/epubforge/utils/html_translator_queue.rb +113 -0
- data/lib/epubforge/utils/htmlizer.rb +61 -0
- data/lib/{utils → epubforge/utils}/misc.rb +0 -0
- data/lib/epubforge/utils/root_path.rb +8 -0
- data/lib/epubforge/utils/settings.rb +147 -0
- data/lib/epubforge/utils/template_evaluator.rb +7 -0
- data/templates/{default/book/afterword.markdown.template → project/book/afterword.markdown} +0 -0
- data/templates/project/book/chapter-%0000chapter%.markdown.template +4 -0
- data/templates/{default → project}/book/cover.xhtml.template +2 -2
- data/templates/{default/book/foreword.markdown.template → project/book/foreword.markdown} +0 -0
- data/templates/{default → project}/book/images/cover.png +0 -0
- data/templates/{default/book/stylesheets/stylesheet.css.template → project/book/stylesheets/stylesheet.css} +0 -0
- data/templates/project/book/title_page.markdown.template +5 -0
- data/templates/project/notes/character.%character.name_for_file%.markdown.template +15 -0
- data/templates/{default → project}/notes/images/cover.png +0 -0
- data/templates/{default/notes/stylesheets/stylesheet.css.template → project/notes/stylesheets/stylesheet.css} +0 -0
- data/templates/{default → project}/settings/actions/local_action.rb.example +1 -1
- data/templates/project/settings/config.rb.template +70 -0
- data/templates/project/settings/html_translators/example_translator.rb +29 -0
- data/templates/{default → project}/settings/wordcount.template +1 -1
- data/test/answers01.yml +30 -0
- data/test/helper.rb +62 -39
- data/test/misc/config.rb +5 -7
- data/test/test_epubforge.rb +18 -14
- data/test/{test_htmlizers.rb → test_html_translators.rb} +4 -8
- data/test/test_template_evaluator.rb +42 -0
- data/test/test_utils.rb +0 -11
- metadata +186 -189
- data/config/actions/gitify.rb +0 -72
- data/config/actions/init.rb +0 -138
- data/config/actions/notes_to_epub.rb +0 -18
- data/config/actions/notes_to_kindle.rb +0 -17
- data/config/htmlizers.rb +0 -70
- data/lib/action/actions_lookup.rb +0 -45
- data/lib/core_extensions/array.rb +0 -5
- data/lib/core_extensions/nil_class.rb +0 -5
- data/lib/core_extensions/object.rb +0 -5
- data/lib/epub/assets/html.rb +0 -8
- data/lib/epub/assets/markdown.rb +0 -8
- data/lib/epub/assets/textile.rb +0 -8
- data/lib/epub/assets/xhtml.rb +0 -8
- data/lib/epub/packager.rb +0 -16
- data/lib/utils/action_loader.rb +0 -7
- data/lib/utils/class_loader.rb +0 -102
- data/lib/utils/directory_builder.rb +0 -181
- data/lib/utils/file_path.rb +0 -152
- data/lib/utils/html_translator.rb +0 -100
- data/lib/utils/html_translator_queue.rb +0 -70
- data/lib/utils/htmlizer.rb +0 -92
- data/lib/utils/root_path.rb +0 -20
- data/lib/utils/settings.rb +0 -146
- data/lib/utils/template_evaluator.rb +0 -20
- data/templates/default/book/chapter-%i%.markdown.sequence +0 -4
- data/templates/default/book/title_page.markdown.template +0 -4
- data/templates/default/notes/character.named.markdown.template +0 -4
- data/templates/default/payload.rb +0 -65
- data/templates/default/settings/config.rb.form +0 -55
- data/templates/default/settings/htmlizers.rb +0 -0
- data/test/test_directory_builder.rb +0 -141
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module EpubForge
|
|
2
|
+
module Builder
|
|
3
|
+
class Html < Builder
|
|
4
|
+
def build
|
|
5
|
+
@html_content = ""
|
|
6
|
+
|
|
7
|
+
@sections.each do |section|
|
|
8
|
+
@html_content << section.html
|
|
9
|
+
@html_content << "\n\n" # couldn't hurt?
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def package( html_filename )
|
|
14
|
+
html_filename.write( wrap_page( @html_content ) )
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def clean
|
|
18
|
+
# do nothing
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
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
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# class Object
|
|
2
|
+
# def umethods( regex = /.*/ )
|
|
3
|
+
# (self.methods.sort - Object.new.methods).grep( regex )
|
|
4
|
+
# end
|
|
5
|
+
#
|
|
6
|
+
# def get_and_set( *method_names )
|
|
7
|
+
# for name in method_names
|
|
8
|
+
# if self.is_a?(Class) || self.is_a?(Module)
|
|
9
|
+
# eval "define_method( :#{name} ) do |*args|
|
|
10
|
+
# self.instance_variable_set( :@#{name}, args.first ) if args.length == 1
|
|
11
|
+
# self.instance_variable_get( :@#{name} )
|
|
12
|
+
# end"
|
|
13
|
+
# else
|
|
14
|
+
# m = Module.new
|
|
15
|
+
# m.get_and_set( *method_names )
|
|
16
|
+
# self.extend( m )
|
|
17
|
+
# end
|
|
18
|
+
# # define_method( name ) do |*args|
|
|
19
|
+
# # self.instance_variable_set( :"@#{__method__}", args.first ) if args.length == 1
|
|
20
|
+
# # self.instance_variable_get( :"@#{__method__}" )
|
|
21
|
+
# # end
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
class String
|
|
2
|
-
def epf_blank?
|
|
3
|
-
self.strip.length == 0
|
|
4
|
-
end
|
|
5
|
-
|
|
6
2
|
def epf_camelize
|
|
7
3
|
gsub(/(?:^|_)(.)/) { $1.upcase }
|
|
8
4
|
end
|
|
@@ -28,7 +24,7 @@ class String
|
|
|
28
24
|
nocaps = %w(a and at be but in is nor of or so teh the to with)
|
|
29
25
|
upcase = %w(Ii Ii: Iii M.d.) # TODO: ick
|
|
30
26
|
|
|
31
|
-
words = self.downcase.gsub(/\u00a0/, ' ').split(/(\s|\n)+/).map(&:strip).delete_if(&:
|
|
27
|
+
words = self.downcase.gsub(/\u00a0/, ' ').split(/(\s|\n)+/).map(&:strip).delete_if(&:fwf_blank?)
|
|
32
28
|
first_word = true
|
|
33
29
|
|
|
34
30
|
for word in words
|
|
File without changes
|
|
@@ -4,29 +4,26 @@ module EpubForge
|
|
|
4
4
|
CONFIG_FILE_NAME = "config.rb"
|
|
5
5
|
PROJECT_ACTIONS_DIRECTORY = "actions"
|
|
6
6
|
|
|
7
|
-
attr_reader :
|
|
8
|
-
:notes_dir, :project_basename, :
|
|
9
|
-
:
|
|
10
|
-
:filename_for_mobi_notes, :actions_dir
|
|
7
|
+
attr_reader :root_dir, :config_file, :config, :book_dir,
|
|
8
|
+
:notes_dir, :project_basename, :filename_for_book,
|
|
9
|
+
:filename_for_notes, :actions_dir
|
|
11
10
|
|
|
12
|
-
def initialize(
|
|
13
|
-
@
|
|
11
|
+
def initialize( root_dir )
|
|
12
|
+
@root_dir = FunWith::Files::FilePath.new( root_dir ).expand
|
|
14
13
|
|
|
15
14
|
load_configuration
|
|
16
15
|
|
|
17
|
-
@notes_dir = config.notes_dir || @
|
|
18
|
-
@book_dir = config.book_dir || @
|
|
16
|
+
@notes_dir = config.notes_dir || @root_dir.join( "notes" )
|
|
17
|
+
@book_dir = config.book_dir || @root_dir.join( "book" )
|
|
19
18
|
|
|
20
19
|
@project_basename = default_project_basename
|
|
21
|
-
@
|
|
22
|
-
@
|
|
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" )
|
|
20
|
+
@filename_for_book = @root_dir.join( "#{default_project_basename}" )
|
|
21
|
+
@filename_for_notes = @root_dir.join( "#{default_project_basename}.notes" )
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
# shorthand string that 'names' the project, like the_vampire_of_the_leeky_hills. Variable-ish, used within filenames
|
|
28
25
|
def default_project_basename
|
|
29
|
-
config.filename || @
|
|
26
|
+
config.filename || @root_dir.basename.to_s.gsub( /\.epubforge$/ , '' )
|
|
30
27
|
end
|
|
31
28
|
|
|
32
29
|
# TODO: should test be more definitive?
|
|
@@ -38,11 +35,11 @@ module EpubForge
|
|
|
38
35
|
end
|
|
39
36
|
|
|
40
37
|
def project_exists?
|
|
41
|
-
@
|
|
38
|
+
@root_dir.exist? && config_file.exist?
|
|
42
39
|
end
|
|
43
40
|
|
|
44
41
|
def settings_folder(*args)
|
|
45
|
-
@settings_folder ||= @
|
|
42
|
+
@settings_folder ||= @root_dir.join( SETTINGS_FOLDER )
|
|
46
43
|
@settings_folder.join( *args )
|
|
47
44
|
end
|
|
48
45
|
|
|
@@ -71,11 +68,20 @@ module EpubForge
|
|
|
71
68
|
raise "Project#pages cannot take #{order.class} as an ordering object."
|
|
72
69
|
end
|
|
73
70
|
|
|
74
|
-
orderer.reorder( @book_dir.glob( ext: EpubForge::
|
|
71
|
+
orderer.reorder( @book_dir.glob( ext: EpubForge::Builder::PAGE_FILE_EXTENSIONS ) )
|
|
75
72
|
end
|
|
76
73
|
|
|
77
74
|
def load_configuration
|
|
78
|
-
|
|
75
|
+
puts "NO CONFIGURATION FILE DETECTED" unless config_file.file?
|
|
76
|
+
|
|
77
|
+
begin
|
|
78
|
+
self.install_fwc_config_from_file( config_file )
|
|
79
|
+
true
|
|
80
|
+
rescue SyntaxError => e
|
|
81
|
+
puts "Syntax Error in project configuration file #{config_file}. Quitting.".paint(:red)
|
|
82
|
+
puts e.message
|
|
83
|
+
exit(-1)
|
|
84
|
+
end
|
|
79
85
|
end
|
|
80
86
|
end
|
|
81
87
|
end
|
|
@@ -0,0 +1,102 @@
|
|
|
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 classes from."
|
|
77
|
+
# end
|
|
78
|
+
# end
|
|
79
|
+
# end
|
|
80
|
+
#
|
|
81
|
+
# # just loading all the files is simpler, and probably little harm from reloading. Plus, I want
|
|
82
|
+
# # to be able to split up existing ThorClasses across multiple files.
|
|
83
|
+
# def self.load_me( *loadables )
|
|
84
|
+
# silence_warnings do
|
|
85
|
+
# for loadable in loadables
|
|
86
|
+
# loadable = loadable.fwf_filepath
|
|
87
|
+
#
|
|
88
|
+
# if loadable.file?
|
|
89
|
+
# load( loadable )
|
|
90
|
+
# elsif loadable.directory?
|
|
91
|
+
# for entry in loadable.glob( :ext => "rb", :recursive => true )
|
|
92
|
+
# load( entry )
|
|
93
|
+
# end
|
|
94
|
+
# else
|
|
95
|
+
# puts "Warning: No idea what I'm trying to load (#{loadable}:#{loadable.class})"
|
|
96
|
+
# end
|
|
97
|
+
# end
|
|
98
|
+
# end
|
|
99
|
+
# end
|
|
100
|
+
# end
|
|
101
|
+
# end
|
|
102
|
+
# end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module EpubForge
|
|
2
|
+
module Utils
|
|
3
|
+
|
|
4
|
+
# TODO: Starting to get the feeling that an HtmlTranslator is just a subtype of Converter.
|
|
5
|
+
class Converter
|
|
6
|
+
get_and_set :command, :executable, :help, :input_format, :label, :output_format
|
|
7
|
+
|
|
8
|
+
include FunWith::Patterns::Loader
|
|
9
|
+
loader_pattern_configure( :bracketwise_lookup,
|
|
10
|
+
:warn_on_key_change,
|
|
11
|
+
{ :key => :label, :verbose => true } )
|
|
12
|
+
|
|
13
|
+
def self.all
|
|
14
|
+
self.loader_pattern_registry
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.converts( input_format, output_format = :any )
|
|
18
|
+
self.all.select{ |k,v|
|
|
19
|
+
if v.input_format == input_format
|
|
20
|
+
output_format == :any || v.output_format == output_format
|
|
21
|
+
else
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
}.values
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize( &block )
|
|
28
|
+
instance_exec( &block )
|
|
29
|
+
@command ||= "{{x}} {{o}} '{{src}}' '{{dst}}'" # default
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# def label( lbl = nil )
|
|
34
|
+
# @label = lbl unless lbl.nil?
|
|
35
|
+
# @label
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# def from( fmt = nil)
|
|
39
|
+
# @src_format = fmt unless fmt.nil?
|
|
40
|
+
# @src_format
|
|
41
|
+
# end
|
|
42
|
+
#
|
|
43
|
+
# def to( fmt = nil)
|
|
44
|
+
# @dst_format = fmt unless fmt.nil?
|
|
45
|
+
# @dst_format
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# def executable( executable_name = nil )
|
|
49
|
+
# @executable_name = executable_name unless executable_name.nil?
|
|
50
|
+
# @executable_name
|
|
51
|
+
# end
|
|
52
|
+
|
|
53
|
+
def is_executable_installed?
|
|
54
|
+
@executable && `which #{executable}`.strip.fwf_blank? == false
|
|
55
|
+
end
|
|
56
|
+
#
|
|
57
|
+
# def command( cmd = nil )
|
|
58
|
+
# @command = cmd unless cmd.nil?
|
|
59
|
+
# @command ||= "{{x}} {{opts}} '{{src}}' '{{dst}}'" # default
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
|
|
63
|
+
# opts {
|
|
64
|
+
# :dest => Destination (output) file,
|
|
65
|
+
# :command_line_options => Arguments to feed to the executable. Just a string, replaces the {{o}} in @command
|
|
66
|
+
# }
|
|
67
|
+
def convert( src, opts = {} )
|
|
68
|
+
src = src.fwf_filepath
|
|
69
|
+
dst = opts[:dest].is_a?(String) ? opts[:dest].fwf_filepath : opts[:dest]
|
|
70
|
+
|
|
71
|
+
if dst.nil?
|
|
72
|
+
dst = src.gsub( /#{@input_format}$/, @output_format.to_s )
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if is_executable_installed?
|
|
76
|
+
if src.file?
|
|
77
|
+
cmd = command.gsub("{{x}}", executable.to_s).gsub("{{o}}", opts[:command_line_options]).gsub("{{src}}", src).gsub("{{dst}}", dst)
|
|
78
|
+
puts "running command : #{cmd}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
`#{cmd}`
|
|
83
|
+
$?.success?
|
|
84
|
+
else
|
|
85
|
+
warn( "Source file #{src} does not exist.".paint(:red,:bold))
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
false
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
module EpubForge
|
|
2
|
+
module Utils
|
|
3
|
+
# An individual translator, which receives a filename, determines if it's up to the job
|
|
4
|
+
# then returns the resulting HTML translation.
|
|
5
|
+
class HtmlTranslator
|
|
6
|
+
include HtmlTranslatorQueue
|
|
7
|
+
|
|
8
|
+
get_and_set( :name, :opts, :format, :cmd )
|
|
9
|
+
|
|
10
|
+
def self.translate( filename, opts = {} )
|
|
11
|
+
translator = opts[:translator]
|
|
12
|
+
translator = self.named( translator ) if translator.is_a?( Symbol )
|
|
13
|
+
opts = opts[:opts] || ""
|
|
14
|
+
|
|
15
|
+
if translator
|
|
16
|
+
if result = translator.translate( filename, {opts: opts } )
|
|
17
|
+
return result
|
|
18
|
+
else
|
|
19
|
+
puts "Named HtmlTranslator #{translator} did not return html. Falling back on other html translators"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
for translator in HtmlTranslator.each_translator
|
|
24
|
+
if result = translator.translate( filename, opts )
|
|
25
|
+
return result
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
"<!-- COULD NOT FIND HTML TRANSLATOR FOR FORMAT (#{filename}) -->"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Unneeded?
|
|
33
|
+
# def self.format_from_filename( filename )
|
|
34
|
+
# ext = filename.fwf_filepath.ext
|
|
35
|
+
# ext.fwf_blank? ? :unknown : ext.to_sym
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def initialize( &block )
|
|
42
|
+
# set some defaults
|
|
43
|
+
group( :user )
|
|
44
|
+
opts( "" )
|
|
45
|
+
|
|
46
|
+
self.instance_exec( &block ) if block_given?
|
|
47
|
+
self # explicitly return. Thought that wasn't necessary, but...
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def group( g = nil )
|
|
51
|
+
if g
|
|
52
|
+
raise "group must be one of the following symbols: #{HtmlTranslatorQueue::GROUP_NAMES.inspect}" unless HtmlTranslatorQueue::GROUP_NAMES.include?(g)
|
|
53
|
+
@group = g
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@group
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def executable( executable_name = nil )
|
|
60
|
+
if executable_name
|
|
61
|
+
@executable_name = HtmlTranslator.location( executable_name ) || `which #{executable_name}`.strip
|
|
62
|
+
end
|
|
63
|
+
@executable_name || ""
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def custom_proc( *args, &block )
|
|
68
|
+
if block_given?
|
|
69
|
+
@custom_proc = block
|
|
70
|
+
elsif args.first.is_a?(Proc)
|
|
71
|
+
@custom_proc = args.first
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
@custom_proc
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def installed?
|
|
78
|
+
executable.length > 0
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def handles_format?( f )
|
|
82
|
+
@format == get_file_format( f ) || @format == :unknown
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def can_do_job?( f )
|
|
86
|
+
handles_format?( f ) && ( has_executable_installed? || has_custom_proc? )
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def has_executable_installed?
|
|
90
|
+
executable.is_a?(String) && ! executable.fwf_blank? # 'which will return an empty string if the given executable isn't in the path'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def has_custom_proc?
|
|
94
|
+
@custom_proc.is_a?( Proc )
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# opts allows you to override the normal command line arguments
|
|
98
|
+
# Maybe a description of the job's requirements should be more
|
|
99
|
+
# elaborate than just a filename. OTOH, simple can have its advantages.
|
|
100
|
+
def translate( filename, opts = "" )
|
|
101
|
+
return false unless can_do_job?( filename )
|
|
102
|
+
|
|
103
|
+
result = ""
|
|
104
|
+
if @custom_proc
|
|
105
|
+
result += @custom_proc.call( filename, *opts )
|
|
106
|
+
elsif @cmd
|
|
107
|
+
exec_string = cmd.gsub( /\{\{f\}\}/, "\"#{filename.to_s}\"" )
|
|
108
|
+
opts = @opts if opts.fwf_blank?
|
|
109
|
+
exec_string.gsub!( /\{\{o\}\}/, opts )
|
|
110
|
+
exec_string.gsub!( /\{\{x\}\}/, executable )
|
|
111
|
+
|
|
112
|
+
result += `#{exec_string}`
|
|
113
|
+
else
|
|
114
|
+
return false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
result += "\n\n<!-- generated from #{@format} by html translator #{@name} -->\n"
|
|
118
|
+
result
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def get_file_format( file )
|
|
122
|
+
file.fwf_filepath.ext.to_sym
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|