# encoding: utf-8 # # Copyright (c) 2002-2007 Minero Aoki # 2008-2016 Minero Aoki, Kenshi Muto, Masayoshi Takahashi, # KADO Masanori # # 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/template' require 'review/textutils' require 'review/webtocprinter' module ReVIEW class HTMLBuilder < Builder include TextUtils include HTMLUtils [:ref].each {|e| Compiler.definline(e) } Compiler.defblock(:planning, 0..1) Compiler.defblock(:best, 0..1) Compiler.defblock(:security, 0..1) Compiler.defblock(:point, 0..1) Compiler.defblock(:shoot, 0..1) def pre_paragraph '
' end def post_paragraph '
' end def extname ".#{@book.config["htmlext"]}" end def builder_init(no_error = false) @no_error = no_error @noindent = nil @ol_num = nil end private :builder_init def builder_init_file @warns = [] @errors = [] @chapter.book.image_types = %w(.png .jpg .jpeg .gif .svg) @column = 0 @sec_counter = SecCounter.new(5, @chapter) @nonum_counter = 0 @body_ext = nil @toc = nil end private :builder_init_file def result if @book.config.maker == "webmaker" htmldir = "web/html" localfilename = "layout-web.html.erb" else htmldir = "html" localfilename = "layout.html.erb" end if @book.htmlversion == 5 htmlfilename = File.join(htmldir, "layout-html5.html.erb") else htmlfilename = File.join(htmldir, "layout-xhtml1.html.erb") end layout_file = File.join(@book.basedir, "layouts", localfilename) if !File.exist?(layout_file) && File.exist?(File.join(@book.basedir, "layouts", "layout.erb")) raise ReVIEW::ConfigError, "layout.erb is obsoleted. Please use layout.html.erb." end if File.exist?(layout_file) if ENV["REVIEW_SAFE_MODE"].to_i & 4 > 0 warn "user's layout is prohibited in safe mode. ignored." layout_file = File.expand_path(htmlfilename, ReVIEW::Template::TEMPLATE_DIR) end else layout_file = File.expand_path(htmlfilename, ReVIEW::Template::TEMPLATE_DIR) end # default XHTML header/footer @error_messages = error_messages @warning_messages = warning_messages @title = strip_html(compile_inline(@chapter.title)) @body = @output.string @language = @book.config['language'] @stylesheets = @book.config["stylesheet"] @next = @chapter.next_chapter @prev = @chapter.prev_chapter @next_title = @next ? compile_inline(@next.title) : "" @prev_title = @prev ? compile_inline(@prev.title) : "" if @book.config.maker == "webmaker" @toc = ReVIEW::WEBTOCPrinter.book_to_string(@book) end tmpl = ReVIEW::Template.load(layout_file) tmpl.result(binding) end def xmlns_ops_prefix if @book.config["epubversion"].to_i == 3 "epub" else "ops" end end def warn(msg) if @no_error @warns.push [@location.filename, @location.lineno, msg] puts "----WARNING: #{escape_html(msg)}----" else $stderr.puts "#{@location}: warning: #{msg}" end end def error(msg) if @no_error @errors.push [@location.filename, @location.lineno, msg] puts "----ERROR: #{escape_html(msg)}----" else $stderr.puts "#{@location}: error: #{msg}" end end def messages error_messages() + warning_messages() end def error_messages return '' if @errors.empty? "#{compile_inline(caption)}
] end blocked_lines = split_paragraph(lines) puts blocked_lines.join("\n") puts '#{compile_inline(caption)}
] unless caption.nil? print %Q[] lines.each {|line| puts detab(line) } puts '' puts '
#{lines.join}
" else puts %Q[#{lines.join}
] @noindent = nil end end def parasep puts '#{I18n.t("list")}#{I18n.t("format_number_header_without_chapter", [@chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}
] else puts %Q[#{I18n.t("list")}#{I18n.t("format_number_header", [get_chap, @chapter.list(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}
] end end def list_body(id, lines, lang) id ||= '' class_names = ["list"] lexer = lang || File.extname(id).gsub(/\./, '') class_names.push("language-#{lexer}") unless lexer.blank? print %Q[] body = lines.inject(''){|i, j| i + detab(j) + "\n"} puts highlight(:body => body, :lexer => lexer, :format => 'html') puts '' end def source(lines, caption = nil, lang = nil) puts %Q[
#{compile_inline(caption)}
] end end def source_body(id, lines, lang) id ||= '' print %Q[] body = lines.inject(''){|i, j| i + detab(j) + "\n"} lexer = lang || File.extname(id).gsub(/\./, '') puts highlight(:body => body, :lexer => lexer, :format => 'html') puts '' end def listnum(lines, id, caption, lang = nil) puts %Q[
] lines.each_with_index do |line, i| puts detab((i+1).to_s.rjust(2) + ": " + line) end puts '' end end def emlist(lines, caption = nil, lang = nil) puts %Q[
#{compile_inline(caption)}
) end class_names = ["emlist"] class_names.push("language-#{lang}") unless lang.blank? print %Q[] body = lines.inject(''){|i, j| i + detab(j) + "\n"} lexer = lang puts highlight(:body => body, :lexer => lexer, :format => 'html') puts '' puts '
#{compile_inline(caption)}
) end if highlight? body = lines.inject(''){|i, j| i + detab(j) + "\n"} lexer = lang puts highlight(:body => body, :lexer => lexer, :format => 'html', :options => {:linenos => 'inline', :nowrap => false}) else class_names = ["emlist"] class_names.push("language-#{lang}") unless lang.blank? print %Q[] lines.each_with_index do |line, i| puts detab((i+1).to_s.rjust(2) + ": " + line) end puts '' end puts '
#{compile_inline(caption)}
) end print %Q[] body = lines.inject(''){|i, j| i + detab(j) + "\n"} lexer = 'shell-session' puts highlight(:body => body, :lexer => lexer, :format => 'html') puts '' puts '
' end private :quotedlist def quote(lines) blocked_lines = split_paragraph(lines) puts "] lines.each do |line| puts detab(line) end puts '
#{blocked_lines.join("\n")}" end def doorquote(lines, ref) blocked_lines = split_paragraph(lines) puts %Q[
] puts "#{blocked_lines.join("\n")}" puts %Q[] end def talk(lines) puts %Q[#{ref}より
] puts %Q[
' puts "#{lines.join("\n")}" puts '' end puts '
] lines.each do |line| puts detab(line) end puts %Q[] image_header id, caption puts %Q[
] if get_chap.nil? puts %Q[#{I18n.t("image")}#{I18n.t("format_number_header_without_chapter", [@chapter.image(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] else puts %Q[#{I18n.t("image")}#{I18n.t("format_number_header", [get_chap, @chapter.image(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] end 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) if id puts %Q[#{I18n.t("table")}#{I18n.t("format_number_header_without_chapter", [@chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}
] else puts %Q[#{I18n.t("table")}#{I18n.t("format_number_header", [get_chap, @chapter.table(id).number])}#{I18n.t("caption_prefix")}#{compile_inline(caption)}
] end end def table_begin(ncols) puts '#{str} | " end def td(str) "#{str} | " end def table_end puts '
---|
[*#{@chapter.footnote(id).number}] #{compile_inline(str)}
[*#{@chapter.footnote(id).number}] #{compile_inline(str)}
missing image: #{id}] end unless caption.empty? puts %Q[
] puts %Q[#{I18n.t("numberless_image")}#{I18n.t("caption_prefix")}#{compile_inline(caption)}] puts %Q[
] end puts %Q[#{escape_html(str)}
)
else
%Q(#{escape_html(str)})
end
end
def inline_ttb(str)
if @book.htmlversion == 5
%Q(#{escape_html(str)}
)
else
%Q(#{escape_html(str)})
end
end
def inline_dtp(str)
""
end
def inline_code(str)
if @book.htmlversion == 5
%Q(#{escape_html(str)}
)
else
%Q(#{escape_html(str)})
end
end
def inline_idx(str)
%Q(#{escape_html(str)})
end
def inline_hidx(str)
%Q()
end
def inline_br(str)
%Q(#{escape_html(str)}
)
else
%Q(#{escape_html(str)})
end
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)
%Q(「#{escape_html(str)}」)
end
def inline_icon(id)
begin
%Q[missing image: #{id}] end end def inline_uchar(str) %Q(#{str};) end def inline_comment(str) if @book.config["draft"] %Q(#{escape_html(str)}) else %Q() end end def inline_tcy(str) # 縦中横用のtcy、uprightのCSSスタイルについては電書協ガイドラインを参照 style = "tcy" style = "upright" if str.size == 1 && str.match(/[[:ascii:]]/) %Q[#{escape_html(str)}] end def inline_raw(str) super(str) end def nofunc_text(str) escape_html(str) end def compile_href(url, label) if @book.config["externallink"] %Q(#{label.nil? ? escape_html(url) : escape_html(label)}) else label.nil? ? escape_html(url) : I18n.t('external_link', [escape_html(label), escape_html(url)]) end end def flushright(lines) puts split_paragraph(lines).join("\n").gsub("
", "
") end def centering(lines) puts split_paragraph(lines).join("\n").gsub("
", "
") end def image_ext "png" end def olnum(num) @ol_num = num.to_i end end end # module ReVIEW