Skip to content

Commit

Permalink
resolves #276 try to use KindleGen/EPUBCheck binary from $PATH (#277)
Browse files Browse the repository at this point in the history
  • Loading branch information
slonopotamus authored Jan 30, 2020
1 parent 05ec0c6 commit 9707cfc
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 26 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/master[
* make `KINDLEGEN` env var work again (#269)
* enable Pygments on non-Windows JRuby platforms (#264)
* provide a human-readable error message when we fail to find KindleGen (#268)
* try to use KindleGen/EPUBCheck binary from `$PATH` (#276)
* add `ebook-kindlegen-path`/`ebook-epubcheck-path` attributes to override KindleGen/EPUBCheck executable location (#276)

== 1.5.0.alpha.11 (2020-01-26) - @slonopotamus

Expand Down
20 changes: 19 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -540,21 +540,39 @@ For more information about this attribute and other related attributes, see {uri
*-D, --destination-dir* ::
Writes files to specified directory (defaults to the current directory)

*-a ebook-epubcheck-path=<path>*::
Specifies path to EPUBCheck executable to use with `-a ebook-validate`.
This attribute takes precedence over `EPUBCHECK` environment variable.

*-a ebook-extract* ::
Extracts the EPUB3 to a folder in the destination directory after the file is generated

*-a ebook-format=<format>* ::
Specifies the ebook format to generate (epub3 or kf8, default: epub3)

*-a ebook-kindlegen-path=<path>*::
Specifies path to KindleGen executable to use when producing KF8/Mobi.
This attribute takes precedence over `KINDLEGEN` environment variable.

*-a ebook-validate* ::
Runs {uri-epubcheck}[EpubCheck] to validate output file against the EPUB3 specification
Runs {uri-epubcheck}[EPUBCheck] to validate output file against the EPUB3 specification

*-a ebook-compress=<0|1|2|none|standard|huffdic>* ::
Controls the compression type used by kindlegen (0=none [default if unset], 1=standard [default if empty], 2=huffdic)

*-v, --version* ::
Display the program version

=== Environment variables

*EPUBCHECK*::
Specifies path to EPUBCheck executable to use with `-a ebook-validate`.
Effect of this variable can be overriden with `-a ebook-epubcheck-path` attribute.

*KINDLEGEN*::
Specifies path to KindleGen executable to use when producing KF8/Mobi.
Effect of this variable can be overriden with `-a ebook-kindlegen-path` attribute.

=== EPUB3 Archive Structure

Here's a sample manifest of files found in an EPUB3 document produced by {project-name}.
Expand Down
1 change: 0 additions & 1 deletion WORKLOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
* allow role to be applied to chapter (which means the role must be on the document)
* should we enable hyphens in non-Kindle?
** we can reenable once we confirm it doesn't crash Kindle for Mac
* document KINDLEGEN and EPUBCHECK env vars
* part vs chapter? a difference?

* create a video to demonstrate Google Play Books read aloud reading complete sentences in books generated with Asciidoctor EPUB3
Expand Down
6 changes: 5 additions & 1 deletion lib/asciidoctor-epub3/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ def initialize backend, opts
htmlsyntax 'xml'
@validate = false
@extract = false
@kindlegen_path = nil
@epubcheck_path = nil
end

def convert node, name = nil
if (name ||= node.node_name) == 'document'
@validate = node.attr? 'ebook-validate'
@extract = node.attr? 'ebook-extract'
@compress = node.attr 'ebook-compress'
@kindlegen_path = node.attr 'ebook-kindlegen-path'
@epubcheck_path = node.attr 'ebook-epubcheck-path'
spine_items = node.references[:spine_items]
if spine_items.nil?
logger.error %(#{::File.basename node.document.attr('docfile')}: failed to find spine items, produced file will be invalid)
Expand All @@ -44,7 +48,7 @@ def convert node, name = nil

# FIXME: we have to package in write because we don't have access to target before this point
def write packager, target
packager.package validate: @validate, extract: @extract, compress: @compress, target: target
packager.package validate: @validate, extract: @extract, compress: @compress, kindlegen_path: @kindlegen_path, epubcheck_path: @epubcheck_path, target: target
nil
end
end
Expand Down
81 changes: 58 additions & 23 deletions lib/asciidoctor-epub3/packager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -609,30 +609,46 @@ def package options = {}

if fmt == :kf8
# QUESTION shouldn't we validate this epub file too?
distill_epub_to_mobi epub_file, target, options[:compress]
distill_epub_to_mobi epub_file, target, options[:compress], options[:kindlegen_path]
elsif options[:validate]
validate_epub epub_file
validate_epub epub_file, options[:epubcheck_path]
end
end

def distill_epub_to_mobi epub_file, target, compress
if !(kindlegen_cmd = ENV['KINDLEGEN']).nil?
argv = [kindlegen_cmd]
else
begin
require 'kindlegen' unless defined? ::Kindlegen
rescue LoadError => e
raise 'Unable to find KindleGen. Either install the kindlegen gem or set KINDLEGEN environment variable with path to KindleGen executable', cause: e
end
argv = [::Kindlegen.command.to_s]
def get_kindlegen_command kindlegen_path
unless kindlegen_path.nil?
logger.debug %(Using ebook-kindlegen-path attribute: #{kindlegen_path})
return [kindlegen_path]
end

unless (result = ENV['KINDLEGEN']).nil?
logger.debug %(Using KINDLEGEN env variable: #{result})
return [result]
end

begin
require 'kindlegen' unless defined? ::Kindlegen
result = ::Kindlegen.command.to_s
logger.debug %(Using KindleGen from gem: #{result})
[result]
rescue LoadError => e
logger.debug %(#{e}; Using KindleGen from PATH)
[%(kindlegen#{::Gem.win_platform? ? '.exe' : ''})]
end
end

def distill_epub_to_mobi epub_file, target, compress, kindlegen_path
mobi_file = ::File.basename target.sub(EpubExtensionRx, '.mobi')
compress_flag = KindlegenCompression[compress ? (compress.empty? ? '1' : compress.to_s) : '0']
argv += ['-dont_append_source', compress_flag, '-o', mobi_file, epub_file].compact

# This duplicates Kindlegen.run, but we want to override executable
out, err, res = Open3.capture3(*argv) do |r|
r.force_encoding 'UTF-8' if windows? && r.respond_to?(:force_encoding)
argv = get_kindlegen_command(kindlegen_path) + ['-dont_append_source', compress_flag, '-o', mobi_file, epub_file].compact
begin
# This duplicates Kindlegen.run, but we want to override executable
out, err, res = Open3.capture3(*argv) do |r|
r.force_encoding 'UTF-8' if ::Gem.win_platform? && r.respond_to?(:force_encoding)
end
rescue Errno::ENOENT => e
raise 'Unable to run KindleGen. Either install the kindlegen gem or set KINDLEGEN environment variable with path to KindleGen executable', cause: e
end

out.each_line do |line|
Expand All @@ -650,15 +666,34 @@ def distill_epub_to_mobi epub_file, target, compress
end
end

def validate_epub epub_file
if !(epubcheck = ENV['EPUBCHECK']).nil?
argv = [epubcheck]
else
argv = [::Gem.ruby, ::Gem.bin_path('epubcheck-ruby', 'epubcheck')]
def get_epubcheck_command epubcheck_path
unless epubcheck_path.nil?
logger.debug %(Using ebook-epubcheck-path attribute: #{epubcheck_path})
return [epubcheck_path]
end

unless (result = ENV['EPUBCHECK']).nil?
logger.debug %(Using EPUBCHECK env variable: #{result})
return [result]
end

argv += ['-w', epub_file]
out, err, res = Open3.capture3(*argv)
begin
result = ::Gem.bin_path 'epubcheck-ruby', 'epubcheck'
logger.debug %(Using EPUBCheck from gem: #{result})
[::Gem.ruby, result]
rescue ::Gem::Exception => e
logger.debug %(#{e}; Using EPUBCheck from PATH)
['epubcheck']
end
end

def validate_epub epub_file, epubcheck_path
argv = get_epubcheck_command(epubcheck_path) + ['-w', epub_file]
begin
out, err, res = Open3.capture3(*argv)
rescue Errno::ENOENT => e
raise 'Unable to run EPUBCheck. Either install epubcheck-ruby gem or set EPUBCHECK environment variable with path to EPUBCheck executable', cause: e
end

out.each_line do |line|
logger.info line
Expand Down

0 comments on commit 9707cfc

Please sign in to comment.