1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
##
## $Release:$
## $Copyright$
##
module Erubis
##
## tiny and the simplest implementation of eRuby
##
## ex.
## eruby = TinyEruby.new(File.read('example.rhtml'))
## print eruby.src # print ruby code
## print eruby.result(binding()) # eval ruby code with Binding object
## print eruby.evalute(context) # eval ruby code with context object
##
class TinyEruby
def initialize(input=nil)
@src = convert(input) if input
end
attr_reader :src
EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m
def convert(input)
src = "_buf = '';" # preamble
pos = 0
input.scan(EMBEDDED_PATTERN) do |indicator, code|
match = Regexp.last_match
len = match.begin(0) - pos
text = input[pos, len]
pos = match.end(0)
#src << " _buf << '" << escape_text(text) << "';"
text.gsub!(/['\\]/, '\\\\\&')
src << " _buf << '" << text << "';" unless text.empty?
if !indicator # <% %>
src << code << ";"
elsif indicator == '#' # <%# %>
src << ("\n" * code.count("\n"))
else # <%= %>
src << " _buf << (" << code << ").to_s;"
end
end
#rest = $' || input # ruby1.8
rest = pos == 0 ? input : input[pos..-1] # ruby1.9
#src << " _buf << '" << escape_text(rest) << "';"
rest.gsub!(/['\\]/, '\\\\\&')
src << " _buf << '" << rest << "';" unless rest.empty?
src << "\n_buf.to_s\n" # postamble
return src
end
#def escape_text(text)
# return text.gsub!(/['\\]/, '\\\\\&') || text
#end
def result(_binding=TOPLEVEL_BINDING)
eval @src, _binding
end
def evaluate(_context=Object.new)
if _context.is_a?(Hash)
_obj = Object.new
_context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
_context = _obj
end
_context.instance_eval @src
end
end
module PI
end
class PI::TinyEruby
def initialize(input=nil, options={})
@escape = options[:escape] || 'Erubis::XmlHelper.escape_xml'
@src = convert(input) if input
end
attr_reader :src
EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m
def convert(input)
src = "_buf = '';" # preamble
pos = 0
input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr|
match = Regexp.last_match
len = match.begin(0) - pos
text = input[pos, len]
pos = match.end(0)
#src << " _buf << '" << escape_text(text) << "';"
text.gsub!(/['\\]/, '\\\\\&')
src << " _buf << '" << text << "';" unless text.empty?
if stmt # <?rb ... ?>
if lspace && rspace
src << "#{lspace}#{stmt}#{rspace}"
else
src << " _buf << '" << lspace << "';" if lspace
src << stmt << ";"
src << " _buf << '" << rspace << "';" if rspace
end
else # ${...}, $!{...}
if !indicator
src << " _buf << " << @escape << "(" << expr << ");"
elsif indicator == '!'
src << " _buf << (" << expr << ").to_s;"
end
end
end
#rest = $' || input # ruby1.8
rest = pos == 0 ? input : input[pos..-1] # ruby1.9
#src << " _buf << '" << escape_text(rest) << "';"
rest.gsub!(/['\\]/, '\\\\\&')
src << " _buf << '" << rest << "';" unless rest.empty?
src << "\n_buf.to_s\n" # postamble
return src
end
#def escape_text(text)
# return text.gsub!(/['\\]/, '\\\\\&') || text
#end
def result(_binding=TOPLEVEL_BINDING)
eval @src, _binding
end
def evaluate(_context=Object.new)
if _context.is_a?(Hash)
_obj = Object.new
_context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
_context = _obj
end
_context.instance_eval @src
end
end
end
|