Index: html_formatter.rb
===================================================================
--- html_formatter.rb (リビジョン 621)
+++ html_formatter.rb (作業コピー)
@@ -6,251 +6,216 @@
require 'hiki/interwiki'
require 'hiki/aliaswiki'
require 'hiki/hiki_formatter'
-require 'uri'
+require 'style/default/hikidoc'
module Hiki
class HTMLFormatter_default < HikiFormatter
- def initialize( s, db, plugin, conf, prefix = 'l')
- @html = s
- @db = db
- @plugin = plugin
- @conf = conf
- @prefix = prefix
- @references = Array::new
- @interwiki = InterWiki::new( @db.load( @conf.interwiki_name ) )
- @aliaswiki = AliasWiki::new( @db.load( @conf.aliaswiki_name ) )
- get_auto_links if @conf.auto_link
+ def initialize( parser, db, plugin, conf, prefix = 'l')
+ @parser = parser
+ @conf = conf
+ @output = HikiDocOutput.new(">", db, plugin, conf, prefix)
+ convert
end
+ attr_reader :toc, :references
def to_s
- s = @html
- s = replace_inline_image( s )
- s = replace_wikiname( s ) if @conf.use_wikiname
- s = replace_link( s )
- s = replace_auto_link( s ) if @conf.auto_link
- s = replace_heading( s )
- s = replace_plugin( s ) if @conf.use_plugin
- @html_converted = s
- s
+ @html_converted
end
- def references
- @references.uniq
- end
+ private
+
+ def convert
+ @html_converted = @parser.call(@output, @conf.use_wiki_name)
+ @toc = gen_toc(@html_converted)
+ @references = @output.references
+ end
- HEADING_RE = %r!.*.*?(.*?)!
+ HEADING_RE = %r!.*.*?(.*?)!
TAG_RE = %r!(<.+?>)!
- def toc
+ def gen_toc(html)
s = "
\n"
num = -1
level = 1
- to_s unless @html_converted
- @html_converted.each do |line|
- if HEADING_RE =~ line
- new_level = $1.to_i - 1
- num += 1
- title = $2.gsub( TAG_RE, '' ).strip
- if new_level > level
- s << ( "\n" * ( new_level - level ) )
- level = new_level
- elsif new_level < level
- s << ( "
\n" * ( level - new_level ) )
- level = new_level
- end
- s << %Q!- #{title}
\n!
+ html.scan(HEADING_RE) do |new_level, anchor, title|
+ new_level = new_level.to_i - 1
+ num += 1
+ title = title.gsub( TAG_RE, '' ).strip
+ if new_level > level
+ s << ( "\n" * ( new_level - level ) )
+ level = new_level
+ elsif new_level < level
+ s << ( "
\n" * ( level - new_level ) )
+ level = new_level
end
+ s << %Q!- #{title}
\n!
end
s << ("
\n" * level)
s
end
- private
+ class HikiDocOutput < HikiDoc::HTMLOutput
+ def initialize(suffix, db, plugin, conf, prefix)
+ super(suffix || '/>')
+ @toc = ''
+ @references = []
- def replace_inline_image( text )
- text.gsub( /(.+?)<\/a>/i ) do |str|
- %Q||
+ @db = db
+ @plugin = plugin
+ @conf = conf
+ @prefix = prefix
+ @interwiki = InterWiki::new( db.load( conf.interwiki_name ) )
+ @aliaswiki = AliasWiki::new( db.load( conf.aliaswiki_name ) )
+ @reverse_dic= gen_reverse_dic
+ @auto_links_re = get_auto_links_re if conf.auto_link
end
- end
+ attr_reader :toc, :references
- def replace_auto_link( text )
- return text if @auto_links.empty?
- replace_inline( text ) do |str|
- str.gsub!( @auto_links_re ) do |match|
- @plugin.hiki_anchor( @auto_links[match].unescapeHTML.escape, match )
- end
+ def reset
+ @toc = ''
+ @references = []
+ @heading_level = 1
+ @heading_serial = 0
+ @blockquote_level = 0
+ super
end
- end
- WIKINAME_RE = /(\b(?:[A-Z][a-z0-9]+){2,}[A-Z]*\b)/n
-
- def replace_wikiname( text )
- replace_inline( text ) do |str|
- str.gsub!( WIKINAME_RE ) do |i|
- %Q|#{i}|
- end
+ def finish
+ @toc << ("\n" * @heading_level)
+ @references.uniq!
+ super
end
- end
- PLUGIN_OPEN_RE = /<(span|div) class="plugin">/
- PLUGIN_CLOSE_RE = %r!(span|div)>!
- LINK_OPEN_RE = /!
- PRE_OPEN_RE = //
- PRE_CLOSE_RE = %r!
!
+ TAG_RE = %r!(<.+?>)!
- def replace_inline( text )
- status = []
- ret = text.split( TAG_RE ).collect do |str|
- case str
- when PLUGIN_OPEN_RE
- status << :plugin
- when LINK_OPEN_RE
- status << :a
- when PRE_OPEN_RE
- status << :pre
- when PLUGIN_CLOSE_RE, LINK_CLOSE_RE, PRE_CLOSE_RE
- status.pop
- when TAG_RE
- # do nothing
+ def headline(level, title)
+ @f.print ""
+
+ if @blockquote_level != 0
+ @f.print title
else
- if status.empty?
- yield( str )
+ # toc
+ if @heading_level < level
+ @toc << ("\n" * (level - @heading_level))
+ @heading_level = level
+ elsif level < @heading_level
+ @toc << ("
\n" * (@heading_level - level))
+ @heading_level = level
end
+ @toc << %Q!#{title.gsub(TAG_RE,'').strip.escapeHTML}\n!
+
+ # heading
+ case level
+ when 2
+ @f.print %Q! #{title}!
+ when 3
+ @f.print %Q! #{title}!
+ else
+ @f.print %Q! #{title}!
+ end
+ @heading_serial += 1;
end
- str
+
+ @f.puts ""
end
- ret.join
- end
- URI_RE = /\A#{URI.regexp( %w( http https ftp file mailto ) )}\z/
+ def blockquote_open
+ @blockquote_level += 1
+ super
+ end
- def replace_link( text )
- text.gsub( %r|(.+?)| ) do |str|
- k, u = $2, $1
- if URI_RE =~ u # uri
- @plugin.make_anchor(u, k, 'external')
+ def blockquote_close
+ @blockquote_level -= 1
+ super
+ end
+
+ def block_plugin(src)
+ if(@conf.use_plugin)
+ @f.puts @plugin.block_context{ apply_plugin( src, @plugin, @conf ) }
else
- u = u.unescapeHTML
- u = @aliaswiki.aliaswiki_names.key( u ) || u # alias wiki
- if /(.*)(#l\d+)\z/ =~ u
- u, anchor = $1, $2
- else
- anchor = ''
- end
- if @db.exist?( u ) # page name
- k = @plugin.page_name( k ) if k == u
- @references << u
- @plugin.hiki_anchor( u.escape + anchor, k )
- elsif orig = @db.select{|i| i[:title] == u}.first # page title
- k = @plugin.page_name( k ) if k == u
- u = orig
- @references << u
- @plugin.hiki_anchor( u.escape + anchor, k )
- elsif outer_alias = @interwiki.outer_alias( u ) # outer alias
- @plugin.make_anchor(outer_alias[0] + anchor, k, 'external')
- elsif /:/ =~ u # inter wiki ?
- s, p = u.split( /:/, 2 )
- if s.empty? # normal link
- @plugin.make_anchor( p.escapeHTML + anchor, k, 'external')
- elsif inter_link = @interwiki.interwiki( s, p.unescapeHTML, "#{s}:#{p}" )
- @plugin.make_anchor(inter_link[0], k, 'external')
- else
- missing_page_anchor( k, u )
- end
- else
- missing_page_anchor( k, u )
- end
+ @f.puts %Q({{#{escape_html(src)}}}
)
end
end
- end
- def missing_page_anchor( k, u )
- if @plugin.creatable?
- missing_anchor_title = @conf.msg_missing_anchor_title % [ u.escapeHTML ]
- "#{k}?"
- else
- k
+ def inline_plugin(src)
+ if(@conf.use_plugin)
+ @plugin.inline_context{ apply_plugin( src, @plugin, @conf ) }
+ else
+ %Q({{#{escape_html(src)}}})
+ end
end
- end
- BLOCKQUOTE_OPEN_RE = //
- BLOCKQUOTE_CLOSE_RE = %r!
!
- HEADING_OPEN_RE = //
- HEADING_CLOSE_RE = %r!!
+ def wiki_name(name)
+ hyperlink(name, text(name))
+ end
- def replace_heading( text )
- status = []
- num = -1
- ret = text.split( TAG_RE ).collect do |str|
- case str
- when BLOCKQUOTE_OPEN_RE
- status << :blockquote
- when BLOCKQUOTE_CLOSE_RE
- status.pop
- when HEADING_OPEN_RE
- unless status.include?( :blockquote )
- num += 1
- level = $1.to_i
- status << level
- case level
- when 2
- str << %Q! !
- when 3
- str << %Q! !
+ URI_RE = /(?:https?|ftp|file|mailto|javascript):[A-Za-z0-9;\/?:@&=+$,\-_.!~*\'()#%]+/
+
+ def hyperlink(uri, label)
+ if URI_RE =~ uri # uri
+ @plugin.make_anchor(escape_html(uri), label, 'external')
+ else
+ page, anchor = uri.split("\##{@prefix}", 2)
+ anchor = anchor.nil? || anchor !~ /\A\d+\z/ ? '' : "\##{@prefix}#{anchor}"
+
+ if((p = @reverse_dic[page]) and @db.exist?(p)) # title or alias or page name
+ label = escape_html(@plugin.page_name(p)) if unescape_html(label) == p
+ @references << p
+ @plugin.hiki_anchor( escape_html( p.escape + anchor ), label )
+ elsif outer_alias = @interwiki.outer_alias( page ) # outer alias
+ @plugin.make_anchor(escape_html(outer_alias[0] + anchor), label, 'external')
+ elsif colon = page.index(':') # inter wiki ?
+ if colon == 0 # normal link
+ @plugin.make_anchor( escape_html(page[1,page.length] + anchor), label, 'external')
+ elsif inter_link = @interwiki.interwiki( page[0,colon], page[colon+1,page.length], label )
+ @plugin.make_anchor(inter_link[0], label, 'external')
else
- str << %Q! !
+ missing_page_anchor( label, page )
end
+ else
+ missing_page_anchor( label, page )
end
- when HEADING_CLOSE_RE
- unless status.include?( :blockquote )
- level = status.pop
- str = "#{str}" if level == 2
- end
end
+ end
+
+ # make sure that text() is not called under hyperlink().
+ def text(str)
+ return escape_html(str) unless @auto_links_re
+ pages = @reverse_dic
+ str.gsub!( @auto_links_re ) {|match|
+ @plugin.hiki_anchor( pages[match].escape.escapeHTML, escape_html(match) )
+ }
str
end
- ret.join
- end
- def replace_plugin( text )
- text.gsub( %r!<(span|div) class="plugin">\{\{(.+?)\}\}\1>!m ) do |str|
- tag, plugin_str = $1, $2
- begin
- case tag
- when 'span'
- result = @plugin.inline_context{ apply_plugin( plugin_str, @plugin, @conf ) }
- when 'div'
- result = @plugin.block_context{ apply_plugin( plugin_str, @plugin, @conf ) }
- end
- result.class == String ? result : ''
- rescue Exception => e
- $& + e.message
+ private
+
+ def gen_reverse_dic
+ pages = {}
+ @db.pages.each do |p|
+ pages[p] = p
+ title = @plugin.page_name( p ).unescapeHTML
+ pages[title] = p unless title == p
end
+ @aliaswiki.aliaswiki_names.each do |orig, alas|
+ pages[alas] = orig
+ end
+ pages
end
- end
- def get_auto_links
- pages = {}
- @db.pages.each do |p|
- page_h = escape_html( p )
- pages[page_h] = page_h
- title_h = @plugin.page_name( p ).gsub( /"/, '"' )
- pages[title_h] = page_h unless title_h == page_h
+ def get_auto_links_re
+ pages = @reverse_dic
+ pages && !pages.empty? ? Regexp.union( * pages.keys.sort_by{|i| -i.size} ) : nil
end
- @aliaswiki.aliaswiki_names.each do |key, value|
- orig_h = escape_html( key )
- alias_h = escape_html( value )
- pages[alias_h] = orig_h
+
+ def missing_page_anchor( k, u )
+ if @plugin.creatable?
+ missing_anchor_title = @conf.msg_missing_anchor_title % [ u.escapeHTML ]
+ "#{k}?"
+ else
+ k
+ end
end
- @auto_links_re = Regexp.union( * pages.keys.sort_by{|i| -i.size} )
- @auto_links = pages
end
-
- def escape_html( text )
- text.gsub( /&/, '&' ).
- gsub( /, '<' ).
- gsub( />/, '>' )
- end
end
end
Index: parser.rb
===================================================================
--- parser.rb (リビジョン 621)
+++ parser.rb (作業コピー)
@@ -24,12 +24,14 @@
end
def parse( s, top_level = 2 )
- HikiDoc.to_html( s,
- :level => top_level,
- :use_wiki_name => false,
- :allow_bracket_inline_image => false,
- :plugin_syntax => method(:valid_plugin_syntax?)
- )
+ lambda {|formatter, use_wiki_name|
+ HikiDoc.new(formatter, {
+ :level => top_level,
+ :use_wiki_name => use_wiki_name,
+ :allow_bracket_inline_image => true,
+ :plugin_syntax => method(:valid_plugin_syntax?)
+ }).compile(s)
+ }
end
private