module HtmlModule class Html attr_reader :name, :attrs, :content, :style def initialize(name, attrs=nil, content=nil) @name = name @attrs = Hash.new @style = Hash.new attrs.each { |k, v| set_attr(k, v) } if attrs if content == false @content = Array.new @uniq = true else @content = content ? content : Array.new @uniq = false end self end @@quotechars = { 'é' => 'é', 'è' => 'è', 'ë' => 'ë', 'à' => 'à', '>' => '>', '<' => '<', '"' => '"', '&' => '&', } def add(*content) content.each { |e| if (e.class == Array) add *e next end if e.class.ancestors.include? Html @content << e else @content << e.to_s.gsub(Regexp.new("(#{@@quotechars.keys.join('|')})")) { |x| @@quotechars[x] } end } self end def add_style(k, v) @style[k] = v self end def set_attr(k, v) if k == 'style' v.split(/\s*;\s*/).each { |s| add_style($1, $2) if s =~ /^\s*(\S+)\s*:\s*(.*?)\s*$/ } else @attrs[k]=v end self end def bg(c) @style['background'] = c self end def hclass(c) @attrs['class'] = c self end def length(start=nil) # taille du texte sans \n\s* if start l = start.length else # '' l = @name.length + 2 @attrs.each{ |k, v| l += " #{k}=\"#{v}\"".length } # ' style=""' - last '; ' l += 9-2 unless @style.empty? # 'k: v; ' @style.each{ |k, v| l += "#{k}: #{v}; ".length } # ' /' l += 2 if @uniq end @content.each{ |c| l += c.length } # '' l += 3+@name.length unless @uniq return l end def to_s(indent = '') attrs = @attrs.map { |k, v| " #{k}=\"#{v}\"" }.join attrs += ' style="' + @style.map{ |k, v| "#{k}: #{v}" }.join('; ') + '"' unless @style.empty? s = indent + '<' + @name + attrs + (@uniq ? ' />' : '>') s + if @uniq '' else if length(s) > 80 "\n" + @content.map{ |c| if c.class.ancestors.include? Html c.to_s(indent + ' ') + "\n" else indent + ' ' + c.to_s + "\n" end }.join + indent + '' else @content.map{ |c| c.to_s }.join + '' end end end def inspect "<#{@name}"+@content.map{|c|"\n"+c.inspect}.join+"\n#{@name}>" end end # returns GET info from apache def GET unless $GEThash $GEThash = Hash.new if q=ENV['QUERY_STRING'] q.split('&').each{ |r| $GEThash[$1] = $2 if r=~/^(.*?)=(.*)$/ } end end $GEThash end # return path info (for GET http://server.host/script.html/virtual/path) def PATH ENV['PATH_INFO'] end def POST unless $POSThash $POSThash = Hash.new if $stdin.headers_in['Content_Length'] > 0 and not $POSThash.empty? data = $stdin.read($stdin.headers_in['Content_Length']) data.split('\n').each { |l| $POSThash[$1] = $2 if l =~ /^(.*?)=(.*)$/ } end end $POSThash end class Page < Html attr_reader :body, :head def initialize @body = Html.new('body') @head = Html.new('head') super('html', {'xmlns'=>'http://www.w3.org/1999/xhtml', 'xml:lang'=>'fr'}) add(@head) add(@body) end def to_s ''+"\n"+ ''+"\n"+ super.to_s end end # Helpers class Img < Html def initialize(src, alt=nil) super('img', {'src'=>src}, false) set_attr('alt', alt) if alt self end end class A < Html def initialize(href, text) super('a', {'href'=>href}, [text]) end end class P < Html def initialize(content = nil) super('p') add(content) if content self end end class Div < Html def initialize(hclass = nil) super('div') hclass(hclass) if hclass self end end class Span < Html def initialize(hclass = nil) super('span') hclass(hclass) if hclass self end end class Body < Html def initialize super('body') end end class Stylesheet < Html def initialize(href) super('link', {'rel'=>'stylesheet', 'type'=>'text/css', 'href'=>href}, false) end end class Br < Html def initialize super('br', nil, false) end end class Hr < Html def initialize super('hr', nil, false) end end class Input < Html def initialize(type, name=nil, value=nil) super('input', {'type' => type}, false) set_attr('name', name) if name set_attr('value', value) if value self end end class Form < Html def initialize(method=nil, target=nil, defaultbutton=false) super('form') set_attr('method', method) if method set_attr('target', target) if target add(Input.new('submit')) if defaultbutton self end end class HtmlDef < Html def initialize(term, defn) super('dl') add_def(term, defn) end def add_def(term, defn) add(Html.new('dt').add(term)) defn = [defn] if (defn.class != Array) defn.each { |d| add(Html.new('dd').add(d)) } self end end class Td < Html def initialize super('td') end end class Tr < Html def initialize(*cells) super('tr') cells.each { |e| add(Td.new.add(*e)) } self end # tr[2] => 3rd Td def [](idx) (@content.find_all{ |t| t.name == 'tr' })[idx] end end class Table < Html def initialize(nb_col=nil, layout=nil) @nb_col = nb_col super('table') if layout cg = Html.new('colgroup') layout.each { |c| cg.add(Html.new('col', {'width'=>c}, false)) } add cg end self end def caption(caption) # replace the caption if it exists, create otherwise if (c = @content.find { |e| e.name=='caption' }) c.content = [caption] else @content.unshift(Html.new('caption').add(caption)) end self end def add_rows(*rows) rows.each{ |r| add_row *r } self end def add_row(*row) row.unshift("BUG: #{row.length}!=#{@nb_col}") if @nb_col and row.length != @nb_col add Tr.new(*row) self end def rows content.find_all { |e| e.name=='tr' } end end end