lib/asciidoctor-epub3/packager.rb in asciidoctor-epub3-1.5.0.alpha.10 vs lib/asciidoctor-epub3/packager.rb in asciidoctor-epub3-1.5.0.alpha.11
- old
+ new
@@ -1,15 +1,14 @@
# frozen_string_literal: true
-require_relative 'core_ext/string'
autoload :FileUtils, 'fileutils'
autoload :Open3, 'open3'
-autoload :Shellwords, 'shellwords'
module Asciidoctor
module Epub3
module GepubBuilderMixin
+ include ::Asciidoctor::Logging
DATA_DIR = ::File.expand_path ::File.join(::File.dirname(__FILE__), '..', '..', 'data')
SAMPLES_DIR = ::File.join DATA_DIR, 'samples'
LF = ?\n
CharEntityRx = ContentConverter::CharEntityRx
XmlElementRx = ContentConverter::XmlElementRx
@@ -124,21 +123,21 @@
imagesdir = (imagesdir == '.' ? nil : %(#{imagesdir}/))
if (image_path = doc.attr 'front-cover-image')
image_attrs = {}
if (image_path.include? ':') && image_path =~ ImageMacroRx
- warn %(asciidoctor: WARNING: deprecated block macro syntax detected in front-cover-image attribute) if image_path.start_with? 'image::'
+ 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
- warn %(asciidoctor: ERROR: #{::File.basename doc.attr('docfile')}: front cover image not found or readable: #{::File.expand_path image_path, workdir})
+ logger.error %(#{::File.basename doc.attr('docfile')}: front cover image not found or readable: #{::File.expand_path image_path, workdir})
image_path = nil
end
end
image_path, workdir, width, height = DefaultCoverImage, DATA_DIR, 1050, 1600 unless image_path
@@ -221,19 +220,20 @@
def add_content_images doc, images
docimagesdir = (doc.attr 'imagesdir', '.').chomp '/'
docimagesdir = (docimagesdir == '.' ? nil : %(#{docimagesdir}/))
+ self_logger = logger
workdir = (workdir = doc.attr 'docdir').nil_or_empty? ? '.' : workdir
resources workdir: workdir do
images.each do |image|
if (image_path = image[:path]).start_with? %(#{docimagesdir}jacket/cover.)
- warn %(asciidoctor: WARNING: image path is reserved for cover artwork: #{image_path}; skipping image found in content)
+ self_logger.warn %(image path is reserved for cover artwork: #{image_path}; skipping image found in content)
elsif ::File.readable? image_path
file image_path
else
- warn %(asciidoctor: ERROR: #{::File.basename image[:docfile]}: image not found or not readable: #{::File.expand_path image_path, workdir})
+ self_logger.error %(#{::File.basename image[:docfile]}: image not found or not readable: #{::File.expand_path image_path, workdir})
end
end
end
nil
end
@@ -245,26 +245,27 @@
resources do
file %(#{imagesdir}avatars/default.jpg) => ::File.join(DATA_DIR, 'images/default-avatar.jpg')
file %(#{imagesdir}headshots/default.jpg) => ::File.join(DATA_DIR, 'images/default-headshot.jpg')
end
+ self_logger = logger
workdir = (workdir = doc.attr 'docdir').nil_or_empty? ? '.' : workdir
resources do
usernames.each do |username|
avatar = %(#{imagesdir}avatars/#{username}.jpg)
if ::File.readable? (resolved_avatar = (::File.join workdir, avatar))
file avatar => resolved_avatar
else
- warn %(asciidoctor: ERROR: avatar for #{username} not found or readable: #{avatar}; falling back to default avatar)
+ self_logger.error %(avatar for #{username} not found or readable: #{avatar}; falling back to default avatar)
file avatar => ::File.join(DATA_DIR, 'images/default-avatar.jpg')
end
headshot = %(#{imagesdir}headshots/#{username}.jpg)
if ::File.readable? (resolved_headshot = (::File.join workdir, headshot))
file headshot => resolved_headshot
elsif doc.attr? 'builder', 'editions'
- warn %(asciidoctor: ERROR: headshot for #{username} not found or readable: #{headshot}; falling back to default headshot)
+ self_logger.error %(headshot for #{username} not found or readable: #{headshot}; falling back to default headshot)
file headshot => ::File.join(DATA_DIR, 'images/default-headshot.jpg')
end
end
end
nil
@@ -473,12 +474,12 @@
(@last_defined_item['properties'] || []).include? property
end
end
class Packager
- KINDLEGEN = ENV['KINDLEGEN'] || 'kindlegen'
- EPUBCHECK = ENV['EPUBCHECK'] || %(epubcheck#{::Gem.win_platform? ? '.bat' : '.sh'})
+ include ::Asciidoctor::Logging
+
EpubExtensionRx = /\.epub$/i
KindlegenCompression = ::Hash['0', '-c0', '1', '-c1', '2', '-c2', 'none', '-c0', 'standard', '-c1', 'huffdic', '-c2']
def initialize spine_doc, spine, format = :epub3, _options = {}
@document = spine_doc
@@ -550,14 +551,18 @@
# TODO: getting author list should be a method on Asciidoctor API
contributors(*authors)
if doc.attr? 'revdate'
- # TODO: ensure this is a real date
- date doc.attr('revdate')
+ begin
+ date doc.attr('revdate')
+ rescue ArgumentError => e
+ logger.error %(#{::File.basename doc.attr('docfile')}: failed to parse revdate: #{e}, using current time as a fallback)
+ date ::Time.now
+ end
else
- date ::Time.now.strftime('%Y-%m-%dT%H:%M:%SZ')
+ date ::Time.now
end
description doc.attr('description') if doc.attr? 'description'
(collect_keywords doc, spine).each do |s|
@@ -581,11 +586,11 @@
::FileUtils.mkdir_p dest unless ::File.directory? dest
epub_file = fmt == :kf8 ? %(#{::Asciidoctor::Helpers.rootname target}-kf8.epub) : target
builder.generate_epub epub_file
- puts %(Wrote #{fmt.upcase} to #{epub_file}) if $VERBOSE
+ logger.debug %(Wrote #{fmt.upcase} to #{epub_file})
if options[:extract]
extract_dir = epub_file.sub EpubExtensionRx, ''
::FileUtils.remove_dir extract_dir if ::File.directory? extract_dir
::Dir.mkdir extract_dir
::Dir.chdir extract_dir do
@@ -597,11 +602,11 @@
end
entry.extract
end
end
end
- puts %(Extracted #{fmt.upcase} to #{extract_dir}) if $VERBOSE
+ 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]
@@ -609,39 +614,70 @@
validate_epub epub_file
end
end
def distill_epub_to_mobi epub_file, target, compress
- kindlegen_cmd = KINDLEGEN
- unless ::File.executable? kindlegen_cmd
+ if !(kindlegen_cmd = ENV['kindlegen']).nil?
+ argv = [kindlegen_cmd]
+ else
require 'kindlegen' unless defined? ::Kindlegen
- kindlegen_cmd = ::Kindlegen.command
+ argv = [::Kindlegen.command.to_s]
end
mobi_file = ::File.basename target.sub(EpubExtensionRx, '.mobi')
compress_flag = KindlegenCompression[compress ? (compress.empty? ? '1' : compress.to_s) : '0']
- cmd = [kindlegen_cmd, '-dont_append_source', compress_flag, '-o', mobi_file, epub_file].compact
- ::Open3.popen2e ::Shellwords.join(cmd) do |_input, output, _wait_thr|
- output.each {|line| puts line } unless $VERBOSE.nil?
+ 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)
end
- puts %(Wrote MOBI to #{::File.join ::File.dirname(epub_file), mobi_file}) if $VERBOSE
+
+ out.each_line do |line|
+ logger.info line
+ end
+ err.each_line do |line|
+ log_line line
+ end
+
+ output_file = ::File.join ::File.dirname(epub_file), mobi_file
+ if res.success?
+ logger.debug %(Wrote MOBI to #{output_file})
+ else
+ logger.error %(kindlegen failed to write MOBI to #{output_file})
+ end
end
def validate_epub epub_file
- if ::File.executable? EPUBCHECK
- argv = [EPUBCHECK]
+ if !(epubcheck = ENV['EPUBCHECK']).nil?
+ argv = [epubcheck]
else
argv = [::Gem.ruby, ::Gem.bin_path('epubcheck-ruby', 'epubcheck')]
end
- if $VERBOSE.nil?
- argv << '-q'
- else
- argv << '-w'
+ argv += ['-w', epub_file]
+ out, err, res = Open3.capture3(*argv)
+
+ out.each_line do |line|
+ logger.info line
end
- argv << epub_file
+ err.each_line do |line|
+ log_line line
+ end
- ::Open3.popen2e ::Shellwords.join(argv) do |_input, output, _wait_thr|
- output.each {|line| puts line }
+ logger.error %(EPUB validation failed: #{epub_file}) unless res.success?
+ end
+
+ def log_line line
+ line = line.strip
+
+ if line =~ /^fatal/i
+ logger.fatal line
+ elsif line =~ /^error/i
+ logger.error line
+ elsif line =~ /^warning/i
+ logger.warn line
+ else
+ logger.info line
end
end
end
end
end