# rd2html.rb for Hiki/RD+ # # Copyright (C) 2003,2004 Masao Mutoh # # You can redistribute it and/or modify it under the terms of # the Ruby's licence. # # The original rd2html-lib.rb in rdtool-0.6.11: # Copyright (C) 2002 Tosh # # You can redistribute it and/or modify it under the terms of # the Ruby's licence. require "cgi" require "rd/rd2html-lib" require 'style/rd+/anchorlist' require 'hiki/pluginutil' module Hiki class RD2HTMLVisitor < RD::RD2HTMLVisitor attr_reader :references, :toc EVAL_PLUGIN_RE = /\{\{(.*?)\}\}/m LAST_WORD_RE = /^[A-Z0-9_]*$/ CLASS_RE = /\#|::|\./ CHR_ENTITY_RE = "<|>|&|"" CONSTANT_RE = /([a-zA-Z0-9_\+!\?\=\|\[\]]|#{CHR_ENTITY_RE})+/ ESC_WORD = '_h_i-k-i_' ESC_WORD_RE = /#{ESC_WORD}/ def initialize(plugin, db, conf) super() @title = "Untitled" @plugin = plugin @db = db @conf = conf @references = Array.new @regex = nil @toc = [] if text = @db.load("ModuleNames") @modulenames = text.split(/\s/).join("|") @esc_modulenames = /(#{text.split(/\s/).join(ESC_WORD + "|") + ESC_WORD})/ @regex_modulenames = /#{@modulenames}/ @regex = /(#{@modulenames})[\#\.\:](#{CHR_ENTITY_RE}|[a-zA-Z0-9_\#\.\:\=\[])*(#{CHR_ENTITY_RE}|[a-zA-Z0-9_!\+\?\=&\|\]])/ end #InterWikiName @anchorlist = AnchorList.new(@db.load(@conf.interwiki_name), plugin) end def get_anchor(element) element.label.escape end def div_class_method(s) if sep = s.scan(CLASS_RE) # Gtk::Hoge#fuga, Gtk::Hoge.fuga, Gtk::Hoge::Foo # If Gtk::Hoge. << period for document, unscan it. if constant = s.scan(CONSTANT_RE) constant = constant.unescapeHTML child = div_class_method(s) if child [sep, constant] << child else [sep, constant] end else [sep] end else nil end end def special_parse(content) return content if content.nil? or content == "" #Eval Plugin content = content.gsub(EVAL_PLUGIN_RE) do |match| method = $1 ret = '' begin ret = Hiki::Util.apply_plugin(method, @plugin, @conf) ret.gsub!(@regex_modulenames, "\\&#{ESC_WORD}") if @regex_modulenames rescue Exception err = "Plugin Error: #{$!}" #
#{match.to_s.escapeHTML}
" if @conf.plugin_debug err += "

Back trace

"
            $!.backtrace.each do |v|
              err += v + "\n"
              break if v =~ /special_parse/
            end
            err += "
" end ret = err end ret end #Special Parse if @regex content = content.gsub(@regex) do |match| s = StringScanner.new(match) module_name = s.scan(@regex_modulenames) separator = "" lastword = "" name = "" option = nil divary = div_class_method(s) if divary divary.flatten! lastword = divary.pop separator = divary.pop if divary.size == 0 if separator == "::" if lastword =~ LAST_WORD_RE # Constants target = module_name.escape name = module_name + separator + lastword option = lastword else # Class module_name += separator + lastword target = module_name.escape name = module_name end else # Module method target = module_name.escape name = module_name + separator + lastword option = module_name + (separator + lastword).escape end elsif divary.size > 1 module_name += divary.join target = module_name.escape name = module_name + separator + lastword if separator == "." option = "#{target}.#{lastword.escape}" else option = lastword.escape end end #Create result if @db.exist?(module_name) @references << module_name if option ret = @plugin.hiki_anchor(target + "#" + option, name) else ret = @plugin.hiki_anchor(target, name) end else ret = %Q[#{name}?] end ret else match end end content = content.gsub(@esc_modulenames) do |match| match.gsub(ESC_WORD_RE, "") end end content end def apply_to_DocumentElement(element, content) html_body(content) + "\n" end def a_name_href(anchor, label) if label.is_a? String label.gsub!(ESC_WORD_RE, "") else label[0].gsub!(ESC_WORD_RE, "") end %Q[#{label}] end def apply_to_Headline(element, title) title = special_parse(title.join) anchor = get_anchor(element) label = hyphen_escape(element.label) @toc.push({'level' => element.level, 'index' => anchor, 'title' => title}) depth = element.level depth += @conf.options['rd.header_depth'] - 1 if @conf.options['rd.header_depth'] %Q[#{a_name_href(anchor, title)}] + %Q[] end def apply_to_TextBlock(element, content) content = content.join("") content = special_parse(content) if (is_this_textblock_only_one_block_of_parent_listitem?(element) or is_this_textblock_only_one_block_other_than_sublists_in_parent_listitem?(element)) content.chomp else %Q[

#{content.chomp}

] end end def apply_to_DescListItem(element, term, description) anchor = get_anchor(element.term) label = hyphen_escape(element.label) if description.empty? %Q[
#{a_name_href(anchor, term)}
] else %Q[
#{a_name_href(anchor, term)}
\n] + %Q[
\n#{description.join("\n").chomp}\n
] end end def apply_to_MethodListItem(element, term, description) term = parse_method(term) # maybe: term -> element.term anchor = get_anchor(element.term) label = hyphen_escape(element.label) if description.empty? %Q[
#{a_name_href(anchor, "" + term + "")}
] else %Q[
#{a_name_href(anchor, "" + term + "")}
] + %Q[
\n#{description.join("\n")}
] end end def apply_to_Reference_with_URL(element, content) url = element.label.url if /\.(jpg|jpeg|png|gif)\z/ =~ url %Q[#{content.join(] elsif /^(.*?)\#(.*?)$/ =~ url url = $1 + '#' + $2.escape.gsub(/^%/, '').gsub(/%/, '-') content_join = content.join("") if content_join =~ /^\<URL:\#(.*?)\>$/ content_join = $1 end %Q[#{content_join}] else %Q[#{content.join("")}] end end def apply_to_Reference(element, content) content end def apply_to_RefToElement(element, content) content = content.join("") content.gsub!(@regex_modulenames, "\\&#{ESC_WORD}") if @regex_modulenames label = element.to_label key, *option = label.split(/\#/) if @db.infodb_exist? and @db.info_exist?(key) escaped = key.escape if @regex_modulenames escaped.gsub!(@regex_modulenames, "\\&#{ESC_WORD}") escaped += '#' + option.join.gsub(@regex_modulenames, "\\&#{ESC_WORD}").escape if option and option.size > 0 end @references << key internal_link = '' internal_link << '#' + option[0].escape.gsub(/^%/, '').gsub(/%/, '-') if option.size > 0 @plugin.hiki_anchor(escaped + internal_link, content) else key, option, name = @anchorlist.separate(label) if @anchorlist.has_key?(key) name = content if content @anchorlist.create_anchor(key, option, name) else if @regex_modulenames and @regex_modulenames =~ label label.gsub!(@regex_modulenames, "\\&#{ESC_WORD}") end escaped = label.escape content + %Q[?] end end end def apply_to_Verbatim(element) begin require 'rt/rt2html-lib' content = element.content if /\A#\s*RT\s*/ =~ content[0] content.shift rt_visitor = ::RT::RT2HTMLVisitor.new htm = rt_visitor.visit(::RT::RTParser.parse(content.join)) htm = "
\n" + htm + "\n
\n" return htm end rescue LoadError $stderr.puts "RTtool cannot be load" end super(element) end end end