lib/asciidoctor-epub3/packager.rb in asciidoctor-epub3-1.5.0.alpha.11 vs lib/asciidoctor-epub3/packager.rb in asciidoctor-epub3-1.5.0.alpha.12

- old
+ new

@@ -5,19 +5,18 @@ module Asciidoctor module Epub3 module GepubBuilderMixin include ::Asciidoctor::Logging - DATA_DIR = ::File.expand_path ::File.join(::File.dirname(__FILE__), '..', '..', 'data') + DATA_DIR = ::File.expand_path ::File.join(__dir__, '..', '..', 'data') SAMPLES_DIR = ::File.join DATA_DIR, 'samples' LF = ?\n CharEntityRx = ContentConverter::CharEntityRx XmlElementRx = ContentConverter::XmlElementRx FromHtmlSpecialCharsMap = ContentConverter::FromHtmlSpecialCharsMap FromHtmlSpecialCharsRx = ContentConverter::FromHtmlSpecialCharsRx CsvDelimiterRx = /\s*,\s*/ - DefaultCoverImage = 'images/default-cover.png' ImageMacroRx = /^image::?(.*?)\[(.*?)\]$/ ImgSrcScanRx = /<img src="(.+?)"/ SvgImgSniffRx = /<img src=".+?\.svg"/ attr_reader :book, :format, :spine @@ -117,33 +116,32 @@ end nil end def add_cover_image doc + return if (image_path = doc.attr 'front-cover-image').nil? + imagesdir = (doc.attr 'imagesdir', '.').chomp '/' imagesdir = (imagesdir == '.' ? nil : %(#{imagesdir}/)) - if (image_path = doc.attr 'front-cover-image') - image_attrs = {} - if (image_path.include? ':') && image_path =~ ImageMacroRx - logger.warn %(deprecated block macro syntax detected in front-cover-image attribute) if image_path.start_with? 'image::' - image_path = %(#{imagesdir}#{$1}) - (::Asciidoctor::AttributeList.new $2).parse_into image_attrs, %w(alt width height) unless $2.empty? - end - workdir = (workdir = doc.attr 'docdir').nil_or_empty? ? '.' : workdir - if ::File.readable? ::File.join(workdir, image_path) - unless !image_attrs.empty? && (width = image_attrs['width']) && (height = image_attrs['height']) - width, height = 1050, 1600 - end - else - logger.error %(#{::File.basename doc.attr('docfile')}: front cover image not found or readable: #{::File.expand_path image_path, workdir}) - image_path = nil - end + image_attrs = {} + if (image_path.include? ':') && image_path =~ ImageMacroRx + logger.warn %(deprecated block macro syntax detected in front-cover-image attribute) if image_path.start_with? 'image::' + image_path = %(#{imagesdir}#{$1}) + (::Asciidoctor::AttributeList.new $2).parse_into image_attrs, %w(alt width height) unless $2.empty? end - image_path, workdir, width, height = DefaultCoverImage, DATA_DIR, 1050, 1600 unless image_path + workdir = (workdir = doc.attr 'docdir').nil_or_empty? ? '.' : workdir + unless ::File.readable? ::File.join(workdir, image_path) + logger.error %(#{::File.basename doc.attr('docfile')}: front cover image not found or readable: #{::File.expand_path image_path, workdir}) + return + end + unless !image_attrs.empty? && (width = image_attrs['width']) && (height = image_attrs['height']) + width, height = 1050, 1600 + end + resources do cover_image %(#{imagesdir}jacket/cover#{::File.extname image_path}) => (::File.join workdir, image_path) @last_defined_item.tap do |last_item| last_item['width'] = width last_item['height'] = height @@ -152,11 +150,12 @@ nil end # NOTE must be called within the ordered block def add_cover_page doc, spine_builder, manifest - cover_item_attrs = manifest.items['item_cover'].instance_variable_get :@attributes + return if (cover_item_attrs = manifest.items['item_cover'].instance_variable_get :@attributes).nil? + href = cover_item_attrs['href'] # NOTE we only store width and height temporarily to pass through the values width = cover_item_attrs.delete 'width' height = cover_item_attrs.delete 'height' @@ -607,30 +606,50 @@ logger.debug %(Extracted #{fmt.upcase} to #{extract_dir}) end 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 + 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 - argv = [::Kindlegen.command.to_s] + 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| logger.info line end @@ -644,18 +663,37 @@ else logger.error %(kindlegen failed to write MOBI to #{output_file}) 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 - argv += ['-w', epub_file] - out, err, res = Open3.capture3(*argv) + unless (result = ENV['EPUBCHECK']).nil? + logger.debug %(Using EPUBCHECK env variable: #{result}) + return [result] + end + + 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 end err.each_line do |line|