# = epubv3.rb -- EPUB version 3 producer.
#
# Copyright (c) 2010-2017 Kenshi Muto
#
# This program is free software.
# You can distribute or modify this program under the terms of
# the GNU LGPL, Lesser General Public License version 2.1.
# For details of the GNU LGPL, see the file "COPYING".
#
require 'epubmaker/epubcommon'
require 'epubmaker/zip_exporter'
module EPUBMaker
# EPUBv3 is EPUB version 3 producer.
class EPUBv3 < EPUBCommon
# Construct object with parameter hash +config+ and message resource hash +res+.
def initialize(producer)
super
@opf_prefix = {}
if @producer.config['opf_prefix'].present?
@producer.config['opf_prefix'].each { |k, v| @opf_prefix[k] = v }
end
end
# Return opf file content.
def opf
@opf_metainfo = opf_metainfo
@opf_coverimage = opf_coverimage
@opf_manifest = opf_manifest
@opf_toc = opf_tocx
@package_attrs = ''
if @opf_prefix && @opf_prefix.size > 0
prefixes_str = @opf_prefix.map { |k, v| %Q(#{k}: #{v}) }.join(' ')
@package_attrs << %Q( prefix="#{prefixes_str}")
end
tmplfile = File.expand_path('./opf/epubv3.opf.erb', ReVIEW::Template::TEMPLATE_DIR)
ReVIEW::Template.load(tmplfile).result(binding)
end
def opf_metainfo
s = ''
%w[title language date type format source description relation coverage subject rights].each do |item|
next unless @producer.config[item]
if @producer.config[item].is_a?(Array)
@producer.config[item].each_with_index do |v, i|
if v.is_a?(Hash)
s << %Q( #{CGI.escapeHTML(v['name'])}\n)
v.each_pair do |name, val|
next if name == 'name'
s << %Q( #{CGI.escapeHTML(val)}\n)
end
else
s << %Q( #{CGI.escapeHTML(v.to_s)}\n)
end
end
elsif @producer.config[item].is_a?(Hash)
s << %Q( #{CGI.escapeHTML(@producer.config[item]['name'])}\n)
@producer.config[item].each_pair do |name, val|
next if name == 'name'
s << %Q( #{CGI.escapeHTML(val)}\n)
end
else
s << %Q( #{CGI.escapeHTML(@producer.config[item].to_s)}\n)
end
end
s << %Q( #{@producer.config['modified']}\n)
# ID
if @producer.config['isbn'].nil?
s << %Q( #{@producer.config['urnid']}\n)
else
s << %Q( #{@producer.config['isbn']}\n)
end
# creator (should be array)
%w[a-adp a-ann a-arr a-art a-asn a-aqt a-aft a-aui a-ant a-bkp a-clb a-cmm a-csl a-dsr a-edt a-ill a-lyr a-mdc a-mus a-nrt a-oth a-pht a-prt a-red a-rev a-spn a-ths a-trc a-trl aut].each do |role|
next unless @producer.config[role]
@producer.config[role].each_with_index do |v, i|
if v.is_a?(Hash)
s << %Q( #{CGI.escapeHTML(v['name'])}\n)
s << %Q( #{role.sub('a-', '')}\n)
v.each_pair do |name, val|
next if name == 'name'
s << %Q( #{CGI.escapeHTML(val)}\n)
end
else
s << %Q( #{CGI.escapeHTML(v)}\n)
s << %Q( #{role.sub('a-', '')}\n)
end
end
end
# contributor (should be array)
%w[adp ann arr art asn aqt aft aui ant bkp clb cmm csl dsr edt ill lyr mdc mus nrt oth pbd pbl pht prt red rev spn ths trc trl].each do |role|
next unless @producer.config[role]
@producer.config[role].each_with_index do |v, i|
if v.is_a?(Hash)
s << %Q( #{CGI.escapeHTML(v['name'])}\n)
s << %Q( #{role}\n)
v.each_pair do |name, val|
next if name == 'name'
s << %Q( #{CGI.escapeHTML(val)}\n)
end
else
s << %Q( #{CGI.escapeHTML(v)}\n)
s << %Q( #{role}\n)
end
if %w[prt pbl].include?(role)
if v.is_a?(Hash)
s << %Q( #{CGI.escapeHTML(v['name'])}\n)
s << %Q( #{role}\n)
v.each_pair do |name, val|
next if name == 'name'
s << %Q( #{CGI.escapeHTML(val)}\n)
end
else
s << %Q( #{CGI.escapeHTML(v)}\n)
s << %Q( prt\n)
end
end
end
end
## add custom element
if @producer.config['opf_meta'].present?
@producer.config['opf_meta'].each do |k, v|
s << %Q( #{CGI.escapeHTML(v)}\n)
end
end
s
end
def opf_manifest
s = ''
s << <
EOT
if @producer.config['coverimage']
@producer.contents.each do |item|
next if !item.media.start_with?('image') || File.basename(item.file) != @producer.config['coverimage']
s << %Q( \n)
item.id = nil
break
end
end
@producer.contents.each do |item|
next if item.file =~ /#/ || item.id.nil? # skip subgroup, or id=nil (for cover)
propstr = ''
if item.properties.size > 0
propstr = %Q( properties="#{item.properties.sort.uniq.join(' ')}")
end
s << %Q( \n)
end
s << %Q( \n)
s
end
def opf_tocx
if @producer.config['epubmaker']['cover_linear'] && @producer.config['epubmaker']['cover_linear'] != 'no'
cover_linear = 'yes'
else
cover_linear = 'no'
end
s = ''
if @producer.config['direction']
s << %Q( \n)
else
s << %Q( \n)
end
s << %Q( \n)
toc = nil
@producer.contents.each do |item|
next if item.media !~ /xhtml\+xml/ # skip non XHTML
if toc.nil? && item.chaptype != 'pre'
if @producer.config['toc']
s << %Q( \n)
end
toc = true
end
s << %Q( \n)
end
s << %Q( \n)
s
end
def ncx(indentarray)
ncx_main = if @producer.config['epubmaker']['flattoc'].nil?
hierarchy_ncx('ol')
else
flat_ncx('ol', @producer.config['epubmaker']['flattocindent'])
end
@body = <
#{CGI.escapeHTML(@producer.res.v('toctitle'))}
#{ncx_main}
EOT
@title = CGI.escapeHTML(@producer.res.v('toctitle'))
@language = @producer.config['language']
@stylesheets = @producer.config['stylesheet']
tmplfile = File.expand_path('./html/layout-html5.html.erb', ReVIEW::Template::TEMPLATE_DIR)
ReVIEW::Template.load(tmplfile).result(binding)
end
# Produce EPUB file +epubfile+.
# +basedir+ points the directory has contents.
# +tmpdir+ defines temporary directory.
def produce(epubfile, basedir, tmpdir)
produce_write_common(basedir, tmpdir)
File.open("#{tmpdir}/OEBPS/#{@producer.config['bookname']}-toc.#{@producer.config['htmlext']}", 'w') { |f| @producer.ncx(f, @producer.config['epubmaker']['ncxindent']) }
@producer.call_hook(@producer.config['epubmaker']['hook_prepack'], tmpdir)
expoter = EPUBMaker::ZipExporter.new(tmpdir, @producer.config)
expoter.export_zip(epubfile)
end
end
end