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 + '' + @name + '>'
else
@content.map{ |c| c.to_s }.join + '' + @name + '>'
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