|
What this is
Other links
The source code
# Copyritght (c) 2002 TANIGUCHI Takaki
# This program is distributed under the GNU GPL 2 or later.
require 'strscan'
require 'uri/common'
require 'delegate'
# require 'obaq/htmlgen'
require 'aswiki/scanner'
require 'aswiki/node'
require 'aswiki/util'
require 'aswiki/plugin'
require "aswiki/i18n/#{$LANG}"
module AsWiki
class Parser
# include Obaq::HtmlGen
include AsWiki::Util
include AsWiki::I18N
WORD = [:SPACE, :OTHER, :WORD]
TAG = [:ENDPERIOD, :INTERWIKINAME, :WIKINAME1, :WIKINAME2, :URI,:MOINHREF,
:MOINHREFIMG]
DECORATION = [:EM, :STRONG]
ESCAPE = [:ESCAPE_BEGIN, :ESCAPE_END]
TEXTLINE = WORD + TAG + [:EOL] + ESCAPE
PLAINTEXT = TEXTLINE + DECORATION
ELEMENT = PLAINTEXT + [:UL, :OL]
D_TAG = {:EM => 'Em' , :STRONG => 'Strong'}
def initialize(scanner, name='')
@name = name
@s = scanner
@rawwikinames = []
@plugin = AsWiki::Plugin.new(@name)
@tocdata = []
@tocnum = 0
@tocdata = [{:number => "##{@tocnum}", :text => '',
:msg_edit => msg_edit,
:partialedit => cgiurl([['c', 'e'],
['ebol',1],
['eeol',0]], @name)}]
@lastbol = 1
@tree = parse
end
attr_reader :tree, :tocdata
def wikinames
@rawwikinames.collect{|n|
expandwikiname(n,@name)
}
end
private
def next_token
@token = @s.next_token
end
def current_indent # To handle indents of ul and ol at onece
indent = 0
indent = $1.size if @token[1] =~ /^(\s*)/
## Original
## indent = @token[1].size
return indent
end
def parse
@line = 1
node = Node.new('Root')
next_token
while true
case @token[0]
when *PLAINTEXT
node << paragraph
when :UL
node << simple_list('Ul')
when :OL
node << simple_list('Ol')
when :BLANK
node << blank
when :DL
node << dl
when :EOL
eol
node << "\n"
when :HN_BEGIN
node << hn
when :HR
node << Node.new('Hr')
next_token
when :PLUGIN
node << plugin
when :PLUGIN_BEGIN
node << plugin_block
when :PRE_BEGIN
node << preblock
when :TABLE_BEGIN
node << table
when :EOF
break
else
node << syntax_error
end
end
return node
end
def blank
next_token
while true
case @token[0]
when :BLANK
next_token
when :EOL
eol
else
break
end
end
return "\n"
end
def hn
level = @token[1].size
lineno = @line
node = Node.new("H#{level}")
next_token
ret = textline
if level == 2
@tocnum = @tocnum + 1
@tocdata[-1][:partialedit] = cgiurl([['c', 'e'],
['ebol',@lastbol],
['eeol',lineno-1]],@name)
@lastbol = lineno
@tocdata << {:number => "##{@tocnum}", :text => ret,
:msg_edit => msg_edit,
:partialedit => cgiurl([['c', 'e'],['ebol',@lastbol]],
@name)
}
node << {:number => @tocnum, :text=> ret, }
else
node << {:number => nil, :text=> ret}
end
return node
end
def plugin_block
block = [] << (@token[1]+"\n")
block_b = @line
if :EOL == next_token[0] then eol else node << syntax_error end
block += textblock(:PLUGIN_END)
while true
case @token[0]
when :PLUGIN_END
block << @token[1]
next_token
when :EOL
eol
break
when :EOF
break
else node << syntax_error
end
end
block_e = @line
return @plugin.onview(block, block_b, block_e)
end
def plugin
node = @token[1]
next_token
return @plugin.onview(node.to_a, @line, 0)
end
def dl
node = Node.new('Dl')
while true
next_token
node << { :title => textline, :doc => element}
case @token[0]
when :DL
next
else
break
end
end
return node
end
def simple_list(kind = 'Ol') # kind = 'Ol' or 'Ul'
node = Node.new(kind)
indent = current_indent
next_token
node << catch(:simple_list_end) do
while true
case @token[0]
when *ELEMENT
node << element(indent)
else
break
end
end
end
return node
end
def table
node = Node.new('Table')
while true
case @token[0]
when :TABLE_BEGIN
next_token
node << table_tr
when :EOL
eol
when :EOF
break
else
break
end
end
return node
end
def table_tr
col = []
while true
col << plaintext
case @token[0]
when :TABLE_END
eol
break # XXX
when :TABLE
next_token
next
else
break
end
end
return {:col => col}
end
def paragraph
node = Node.new('Paragraph')
node << plaintext
return node
end
def plaintext
node = Node.new('Plaintext')
while true
case @token[0]
when *TEXTLINE
node << textline
when :STRONG
node << decorate(:STRONG)
when :EM
node << decorate(:EM)
else
break
end
end
return node
end
def element(indent=0)
node = Node.new('Element')
while true
case @token[0]
when *PLAINTEXT
node << plaintext
when :UL
cur_indent = current_indent
if indent == cur_indent
next_token
break
elsif indent < cur_indent
node << simple_list('Ul')
elsif indent > cur_indent
throw :simple_list_end, node
else
raise RangeError
end
when :OL
cur_indent = current_indent
if indent == cur_indent
next_token
break
elsif indent < cur_indent
node << simple_list('Ol')
elsif indent > cur_indent
throw :simple_list_end, node
else
raise RangeError
end
else
break
end
end
return node
end
def decorate(tag)
next_token
node = Node.new(D_TAG[tag])
node << textline
if @token[0] == tag
next_token
else
node << syntax_error
end
return node
end
def textline
node = Node.new('Textline')
while true
case @token[0]
when :ESCAPE_BEGIN
next_token
ret = textblock(:ESCAPE_END)
node << ret
when :ESCAPE_END
node << @token[1]
when :OTHER, :SPACE, :WORD
node << @token[1]
when :WIKINAME1,:INTERWIKINAME
@rawwikinames << @token[1]
# node << wikilink(@token[1], @name) # XXX
node << wikilink(expandwikiname(@token[1], @name))
when :WIKINAME2
name = @token[1][2..-3]
@rawwikinames << name
# node << wikilink(name, @name) # XXX
node << wikilink(expandwikiname(name, @name))
when :URI
tn = Node.new('Url')
tn << {:url=>@token[1],:text=>@token[1]}
node << tn
when :MOINHREFIMG
tn = Node.new('MoinhrefImg')
urlt, key = @token[1][1..-2].split(/\s+/, 2)
url = Amrita::Sanitizer::sanitize_url(urlt[4..-1], {'http' => true, 'https' => true})
tn << {:url => url, :alt => key}
node << tn
when :MOINHREF
allowedscheme = {'http' => true, 'https' => true, 'file' => true,
'news' => true, 'ftp' => true, 'mailto' => true }
tn = Node.new('Moinhref')
url, key = @token[1][1..-2].split(/\s+/, 2)
url = Amrita::Sanitizer::sanitize_url(url,allowedscheme)
tn << {:url => url, :text => key }
node << tn
when :ENDPERIOD
node << Node.new('Br')
when :EOL
node << "\n"
eol
break
else
break
end
next_token
end
return node
end
def textblock(endtag)
node = []
line = ""
while true
case @token[0]
when :EOF
break
when :EOL
line << "\n"
node << line
line = ""
eol
when endtag
if not line.empty?
node << line
end
break
else line << @token[1]
next_token
end
end
return node
end
def preblock
next_token
ret = Amrita::e(:pre, :class=>"code") { Amrita::CompactSpace.new(false) { textblock(:PRE_END).join } } # XXX use template ???
next_token
return ret
end
def eol
@line +=1
next_token
return
end
def syntax_error
s = "(Syntax error at line #{@line}. ; #{@token.inspect})\n"
next_token
return s
end
end
end
|
Copyright 1998-2008 Alvin Alexander
All Rights Reserved.
devdaily.com is based in louisville, kentucky, and this web site is hosted by godaddy.com