# = epubcommon.rb -- super class for EPUBv2 and EPUBv3 # # Copyright (c) 2010-2023 Kenshi Muto and Masayoshi Takahashi # # 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 'review/i18n' require 'review/template' begin require 'cgi/escape' rescue LoadError require 'cgi/util' end module ReVIEW class EPUBMaker # EPUBCommon is the common class for EPUB producer. # Some methods of this class are overridden by subclasses class EPUBCommon # Construct object with parameter hash +config+ and message resource hash +res+. def initialize(producer) @config = producer.config @contents = producer.contents @body_ext = nil @logger = ReVIEW.logger @workdir = nil end attr_reader :config attr_reader :contents def h(str) CGI.escapeHTML(str) end def produce(_epubfile, _basedir, _tmpdir, base_dir:) @workdir = base_dir raise NotImplementedError # should be overridden end # Return mimetype content. def mimetype 'application/epub+zip' end def opf raise NotImplementedError # should be overridden end def opf_manifest raise NotImplementedError # should be overridden end def opf_metainfo raise NotImplementedError # should be overridden end def opf_tocx raise NotImplementedError # should be overridden end def opf_path "OEBPS/#{config['bookname']}.opf" end def opf_coverimage if config['coverimage'] item = contents.find { |content| content.coverimage?(config['coverimage']) } unless item raise ApplicationError, "coverimage #{config['coverimage']} not found. Abort." end %Q( \n) else '' end end def ncx(indentarray) raise NotImplementedError # should be overridden end # Return container content. def container @opf_path = opf_path ReVIEW::Template.generate(path: './xml/container.xml.erb', binding: binding) end def coverimage return nil unless config['coverimage'] item = contents.find { |content| content.coverimage?(config['coverimage']) } if item item.file end end def template_name(localfile: 'layout.html.erb', systemfile: nil) if @workdir layoutfile = File.join(@workdir, 'layouts', localfile) if File.exist?(layoutfile) return layoutfile end end if systemfile return systemfile end if config['htmlversion'].to_i == 5 './html/layout-html5.html.erb' else './html/layout-xhtml1.html.erb' end end # Return cover content. # If Producer#config["coverimage"] is defined, it will be used for # the cover image. def cover @body_ext = config['epubversion'] >= 3 ? %Q( epub:type="cover") : nil if config['coverimage'] @coverimage_src = coverimage raise ApplicationError, "coverimage #{config['coverimage']} not found. Abort." unless @coverimage_src end @body = ReVIEW::Template.generate(path: template_name(localfile: '_cover.html.erb', systemfile: 'html/_cover.html.erb'), binding: binding) @title = h(config.name_of('title')) @language = config['language'] @stylesheets = config['stylesheet'] ret = ReVIEW::Template.generate(path: template_name, binding: binding) @body_ext = nil ret end # Return title (copying) content. # NOTE: this method is not used yet. # see lib/review/epubmaker.rb#build_titlepage def titlepage @title = h(config.name_of('title')) @title_str = config.name_of('title') if config['subtitle'] @subtitle_str = config.name_of('subtitle') end if config['aut'] @author_str = join_with_separator(config.names_of('aut'), ReVIEW::I18n.t('names_splitter')) end if config.names_of('pbl') @publisher_str = join_with_separator(config.names_of('pbl'), ReVIEW::I18n.t('names_splitter')) end @body = ReVIEW::Template.generate(path: template_name(localfile: '_titlepage.html.erb', systemfile: './html/_titlepage.html.erb'), binding: binding) @language = config['language'] @stylesheets = config['stylesheet'] ReVIEW::Template.generate(path: template_name, binding: binding) end # Return colophon content. def colophon @title = h(ReVIEW::I18n.t('colophontitle')) @isbn_hyphen = isbn_hyphen @body = ReVIEW::Template.generate(path: template_name(localfile: '_colophon.html.erb', systemfile: './html/_colophon.html.erb'), binding: binding) @language = config['language'] @stylesheets = config['stylesheet'] ReVIEW::Template.generate(path: template_name, binding: binding) end def isbn_hyphen str = config['isbn'].to_s if /\A\d{10}\Z/.match?(str) "#{str[0..0]}-#{str[1..5]}-#{str[6..8]}-#{str[9..9]}" elsif /\A\d{13}\Z/.match?(str) "#{str[0..2]}-#{str[3..3]}-#{str[4..8]}-#{str[9..11]}-#{str[12..12]}" end end def colophon_history @col_history = [] if config['history'] config['history'].each_with_index do |items, edit| items.each_with_index do |item, rev| editstr = edit == 0 ? ReVIEW::I18n.t('first_edition') : ReVIEW::I18n.t('nth_edition', (edit + 1).to_s) revstr = ReVIEW::I18n.t('nth_impression', (rev + 1).to_s) if /\A\d+-\d+-\d+\Z/.match?(item) @col_history << ReVIEW::I18n.t('published_by1', [date_to_s(item), editstr + revstr]) elsif /\A(\d+-\d+-\d+)[\s ](.+)/.match?(item) # custom date with string item.match(/\A(\d+-\d+-\d+)[\s ](.+)/) do |m| @col_history << ReVIEW::I18n.t('published_by3', [date_to_s(m[1]), m[2]]) end else # free format @col_history << item end end end end ReVIEW::Template.generate(path: template_name(localfile: '_colophon_history.html.erb', systemfile: './html/_colophon_history.html.erb'), binding: binding) end def date_to_s(date) require 'date' d = Date.parse(date) d.strftime(ReVIEW::I18n.t('date_format')) end # Return own toc content. def mytoc @title = h(ReVIEW::I18n.t('toctitle')) @body = %Q(