module WikiCloth class WikiBuffer def initialize(data="",options={}) @options = options self.data = data self.buffer_type = nil @section_count = 0 @buffers ||= [ ] @buffers << self @list_data = [] end def run_globals? true end def skip_html? false end def data @data ||= "" end def params @params ||= [ "" ] end def buffer_type @buffer_type end def to_s "

" + self.params.join("\n") + "

" end def check_globals() return false if self.class != WikiBuffer if previous_char == "\n" if @indent == @buffers[-1].object_id && current_char != " " # close pre tag cc_temp = current_char "".each_char { |c| self.add_char(c) } # get the parser back on the right track "\n#{cc_temp}".each_char { |c| @buffers[-1].add_char(c) } @indent = nil return true end if current_char == " " && @indent.nil? && @buffers[-1].class != WikiBuffer::HTMLElement "
 ".each_char { |c| @buffers[-1].add_char(c) }
        @indent = @buffers[-1].object_id
        return true
      end
    end

    if @buffers[-1].run_globals?
      # new html tag
      if @check_new_tag == true && current_char =~ /([a-z])/ && !@buffers[-1].skip_html?
        @buffers[-1].data.chop!
        parent = @buffers[-1].element_name if @buffers[-1].class == WikiBuffer::HTMLElement
        @buffers << WikiBuffer::HTMLElement.new("",@options,parent)
      end
      @check_new_tag = current_char == '<' ? true : false

      # global
      case
      # start variable
      when previous_char == '{' && current_char == '{'
        @buffers[-1].data.chop!
        @buffers << WikiBuffer::Var.new("",@options)
        return true

      # start link
      when current_char == '[' && previous_char != '['
        @buffers << WikiBuffer::Link.new("",@options)
        return true

      # start table
      when previous_char == '{' && current_char == "|"
        @buffers[-1].data.chop!
        @buffers << WikiBuffer::Table.new("",@options)
        return true

      end
    end

    return false
  end

  def add_char(c)
    self.previous_char = self.current_char
    self.current_char = c

    if self.check_globals() == false
      case
      when @buffers.size == 1
        return self.new_char()
      when @buffers[-1].add_char(c) == false && self.class == WikiBuffer
        tmp = @buffers.pop
        @buffers[-1].data += tmp.to_s
        # any data left in the buffer we feed into the parent
        unless tmp.data.blank?
          tmp.data.each_char { |c| self.add_char(c) }
        end
      end
    end
  end

  protected
  # only executed in the default state
  def new_char()
    case
    when current_char == "\n"
      if @options[:extended_markup] == true
        self.data.gsub!(/---([^-]+)---/,"\\1")
        self.data.gsub!(/_([^_]+)_/,"\\1")
      end
      self.data.gsub!(/__([a-zA-Z0-9]+)__/) { |r|
        case $1
        when "NOEDITSECTION"
          @noeditsection = true
        end
        ""
      }
      self.data.gsub!(/^([-]{4,})/) { |r| "
" } self.data.gsub!(/^([=]{1,6})\s*(.*?)\s*(\1)/) { |r| @section_count += 1 "" + (@noeditsection == true ? "" : "[edit]") + " #{$2}" } self.data.gsub!(/([\']{2,5})(.*?)(\1)/) { |r| tmp = "#{$2}" if $1.length == 2 tmp = "#{$2}" if $1.length == 3 tmp = "'#{$2}'" if $1.length == 4 tmp = "#{$2}" if $1.length == 5 tmp } lines = self.data.split("\n") self.data = "" for line in lines if !@list_data.empty? && (line.blank? || line =~ /^([^#\*:;]+)/) tmp = "" @list_data.reverse! @list_data.each { |x| tmp += "" } line = "#{tmp} #{line}" @list_data = [] end line.gsub!(/^([#\*:;]+)(.*)$/) { |r| cdata = [] tmp = "" $1.each_char { |c| cdata << c } if @list_data.empty? tmp += "<#{list_tag_for(cdata[0])}>" cdata[1..-1].each { |x| tmp += "<" + list_inner_tag_for(cdata[0]) + "><#{list_tag_for(x)}>" } if cdata.size > 1 else case when cdata.size > @list_data.size i = cdata.size-@list_data.size cdata[-i,i].each { |x| tmp += "<#{list_tag_for(x)}>" } when cdata.size < @list_data.size i = @list_data.size-cdata.size nlist = @list_data[-i,i].reverse nlist.each { |x| tmp += "" } tmp += "" else if cdata != @list_data # FIXME: this will only work if the change depth is one level unless (@list_data.last == ';' || @list_data.last == ':') && (cdata.last == ';' || cdata.last == ':') tmp += "" tmp += "<#{list_tag_for(cdata.last)}>" end else tmp += "" end end end # FIXME: still probably does not detect the : properly peices = cdata.last == ";" ? $2.smart_split(":") : [ $2 ] if peices.size > 1 tmp += "<#{list_inner_tag_for(cdata.last)}>#{peices[0]}" tmp += "
#{peices[1..-1].join(":")}
" cdata[-1] = ":" else tmp += "<#{list_inner_tag_for(cdata.last)}>#{peices[0]}" end @list_data = cdata tmp } self.data += line + "\n" end self.data = "

" if self.data.blank? self.params << self.data.auto_link self.data = "" else self.data += current_char end return true end def name_current_param() params[-1] = { :value => "", :name => params[-1] } unless params[-1].kind_of?(Hash) || params[-1].nil? end def current_param=(val) unless self.params[-1].nil? || self.params[-1].kind_of?(String) self.params[-1][:value] = val else self.params[-1] = val end end def params=(val) @params = val end def buffer_type=(val) @buffer_type = val end def data=(val) @data = val end def current_char=(val) @current_char = val end def current_char @current_char ||= "" end def previous_char=(val) @previous_char = val end def previous_char @previous_char end def current_line=(val) @current_line = val end def current_line @current_line ||= "" end def list_tag_for(tag) case tag when "#" then "ol" when "*" then "ul" when ";" then "dl" when ":" then "dl" end end def list_inner_tag_for(tag) case tag when "#" then "li" when "*" then "li" when ";" then "dt" when ":" then "dd" end end end end require File.join(File.expand_path(File.dirname(__FILE__)), "wiki_buffer", "html_element") require File.join(File.expand_path(File.dirname(__FILE__)), "wiki_buffer", "table") require File.join(File.expand_path(File.dirname(__FILE__)), "wiki_buffer", "var") require File.join(File.expand_path(File.dirname(__FILE__)), "wiki_buffer", "link")