# $Id: html_formatter.rb,v 1.5 2003-02-23 02:20:08 hitoshi Exp $
# Copyright (C) 2002-2003 TAKEUCHI Hitoshi
require 'hiki/util'
require 'hiki/interwiki'
module Hiki
class HTMLFormatter
MAP = Hash::new
MAP[:heading1_open] = ''
MAP[:heading1_close] = '
'
MAP[:heading2_open] = ''
MAP[:heading2_close] = '
'
MAP[:heading3_open] = ''
MAP[:heading3_close] = '
'
MAP[:heading4_open] = ''
MAP[:heading4_close] = '
'
MAP[:heading5_open] = ''
MAP[:heading5_close] = '
'
MAP[:horizontal_rule] = '
'
MAP[:unordered_list_open] = ''
MAP[:unordered_list_close] = '
'
MAP[:ordered_list_open] = ''
MAP[:ordered_list_close] = '
'
MAP[:listitem_open] = ''
MAP[:listitem_close] = ''
MAP[:blockquote_open] = ''
MAP[:blockquote_close] = '
'
MAP[:definition_list_open] = ''
MAP[:definition_list_close]= '
'
MAP[:definition_term_open] = ''
MAP[:definition_term_close]= ''
MAP[:definition_desc_open] = ''
MAP[:definition_desc_close]= ''
MAP[:pre_open] = ''
MAP[:pre_close] = ''
MAP[:p_open] = ''
MAP[:p_close] = '
'
MAP[:emphasis_open] = ''
MAP[:emphasis_close] = ''
MAP[:strong_open] = ''
MAP[:strong_close] = ''
MAP[:delete_open] = ''
MAP[:delete_close] = ''
def initialize( s, db, plugin, suffix = 'l')
@tokens = s
@db = db
@plugin = plugin
@suffix = suffix
@toc_cnt = 0
@toc = Array::new
@references = Array::new
@interwiki = InterWiki::new( @db )
end
def HTMLFormatter::diff ( d )
s = ''
d.each do |l|
lines = l[2]
case l[0]
when :+
s << "#{lines.join.escapeHTML}\n"
when :-
s << "#{lines.join.escapeHTML}\n"
end
end
s
end
def to_s
html = ''
toc_level = 0
toc_title = ''
normal_text = ''
pre = false
@tokens.each do |t|
if (normal_text.size > 0 && t[:e] != :normal_text)
normal_text.chomp!
html << normal_text
html << "\n" if pre
normal_text = ''
end
case t[:e]
when :normal_text
if pre
html << "#{t[:s].escapeHTML}\n"
else
normal_text << "#{t[:s].escapeHTML}"
toc_title << t[:s] if toc_level > 0
end
when :reference
html << %Q!#{t[:s].escapeHTML}!
toc_title << t[:s] if toc_level > 0
when :wikiname
if @db.exist?( t[:s] )
html << "#{t[:s].escapeHTML}"
@references << t[:s]
else
html << "#{t[:s].escapeHTML}?"
end
toc_title << t[:s] if toc_level > 0
when :interwiki
html << @interwiki.interwiki(t[:href], t[:s])
when :empty
html << "\n"
when :heading1_open, :heading2_open, :heading3_open, :heading4_open, :heading5_open
toc_level = t[:lv]
html << %Q!#{MAP[t[:e]]} !
when :heading1_close, :heading2_close, :heading3_close, :heading4_close, :heading5_close
add_toc( toc_level, toc_title )
toc_level = 0
toc_title = ''
html << "#{MAP[t[:e]]}\n"
when :image
html << %Q!
!
when :plugin, :inline_plugin
tag = ( t[:e] == :plugin ) ? 'div' : 'span'
begin
s = call_plugin_method( t )
if s.class == String
html << %Q!<#{tag} class = "plugin">\n!
html << s
html << "#{tag}>\n"
end
rescue Exception
html << plugin_error( t[:method], $! )
end
else
if t[:e] == :pre_open
pre = true
elsif t[:e] == :pre_close
pre = false
end
html << "#{MAP[t[:e]]}\n"
end
end
html
end
def references
@references.uniq
end
def toc
s = "#{MAP[:unordered_list_open]}\n"
lv = 1
@toc.each do |h|
if h['level'] > lv
s << ( "#{MAP[:unordered_list_open]}\n" * ( h['level'] - lv ) )
lv = h['level']
elsif h['level'] < lv
s << ( "#{MAP[:unordered_list_close]}\n" * ( lv - h['level'] ) )
lv = h['level']
end
s << %Q!#{MAP[:listitem_open]}#{h['title'].escapeHTML}\n!
end
s << ("#{MAP[:unordered_list_close]}\n" * lv)
end
private
def add_toc( level, title )
@toc << {"level" => level, "title" => title, "index" => @toc_cnt}
@toc_cnt = @toc_cnt + 1
end
def call_plugin_method( t )
return nil unless $use_plugin
method = t[:method]
args = nil
if t[:param]
args = csv_split( t[:param] ).collect! do |a|
case a
when /^[-+]?\d+(\.\d+)?$/
$1 ? a.to_f : a.to_i
when /^'(.+)'$/, /^"(.+)"$/
$1.escapeHTML
else
a
end
end
end
begin
if @plugin.respond_to?( method ) && !Object.method_defined?( method )
if args
@plugin.send( method, *args )
else
@plugin.send( method )
end
else
raise PluginException, 'not plugin method'
end
rescue
raise PluginException, $!.message
end
end
end
end