Changed wiki parser to wikicloth.

* Temporarly removing of TOC.
This commit is contained in:
Benjamin Meichsner 2009-08-11 14:30:35 +02:00
parent 55729e20f9
commit 5d9385cde4
39 changed files with 3474 additions and 64 deletions

View file

@ -0,0 +1,237 @@
require 'rubygems'
require 'builder'
module WikiCloth
class WikiBuffer::HTMLElement < WikiBuffer
ALLOWED_ELEMENTS = ['a','b','i','div','span','sup','sub','strike','s','u','font','big','ref','tt','del',
'small','blockquote','strong','pre','code','references','ol','li','ul','dd','dt','dl','center',
'h2','h3','h4','h5','h6']
ALLOWED_ATTRIBUTES = ['id','name','style','class','href','start','value']
ESCAPED_TAGS = [ 'nowiki', 'pre', 'code' ]
SHORT_TAGS = [ 'meta','br','hr','img' ]
NO_NEED_TO_CLOSE = ['li','p'] + SHORT_TAGS
def initialize(d="",options={},check=nil)
super("",options)
self.buffer_type = "Element"
@in_quotes = false
@in_single_quotes = false
@start_tag = 1
@tag_check = check unless check.nil?
end
def run_globals?
return ESCAPED_TAGS.include?(self.element_name) ? false : true
end
def to_s
if NO_NEED_TO_CLOSE.include?(self.element_name)
return "<#{self.element_name} />" if SHORT_TAGS.include?(self.element_name)
return "</#{self.element_name}><#{self.element_name}>" if @tag_check == self.element_name
end
if ESCAPED_TAGS.include?(self.element_name)
# escape all html inside this element
self.element_content = self.element_content.gsub('<','&lt;').gsub('>','&gt;')
# hack to fix <code><nowiki> nested mess
self.element_content = self.element_content.gsub(/&lt;[\/]*\s*nowiki\s*&gt;/,'')
end
lhandler = @options[:link_handler]
case self.element_name
when "ref"
self.element_name = "sup"
named_ref = self.name_attribute
ref = lhandler.find_reference_by_name(named_ref) unless named_ref.nil?
if ref.nil?
lhandler.references << { :name => named_ref, :value => self.element_content, :count => 0 }
ref = lhandler.references.last
end
ref_id = (named_ref.nil? ? "" : "#{named_ref}_") + "#{lhandler.reference_index(ref)}-#{ref[:count]}"
self.params << { :name => "id", :value => "cite_ref-#{ref_id}" }
self.params << { :name => "class", :value => "reference" }
self.element_content = "[<a href=\"#cite_note-" + (named_ref.nil? ? "" : "#{named_ref}_") +
"#{lhandler.reference_index(ref)}\">#{lhandler.reference_index(ref)}</a>]"
ref[:count] += 1
when "references"
ref_count = 0
self.element_name = "ol"
self.element_content = lhandler.references.collect { |r|
ref_count += 1
ref_name = (r[:name].nil? ? "" : r[:name].to_slug + "_")
ret = "<li id=\"cite_note-#{ref_name}#{ref_count}\"><b>"
1.upto(r[:count]) { |x| ret += "<a href=\"#cite_ref-#{ref_name}#{ref_count}-#{x-1}\">" +
(r[:count] == 1 ? "^" : (x-1).to_s(26).tr('0-9a-p', 'a-z')) + "</a> " }
ret += "</b> #{r[:value]}</li>"
}.to_s
when "nowiki"
return self.element_content
end
tmp = elem.tag!(self.element_name, self.element_attributes) { |x| x << self.element_content }
unless ALLOWED_ELEMENTS.include?(self.element_name)
tmp.gsub!(/[\-!\|&"\{\}\[\]]/) { |r| self.escape_char(r) }
return tmp.gsub('<', '&lt;').gsub('>', '&gt;')
end
tmp
end
def name_attribute
params.each { |p| return p[:value].to_slug if p.kind_of?(Hash) && p[:name] == "name" }
return nil
end
def element_attributes
attr = {}
params.each { |p| attr[p[:name]] = p[:value] if p.kind_of?(Hash) }
if ALLOWED_ELEMENTS.include?(self.element_name.strip.downcase)
attr.delete_if { |key,value| !ALLOWED_ATTRIBUTES.include?(key.strip) }
end
return attr
end
def element_name
@ename ||= ""
end
def element_content
@econtent ||= ""
end
protected
def escape_char(c)
c = case c
when '-' then '&#45;'
when '!' then '&#33;'
when '|' then '&#124;'
when '&' then '&amp;'
when '"' then '&quot;'
when '{' then '&#123;'
when '}' then '&#125;'
when '[' then '&#91;'
when ']' then '&#93;'
when '*' then '&#42;'
when '#' then '&#35;'
when ':' then '&#58;'
when ';' then '&#59;'
when "'" then '&#39;'
when '=' then '&#61;'
else
c
end
return c
end
def elem
Builder::XmlMarkup.new
end
def element_name=(val)
@ename = val
end
def element_content=(val)
@econtent = val
end
def in_quotes?
@in_quotes || @in_single_quotes ? true : false
end
def new_char()
case
# tag name
when @start_tag == 1 && current_char == ' '
self.element_name = self.data.strip.downcase
self.data = ""
@start_tag = 2
# tag is closed <tag/> no attributes
when @start_tag == 1 && previous_char == '/' && current_char == '>'
self.data.chop!
self.element_name = self.data.strip.downcase
self.data = ""
@start_tag = 0
return false
# open tag
when @start_tag == 1 && previous_char != '/' && current_char == '>'
self.element_name = self.data.strip.downcase
self.data = ""
@start_tag = 0
return false if SHORT_TAGS.include?(self.element_name)
return false if self.element_name == @tag_check && NO_NEED_TO_CLOSE.include?(self.element_name)
# new tag attr
when @start_tag == 2 && current_char == ' ' && self.in_quotes? == false
self.current_param = self.data
self.data = ""
self.params << ""
# tag attribute name
when @start_tag == 2 && current_char == '=' && self.in_quotes? == false
self.current_param = self.data
self.data = ""
self.name_current_param()
# tag is now open
when @start_tag == 2 && previous_char != '/' && current_char == '>'
self.current_param = self.data
self.data = ""
@start_tag = 0
return false if SHORT_TAGS.include?(self.element_name)
return false if self.element_name == @tag_check && NO_NEED_TO_CLOSE.include?(self.element_name)
# tag is closed <example/>
when @start_tag == 2 && previous_char == '/' && current_char == '>'
self.current_param = self.data.chop
self.data = ""
@start_tag = 0
return false
# in quotes
when @start_tag == 2 && current_char == "'" && previous_char != '\\' && !@in_quotes
@in_single_quotes = !@in_single_quotes
# in quotes
when @start_tag == 2 && current_char == '"' && previous_char != '\\' && !@in_single_quotes
@in_quotes = !@in_quotes
# start of a closing tag
when @start_tag == 0 && previous_char == '<' && current_char == '/'
self.element_content += self.data.chop
self.data = ""
@start_tag = 5
when @start_tag == 5 && (current_char == '>' || current_char == ' ') && !self.data.blank?
self.data = self.data.strip.downcase
if self.data == self.element_name
self.data = ""
return false
else
if @tag_check == self.data && NO_NEED_TO_CLOSE.include?(self.element_name)
self.data = "</#{self.data}>"
return false
else
self.element_content += "&lt;/#{self.data}&gt;"
@start_tag = 0
self.data = ""
end
end
else
if @start_tag == 0 && ESCAPED_TAGS.include?(self.element_name)
self.data += self.escape_char(current_char)
else
self.data += current_char
end
end
return true
end
end
end

View file

@ -0,0 +1,70 @@
module WikiCloth
class WikiBuffer::Link < WikiBuffer
def initialize(data="",options={})
super(data,options)
@in_quotes = false
end
def internal_link
@internal_link ||= false
end
def to_s
link_handler = @options[:link_handler]
unless self.internal_link
return link_handler.external_link("#{params[0]}".strip, "#{params[1]}".strip)
else
case
when params[0] =~ /^:(.*)/
return link_handler.link_for(params[0],params[1])
when params[0] =~ /^\s*([a-zA-Z0-9-]+)\s*:(.*)$/
return link_handler.link_for_resource($1,$2,params[1..-1])
else
return link_handler.link_for(params[0],params[1])
end
end
end
protected
def internal_link=(val)
@internal_link = (val == true ? true : false)
end
def new_char()
case
# check if this link is internal or external
when previous_char.blank? && current_char == '['
self.internal_link = true
# Marks the beginning of another paramater for
# the current object
when current_char == '|' && self.internal_link == true && @in_quotes == false
self.current_param = self.data
self.data = ""
self.params << ""
# URL label
when current_char == ' ' && self.internal_link == false && params[1].nil? && !self.data.blank?
self.current_param = self.data
self.data = ""
self.params << ""
# end of link
when current_char == ']' && ((previous_char == ']' && self.internal_link == true) || self.internal_link == false) && @in_quotes == false
self.data.chop! if self.internal_link == true
self.current_param = self.data
self.data = ""
return false
else
self.data += current_char unless current_char == ' ' && self.data.blank?
end
return true
end
end
end

View file

@ -0,0 +1,159 @@
module WikiCloth
class WikiBuffer::Table < WikiBuffer
def initialize(data="",options={})
super(data,options)
self.buffer_type = "table"
@start_table = true
@start_row = false
@start_caption = false
@in_quotes = false
end
def table_caption
@caption ||= ""
return @caption.kind_of?(Hash) ? @caption[:value] : @caption
end
def table_caption_attributes
@caption.kind_of?(Hash) ? @caption[:style] : ""
end
def rows
@rows ||= [ [] ]
end
def to_s
row_count = 0
ret = "<table" + (params[0].blank? ? "" : " #{params[0].strip}") + ">"
ret += "<caption" + (self.table_caption_attributes.blank? ? "" : " #{table_caption_attributes.strip}") +
">#{table_caption.strip}</caption>" unless self.table_caption.blank?
for row in rows
row_count += 1
ret += "<tr" + (params[row_count].nil? || params[row_count].blank? ? "" : " #{params[row_count].strip}") + ">"
for cell in row
cell_attributes = cell[:style].blank? ? "" : " #{cell[:style].strip}"
ret += "<#{cell[:type]}#{cell_attributes}>\n#{cell[:value].strip}\n</#{cell[:type]}>"
end
ret += "</tr>"
end
ret += "</table>"
end
protected
def rows=(val)
@rows = val
end
def table_caption_attributes=(val)
@caption = { :style => val, :value => self.table_caption } unless @caption.kind_of?(Hash)
@caption[:style] = val if @caption.kind_of?(Hash)
end
def table_caption=(val)
@caption = val unless @caption.kind_of?(Hash)
@caption[:value] = val if @caption.kind_of?(Hash)
end
def next_row()
self.params << ""
self.rows << []
end
def next_cell(type="td")
if self.rows[-1].size == 0
self.rows[-1] = [ { :type => type, :value => "", :style => "" } ]
else
self.rows[-1][-1][:value] = self.data
self.rows[-1] << { :type => type, :value => "", :style => "" }
end
end
def new_char()
if @check_cell_data == 1
case
when current_char != '|' && @start_caption == false && self.rows[-1][-1][:style].blank?
self.rows[-1][-1][:style] = self.data
self.data = ""
when current_char != '|' && @start_caption == true && self.table_caption_attributes.blank?
self.table_caption_attributes = self.data
self.data = ""
end
@check_cell_data = 0
end
case
# Next table cell in row (TD)
when current_char == "|" && (previous_char == "\n" || previous_char == "|") && @in_quotes == false
self.data.chop!
self.next_cell() unless self.data.blank? && previous_char == "|"
self.data = ""
# Next table cell in row (TH)
when current_char == "!" && (previous_char == "\n" || previous_char == "!") && @in_quotes == false
self.data.chop!
self.next_cell('th')
self.data = ""
# End of a table
when current_char == '}' && previous_char == '|'
self.data = ""
self.rows[-1].pop
return false
# Start table caption
when current_char == '+' && previous_char == '|' && @in_quotes == false
self.data = ""
self.rows[-1].pop
@start_caption = true
# Table cell might have attributes
when current_char == '|' && previous_char != "\n" && @in_quotes == false
@check_cell_data = 1
# End table caption
when current_char == "\n" && @start_caption == true && @in_quotes == false
@start_caption = false
self.table_caption = self.data
self.data = ""
# in quotes
when current_char == '"' && previous_char != '\\'
@in_quotes = !@in_quotes
self.data += '"'
# Table params
when current_char == "\n" && @start_table == true && @in_quotes == false
@start_table = false
unless self.data.blank?
self.current_param = self.data
self.params << ""
end
self.data = ""
# Table row params
when current_char == "\n" && @start_row == true && @in_quotes == false
@start_row = false
unless self.data.blank?
self.current_param = self.data
end
self.data = ""
# Start new table row
when current_char == '-' && previous_char == '|' && @in_quotes == false
self.data.chop!
self.rows[-1].pop
self.next_row()
@start_row = true
else
self.data += current_char
end
return true
end
end
end

View file

@ -0,0 +1,77 @@
module WikiCloth
class WikiBuffer::Var < WikiBuffer
def initialize(data="",options={})
super(data,options)
self.buffer_type = "var"
@in_quotes = false
end
def skip_html?
true
end
def function_name
@fname
end
def to_s
if self.is_function?
ret = "#{buffer_type}"
ret += " function #{function_name}"
ret += "(#{params.inspect})"
ret += " [#{data}]"
else
ret = @options[:link_handler].include_resource("#{params[0]}".strip,params[1..-1])
end
ret ||= "<!-- TEMPLATE[#{params[0]}] NOT FOUND -->"
ret
end
def is_function?
self.function_name.nil? || self.function_name.blank? ? false : true
end
protected
def function_name=(val)
@fname = val
end
def new_char()
case
when current_char == '|' && @in_quotes == false
self.current_param = self.data
self.data = ""
self.params << ""
# Start of either a function or a namespace change
when current_char == ':' && @in_quotes == false && self.params.size <= 1
self.function_name = self.data
self.data = ""
puts "[found var function (#{function_name})"
# Dealing with variable names within functions
# and variables
when current_char == '=' && @in_quotes == false
self.current_param = self.data
self.data = ""
self.name_current_param()
# End of a template, variable, or function
when current_char == '}' && previous_char == '}'
self.data.chop!
self.current_param = self.data
self.data = ""
return false
else
self.data += current_char
end
return true
end
end
end