# $Id: template.rb,v 1.4 2002/01/04 18:32:05 ikechin Exp $ # $Revision: 1.4 $ module HTML class Template def initialize(param = nil) @path = ['.',''] @html file = nil if param.is_a?(Hash) file = param['filename'] # allow Array and String @path.push(*param['path']) if param['path'] elsif param.is_a?(String) file = param end if file then load(file) end end def load(file) @path.each do |path| if FileTest.exist?(filepath = File.join(path,file)) begin fp = File.open(filepath,"r") @html = fp.read fp.close rescue raise IOError end end end if @html parse return end raise IOError,"Template file #{file} not found" end def set_html(html) @html = html parse end attr_accessor :html attr_accessor :path ## # set params def param(key = {},*val) hash = if key.is_a?(String) {key => val} else key end hash.each do |k,v| if v.is_a?(Array) v.each do |h| node(k).param(h) end elsif v.is_a?(Hash) node(k).param(v) else @html.gsub!(//i,escape_re(v.to_s)) end end end ## # return HTML::TemplateNode object def node(name) if @node[name] != nil return @node[name] else raise ArgumentError,"node #{name} not found\n" end end ## # return result def output @html.gsub!(/]+>/,"") @html.gsub!(/]+)>/,"") ret_val = @html.dup # recycle the instance, but dirty way :-p set_html(@orig_text) return ret_val end ## aliases alias expand param alias loop node alias cond node alias to_s output private def escape_re(str) str.gsub(%r/\\/, "\\\\\\") end ## # parse HTML documents def parse @node = {} # save original HTML @orig_text = @html.dup # support HTML comment style @html.gsub!(%r~<\!\-\-\s+(begin|end|var|include):([\w\./\-]+)\s+\-\->~,'') # include allow \w,/,- only @html.gsub!(%r~~m) do fp = nil @path.each do |path| if FileTest.exist?(filepath = File.join(path,$1)) begin fp = File.open(filepath,"r") rescue raise IOError end break if fp end end begin fp.read rescue NameError raise IOError, "Include template #{$1} not found" end end # block allow \w,-,. only @html.gsub!(/(.*?)/m) do name = $1 body = $2 @node[name] = HTML::TemplateNode.new(self,name,body) "" end end end class TemplateNode < HTML::Template def initialize(parent,name,body) @parent = parent @name = name @html = body parse @original = @html.dup end attr_accessor :body def param(key = {},*val) hash = if key.is_a?(String) {key => val} else key end hash.each do |k,v| if v.is_a?(Array) v.each do |h| node(k).param(h) end elsif v.is_a?(Hash) node(k).param(v) else @html.gsub!(//i,escape_re(v.to_s)) end end html = @html.dup @parent.html.gsub!(/()/) do "#{html}#{$1}" end @html = @original.dup end alias expand param alias add param alias loop node alias cond node end end