require 'pp' require 'sanitize' module TracWiki class RawHtml def initialize(text) @text = text end def to_s @text end end class Node attr_accessor :tag attr_accessor :par attr_accessor :cont attr_accessor :attrs def initialize(tag_name, par=nil, attrs={}, cont=[]) @tag = nil @tag = tag_name.to_sym if tag_name @par = par cont = [ cont ] if cont.is_a? String @cont = cont || [] @attrs = attrs || {} end def add(cont) @cont << cont end end class Tree def initialize @root = Node.new(nil) @cur = @root end def tag(tag, attrs = nil, cont = nil) if cont.nil? && ! attrs.is_a?(Hash) # tag(:b, "ahoj") -> tag(:b, {}, "ahoj") cont = attrs attrs = nil end cont = [ cont ] if cont.is_a? String @cur.add(Node.new(tag, @cur, attrs, cont)) self end def tag_beg(tag_name, attrs = nil, cont = nil) node = Node.new(tag_name, @cur, attrs, cont) @cur.add(node) @cur = node self end def tag_end(tag_name) if @cur.tag == tag_name.to_sym @cur = @cur.par else raise "tag_end: cur tag is not <#{tag_name}>, but <#{@cur.tag}>" end self end # add space if needed def add_spc if @cur.cont.size > 0 last = @cur.cont.last if last.is_a?(String) && last[-1] == ?\s return end end add(' ') end def add(cont) @cur.add(cont) self end def add_raw(cont) cont_san = Sanitize.clean(cont, san_conf) @cur.add(RawHtml.new(cont_san)) self end def find_par(tag_name, node = nil) node = @cur if node.nil? while ! node.par.nil? if node.tag == tag_name return node.par end node = node.par end nil end def to_html tree_to_html(@root) end def tree_to_html(node) tag = node.tag if tag.nil? return cont_to_s(node.cont) end nl = "" #nl = "\n" if [:div, :h1, :h2, :h3, :h4, :h5, :p].include? tag nl = "\n" if [:div, :p].include? tag if node.cont.size == 0 if [:a, :td, :h1, :h2, :h3, :h4, :h5, :h6,:strong, :script].include? tag return "<#{tag}#{attrs_to_s(node.attrs)}></#{tag}>" end return "<#{tag}#{attrs_to_s(node.attrs)}/>#{nl}" end return "<#{tag}#{attrs_to_s(node.attrs)}>#{cont_to_s(node.cont)}</#{tag}>#{nl}" end def cont_to_s(cont) cont = [cont] if cont.is_a? String cont.map do |c| if c.is_a? Node tree_to_html(c) elsif c.is_a? RawHtml c.to_s else TracWiki::Parser.escapeHTML(c.to_s) end end.join('') end def attrs_to_s(attrs) return '' if attrs.nil? || attrs.size == 0 ret = [''] attrs.each_pair do |k,v| ret.push "#{TracWiki::Parser.escapeHTML(k.to_s)}=\"#{TracWiki::Parser.escapeHTML(v.to_s)}\"" if !v.nil? end return ret.sort.join(' ') end def san_conf return @san_conf if @san_conf conf = { elements: ['form', 'input', 'span', 'div'], attributes: { 'form' => ['action', 'meth'], 'input' => ['type', 'value'], 'span' => ['class'], 'div' => ['class'], }, } @san_conf = conf.merge(Sanitize::Config::RELAXED){|k,o,n| o.is_a?(Hash) ? o.merge(n) : o.is_a?(Array) ? o + n : n } #pp @san_conf @san_conf end end end