2002-11-17 11:11:40 -05:00
|
|
|
# Tiny eRuby --- ERB2
|
2003-01-20 06:32:19 -05:00
|
|
|
# Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI
|
2002-11-17 11:11:40 -05:00
|
|
|
# You can redistribute it and/or modify it under the same terms as Ruby.
|
|
|
|
|
|
|
|
class ERB
|
|
|
|
Revision = '$Date$' #'
|
|
|
|
|
|
|
|
def self.version
|
2003-01-20 06:32:19 -05:00
|
|
|
"erb.rb [2.0.2 #{ERB::Revision.split[1]}]"
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# ERB::Compiler
|
|
|
|
class ERB
|
|
|
|
class Compiler
|
2003-01-20 06:32:19 -05:00
|
|
|
class ParcentLine
|
|
|
|
def initialize(compiler, str)
|
|
|
|
@compiler = compiler
|
|
|
|
@line = str
|
|
|
|
end
|
|
|
|
|
|
|
|
def expand(list)
|
|
|
|
str = @line.dup
|
|
|
|
str[0] = ''
|
|
|
|
if /^%%/ === @line
|
|
|
|
list.unshift("\n")
|
|
|
|
list.unshift(str)
|
|
|
|
else
|
|
|
|
list.unshift('%>')
|
|
|
|
list.unshift(str)
|
|
|
|
list.unshift('<%')
|
|
|
|
end
|
|
|
|
list
|
|
|
|
end
|
|
|
|
|
|
|
|
def expand_in_script(list)
|
|
|
|
ary = []
|
|
|
|
@compiler.push_line(ary, @line)
|
|
|
|
ary.reverse_each do |x|
|
|
|
|
list.unshift(x)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
ERbTag = "<%% %%> <%= <%# <% %>".split
|
2002-11-17 11:11:40 -05:00
|
|
|
def is_erb_tag?(s)
|
|
|
|
ERbTag.member?(s)
|
|
|
|
end
|
|
|
|
|
2003-01-20 06:32:19 -05:00
|
|
|
SplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
|
|
|
|
|
2002-11-17 11:11:40 -05:00
|
|
|
def prepare_trim_mode(mode)
|
|
|
|
case mode
|
|
|
|
when 1
|
|
|
|
return [false, '>']
|
|
|
|
when 2
|
|
|
|
return [false, '<>']
|
|
|
|
when 0
|
|
|
|
return [false, nil]
|
|
|
|
when String
|
|
|
|
perc = mode.include?('%')
|
|
|
|
if mode.include?('<>')
|
|
|
|
return [perc, '<>']
|
|
|
|
elsif mode.include?('>')
|
|
|
|
return [perc, '>']
|
|
|
|
else
|
|
|
|
[perc, nil]
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return [false, nil]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2003-01-20 06:32:19 -05:00
|
|
|
def pre_compile(s)
|
2002-11-17 11:11:40 -05:00
|
|
|
re = SplitRegexp
|
2003-01-20 06:32:19 -05:00
|
|
|
if @trim_mode.nil? && !@perc
|
2002-11-17 11:11:40 -05:00
|
|
|
list = s.split(re)
|
|
|
|
else
|
|
|
|
list = []
|
|
|
|
has_cr = (s[-1] == ?\n)
|
|
|
|
s.each do |line|
|
|
|
|
line = line.chomp
|
2003-01-20 06:32:19 -05:00
|
|
|
if @perc && (/^%/ =~ line)
|
|
|
|
list.push(ParcentLine.new(self, line))
|
2002-11-17 11:11:40 -05:00
|
|
|
else
|
2003-01-20 06:32:19 -05:00
|
|
|
push_line(list, line)
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
end
|
2003-01-20 06:32:19 -05:00
|
|
|
list.pop if list[-1] == "\n" && !has_cr
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
list
|
|
|
|
end
|
|
|
|
|
2003-01-20 06:32:19 -05:00
|
|
|
def push_line(list, line)
|
|
|
|
re = SplitRegexp
|
|
|
|
line = line.split(re)
|
|
|
|
line.shift if line[0]==''
|
|
|
|
list.concat(line)
|
|
|
|
unless ((@trim_mode == '>' && line[-1] == '%>') ||
|
|
|
|
(@trim_mode == '<>' && (is_erb_tag?(line[0])) &&
|
|
|
|
line[-1] == '%>'))
|
|
|
|
list.push("\n")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2002-11-17 11:11:40 -05:00
|
|
|
def compile(s)
|
2003-01-20 06:32:19 -05:00
|
|
|
list = pre_compile(s)
|
2002-11-17 11:11:40 -05:00
|
|
|
cmd = []
|
|
|
|
cmd.concat(@pre_cmd)
|
|
|
|
|
|
|
|
stag = nil
|
|
|
|
content = []
|
|
|
|
while (token = list.shift)
|
|
|
|
if token == '<%%'
|
|
|
|
token = '<'
|
|
|
|
list.unshift '%'
|
|
|
|
elsif token == '%%>'
|
|
|
|
token = '%'
|
|
|
|
list.unshift '>'
|
|
|
|
end
|
|
|
|
if stag.nil?
|
|
|
|
if ['<%', '<%=', '<%#'].include?(token)
|
|
|
|
stag = token
|
2003-01-20 06:32:19 -05:00
|
|
|
str = content.join('')
|
2002-11-17 11:11:40 -05:00
|
|
|
if str.size > 0
|
|
|
|
cmd.push("#{@put_cmd} #{str.dump}")
|
|
|
|
end
|
|
|
|
content = []
|
|
|
|
elsif token == "\n"
|
|
|
|
content.push("\n")
|
2003-01-20 06:32:19 -05:00
|
|
|
cmd.push("#{@put_cmd} #{content.join('').dump}")
|
2002-11-17 11:11:40 -05:00
|
|
|
cmd.push(:cr)
|
|
|
|
content = []
|
2003-01-20 06:32:19 -05:00
|
|
|
elsif ParcentLine === token
|
|
|
|
token.expand(list)
|
|
|
|
next
|
2002-11-17 11:11:40 -05:00
|
|
|
else
|
|
|
|
content.push(token)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if token == '%>'
|
|
|
|
case stag
|
|
|
|
when '<%'
|
2003-01-20 06:32:19 -05:00
|
|
|
str = content.join('')
|
2002-11-17 11:11:40 -05:00
|
|
|
if str[-1] == ?\n
|
|
|
|
str.chop!
|
|
|
|
cmd.push(str)
|
|
|
|
cmd.push(:cr)
|
|
|
|
else
|
|
|
|
cmd.push(str)
|
|
|
|
end
|
|
|
|
when '<%='
|
2003-01-20 06:32:19 -05:00
|
|
|
cmd.push("#{@put_cmd}((#{content.join('')}).to_s)")
|
2002-11-17 11:11:40 -05:00
|
|
|
when '<%#'
|
|
|
|
# cmd.push("# #{content.dump}")
|
|
|
|
end
|
|
|
|
stag = nil
|
|
|
|
content = []
|
2003-01-20 06:32:19 -05:00
|
|
|
elsif ParcentLine === token
|
|
|
|
token.expand_in_script(list)
|
|
|
|
next
|
2002-11-17 11:11:40 -05:00
|
|
|
else
|
|
|
|
content.push(token)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if content.size > 0
|
2003-01-20 06:32:19 -05:00
|
|
|
cmd.push("#{@put_cmd} #{content.join('').dump}")
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
cmd.push(:cr)
|
|
|
|
cmd.concat(@post_cmd)
|
|
|
|
|
|
|
|
ary = []
|
|
|
|
cmd.each do |x|
|
|
|
|
if x == :cr
|
|
|
|
ary.pop
|
|
|
|
ary.push("\n")
|
|
|
|
else
|
|
|
|
ary.push(x)
|
|
|
|
ary.push('; ')
|
|
|
|
end
|
|
|
|
end
|
2003-01-20 06:32:19 -05:00
|
|
|
ary.join('')
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
|
2003-01-20 06:32:19 -05:00
|
|
|
def initialize(trim_mode)
|
|
|
|
@perc, @trim_mode = prepare_trim_mode(trim_mode)
|
2002-11-17 11:11:40 -05:00
|
|
|
@put_cmd = 'print'
|
|
|
|
@pre_cmd = []
|
|
|
|
@post_cmd = []
|
|
|
|
end
|
2003-01-20 06:32:19 -05:00
|
|
|
|
|
|
|
attr_accessor(:put_cmd)
|
|
|
|
attr_accessor(:pre_cmd)
|
|
|
|
attr_accessor(:post_cmd)
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# ERB
|
|
|
|
class ERB
|
|
|
|
def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
|
|
|
|
@safe_level = safe_level
|
2003-01-20 06:32:19 -05:00
|
|
|
compiler = ERB::Compiler.new(trim_mode)
|
2002-11-17 11:11:40 -05:00
|
|
|
set_eoutvar(compiler, eoutvar)
|
|
|
|
@src = compiler.compile(str)
|
|
|
|
end
|
|
|
|
attr :src
|
|
|
|
|
|
|
|
def set_eoutvar(compiler, eoutvar = '_erbout')
|
|
|
|
compiler.put_cmd = "#{eoutvar}.concat"
|
|
|
|
|
|
|
|
cmd = []
|
|
|
|
cmd.push "#{eoutvar} = ''"
|
|
|
|
|
|
|
|
compiler.pre_cmd = cmd
|
|
|
|
|
|
|
|
cmd = []
|
|
|
|
cmd.push(eoutvar)
|
|
|
|
|
|
|
|
compiler.post_cmd = cmd
|
|
|
|
end
|
|
|
|
|
|
|
|
def run(b=TOPLEVEL_BINDING)
|
|
|
|
print self.result(b)
|
|
|
|
end
|
|
|
|
|
|
|
|
def result(b=TOPLEVEL_BINDING)
|
|
|
|
if @safe_level
|
|
|
|
th = Thread.start {
|
|
|
|
$SAFE = @safe_level
|
|
|
|
eval(@src, b)
|
|
|
|
}
|
|
|
|
return th.value
|
|
|
|
else
|
|
|
|
return eval(@src, b)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_method(mod, methodname, fname='(ERB)')
|
|
|
|
mod.module_eval("def #{methodname}\n" + self.src + "\nend\n", fname, 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_module(methodname='erb')
|
|
|
|
mod = Module.new
|
|
|
|
def_method(mod, methodname)
|
|
|
|
mod
|
|
|
|
end
|
|
|
|
|
|
|
|
def def_class(superklass=Object, methodname='result')
|
2002-11-21 09:39:26 -05:00
|
|
|
cls = Class.new(superklass)
|
2002-11-17 11:11:40 -05:00
|
|
|
def_method(cls, methodname)
|
|
|
|
cls
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# ERB::Util
|
|
|
|
class ERB
|
|
|
|
module Util
|
|
|
|
public
|
|
|
|
def html_escape(s)
|
|
|
|
s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<")
|
|
|
|
end
|
|
|
|
alias h html_escape
|
|
|
|
|
|
|
|
def url_encode(s)
|
|
|
|
s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
|
|
|
|
end
|
|
|
|
alias u url_encode
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# ERB::DefMethod
|
|
|
|
class ERB
|
|
|
|
module DefMethod
|
|
|
|
public
|
|
|
|
def def_erb_method(methodname, erb)
|
|
|
|
if erb.kind_of? String
|
|
|
|
fname = erb
|
|
|
|
File.open(fname) {|f| erb = ERB.new(f.read) }
|
2003-04-22 12:29:47 -04:00
|
|
|
erb.def_method(self, methodname, fname)
|
|
|
|
else
|
|
|
|
erb.def_method(self, methodname)
|
2002-11-17 11:11:40 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
module_function :def_erb_method
|
|
|
|
end
|
|
|
|
end
|