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
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 kuwata-lab.com
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,315 @@
|
|
1
|
+
BabyErubis.rb
|
2
|
+
=============
|
3
|
+
|
4
|
+
$Release: 0.1.0 $
|
5
|
+
|
6
|
+
BabyErubis is an yet another eRuby implementation, based on Erubis.
|
7
|
+
|
8
|
+
* Small and fast
|
9
|
+
* Easy to customize
|
10
|
+
* Supports HTML as well as plain text
|
11
|
+
* Accepts both template file and template string
|
12
|
+
|
13
|
+
BabyErubis support Ruby 1.9 or higher.
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
Examples
|
18
|
+
========
|
19
|
+
|
20
|
+
|
21
|
+
Render template string:
|
22
|
+
|
23
|
+
require 'baby_erubis'
|
24
|
+
template = BabyErubis::Html.new.from_str <<'END', __FILE__, __LINE__+1
|
25
|
+
<h1><%= @title %></h1>
|
26
|
+
<% for item in @items %>
|
27
|
+
<p><%= item %></p>
|
28
|
+
<% end %>
|
29
|
+
END
|
30
|
+
context = {:title=>'Example', :items=>['A', 'B', 'C']}
|
31
|
+
output = template.render(context)
|
32
|
+
print output
|
33
|
+
|
34
|
+
|
35
|
+
Render template file:
|
36
|
+
|
37
|
+
require 'baby_erubis'
|
38
|
+
templat = BabyErubis::Html.new.from_file('example.html.erb', 'utf-8')
|
39
|
+
context = {:title=>'Example', :items=>['A', 'B', 'C']}
|
40
|
+
output = template.render(context)
|
41
|
+
print output
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
Template Syntax
|
46
|
+
===============
|
47
|
+
|
48
|
+
* `<% ... %>` : Ruby statement
|
49
|
+
* `<%= ... %>` : Ruby expression with escaping
|
50
|
+
* `<%== ... %>` : Ruby expression without escaping
|
51
|
+
|
52
|
+
Expression in `<%= ... %>` is escaped according to template class.
|
53
|
+
|
54
|
+
* `BabyErubis::Text` doesn't escape anything.
|
55
|
+
It justs converts expression into a string.
|
56
|
+
* `BabyErubis::Html` escapes html special characters.
|
57
|
+
It converts '< > & " \'' into '< > & " '' respectively.
|
58
|
+
|
59
|
+
(Experimental) `<%- ... -%>` and `<%-= ... -%>` are handled same as
|
60
|
+
`<% ... %>` and `<%= ... %>` respectively.
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
Advanced Topics
|
65
|
+
===============
|
66
|
+
|
67
|
+
|
68
|
+
Template Context
|
69
|
+
----------------
|
70
|
+
|
71
|
+
When rendering template, you can pass not only Hash object but also any object
|
72
|
+
as context values. Internally, rendering method converts Hash object into
|
73
|
+
`BabyErubis::TemplateContext` object automatically.
|
74
|
+
|
75
|
+
Example:
|
76
|
+
|
77
|
+
require 'baby_erubis'
|
78
|
+
|
79
|
+
class MyApp
|
80
|
+
include BabyErubis::HtmlEscaper # necessary to define escape()
|
81
|
+
|
82
|
+
TEMPLATE = BabyErubis::Html.new.from_str <<-'END', __FILE__, __LINE__+1
|
83
|
+
<html>
|
84
|
+
<body>
|
85
|
+
<p>Hello <%= @name %>!</p>
|
86
|
+
</body>
|
87
|
+
</html>
|
88
|
+
END
|
89
|
+
|
90
|
+
def initialize(name)
|
91
|
+
@name = name
|
92
|
+
end
|
93
|
+
|
94
|
+
def render()
|
95
|
+
return TEMPLATE.render(self)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
if __FILE__ == $0
|
101
|
+
print MyApp.new('World').render()
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
String#freeze()
|
106
|
+
---------------
|
107
|
+
|
108
|
+
BabyErubis supports String#freeze() automatically when Ruby version >= 2.1.
|
109
|
+
And you can controll whether to use freeze() or not.
|
110
|
+
|
111
|
+
template_str = <<'END'
|
112
|
+
<div>
|
113
|
+
<b><%= message %></b>
|
114
|
+
</div>
|
115
|
+
END
|
116
|
+
|
117
|
+
## don't use freeze()
|
118
|
+
t = BabyErubis::Text.new(:freeze=>false).from_str(template_str)
|
119
|
+
print t.src
|
120
|
+
# --- result ---
|
121
|
+
# _buf = ''; _buf << '<div>
|
122
|
+
# <b>'; _buf << (message).to_s; _buf << '</b>
|
123
|
+
# </div>
|
124
|
+
# '; _buf.to_s
|
125
|
+
|
126
|
+
## use freeze() forcedly
|
127
|
+
t = BabyErubis::Text.new(:freeze=>true).from_str(template_str)
|
128
|
+
print t.src
|
129
|
+
# --- result ---
|
130
|
+
# _buf = ''; _buf << '<div>
|
131
|
+
# <b>'.freeze; _buf << (message).to_s; _buf << '</b>
|
132
|
+
# </div>
|
133
|
+
# '.freeze; _buf.to_s
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
Customizing
|
138
|
+
===========
|
139
|
+
|
140
|
+
|
141
|
+
Change Embed Pattern from '<% %>' to '{% %}'
|
142
|
+
--------------------------------------------
|
143
|
+
|
144
|
+
Sample code:
|
145
|
+
|
146
|
+
require 'baby_erubis'
|
147
|
+
|
148
|
+
class MyTemplate < BabyErubis::Html
|
149
|
+
|
150
|
+
rexp = BabyErubis::Template::PATTERN
|
151
|
+
PATTERN = Regexp.compile(rexp.to_s.sub(/<%/, '\{%').sub(/%>/, '%\}'))
|
152
|
+
|
153
|
+
def pattern
|
154
|
+
PATTERN
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
template = MyTemplate.new <<-'END'
|
160
|
+
{% for item in @items %}
|
161
|
+
- {%= item %}
|
162
|
+
{% end %}
|
163
|
+
END
|
164
|
+
|
165
|
+
print template.render(:items=>['A', 'B', 'C'])
|
166
|
+
|
167
|
+
Output:
|
168
|
+
|
169
|
+
- A
|
170
|
+
- B
|
171
|
+
- C
|
172
|
+
|
173
|
+
|
174
|
+
Strip Spaces in HTML Template
|
175
|
+
-----------------------------
|
176
|
+
|
177
|
+
Sample code:
|
178
|
+
|
179
|
+
require 'baby_erubis'
|
180
|
+
|
181
|
+
class MyTemplate < BabyErubis::Html
|
182
|
+
|
183
|
+
def parse(input, *args)
|
184
|
+
stripped = input.gsub(/^[ \t]+</, '<')
|
185
|
+
return super(stripped, *args)
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
template = MyTemplate.new <<-'END'
|
191
|
+
<html>
|
192
|
+
<body>
|
193
|
+
<p>Hello <%= @name %>!</p>
|
194
|
+
</body>
|
195
|
+
</html>
|
196
|
+
END
|
197
|
+
|
198
|
+
print template.render(:name=>"Hello")
|
199
|
+
|
200
|
+
Output:
|
201
|
+
|
202
|
+
<html>
|
203
|
+
<body>
|
204
|
+
<p>Hello Hello!</p>
|
205
|
+
</body>
|
206
|
+
</html>
|
207
|
+
|
208
|
+
|
209
|
+
Layout Template
|
210
|
+
---------------
|
211
|
+
|
212
|
+
Sample code:
|
213
|
+
|
214
|
+
require 'baby_erubis'
|
215
|
+
|
216
|
+
class MyApp
|
217
|
+
include BabyErubis::HtmlEscaper # necessary to define escape()
|
218
|
+
|
219
|
+
LAYOUT = BabyErubis::Html.new.from_str <<-'END', __FILE__, __LINE__+1
|
220
|
+
<html>
|
221
|
+
<body>
|
222
|
+
<% _buf << @_content %> # or <%== @_content %>
|
223
|
+
</body>
|
224
|
+
</html>
|
225
|
+
END
|
226
|
+
|
227
|
+
TEMPLATE = BabyErubis::Html.new.from_str <<-'END', __FILE__, __LINE__+1
|
228
|
+
<p>Hello <%= @name %>!</p>
|
229
|
+
END
|
230
|
+
|
231
|
+
def initialize(name)
|
232
|
+
@name = name
|
233
|
+
end
|
234
|
+
|
235
|
+
def render()
|
236
|
+
@_content = TEMPLATE.render(self)
|
237
|
+
return LAYOUT.render(self)
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
if __FILE__ == $0
|
243
|
+
print MyApp.new('World').render()
|
244
|
+
end
|
245
|
+
|
246
|
+
Output:
|
247
|
+
|
248
|
+
<html>
|
249
|
+
<body>
|
250
|
+
<p>Hello World!</p>
|
251
|
+
</body>
|
252
|
+
</html>
|
253
|
+
|
254
|
+
|
255
|
+
Template Cache File
|
256
|
+
-------------------
|
257
|
+
|
258
|
+
Sample code:
|
259
|
+
|
260
|
+
require 'baby_erubis'
|
261
|
+
require 'logger'
|
262
|
+
|
263
|
+
$logger = Logger.new(STDERR)
|
264
|
+
|
265
|
+
class MyTemplate < BabyErubis::Html
|
266
|
+
|
267
|
+
def from_file(filename, encoding='utf-8')
|
268
|
+
cachefile = "#{filename}.cache"
|
269
|
+
timestamp = File.mtime(filename)
|
270
|
+
has_cache = File.file?(cachefile) && File.mtime(cachefile) == timestamp
|
271
|
+
if has_cache
|
272
|
+
$logger.info("loading template from cache file: #{cachefile}")
|
273
|
+
ruby_code = File.open(cachefile, "rb:#{encoding}") {|f| f.read }
|
274
|
+
compile(ruby_code, filename, 1)
|
275
|
+
else
|
276
|
+
super(filename, encoding)
|
277
|
+
$logger.info("creating template cache file: #{cachefile}")
|
278
|
+
ruby_code = self.src
|
279
|
+
tmpname = "#{cachefile}.#{rand().to_s[2,5]}"
|
280
|
+
File.open(tmpname, "wb:#{encoding}") {|f| f.write(ruby_code) }
|
281
|
+
File.utime(timestamp, timestamp, tmpname)
|
282
|
+
File.rename(tmpname, cachefile)
|
283
|
+
end
|
284
|
+
return self
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
p File.exist?('example.html.erb.cache') #=> false
|
290
|
+
t = MyTemplate.new.from_file('example.html.erb')
|
291
|
+
p File.exist?('example.html.erb.cache') #=> true
|
292
|
+
|
293
|
+
|
294
|
+
|
295
|
+
Changes
|
296
|
+
=======
|
297
|
+
|
298
|
+
Release 0.1.0 (2014-05-06)
|
299
|
+
--------------------------
|
300
|
+
|
301
|
+
* Public release
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
License
|
306
|
+
=======
|
307
|
+
|
308
|
+
$License: MIT License $
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
Copyright
|
313
|
+
=========
|
314
|
+
|
315
|
+
$Copyright: copyright(c) 2014 kuwata-lab.com all rights reserved $
|
data/Rakefile
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
###
|
4
|
+
|
5
|
+
RELEASE = ENV['rel'] || '0.0.0'
|
6
|
+
COPYRIGHT = 'copyright(c) 2014 kuwata-lab.com all rights reserved'
|
7
|
+
LICENSE = 'MIT License'
|
8
|
+
|
9
|
+
###
|
10
|
+
|
11
|
+
task :default => :test
|
12
|
+
|
13
|
+
def edit_content(content)
|
14
|
+
s = content
|
15
|
+
s = s.gsub /\$Release\:.*?\$/, "$Release\: #{RELEASE} $"
|
16
|
+
s = s.gsub /\$Copyright\:.*?\$/, "$Copyright\: #{COPYRIGHT} $"
|
17
|
+
s = s.gsub /\$License\:.*?\$/, "$License\: #{LICENSE} $"
|
18
|
+
s = s.gsub /\$Release\$/, RELEASE
|
19
|
+
s = s.gsub /\$Copyright\$/, COPYRIGHT
|
20
|
+
s = s.gsub /\$License\$/, LICENSE
|
21
|
+
s
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
desc "run test scripts"
|
26
|
+
task :test do
|
27
|
+
#sh "ruby -r minitest/autorun test/*_test.rb"
|
28
|
+
sh "ruby test/run_all.rb"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
desc "copy files into 'dist/#{RELEASE}'"
|
33
|
+
task :dist do
|
34
|
+
require_release_number()
|
35
|
+
spec_src = File.open('baby_erubis.gemspec') {|f| f.read }
|
36
|
+
spec = eval spec_src
|
37
|
+
dir = "dist/#{RELEASE}"
|
38
|
+
rm_rf dir
|
39
|
+
mkdir_p dir
|
40
|
+
sh "tar cf - #{spec.files.join(' ')} | (cd #{dir}; tar xvf -)"
|
41
|
+
spec.files.each do |fpath|
|
42
|
+
#filepath = File.join(dir, fpath)
|
43
|
+
#content = File.open(filepath, 'rb:utf-8') {|f| f.read }
|
44
|
+
#new_content = edit_content(content)
|
45
|
+
#File.open(filepath, 'wb:utf-8') {|f| f.write(new_content) }
|
46
|
+
content = File.open(File.join(dir, fpath), 'r+b:utf-8') do |f|
|
47
|
+
content = f.read
|
48
|
+
new_content = edit_content(content)
|
49
|
+
f.rewind()
|
50
|
+
f.truncate(0)
|
51
|
+
f.write(new_content)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
desc "create rubygem pacakge"
|
58
|
+
task :package => :dist do
|
59
|
+
require_release_number()
|
60
|
+
chdir "dist/#{RELEASE}" do
|
61
|
+
sh "gem build *.gemspec"
|
62
|
+
end
|
63
|
+
mv Dir.glob("dist/#{RELEASE}/*.gem"), 'dist'
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
desc "release gem"
|
68
|
+
task :release => :package do
|
69
|
+
require_release_number()
|
70
|
+
sh "git tag ruby-#{RELEASE}"
|
71
|
+
chdir "dist" do
|
72
|
+
sh "gem push baby_erubis-#{RELEASE}.gem"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def require_release_number
|
78
|
+
if RELEASE == '0.0.0'
|
79
|
+
$stderr.puts "*** Release number is not speicified"
|
80
|
+
$stderr.puts "*** Usage: rake <task> rel=X.X.X"
|
81
|
+
raise StandardError
|
82
|
+
end
|
83
|
+
end
|
data/baby_erubis.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
###
|
4
|
+
### $Release: 0.1.0 $
|
5
|
+
### $License: MIT License $
|
6
|
+
### $Copyright: copyright(c) 2014 kuwata-lab.com all rights reserved $
|
7
|
+
###
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
|
11
|
+
Gem::Specification.new do |s|
|
12
|
+
## package information
|
13
|
+
s.name = "baby_erubis"
|
14
|
+
s.author = "makoto kuwata"
|
15
|
+
s.email = "kwa(at)kuwata-lab.com"
|
16
|
+
s.version = "$Release: 0.1.0 $".split()[1]
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.homepage = "https://github.com/kwatch/BabyErubis/tree/ruby"
|
19
|
+
s.summary = "yet another eRuby implementation based on Erubis"
|
20
|
+
s.description = <<'END'
|
21
|
+
BabyErubis is an yet another eRuby implementation, based on Erubis.
|
22
|
+
|
23
|
+
* Small and fast
|
24
|
+
* Supports HTML as well as plain text
|
25
|
+
* Accepts both template file and template string
|
26
|
+
* Easy to customize
|
27
|
+
|
28
|
+
BabyErubis support Ruby 1.9 or higher.
|
29
|
+
END
|
30
|
+
|
31
|
+
## files
|
32
|
+
files = []
|
33
|
+
files += Dir.glob('lib/*.rb')
|
34
|
+
files += Dir.glob('test/*.rb')
|
35
|
+
files += %w[README.md MIT-LICENSE setup.rb baby_erubis.gemspec Rakefile]
|
36
|
+
s.files = files
|
37
|
+
s.test_file = 'test/run_all.rb'
|
38
|
+
end
|