# = 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