# encoding: utf-8 # = epubv2.rb -- EPUB version 2 producer. # # Copyright (c) 2010 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 'epubmaker/producer' module EPUBMaker # EPUBv2 is EPUB version 2 producer. class EPUBv2 # Construct object with parameter hash +params+ and message resource hash +res+. def initialize(producer) @producer = producer end # Return mimetype content. def mimetype return < EOT %w[title language date type format source description relation coverage subject rights].each do |item| next if @producer.params[item].nil? if @producer.params[item].instance_of?(Array) s << @producer.params[item].map {|i| %Q[ #{i}\n]}.join else s << %Q[ #{@producer.params[item]}\n] end end # ID if @producer.params["isbn"].nil? s << %Q[ #{@producer.params["urnid"]}\n] else s << %Q[ #{@producer.params["isbn"]}\n] end # creator %w[aut 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-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].each do |role| next if @producer.params[role].nil? @producer.params[role].each do |v| s << %Q[ #{v}\n] end end # contributor %w[adp ann arr art asn aqt aft aui ant bkp clb cmm dsr edt ill lyr mdc mus nrt oth pht prt red rev spn ths trc trl].each do |role| next if @producer.params[role].nil? @producer.params[role].each do |v| s << %Q[ #{v}\n] if role == "prt" s << %Q[ #{v}\n] end end end if @producer.params["coverimage"] @producer.contents.each do |item| if item.media =~ /\Aimage/ && item.file =~ /#{@producer.params["coverimage"]}\Z/ s << %Q[ \n] break end end end s << %Q[ \n] # manifest s << < EOT s << %Q[ \n] unless @producer.params["mytoc"].nil? @producer.contents.each do |item| next if item.file =~ /#/ # skip subgroup s << %Q[ \n] end s << %Q[ \n] # tocx s << %Q[ \n] s << %Q[ \n] s << %Q[ \n] unless @producer.params["mytoc"].nil? @producer.contents.each do |item| next if item.media !~ /xhtml\+xml/ # skip non XHTML s << %Q[ \n] if item.notoc.nil? end s << %Q[ \n] # guide s << %Q[ \n] s << %Q[ \n] s << %Q[ \n] unless @producer.params["titlepage"].nil? s << %Q[ \n] unless @producer.params["mytoc"].nil? s << %Q[ \n] unless @producer.params["colophon"].nil? # FIXME: path s << %Q[ \n] s << %Q[\n] return s end # Return ncx content. +indentarray+ defines prefix string for each level. def ncx(indentarray) s = < EOT if @producer.params["isbn"].nil? s << %Q[ \n] else s << %Q[ \n] end s << < #{@producer.params["title"]} #{@producer.params["aut"].nil? ? "" : @producer.params["aut"].join(", ")} #{@producer.params["title"]} EOT nav_count = 2 unless @producer.params["mytoc"].nil? s << < #{@producer.res.v("toctitle")} EOT nav_count += 1 end @producer.contents.each do |item| next if item.title.nil? indent = indentarray.nil? ? [""] : indentarray level = item.level.nil? ? 0 : (item.level - 1) level = indent.size - 1 if level >= indent.size s << < #{indent[level]}#{item.title} EOT nav_count += 1 end s << < EOT return s end # Return container content. def container s = < EOT return s end # Return cover content. def cover s = common_header s << <#{@producer.params["title"]} EOT if @producer.params["coverimage"].nil? s << <#{@producer.params["title"]} EOT else file = nil @producer.contents.each do |item| if item.media =~ /\Aimage/ && item.file =~ /#{@producer.params["coverimage"]}\Z/ # / file = item.file break end end raise "coverimage #{@producer.params["coverimage"]} not found. Abort." if file.nil? s << < #{@producer.params[ EOT end s << < EOT return s end # Return title (copying) content. def titlepage s = common_header s << <#{@producer.params["title"]}

#{@producer.params["title"]}

EOT if @producer.params["aut"] s << <

#{@producer.params["aut"]}

EOT end if @producer.params["prt"] s << <



#{@producer.params["prt"]}

EOT end s << < EOT return s end # Return colophon content. def colophon s = common_header s << <#{@producer.res.v("colophontitle")}

#{@producer.params["title"]}

EOT if @producer.params["pubhistory"] s << %Q[
\n

#{@producer.params["pubhistory"].gsub(/\n/, "
")}

\n
\n] # FIXME: should be array? end s << %Q[ \n] s << %Q[ \n] if @producer.params["aut"] s << %Q[ \n] if @producer.params["dsr"] s << %Q[ \n] if @producer.params["ill"] s << %Q[ \n] if @producer.params["edt"] s << %Q[ \n] if @producer.params["prt"] s << < EOT return s end # Return own toc content. def mytoc s = common_header s << <#{@producer.res.v("toctitle")}

#{@producer.res.v("toctitle")}

    EOT # FIXME: indent current = 1 init_item = true @producer.contents.each do |item| next if !item.notoc.nil? || item.level.nil? || item.file.nil? || item.title.nil? || item.level > @producer.params["toclevel"].to_i if item.level > current s << %Q[\n
      \n] current = item.level elsif item.level < current (current - 1).downto(item.level) do |n| s << %Q[\n
    \n] end s << %Q[\n] current = item.level elsif init_item # noop else s << %Q[\n] end s << %Q[
  • #{item.title}] init_item = false end (current - 1).downto(1) do |n| s << %Q[
  • \n
\n] end if !init_item s << %Q[\n] end s << < EOT return s end # Produce EPUB file +epubfile+. # +basedir+ points the directory has contents. # +tmpdir+ defines temporary directory. def produce(epubfile, basedir, tmpdir) File.open("#{tmpdir}/mimetype", "w") {|f| @producer.mimetype(f) } Dir.mkdir("#{tmpdir}/META-INF") unless File.exist?("#{tmpdir}/META-INF") File.open("#{tmpdir}/META-INF/container.xml", "w") {|f| @producer.container(f) } Dir.mkdir("#{tmpdir}/OEBPS") unless File.exist?("#{tmpdir}/OEBPS") File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}.opf", "w") {|f| @producer.opf(f) } File.open("#{tmpdir}/OEBPS/#{@producer.params["bookname"]}.ncx", "w") {|f| @producer.ncx(f, @producer.params["ncxindent"]) } File.open("#{tmpdir}/OEBPS/#{@producer.params["tocfile"]}", "w") {|f| @producer.mytoc(f) } unless @producer.params["mytoc"].nil? if File.exist?("#{basedir}/#{@producer.params["cover"]}") FileUtils.cp("#{basedir}/#{@producer.params["cover"]}", "#{tmpdir}/OEBPS") else File.open("#{tmpdir}/OEBPS/#{@producer.params["cover"]}", "w") {|f| @producer.cover(f) } end # FIXME:colophon and titlepage should be included in @producer.contents. @producer.contents.each do |item| next if item.file =~ /#/ # skip subgroup fname = "#{basedir}/#{item.file}" raise "#{fname} doesn't exist. Abort." unless File.exist?(fname) FileUtils.mkdir_p(File.dirname("#{tmpdir}/OEBPS/#{item.file}")) unless File.exist?(File.dirname("#{tmpdir}/OEBPS/#{item.file}")) FileUtils.cp(fname, "#{tmpdir}/OEBPS/#{item.file}") end fork { Dir.chdir(tmpdir) {|d| exec("zip -0X #{epubfile} mimetype") } } Process.waitall fork { Dir.chdir(tmpdir) {|d| exec("zip -Xr9D #{epubfile} META-INF OEBPS") } } Process.waitall end private # Return common XHTML headder def common_header s =< EOT @producer.params["stylesheet"].each do |file| s << %Q[ \n] end return s end end end
#{@producer.res.v("c-aut")}#{@producer.params["aut"]}
#{@producer.res.v("c-dsr")}#{@producer.params["dsr"]}
#{@producer.res.v("c-ill")}#{@producer.params["ill"]}
#{@producer.res.v("c-edt")}#{@producer.params["edt"]}
#{@producer.res.v("c-prt")}#{@producer.params["prt"]}