# -*- coding: utf-8 -*- require 'rubygems' require 'erb' require 'uv' module OrgParse module VisitorUtils def execute(node) puts "not implimented => #{node.inspect}" end def exec_list(nodes) ret = '' nodes.each{|n| ret += execute(n) } ret end def exec_children(node) exec_list node.children end end class OrgVisitor @@image_exts = ['jpeg', 'jpg', 'png', 'gif', 'bmp', 'tiff', 'srg'] def initialize make_image_regs @@image_exts end def make_image_regs(exts) @image_file_reg = /\.(#{exts.join('|')})$/ end end # todo: # \\- \\- # -- – -- # --- — --- # ... … \ldots # output HTML format class HtmlVisitor < OrgVisitor include VisitorUtils TEMPLATE = ::File.join(OrgParse::LIBPATH , 'org-parse', 'templates', 'single.html.erb') attr_reader :body def initialize(root, template = nil, cm_opt = {}) @body = @title = @add_to_head = '' @root = root @ul_stack = [] super() template = TEMPLATE unless template @erb = ERB.new(::File.read(template)) @p_tag_flag = true @list_level = 0 @indent_stack = [0] @body = '' @curr_level = 0 @para_level = 0 @options = cm_opt end def make_image_regs(exts) @image_file_reg = /\.(#{exts.join('|')})$/ end # remove HTML tags def rm_html_tag(str) str.sub!(/<[^<>]*>/,"") while /<[^<>]*>/ =~ str str end # build the HTML string def build @options = @root.options @title = exec_list @root.options[:title] @language = @root.options[:language] @charset = @root.options[:charset] @body = '' @footnotes = [] @footnote_idxs = [] @before_text = '' @before_text = exec_list @options[:text] # .each {|n| @before_text += execute(n)} @add_to_head = @options[:style] start_flag = true @root.children.each do |node| if start_flag and node.kind != :SECTION @before_text += execute(node) else start_flag = false @body += execute(node) end end @language = @root.options[:language] @erb.result(binding) end def section_indent(level = nil) level = @curr_level if level.nil? ' ' * level end def get_indent base = section_indent base += (' ' * @list_level) base += (' ' * @para_level) end def close_ul_sec(level) str = '' while @ul_stack.last and @ul_stack.last > level indent = section_indent(@ul_stack.last - 1) @ul_stack.pop str += "#{indent}\n" end str end def table_of_contents toc = "
\n#{exec_children(node).chomp}\n#{indent}
\n" @para_level -= 1 str else str = exec_children node @p_tag_flag = true # next paragraph has
str
end
end
def textline(node)
if node.example? or (node.src? and !@options[:uv])
indent = ' ' * @indent_stack.last
return h node.value.sub(/^#{indent}/,'')
elsif node.src? and @options[:uv]
return node.value
elsif node.html?
return node.value
else
indent = get_indent
str = exec_children(node).sub(/^\s*/, '')
if node.verse?
n = node.indent - @indent_stack.last
n = 0 if n < 0
indent = ' ' * n
indent + str.gsub(/\n/, "
\n")
else
indent + str
end
end
end
def verse(node)
pre = get_indent + %Q|
\n| post = get_indent + "
\n" @indent_stack << node.indent body = exec_children node @indent_stack.pop pre + body.chomp + "\n" + post end def example(node) indent = get_indent this_indent = 0 this_indent = node.children[0].children[0].indent @indent_stack << this_indent body = exec_children(node) @indent_stack.pop %Q|\n#{ body.chomp }\n\n| end def src(node) if @options[:uv] text = exec_children(node) syntax = node.syntax syntax = 'lisp' if syntax == 'emacs-lisp' theme = node.syntax_theme theme = 'amy' if theme.empty? begin Uv.parse( text, "xhtml", syntax, true, theme) rescue "uv can't parse #{syntax}/#{theme}
\n#{body.chomp}\n#{indent}\n| end def blocks(node) case node.block_name when 'VERSE' verse node when 'EXAMPLE' example node when 'QUOTE' blockquote node when 'HTML' html_quote node when 'COMMENT' '' when 'SRC' src node else puts "not implimented block=>[#{node.block_name}](#{node.inspect})" exec_children(node) end end def image_tag(uri, attr = '') %Q|| end def link(node) if node.caption.nil? mk_link(node) else %Q|
#{mk_link(node)}
#{node.caption}
#{n} #{val}
\n| } ret end def execute(node) # puts "node:#{node.kind} [#{node.value}]\n" # STDERR.puts node.inspect return '' if node.done? case node.kind when :SECTION section node when :HEADLINE headline node when :TEXTBLOCK textblock node when :WHITELINE, :WHITELINES @p_tag_flag = true if node.verse? "#{ exec_children node }
"
when :VARIABLE
variable node
when :UNORDERED_LIST, :ORDERED_LIST, :DEFINITION_LIST
lists node
when :LIST_ITEM
list_item node
when :LINK
link node
when :BLOCK
blocks node
when :TABLE
table node
when :TABLE_ROW
table_row node
when :FN_LINK
footnote_link node
when :FN_DEFINE
footnote_define node
else
puts "not implimented=>[#{node.kind}](#{node.inspect})"
''
end
end
# HTML escape
def html_escape(s)
s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/, "<")
end
alias h html_escape
end
end