baby_erubis 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.md +315 -0
- data/Rakefile +83 -0
- data/baby_erubis.gemspec +38 -0
- data/lib/baby_erubis.rb +196 -0
- data/setup.rb +1585 -0
- data/test/context_test.rb +97 -0
- data/test/run_all.rb +12 -0
- data/test/template_test.rb +429 -0
- metadata +68 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 0.1.0 $
|
5
|
+
### $Copyright: copyright(c) 2014 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
libpath = File.class_eval { join(dirname(dirname(__FILE__)), 'lib') }
|
10
|
+
$: << libpath unless $:.include?(libpath)
|
11
|
+
|
12
|
+
require 'minitest/autorun'
|
13
|
+
|
14
|
+
require 'baby_erubis'
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
describe 'BabyErubis::TemplateContext' do
|
19
|
+
|
20
|
+
let(:ctx) { BabyErubis::TemplateContext.new }
|
21
|
+
|
22
|
+
|
23
|
+
describe '#initialize()' do
|
24
|
+
|
25
|
+
it "[!p69q1] takes hash object and sets them into instance variables." do
|
26
|
+
ctx = BabyErubis::TemplateContext.new(:x=>10, :y=>20)
|
27
|
+
assert_equal 10, ctx.instance_variable_get('@x')
|
28
|
+
assert_equal 20, ctx.instance_variable_get('@y')
|
29
|
+
assert_equal [:@x, :@y], ctx.instance_variables
|
30
|
+
end
|
31
|
+
|
32
|
+
it "[!p853f] do nothing when vars is nil." do
|
33
|
+
ctx = BabyErubis::TemplateContext.new(nil)
|
34
|
+
assert_equal [], ctx.instance_variables
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
describe '#[]' do
|
41
|
+
|
42
|
+
it "returns context value." do
|
43
|
+
ctx = BabyErubis::TemplateContext.new(:x=>10)
|
44
|
+
assert_equal 10, ctx[:x]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
describe '#[]=' do
|
51
|
+
|
52
|
+
it "returns context value." do
|
53
|
+
ctx = BabyErubis::TemplateContext.new
|
54
|
+
ctx[:y] = 20
|
55
|
+
assert_equal 20, ctx[:y]
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
describe '#escape()' do
|
62
|
+
|
63
|
+
it "converts any value into string." do
|
64
|
+
assert_equal '10', ctx.escape(10)
|
65
|
+
assert_equal 'true', ctx.escape(true)
|
66
|
+
assert_equal '', ctx.escape(nil)
|
67
|
+
assert_equal '["A", "B"]', ctx.escape(['A', 'B'])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "does not escape html special chars." do
|
71
|
+
assert_equal '<>&"', ctx.escape('<>&"')
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
describe 'BabyErubis::HtmlTemplateContext' do
|
82
|
+
|
83
|
+
let(:ctx) { BabyErubis::HtmlTemplateContext.new }
|
84
|
+
|
85
|
+
|
86
|
+
describe '#escape()' do
|
87
|
+
|
88
|
+
it "escapes html special chars." do
|
89
|
+
assert_equal '<>&"'', ctx.__send__(:escape, '<>&"\'')
|
90
|
+
assert_equal '<a href="?x=1&y=2&z=3">click</a>',
|
91
|
+
ctx.__send__(:escape, '<a href="?x=1&y=2&z=3">click</a>')
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
end
|
data/test/run_all.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 0.1.0 $
|
5
|
+
### $Copyright: copyright(c) 2014 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
here = File.dirname(File.expand_path(__FILE__))
|
10
|
+
Dir.glob(here + '/**/*.rb').each do |fpath|
|
11
|
+
require fpath
|
12
|
+
end
|
@@ -0,0 +1,429 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 0.1.0 $
|
5
|
+
### $Copyright: copyright(c) 2014 kuwata-lab.com all rights reserved $
|
6
|
+
### $License: MIT License $
|
7
|
+
###
|
8
|
+
|
9
|
+
libpath = File.class_eval { join(dirname(dirname(__FILE__)), 'lib') }
|
10
|
+
$: << libpath unless $:.include?(libpath)
|
11
|
+
|
12
|
+
require 'minitest/autorun'
|
13
|
+
|
14
|
+
require 'baby_erubis'
|
15
|
+
|
16
|
+
|
17
|
+
def _modify(ruby_code)
|
18
|
+
if (''.freeze).equal?(''.freeze)
|
19
|
+
return ruby_code.gsub(/([^'])';/m, "\\1'.freeze;")
|
20
|
+
else
|
21
|
+
return ruby_code
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
describe BabyErubis::Template do
|
27
|
+
|
28
|
+
let(:template) { BabyErubis::Text.new() }
|
29
|
+
|
30
|
+
|
31
|
+
describe '#parse()' do
|
32
|
+
|
33
|
+
it "[!118pw] parses template string into ruby code." do
|
34
|
+
input = <<'END'
|
35
|
+
title: <%= @title %>
|
36
|
+
items:
|
37
|
+
<% for item in @items %>
|
38
|
+
- <%= item %>
|
39
|
+
<% end %>
|
40
|
+
END
|
41
|
+
expected = <<'END'
|
42
|
+
_buf = ''; _buf << 'title: '; _buf << (@title).to_s; _buf << '
|
43
|
+
'; _buf << 'items:
|
44
|
+
'; for item in @items;
|
45
|
+
_buf << ' - '; _buf << (item).to_s; _buf << '
|
46
|
+
'; end;
|
47
|
+
_buf.to_s
|
48
|
+
END
|
49
|
+
expected = _modify(expected)
|
50
|
+
code = template.parse(input)
|
51
|
+
assert_equal expected, code
|
52
|
+
end
|
53
|
+
|
54
|
+
it "[!7ht59] escapes single quotation and backslash characters." do
|
55
|
+
input = <<'END'
|
56
|
+
who's who?
|
57
|
+
'''
|
58
|
+
\w
|
59
|
+
\\\
|
60
|
+
END
|
61
|
+
expected = <<'END'
|
62
|
+
_buf = ''; _buf << 'who\'s who?
|
63
|
+
\'\'\'
|
64
|
+
\\w
|
65
|
+
\\\\\\
|
66
|
+
'; _buf.to_s
|
67
|
+
END
|
68
|
+
expected = _modify(expected)
|
69
|
+
assert_equal expected, template.parse(input)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "[!u93y5] appends embedded expression in '<%= %>'." do
|
73
|
+
input = <<'END'
|
74
|
+
x = <%= x %>
|
75
|
+
END
|
76
|
+
expected = <<'END'
|
77
|
+
_buf = ''; _buf << 'x = '; _buf << (x).to_s; _buf << '
|
78
|
+
'; _buf.to_s
|
79
|
+
END
|
80
|
+
expected = _modify(expected)
|
81
|
+
assert_equal expected, template.parse(input)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "[!auj95] appends embedded expression in '<%= %>' without escaping." do
|
85
|
+
input = <<'END'
|
86
|
+
x = <%== x %>
|
87
|
+
END
|
88
|
+
expected = <<'END'
|
89
|
+
_buf = ''; _buf << 'x = '; _buf << (x).to_s; _buf << '
|
90
|
+
'; _buf.to_s
|
91
|
+
END
|
92
|
+
expected = _modify(expected)
|
93
|
+
assert_equal expected, template.parse(input)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "[!qveql] appends linefeeds when '<%# %>' found." do
|
97
|
+
input = <<'END'
|
98
|
+
<%#
|
99
|
+
for x in xs
|
100
|
+
%>
|
101
|
+
x = <%#=
|
102
|
+
x
|
103
|
+
%>
|
104
|
+
<%#
|
105
|
+
end
|
106
|
+
%>
|
107
|
+
END
|
108
|
+
expected = <<'END'
|
109
|
+
_buf = '';
|
110
|
+
|
111
|
+
_buf << '
|
112
|
+
'; _buf << 'x = ';
|
113
|
+
|
114
|
+
_buf << '
|
115
|
+
';
|
116
|
+
|
117
|
+
_buf << '
|
118
|
+
'; _buf.to_s
|
119
|
+
END
|
120
|
+
expected = _modify(expected)
|
121
|
+
assert_equal expected, template.parse(input)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "[!b10ns] generates ruby code correctly even when no embedded code." do
|
125
|
+
input = <<'END'
|
126
|
+
abc
|
127
|
+
def
|
128
|
+
END
|
129
|
+
expected = <<'END'
|
130
|
+
_buf = ''; _buf << 'abc
|
131
|
+
def
|
132
|
+
'; _buf.to_s
|
133
|
+
END
|
134
|
+
expected = _modify(expected)
|
135
|
+
assert_equal expected, template.parse(input)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "[!3bx3d] not print extra linefeeds when line starts with '<%' and ends with '%>'" do
|
139
|
+
input = <<'END'
|
140
|
+
<% for item in items %>
|
141
|
+
<% if item %>
|
142
|
+
item = <%= item %>
|
143
|
+
<% end %>
|
144
|
+
<% end %>
|
145
|
+
END
|
146
|
+
expected = <<'END'
|
147
|
+
_buf = ''; for item in items;
|
148
|
+
if item;
|
149
|
+
_buf << ' item = '; _buf << (item).to_s; _buf << '
|
150
|
+
'; end;
|
151
|
+
end;
|
152
|
+
_buf.to_s
|
153
|
+
END
|
154
|
+
expected = _modify(expected)
|
155
|
+
assert_equal expected, template.parse(input)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "handles '<%- -%>' (but do nothing)." do
|
159
|
+
input = <<'END'
|
160
|
+
<%- for item in @items -%>
|
161
|
+
<%-== item -%>
|
162
|
+
<%- end -%>
|
163
|
+
END
|
164
|
+
expected = <<'END'
|
165
|
+
_buf = ''; for item in @items;
|
166
|
+
_buf << ' '; _buf << (item).to_s; _buf << '
|
167
|
+
'; end;
|
168
|
+
_buf.to_s
|
169
|
+
END
|
170
|
+
expected = _modify(expected)
|
171
|
+
assert_equal expected, template.parse(input)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "uses String#freeze forcedly when ':freeze=>true' passed to constructor." do
|
175
|
+
input = "value=<%== value %>"
|
176
|
+
expected = "_buf = ''; _buf << 'value='.freeze; _buf << (value).to_s; _buf.to_s\n"
|
177
|
+
template = BabyErubis::Text.new(:freeze=>true)
|
178
|
+
assert_equal expected, template.parse(input)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "doesn't use String#freeze when ':freeze=>false' passed to constructor." do
|
182
|
+
input = "value=<%== value %>"
|
183
|
+
expected = "_buf = ''; _buf << 'value='; _buf << (value).to_s; _buf.to_s\n"
|
184
|
+
template = BabyErubis::Text.new(:freeze=>false)
|
185
|
+
assert_equal expected, template.parse(input)
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
describe '#pattern()' do
|
192
|
+
|
193
|
+
it "returns default embed pattern." do
|
194
|
+
template = BabyErubis::Template.new
|
195
|
+
assert_equal BabyErubis::Template::PATTERN, template.pattern
|
196
|
+
end
|
197
|
+
|
198
|
+
it "returns new embed pattern when overrided in subclass." do
|
199
|
+
class FooTemplate < BabyErubis::Template
|
200
|
+
rexp = BabyErubis::Template::PATTERN
|
201
|
+
PATTERN = Regexp.compile(rexp.to_s.sub(/<%/, '\{%').sub(/%>/, '%\}'))
|
202
|
+
end
|
203
|
+
template = FooTemplate.new
|
204
|
+
refute_equal BabyErubis::Template::PATTERN, template.pattern
|
205
|
+
assert_equal FooTemplate::PATTERN, template.pattern
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
describe '#render()' do
|
212
|
+
|
213
|
+
it "renders template with context values." do
|
214
|
+
input = <<'END'
|
215
|
+
title: <%== @title %>
|
216
|
+
items:
|
217
|
+
<% for item in @items %>
|
218
|
+
- <%== item %>
|
219
|
+
<% end %>
|
220
|
+
END
|
221
|
+
expected = <<'END'
|
222
|
+
title: Example
|
223
|
+
items:
|
224
|
+
- <AAA>
|
225
|
+
- B&B
|
226
|
+
- "CCC"
|
227
|
+
END
|
228
|
+
context = {:title=>'Example', :items=>['<AAA>', 'B&B', '"CCC"']}
|
229
|
+
output = template.from_str(input).render(context)
|
230
|
+
assert_equal expected, output
|
231
|
+
end
|
232
|
+
|
233
|
+
it "renders context values with no escaping." do
|
234
|
+
input = <<'END'
|
235
|
+
title: <%= @title %>
|
236
|
+
items:
|
237
|
+
<% for item in @items %>
|
238
|
+
- <%= item %>
|
239
|
+
<% end %>
|
240
|
+
END
|
241
|
+
expected = <<'END'
|
242
|
+
title: <b>Example</b>
|
243
|
+
items:
|
244
|
+
- <AAA>
|
245
|
+
- B&B
|
246
|
+
- "CCC"
|
247
|
+
END
|
248
|
+
tmpl = BabyErubis::Text.new.from_str(input)
|
249
|
+
context = {:title=>'<b>Example</b>', :items=>['<AAA>', 'B&B', '"CCC"']}
|
250
|
+
output = tmpl.render(context)
|
251
|
+
assert_equal expected, output
|
252
|
+
end
|
253
|
+
|
254
|
+
it "uses arg as context object when arg is not a hash object." do
|
255
|
+
input = <<'END'
|
256
|
+
title: <%= @title %>
|
257
|
+
items:
|
258
|
+
<% for item in @items %>
|
259
|
+
- <%= item %>
|
260
|
+
<% end %>
|
261
|
+
END
|
262
|
+
expected = <<'END'
|
263
|
+
title: Example
|
264
|
+
items:
|
265
|
+
- <AAA>
|
266
|
+
- B&B
|
267
|
+
- "CCC"
|
268
|
+
END
|
269
|
+
obj = Object.new
|
270
|
+
obj.instance_variable_set('@title', 'Example')
|
271
|
+
obj.instance_variable_set('@items', ['<AAA>', 'B&B', '"CCC"'])
|
272
|
+
output = template.from_str(input).render(obj)
|
273
|
+
assert_equal expected, output
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
describe '#compile()' do
|
280
|
+
|
281
|
+
it "compiles ruby code into proc object." do
|
282
|
+
assert_nil template.instance_variable_get('@_proc')
|
283
|
+
template.compile("_buf = ''; _buf << (x).to_s; _buf")
|
284
|
+
assert_kind_of Proc, template.instance_variable_get('@proc')
|
285
|
+
end
|
286
|
+
|
287
|
+
it "returns self." do
|
288
|
+
assert_same template, template.compile("_buf = ''; _buf << (x).to_s; _buf")
|
289
|
+
end
|
290
|
+
|
291
|
+
it "takes filename and linenum." do
|
292
|
+
begin
|
293
|
+
template.compile("_buf = ''; _buf << (x).to_s; _buf", 'example.erb', 3)
|
294
|
+
rescue SyntaxError => ex
|
295
|
+
assert_match /\Aexample\.erb:3: syntax error/, ex.message
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
it "uses '(eRuby)' as default filename and 1 as default linenum." do
|
300
|
+
begin
|
301
|
+
template.compile("_buf = ''; _buf << (x).to_s; _buf")
|
302
|
+
rescue SyntaxError => ex
|
303
|
+
assert_match /\A\(eRuby\):1: syntax error/, ex.message
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
describe '.from_file()' do
|
311
|
+
|
312
|
+
it "reads template file and returns template object." do
|
313
|
+
input = <<'END'
|
314
|
+
title: <%= @title %>
|
315
|
+
items:
|
316
|
+
<% for item in @items %>
|
317
|
+
- <%= item %>
|
318
|
+
<% end %>
|
319
|
+
END
|
320
|
+
expected = <<'END'
|
321
|
+
title: Example
|
322
|
+
items:
|
323
|
+
- <AAA>
|
324
|
+
- B&B
|
325
|
+
- "CCC"
|
326
|
+
END
|
327
|
+
tmpfile = "test.#{rand()}.erb"
|
328
|
+
File.open(tmpfile, 'wb') {|f| f.write(input) }
|
329
|
+
begin
|
330
|
+
template = BabyErubis::Text.new.from_file(tmpfile)
|
331
|
+
context = {:title=>'Example', :items=>['<AAA>', 'B&B', '"CCC"']}
|
332
|
+
output = template.render(context)
|
333
|
+
assert_equal expected, output
|
334
|
+
ensure
|
335
|
+
File.unlink(tmpfile) if File.exist?(tmpfile)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
it "reads template file with specified encoding." do
|
340
|
+
input = "タイトル: <%= @title %>"
|
341
|
+
expected = "タイトル: サンプル"
|
342
|
+
tmpfile = "test.#{rand()}.erb"
|
343
|
+
File.open(tmpfile, 'wb:utf-8') {|f| f.write(input) }
|
344
|
+
begin
|
345
|
+
# nothing should be raised
|
346
|
+
template = BabyErubis::Text.new.from_file(tmpfile, 'utf-8')
|
347
|
+
output = template.render(:title=>"サンプル")
|
348
|
+
assert_equal expected, output
|
349
|
+
assert_equal 'UTF-8', output.encoding.name
|
350
|
+
# exception should be raised
|
351
|
+
ex = assert_raises ArgumentError do
|
352
|
+
template = BabyErubis::Text.new.from_file(tmpfile, 'us-ascii')
|
353
|
+
end
|
354
|
+
assert_equal "invalid byte sequence in US-ASCII", ex.message
|
355
|
+
ensure
|
356
|
+
File.unlink(tmpfile) if File.exist?(tmpfile)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
describe BabyErubis::HtmlTemplate do
|
368
|
+
|
369
|
+
input = <<'END'
|
370
|
+
<html>
|
371
|
+
<h1><%= @title %></h1>
|
372
|
+
<ul>
|
373
|
+
<% for item in @items %>
|
374
|
+
<!-- <%== item %> -->
|
375
|
+
<li><%= item %></li>
|
376
|
+
<% end %>
|
377
|
+
</ul>
|
378
|
+
</html>
|
379
|
+
END
|
380
|
+
source = <<'END'
|
381
|
+
_buf = ''; _buf << '<html>
|
382
|
+
<h1>'; _buf << escape(@title); _buf << '</h1>
|
383
|
+
<ul>
|
384
|
+
'; for item in @items;
|
385
|
+
_buf << ' <!-- '; _buf << (item).to_s; _buf << ' -->
|
386
|
+
<li>'; _buf << escape(item); _buf << '</li>
|
387
|
+
'; end;
|
388
|
+
_buf << ' </ul>
|
389
|
+
</html>
|
390
|
+
'; _buf.to_s
|
391
|
+
END
|
392
|
+
source = _modify(source)
|
393
|
+
output = <<'END'
|
394
|
+
<html>
|
395
|
+
<h1>Example</h1>
|
396
|
+
<ul>
|
397
|
+
<!-- <AAA> -->
|
398
|
+
<li><AAA></li>
|
399
|
+
<!-- B&B -->
|
400
|
+
<li>B&B</li>
|
401
|
+
<!-- "CCC" -->
|
402
|
+
<li>"CCC"</li>
|
403
|
+
</ul>
|
404
|
+
</html>
|
405
|
+
END
|
406
|
+
|
407
|
+
|
408
|
+
describe '#parse()' do
|
409
|
+
|
410
|
+
it "handles embedded expression with escaping." do
|
411
|
+
tmpl = BabyErubis::Html.new.from_str(input)
|
412
|
+
assert_equal source, tmpl.src
|
413
|
+
end
|
414
|
+
|
415
|
+
end
|
416
|
+
|
417
|
+
|
418
|
+
describe '#render()' do
|
419
|
+
|
420
|
+
it "renders context values with escaping." do
|
421
|
+
tmpl = BabyErubis::Html.new.from_str(input)
|
422
|
+
context = {:title=>'Example', :items=>['<AAA>', 'B&B', '"CCC"']}
|
423
|
+
assert_equal output, tmpl.render(context)
|
424
|
+
end
|
425
|
+
|
426
|
+
end
|
427
|
+
|
428
|
+
|
429
|
+
end
|