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.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +17 -10
  3. data/VERSION +1 -1
  4. data/bin/epubforge +1 -1
  5. data/config/actions/epub.rb +50 -0
  6. data/config/actions/forge.rb +34 -13
  7. data/config/actions/git.rb +106 -0
  8. data/config/actions/help.rb +13 -13
  9. data/config/actions/html.rb +33 -0
  10. data/config/actions/mobi.rb +60 -0
  11. data/config/actions/new.rb +182 -0
  12. data/config/actions/word_count.rb +26 -24
  13. data/config/{actions → actions_to_ignore}/generate.rb +1 -1
  14. data/config/{actions → actions_to_ignore}/generate_chapter.rb +0 -0
  15. data/config/{actions → actions_to_ignore}/git_backup.rb +2 -2
  16. data/config/{actions → actions_to_ignore}/globals.rb +1 -1
  17. data/config/{actions → actions_to_ignore}/kindle.rb +3 -3
  18. data/config/{actions → actions_to_ignore}/local_action.rb +1 -1
  19. data/config/{actions → actions_to_ignore}/mobify.rb +3 -3
  20. data/config/actions_to_ignore/notes_to_epub.rb +19 -0
  21. data/config/actions_to_ignore/notes_to_kindle.rb +18 -0
  22. data/config/{actions → actions_to_ignore}/spell.rb +1 -1
  23. data/config/{actions → actions_to_ignore}/version.rb +3 -3
  24. data/config/{actions → actions_to_ignore}/wrap_scene_notes_in_hidden_div.rb +1 -1
  25. data/config/converters/epub_to_mobi.calibre.rb +8 -0
  26. data/config/converters/epub_to_mobi.kindlegen.rb +11 -0
  27. data/config/html_translators/default_kramdown.html_translator.rb +9 -0
  28. data/config/html_translators/default_markdown.html_translator.rb +10 -0
  29. data/config/html_translators/default_markdown_pandoc.html_translator.rb +10 -0
  30. data/config/html_translators/default_textile_pandoc.html_translator.rb +8 -0
  31. data/config/html_translators/default_xhtml.html_translator.rb +7 -0
  32. data/config/html_translators/fallback_html.html_translator.rb +9 -0
  33. data/config/html_translators/fallback_markdown.html_translator.rb +8 -0
  34. data/config/html_translators/fallback_textile.html_translator.rb +7 -0
  35. data/config/html_translators/fallback_txt.html_translator.rb +8 -0
  36. data/config/html_translators/fallback_unknown.html_translator.rb +7 -0
  37. data/lib/epubforge.rb +37 -82
  38. data/lib/{action/thor_action.rb → epubforge/action/action.rb} +89 -69
  39. data/lib/epubforge/action/action2.rb +109 -0
  40. data/lib/epubforge/action/action_definition.rb +62 -0
  41. data/lib/epubforge/action/actions_lookup.rb +45 -0
  42. data/lib/epubforge/action/chatterbox.rb +93 -0
  43. data/lib/{action → epubforge/action}/cli_command.rb +2 -2
  44. data/lib/{action → epubforge/action}/cli_sequence.rb +0 -0
  45. data/lib/{action → epubforge/action}/file_transformer.rb +0 -0
  46. data/lib/{action → epubforge/action}/hooks_interface.rb +2 -2
  47. data/lib/{action → epubforge/action}/run_description.rb +12 -9
  48. data/lib/{action → epubforge/action}/runner.rb +23 -24
  49. data/lib/{epub → epubforge/builder}/assets/asset.rb +1 -1
  50. data/lib/{epub → epubforge/builder}/assets/font.rb +1 -1
  51. data/lib/epubforge/builder/assets/html.rb +9 -0
  52. data/lib/{epub → epubforge/builder}/assets/image.rb +1 -1
  53. data/lib/epubforge/builder/assets/markdown.rb +9 -0
  54. data/lib/{epub → epubforge/builder}/assets/page.rb +12 -4
  55. data/lib/{epub → epubforge/builder}/assets/stylesheet.rb +1 -1
  56. data/lib/epubforge/builder/assets/textile.rb +9 -0
  57. data/lib/epubforge/builder/assets/xhtml.rb +9 -0
  58. data/lib/epubforge/builder/builder.rb +134 -0
  59. data/lib/{epub/builder.rb → epubforge/builder/epub.rb} +58 -161
  60. data/lib/epubforge/builder/html.rb +22 -0
  61. data/lib/epubforge/builder/packager.rb +16 -0
  62. data/lib/epubforge/core_extensions/array.rb +2 -0
  63. data/lib/{core_extensions → epubforge/core_extensions}/kernel.rb +0 -0
  64. data/lib/epubforge/core_extensions/nil_class.rb +2 -0
  65. data/lib/epubforge/core_extensions/object.rb +24 -0
  66. data/lib/{core_extensions → epubforge/core_extensions}/string.rb +1 -5
  67. data/lib/{custom_helpers.rb → epubforge/custom_helpers.rb} +0 -1
  68. data/lib/{errors.rb → epubforge/exceptions/errors.rb} +0 -0
  69. data/lib/{project → epubforge/project}/project.rb +23 -17
  70. data/lib/epubforge/utils/action_loader.rb +8 -0
  71. data/lib/epubforge/utils/class_loader.rb +102 -0
  72. data/lib/epubforge/utils/converter.rb +94 -0
  73. data/lib/{utils → epubforge/utils}/downloader.rb +0 -0
  74. data/lib/{utils → epubforge/utils}/file_orderer.rb +0 -0
  75. data/lib/epubforge/utils/file_path.rb +8 -0
  76. data/lib/epubforge/utils/html_translator.rb +126 -0
  77. data/lib/epubforge/utils/html_translator_queue.rb +113 -0
  78. data/lib/epubforge/utils/htmlizer.rb +61 -0
  79. data/lib/{utils → epubforge/utils}/misc.rb +0 -0
  80. data/lib/epubforge/utils/root_path.rb +8 -0
  81. data/lib/epubforge/utils/settings.rb +147 -0
  82. data/lib/epubforge/utils/template_evaluator.rb +7 -0
  83. data/templates/{default/book/afterword.markdown.template → project/book/afterword.markdown} +0 -0
  84. data/templates/project/book/chapter-%0000chapter%.markdown.template +4 -0
  85. data/templates/{default → project}/book/cover.xhtml.template +2 -2
  86. data/templates/{default/book/foreword.markdown.template → project/book/foreword.markdown} +0 -0
  87. data/templates/{default → project}/book/images/cover.png +0 -0
  88. data/templates/{default/book/stylesheets/stylesheet.css.template → project/book/stylesheets/stylesheet.css} +0 -0
  89. data/templates/project/book/title_page.markdown.template +5 -0
  90. data/templates/project/notes/character.%character.name_for_file%.markdown.template +15 -0
  91. data/templates/{default → project}/notes/images/cover.png +0 -0
  92. data/templates/{default/notes/stylesheets/stylesheet.css.template → project/notes/stylesheets/stylesheet.css} +0 -0
  93. data/templates/{default → project}/settings/actions/local_action.rb.example +1 -1
  94. data/templates/project/settings/config.rb.template +70 -0
  95. data/templates/project/settings/html_translators/example_translator.rb +29 -0
  96. data/templates/{default → project}/settings/wordcount.template +1 -1
  97. data/test/answers01.yml +30 -0
  98. data/test/helper.rb +62 -39
  99. data/test/misc/config.rb +5 -7
  100. data/test/test_epubforge.rb +18 -14
  101. data/test/{test_htmlizers.rb → test_html_translators.rb} +4 -8
  102. data/test/test_template_evaluator.rb +42 -0
  103. data/test/test_utils.rb +0 -11
  104. metadata +186 -189
  105. data/config/actions/gitify.rb +0 -72
  106. data/config/actions/init.rb +0 -138
  107. data/config/actions/notes_to_epub.rb +0 -18
  108. data/config/actions/notes_to_kindle.rb +0 -17
  109. data/config/htmlizers.rb +0 -70
  110. data/lib/action/actions_lookup.rb +0 -45
  111. data/lib/core_extensions/array.rb +0 -5
  112. data/lib/core_extensions/nil_class.rb +0 -5
  113. data/lib/core_extensions/object.rb +0 -5
  114. data/lib/epub/assets/html.rb +0 -8
  115. data/lib/epub/assets/markdown.rb +0 -8
  116. data/lib/epub/assets/textile.rb +0 -8
  117. data/lib/epub/assets/xhtml.rb +0 -8
  118. data/lib/epub/packager.rb +0 -16
  119. data/lib/utils/action_loader.rb +0 -7
  120. data/lib/utils/class_loader.rb +0 -102
  121. data/lib/utils/directory_builder.rb +0 -181
  122. data/lib/utils/file_path.rb +0 -152
  123. data/lib/utils/html_translator.rb +0 -100
  124. data/lib/utils/html_translator_queue.rb +0 -70
  125. data/lib/utils/htmlizer.rb +0 -92
  126. data/lib/utils/root_path.rb +0 -20
  127. data/lib/utils/settings.rb +0 -146
  128. data/lib/utils/template_evaluator.rb +0 -20
  129. data/templates/default/book/chapter-%i%.markdown.sequence +0 -4
  130. data/templates/default/book/title_page.markdown.template +0 -4
  131. data/templates/default/notes/character.named.markdown.template +0 -4
  132. data/templates/default/payload.rb +0 -65
  133. data/templates/default/settings/config.rb.form +0 -55
  134. data/templates/default/settings/htmlizers.rb +0 -0
  135. 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
@@ -0,0 +1,2 @@
1
+ class Array
2
+ end
@@ -0,0 +1,2 @@
1
+ class NilClass
2
+ end
@@ -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(&:epf_blank?)
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
@@ -63,4 +63,3 @@ module EpubForge
63
63
  end
64
64
  end
65
65
 
66
- EpubForge.extend( EpubForge::CustomHelpers )
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 :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
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( target_dir )
13
- @target_dir = FunWith::Files::FilePath.new( target_dir ).expand
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 || @target_dir.join( "notes" )
18
- @book_dir = config.book_dir || @target_dir.join( "book" )
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
- @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" )
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 || @target_dir.basename.to_s.gsub( /\.epubforge$/ , '' )
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
- @target_dir.exist? && config_file.exist?
38
+ @root_dir.exist? && config_file.exist?
42
39
  end
43
40
 
44
41
  def settings_folder(*args)
45
- @settings_folder ||= @target_dir.join( 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::Epub::PAGE_FILE_EXTENSIONS ) )
71
+ orderer.reorder( @book_dir.glob( ext: EpubForge::Builder::PAGE_FILE_EXTENSIONS ) )
75
72
  end
76
73
 
77
74
  def load_configuration
78
- self.install_fwc_config_from_file( config_file )
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,8 @@
1
+ # module EpubForge
2
+ # module Action
3
+ # class Registry
4
+ # include FunWith::Patterns::Loader
5
+ # alias :loader_pattern_registry_key :keyword
6
+ # end
7
+ # end
8
+ # 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,8 @@
1
+ # Should be obsoleted by FunWith::Files::FilePath
2
+ # Emptying to see if anything breaks.
3
+ module EpubForge
4
+ module Utils
5
+ class FilePath < Pathname
6
+ end
7
+ end
8
+ end
@@ -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