# epubbuilder.rb # derived from htmlbuider.rb # # Copyright (c) 2010 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. # require 'review/builder' require 'review/htmlutils' require 'review/htmllayout' require 'review/textutils' require 'review/htmlbuilder' module ReVIEW class EPUBBuilder < HTMLBuilder [:u, :tti, :idx, :hidx].each {|e| Compiler.definline(e) } Compiler.defsingle(:indepimage, 1) Compiler.defblock(:memo, 0..1) Compiler.defblock(:tip, 0..1) Compiler.defblock(:info, 0..1) Compiler.defblock(:planning, 0..1) Compiler.defblock(:best, 0..1) Compiler.defblock(:important, 0..1) Compiler.defblock(:security, 0..1) Compiler.defblock(:caution, 0..1) Compiler.defblock(:notice, 0..1) Compiler.defblock(:point, 0..1) Compiler.defblock(:shoot, 0..1) def builder_init(no_error = false) @no_error = no_error @section = 0 @subsection = 0 @subsubsection = 0 @subsubsubsection = 0 end private :builder_init def extname '.html' end def raw_result @output.string end def result layout_file = File.join(@book.basedir, "layouts", "layout.erb") if File.exists?(layout_file) messages() + HTMLLayout.new(@output.string, @chapter.title, layout_file).result else # FIXME header = < EOT unless @param["stylesheet"].nil? header += < EOT end header += < #{@chapter.title} EOT footer = < EOT header + messages() + @output.string + footer end end def headline_prefix(level) anchor = "" case level when 1 @section = 0 @subsection = 0 @subsubsection = 0 @subsubsubsection = 0 anchor = "#{@chapter.number}" if @param["secnolevel"] >= 1 if @chapter.number.to_s =~ /\A\d+$/ prefix = "第#{@chapter.number}章 " elsif !@chapter.number.nil? && !@chapter.number.to_s.empty? prefix = "#{@chapter.number} " end end when 2 @section += 1 @subsection = 0 @subsubsection = 0 @subsubsubsection = 0 anchor = "#{@chapter.number}-#{@section}" if @param["secnolevel"] >= 2 if @chapter.number.to_s =~ /\A\d+$/ prefix = "#{@chapter.number}.#{@section} " elsif !@chapter.number.nil? && !@chapter.number.to_s.empty? prefix = "#{@chapter.number}.#{@section} " end end when 3 @subsection += 1 @subsubsection = 0 @subsubsubsection = 0 anchor = "#{@chapter.number}-#{@section}-#{@subsection}" if @param["secnolevel"] >= 3 if @chapter.number.to_s =~ /\A\d+$/ prefix = "#{@chapter.number}.#{@section}.#{@subsection} " elsif !@chapter.number.nil? && !@chapter.number.to_s.empty? prefix = "#{@chapter.number}.#{@section}.#{@subsection} " end end when 4 @subsubsection += 1 @subsubsubsection = 0 anchor = "#{@chapter.number}-#{@section}-#{@subsection}-#{@subsubsection}" if @param["secnolevel"] >= 4 if @chapter.number.to_s =~ /\A\d+$/ prefix = "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection} " elsif !@chapter.number.nil? && !@chapter.number.to_s.empty? prefix = "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection} " end end when 5 @subsubsubsection += 1 anchor = "#{@chapter.number}-#{@section}-#{@subsection}-#{@subsubsection}-#{@subsubsubsection}" if @param["secnolevel"] >= 5 if @chapter.number.to_s =~ /\A\d+$/ prefix = "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection} " elsif !@chapter.number.nil? && !@chapter.number.to_s.empty? prefix = "#{@chapter.number}.#{@section}.#{@subsection}.#{@subsubsection}.#{@subsubsubsection} " end end end [prefix, anchor] end private :headline_prefix def headline(level, label, caption) prefix, anchor = headline_prefix(level) puts '' if level > 1 a_id = "" unless anchor.empty? a_id = "" end if caption.empty? puts a_id unless label.nil? else if label.nil? puts "#{a_id}#{prefix}#{escape_html(caption)}" else puts "#{a_id}#{prefix}#{escape_html(caption)}" end end end def column_begin(level, label, caption) puts "
" headline(level, label, caption) # FIXME end def column_end(level) puts '
' end def xcolumn_begin(level, label, caption) puts "
" headline(level, label, caption) # FIXME end def xcolumn_end(level) puts '
' end def ref_begin(level, label, caption) print "
" headline(level, label, caption) end def ref_end(level) puts '
' end def sup_begin(level, label, caption) print "
" headline(level, label, caption) end def sup_end(level) puts '
' end def tsize(str) # null end def captionblock(type, lines, caption) puts "
" unless caption.nil? puts "

#{escape_html(caption)}

" end lines.each {|l| puts "

#{l}

" } puts '
' end def memo(lines, caption = nil) captionblock("memo", lines, caption) end def tip(lines, caption = nil) captionblock("tip", lines, caption) end def info(lines, caption = nil) captionblock("info", lines, caption) end def planning(lines, caption = nil) captionblock("planning", lines, caption) end def best(lines, caption = nil) captionblock("best", lines, caption) end def important(lines, caption = nil) captionblock("important", lines, caption) end def security(lines, caption = nil) captionblock("security", lines, caption) end def caution(lines, caption = nil) captionblock("caution", lines, caption) end def notice(lines, caption = nil) captionblock("notice", lines, caption) end def point(lines, caption = nil) captionblock("point", lines, caption) end def shot(lines, caption = nil) captionblock("shoot", lines, caption) end def list(lines, id, caption) puts '
' begin list_header id, caption rescue KeyError error "no such list: #{id}" end list_body lines puts '
' end def list_header(id, caption) puts %Q[

リスト#{getChap}#{@chapter.list(id).number}: #{escape_html(caption)}

] end def list_body(lines) puts '
'
      lines.each do |line|
        puts detab(line)
      end
      puts '
' end def source(lines, caption) puts '
' source_header caption source_body lines puts '
' end def source_header(caption) puts %Q[

#{escape_html(caption)}

] end def source_body(lines) puts '
'
      lines.each do |line|
        puts detab(line)
      end
      puts '
' end def listnum(lines, id, caption) puts '
' begin list_header id, caption rescue KeyError error "no such list: #{id}" end listnum_body lines puts '
' end def listnum_body(lines) puts '
'
      lines.each_with_index do |line, i|
        puts detab((i+1).to_s.rjust(2) + ": " + line)
      end
      puts '
' end def emlist(lines, caption = nil) puts '
' puts %Q(

#{caption}

) unless caption.nil? puts '
'
      lines.each do |line|
        puts detab(line)
      end
      puts '
' puts '
' end def emlistnum(lines) puts '
' puts '
'
      lines.each_with_index do |line, i|
        puts detab((i+1).to_s.rjust(2) + ": " + line)
      end
      puts '
' puts '
' end def cmd(lines) puts '
' puts '
'
      lines.each do |line|
        puts detab(line)
      end
      puts '
' puts '
' end def quotedlist(lines, css_class) puts %Q[
]
      lines.each do |line|
        puts detab(line)
      end
      puts '
' end private :quotedlist def quote(lines) puts "
#{lines.join("\n")}
" end def image_image(id, metric, caption) puts %Q[
] puts %Q[(#{escape_html(caption)})] image_header id, caption puts %Q[
] end def image_dummy(id, caption, lines) puts %Q[
] puts %Q[
]
      lines.each do |line|
        puts detab(line)
      end
      puts %Q[
] image_header id, caption puts %Q[
] end def image_header(id, caption) puts %Q[

] puts %Q[図#{getChap}#{@chapter.image(id).number}: #{escape_html(caption)}] puts %Q[

] end def table(lines, id = nil, caption = nil) rows = [] sepidx = nil lines.each_with_index do |line, idx| if /\A[\=\-]{12}/ =~ line # just ignore #error "too many table separator" if sepidx sepidx ||= idx next end rows.push line.strip.split(/\t+/).map {|s| s.sub(/\A\./, '') } end rows = adjust_n_cols(rows) begin table_header id, caption unless caption.nil? rescue KeyError => err error "no such table: #{id}" end table_begin rows.first.size return if rows.empty? if sepidx sepidx.times do tr rows.shift.map {|s| th(compile_inline(s)) } end rows.each do |cols| tr cols.map {|s| td(compile_inline(s)) } end else rows.each do |cols| h, *cs = *cols tr [th(compile_inline(h))] + cs.map {|s| td(compile_inline(s)) } end end table_end end def table_header(id, caption) puts %Q[

表#{getChap}#{@chapter.table(id).number}: #{escape_html(caption)}

] end def table_begin(ncols) puts '' end def tr(rows) puts "#{rows.join('')}" end def th(str) "" end def td(str) "" end def table_end puts '
#{str}#{str}
' end def comment(str) puts %Q() end def footnote(id, str) puts %Q(
) end def hr puts "
" end def label(id) puts %Q() end def linebreak puts "
" end def pagebreak puts %Q(
) end def bpo(lines) puts "" lines.each do |line| puts detab(line) end puts "" end def flushright(lines) puts "

#{lines.join("\n")}

" end def note(lines, caption = nil) puts '
' puts "

#{escape_html(caption)}

" unless caption.nil? puts "#{lines.join("\n")}
" end def inline_fn(id) %Q(
*#{@chapter.footnote(id).number}) end def compile_ruby(base, ruby) %Q[{escape_html(base)}(#{ruby})] end def compile_kw(word, alt) '' + if alt #then escape_html(word + sprintf(@locale[:parens], alt.strip)) then escape_html(word + " (#{alt.strip})") else escape_html(word) end + "" end def compile_href(url, label) %Q(#{label.nil? ? escape_html(url) : escape_html(label)}) end def inline_i(str) %Q(#{escape_html(str)}) end def inline_b(str) %Q(#{escape_html(str)}) end def inline_ami(str) %Q(#{escape_html(str)}) end def inline_tti(str) %Q(#{escape_html(str)}) end def inline_dtp(arg) # ignore all '' end def inline_code(str) %Q(#{str}) end def inline_idx(str) %Q(#{escape_html(str)}) end def inline_hidx(str) %Q() end def text(str) str end def bibpaper_header(id, caption) puts %Q() puts "[#{@chapter.bibpaper(id).number}] #{caption}" puts %Q() end def bibpaper_bibpaper(id, caption, lines) puts %Q(

) lines.each do |line| puts detab(line) end puts %Q(

) end def noindent # dummy end def inline_bib(id) %Q([#{@chapter.bibpaper(id).number}]) end def nofunc_text(str) escape_html(str) end def inline_list(id) "リスト#{getChap}#{@chapter.list(id).number}" rescue KeyError error "unknown list: #{id}" nofunc_text("[UnknownList:#{id}]") end def inline_img(id) "図#{getChap}#{@chapter.image(id).number}" rescue KeyError error "unknown image: #{id}" nofunc_text("[UnknownImage:#{id}]") end def inline_table(id) "表#{getChap}#{@chapter.table(id).number}" rescue KeyError error "unknown table: #{id}" nofunc_text("[UnknownTable:#{id}]") end def inline_asis(str, tag) %Q(<#{tag}>#{escape_html(str)}) end def inline_abbr(str) inline_asis(str, "abbr") end def inline_acronym(str) inline_asis(str, "acronym") end def inline_cite(str) inline_asis(str, "cite") end def inline_dfn(str) inline_asis(str, "dfn") end def inline_em(str) inline_asis(str, "em") end def inline_kbd(str) inline_asis(str, "kbd") end def inline_samp(str) inline_asis(str, "samp") end def inline_strong(str) inline_asis(str, "strong") end def inline_var(str) inline_asis(str, "var") end def inline_big(str) inline_asis(str, "big") end def inline_small(str) inline_asis(str, "small") end def inline_sub(str) inline_asis(str, "sub") end def inline_sup(str) inline_asis(str, "sup") end def inline_tt(str) inline_asis(str, "tt") end def inline_del(str) inline_asis(str, "del") end def inline_ins(str) inline_asis(str, "ins") end def inline_u(str) %Q(#{escape_html(str)}) end def inline_recipe(str) # FIXME %Q(「#{escape_html(str)}」) end def getChap if @param["secnolevel"] > 0 && !@chapter.number.nil? && !@chapter.number.to_s.empty? return "#{@chapter.number}." end return "" end end end # module ReVIEW