tilt 1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -33
- data/lib/tilt.rb +97 -76
- data/test/tilt_blueclothtemplate_test.rb +59 -0
- data/test/tilt_coffeescripttemplate_test.rb +1 -1
- data/test/tilt_compilesite_test.rb +2 -37
- data/test/tilt_erbtemplate_test.rb +25 -7
- data/test/tilt_hamltemplate_test.rb +2 -7
- data/test/tilt_markaby_test.rb +10 -0
- data/test/tilt_nokogiritemplate_test.rb +10 -1
- data/test/tilt_stringtemplate_test.rb +2 -7
- data/test/tilt_template_test.rb +0 -10
- data/tilt.gemspec +3 -2
- metadata +6 -4
data/README.md
CHANGED
@@ -38,6 +38,12 @@ Support for these template engines is included with the package:
|
|
38
38
|
Nokogiri .nokogiri nokogiri
|
39
39
|
CoffeeScript .coffee coffee-script (+node coffee)
|
40
40
|
|
41
|
+
These template engines ship with their own Tilt integration:
|
42
|
+
|
43
|
+
ENGINE FILE EXTENSIONS REQUIRED LIBRARIES
|
44
|
+
-------------------------- ----------------- ----------------------------
|
45
|
+
Slim .slim slim (>= 0.7)
|
46
|
+
|
41
47
|
See [TEMPLATES.md][t] for detailed information on template engine
|
42
48
|
options and supported features.
|
43
49
|
|
@@ -153,44 +159,13 @@ Or, use BlueCloth for markdown instead of RDiscount:
|
|
153
159
|
Template Compilation
|
154
160
|
--------------------
|
155
161
|
|
156
|
-
Tilt
|
157
|
-
|
162
|
+
Tilt compiles generated Ruby source code produced by template engines and reuses
|
163
|
+
it on subsequent template invocations. Benchmarks show this yields a 5x-10x
|
158
164
|
performance increase over evaluating the Ruby source on each invocation.
|
159
165
|
|
160
166
|
Template compilation is currently supported for these template engines:
|
161
167
|
StringTemplate, ERB, Erubis, Haml, and Builder.
|
162
168
|
|
163
|
-
To enable template compilation, the `Tilt::CompileSite` module must be mixed in
|
164
|
-
to the scope object passed to the template's `#render` method. This can be
|
165
|
-
accomplished by including (with `Module#include`) the module in the class used
|
166
|
-
for scope objects or by extending (with `Object#extend`) scope objects before
|
167
|
-
passing to `Template#render`:
|
168
|
-
|
169
|
-
require 'tilt'
|
170
|
-
|
171
|
-
template = Tilt::ERBTemplate.new('foo.erb')
|
172
|
-
|
173
|
-
# Slow. Uses Object#instance_eval to process template
|
174
|
-
class Scope
|
175
|
-
end
|
176
|
-
scope = Scope.new
|
177
|
-
template.render(scope)
|
178
|
-
|
179
|
-
# Fast. Uses compiled template and Object#send to process template
|
180
|
-
class Scope
|
181
|
-
include Tilt::CompileSite
|
182
|
-
end
|
183
|
-
scope = Scope.new
|
184
|
-
template.render(scope)
|
185
|
-
|
186
|
-
# Also fast, though a bit a slower due to having to extend each time
|
187
|
-
scope = Object.new
|
188
|
-
scope.extend Tilt::CompileSite
|
189
|
-
template.render(scope)
|
190
|
-
|
191
|
-
When the `Tilt::CompileSite` module is not present, template execution falls
|
192
|
-
back to evaluating the template from source on each invocation.
|
193
|
-
|
194
169
|
LICENSE
|
195
170
|
-------
|
196
171
|
|
data/lib/tilt.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
|
3
1
|
module Tilt
|
4
|
-
|
2
|
+
TOPOBJECT = defined?(BasicObject) ? BasicObject : Object
|
3
|
+
VERSION = '1.2'
|
5
4
|
|
6
5
|
@template_mappings = {}
|
7
6
|
|
@@ -42,19 +41,10 @@ module Tilt
|
|
42
41
|
@template_mappings[pattern]
|
43
42
|
end
|
44
43
|
|
45
|
-
#
|
46
|
-
#
|
47
|
-
# Including this module in scope objects passed to Template#render
|
48
|
-
# causes template source to be compiled to methods the first time they're
|
49
|
-
# used. This can yield significant (5x-10x) performance increases for
|
50
|
-
# templates that support it (ERB, Erubis, Builder).
|
51
|
-
#
|
52
|
-
# It's also possible (though not recommended) to include this module in
|
53
|
-
# Object to enable template compilation globally. The downside is that
|
54
|
-
# the template methods will polute the global namespace and could lead to
|
55
|
-
# unexpected behavior.
|
44
|
+
# Deprecated module.
|
56
45
|
module CompileSite
|
57
|
-
def
|
46
|
+
def self.append_features(*)
|
47
|
+
warn "WARNING: Tilt::CompileSite is deprecated and will be removed in Tilt 2.0 (#{caller.first})."
|
58
48
|
end
|
59
49
|
end
|
60
50
|
|
@@ -111,12 +101,15 @@ module Tilt
|
|
111
101
|
self.class.engine_initialized = true
|
112
102
|
end
|
113
103
|
|
114
|
-
# used to
|
115
|
-
@
|
116
|
-
@compiled_method_names = {}
|
104
|
+
# used to hold compiled template methods
|
105
|
+
@compiled_method = {}
|
117
106
|
|
118
|
-
#
|
119
|
-
|
107
|
+
# used on 1.9 to set the encoding if it is not set elsewhere (like a magic comment)
|
108
|
+
# currently only used if template compiles to ruby
|
109
|
+
@default_encoding = @options.delete :default_encoding
|
110
|
+
|
111
|
+
# load template data and prepare (uses binread to avoid encoding issues)
|
112
|
+
@reader = block || lambda { |t| File.respond_to?(:binread) ? File.binread(@file) : File.read(@file) }
|
120
113
|
@data = @reader.call(self)
|
121
114
|
prepare
|
122
115
|
end
|
@@ -175,25 +168,21 @@ module Tilt
|
|
175
168
|
end
|
176
169
|
end
|
177
170
|
|
178
|
-
# Process the template and return the result.
|
179
|
-
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
# specified and with support for yielding to the block.
|
171
|
+
# Process the template and return the result. The first time this
|
172
|
+
# method is called, the template source is evaluated with instance_eval.
|
173
|
+
# On the sequential method calls it will compile the template to an
|
174
|
+
# unbound method which will lead to better performance. In any case,
|
175
|
+
# template executation is guaranteed to be performed in the scope object
|
176
|
+
# with the locals specified and with support for yielding to the block.
|
185
177
|
def evaluate(scope, locals, &block)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
else
|
191
|
-
compile_template_method(method_name, locals)
|
192
|
-
scope.send(method_name, locals, &block)
|
193
|
-
end
|
194
|
-
else
|
195
|
-
evaluate_source(scope, locals, &block)
|
178
|
+
# Redefine itself to use method compilation the next time:
|
179
|
+
def self.evaluate(scope, locals, &block)
|
180
|
+
method = compiled_method(locals.keys)
|
181
|
+
method.bind(scope).call(locals, &block)
|
196
182
|
end
|
183
|
+
|
184
|
+
# Use instance_eval the first time:
|
185
|
+
evaluate_source(scope, locals, &block)
|
197
186
|
end
|
198
187
|
|
199
188
|
# Generates all template source by combining the preamble, template, and
|
@@ -207,9 +196,16 @@ module Tilt
|
|
207
196
|
# easier and more appropriate.
|
208
197
|
def precompiled(locals)
|
209
198
|
preamble = precompiled_preamble(locals)
|
199
|
+
template = precompiled_template(locals)
|
200
|
+
magic_comment = extract_magic_comment(template)
|
201
|
+
if magic_comment
|
202
|
+
# Magic comment e.g. "# coding: utf-8" has to be in the first line.
|
203
|
+
# So we copy the magic comment to the first line.
|
204
|
+
preamble = magic_comment + "\n" + preamble
|
205
|
+
end
|
210
206
|
parts = [
|
211
207
|
preamble,
|
212
|
-
|
208
|
+
template,
|
213
209
|
precompiled_postamble(locals)
|
214
210
|
]
|
215
211
|
[parts.join("\n"), preamble.count("\n") + 1]
|
@@ -241,10 +237,10 @@ module Tilt
|
|
241
237
|
''
|
242
238
|
end
|
243
239
|
|
244
|
-
# The
|
245
|
-
def
|
246
|
-
@
|
247
|
-
|
240
|
+
# The compiled method for the locals keys provided.
|
241
|
+
def compiled_method(locals_keys)
|
242
|
+
@compiled_method[locals_keys] ||=
|
243
|
+
compile_template_method(locals_keys)
|
248
244
|
end
|
249
245
|
|
250
246
|
private
|
@@ -274,42 +270,37 @@ module Tilt
|
|
274
270
|
end
|
275
271
|
end
|
276
272
|
|
277
|
-
def
|
278
|
-
parts = [object_id, @stamp] + locals_keys.map { |k| k.to_s }.sort
|
279
|
-
digest = Digest::MD5.hexdigest(parts.join(':'))
|
280
|
-
"__tilt_#{digest}"
|
281
|
-
end
|
282
|
-
|
283
|
-
def compile_template_method(method_name, locals)
|
273
|
+
def compile_template_method(locals)
|
284
274
|
source, offset = precompiled(locals)
|
285
275
|
offset += 5
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
276
|
+
method_name = "__tilt_#{Thread.current.object_id.abs}"
|
277
|
+
Object.class_eval <<-RUBY, eval_file, line - offset
|
278
|
+
#{extract_magic_comment source}
|
279
|
+
TOPOBJECT.class_eval do
|
280
|
+
def #{method_name}(locals)
|
281
|
+
Thread.current[:tilt_vars] = [self, locals]
|
282
|
+
class << self
|
283
|
+
this, locals = Thread.current[:tilt_vars]
|
284
|
+
this.instance_eval do
|
285
|
+
#{source}
|
286
|
+
end
|
293
287
|
end
|
294
288
|
end
|
295
289
|
end
|
296
290
|
RUBY
|
297
|
-
|
298
|
-
Template.compiled_template_method_remover(CompileSite, method_name)
|
291
|
+
unbind_compiled_method(method_name)
|
299
292
|
end
|
300
293
|
|
301
|
-
def
|
302
|
-
|
294
|
+
def unbind_compiled_method(method_name)
|
295
|
+
method = TOPOBJECT.instance_method(method_name)
|
296
|
+
TOPOBJECT.class_eval { remove_method(method_name) }
|
297
|
+
method
|
303
298
|
end
|
304
299
|
|
305
|
-
def
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
rescue NameError
|
310
|
-
# method was already removed (ruby >= 1.9)
|
311
|
-
end
|
312
|
-
end
|
300
|
+
def extract_magic_comment(script)
|
301
|
+
comment = script.slice(/\A[ \t]*\#.*coding\s*[=:]\s*([[:alnum:]\-_]+).*$/)
|
302
|
+
return comment if comment and not %w[ascii-8bit binary].include?($1.downcase)
|
303
|
+
"# coding: #{@default_encoding}" if @default_encoding
|
313
304
|
end
|
314
305
|
|
315
306
|
# Special case Ruby 1.9.1's broken yield.
|
@@ -320,16 +311,18 @@ module Tilt
|
|
320
311
|
# Remove when 1.9.2 dominates 1.9.1 installs in the wild.
|
321
312
|
if RUBY_VERSION =~ /^1.9.1/
|
322
313
|
undef compile_template_method
|
323
|
-
def compile_template_method(
|
314
|
+
def compile_template_method(locals)
|
324
315
|
source, offset = precompiled(locals)
|
325
316
|
offset += 1
|
326
|
-
|
327
|
-
|
328
|
-
|
317
|
+
method_name = "__tilt_#{Thread.current.object_id}"
|
318
|
+
Object.class_eval <<-RUBY, eval_file, line - offset
|
319
|
+
TOPOBJECT.class_eval do
|
320
|
+
def #{method_name}(locals)
|
321
|
+
#{source}
|
322
|
+
end
|
329
323
|
end
|
330
324
|
RUBY
|
331
|
-
|
332
|
-
Template.compiled_template_method_remover(CompileSite, method_name)
|
325
|
+
unbind_compiled_method(method_name)
|
333
326
|
end
|
334
327
|
end
|
335
328
|
end
|
@@ -635,6 +628,7 @@ module Tilt
|
|
635
628
|
xml = ::Nokogiri::XML::Builder.new
|
636
629
|
if data.respond_to?(:to_str)
|
637
630
|
locals[:xml] = xml
|
631
|
+
block &&= proc { yield.gsub(/^<\?xml version=\"1\.0\"\?>\n?/, "") }
|
638
632
|
super(scope, locals, &block)
|
639
633
|
elsif data.kind_of?(Proc)
|
640
634
|
data.call(xml)
|
@@ -744,6 +738,29 @@ module Tilt
|
|
744
738
|
register 'md', RDiscountTemplate
|
745
739
|
|
746
740
|
|
741
|
+
# BlueCloth Markdown implementation. See:
|
742
|
+
# http://deveiate.org/projects/BlueCloth/
|
743
|
+
#
|
744
|
+
# RDiscount is a simple text filter. It does not support +scope+ or
|
745
|
+
# +locals+. The +:smartypants+ and +:escape_html+ options may be set true
|
746
|
+
# to enable those flags on the underlying BlueCloth object.
|
747
|
+
class BlueClothTemplate < Template
|
748
|
+
def initialize_engine
|
749
|
+
return if defined? ::BlueCloth
|
750
|
+
require_template_library 'bluecloth'
|
751
|
+
end
|
752
|
+
|
753
|
+
def prepare
|
754
|
+
@engine = BlueCloth.new(data, options)
|
755
|
+
@output = nil
|
756
|
+
end
|
757
|
+
|
758
|
+
def evaluate(scope, locals, &block)
|
759
|
+
@output ||= @engine.to_html
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
|
747
764
|
# RedCloth implementation. See:
|
748
765
|
# http://redcloth.org/
|
749
766
|
class RedClothTemplate < Template
|
@@ -849,16 +866,20 @@ module Tilt
|
|
849
866
|
builder = self.class.builder_class.new({}, scope)
|
850
867
|
builder.locals = locals
|
851
868
|
|
852
|
-
if
|
869
|
+
if data.kind_of? Proc
|
870
|
+
(class << builder; self end).send(:define_method, :__run_markaby_tilt__, &data)
|
871
|
+
else
|
853
872
|
builder.instance_eval <<-CODE, __FILE__, __LINE__
|
854
873
|
def __run_markaby_tilt__
|
855
874
|
#{data}
|
856
875
|
end
|
857
876
|
CODE
|
877
|
+
end
|
858
878
|
|
879
|
+
if block
|
859
880
|
builder.__capture_markaby_tilt__(&block)
|
860
881
|
else
|
861
|
-
builder.
|
882
|
+
builder.__run_markaby_tilt__
|
862
883
|
end
|
863
884
|
|
864
885
|
builder.to_s
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'contest'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'bluecloth'
|
6
|
+
|
7
|
+
class BlueClothTemplateTest < Test::Unit::TestCase
|
8
|
+
setup do
|
9
|
+
Tilt.register('markdown', Tilt::BlueClothTemplate)
|
10
|
+
Tilt.register('md', Tilt::BlueClothTemplate)
|
11
|
+
Tilt.register('mkd', Tilt::BlueClothTemplate)
|
12
|
+
end
|
13
|
+
|
14
|
+
teardown do
|
15
|
+
# Need to revert to RDiscount, otherwise the RDiscount test will fail
|
16
|
+
Tilt.register('markdown', Tilt::RDiscountTemplate)
|
17
|
+
Tilt.register('md', Tilt::RDiscountTemplate)
|
18
|
+
Tilt.register('mkd', Tilt::RDiscountTemplate)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "registered for '.markdown' files unless RDiscount is loaded" do
|
22
|
+
unless defined?(RDiscount)
|
23
|
+
assert_equal Tilt::BlueClothTemplate, Tilt['test.markdown']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
test "registered for '.md' files unless RDiscount is loaded" do
|
28
|
+
unless defined?(RDiscount)
|
29
|
+
assert_equal Tilt::BlueClothTemplate, Tilt['test.md']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
test "registered for '.mkd' files unless RDiscount is loaded" do
|
34
|
+
unless defined?(RDiscount)
|
35
|
+
assert_equal Tilt::BlueClothTemplate, Tilt['test.mkd']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
test "preparing and evaluating templates on #render" do
|
40
|
+
template = Tilt::BlueClothTemplate.new { |t| "# Hello World!" }
|
41
|
+
assert_equal "<h1>Hello World!</h1>", template.render
|
42
|
+
end
|
43
|
+
|
44
|
+
test "smartypants when :smart is set" do
|
45
|
+
template = Tilt::BlueClothTemplate.new(:smartypants => true) { |t|
|
46
|
+
"OKAY -- 'Smarty Pants'" }
|
47
|
+
assert_equal "<p>OKAY — ‘Smarty Pants’</p>",
|
48
|
+
template.render
|
49
|
+
end
|
50
|
+
|
51
|
+
test "stripping HTML when :filter_html is set" do
|
52
|
+
template = Tilt::BlueClothTemplate.new(:escape_html => true) { |t|
|
53
|
+
"HELLO <blink>WORLD</blink>" }
|
54
|
+
assert_equal "<p>HELLO <blink>WORLD</blink></p>", template.render
|
55
|
+
end
|
56
|
+
end
|
57
|
+
rescue LoadError => boom
|
58
|
+
warn "Tilt::BlueClothTemplate (disabled)\n"
|
59
|
+
end
|
@@ -11,7 +11,7 @@ begin
|
|
11
11
|
|
12
12
|
test "compiles and evaluates the template on #render" do
|
13
13
|
template = Tilt::CoffeeScriptTemplate.new { |t| "puts 'Hello, World!'\n" }
|
14
|
-
|
14
|
+
assert_match "puts('Hello, World!');", template.render
|
15
15
|
end
|
16
16
|
|
17
17
|
test "disabling coffee-script wrapper" do
|
@@ -17,48 +17,13 @@ class CompileSiteTest < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
|
19
19
|
class Scope
|
20
|
-
include Tilt::CompileSite
|
21
20
|
end
|
22
21
|
|
23
22
|
test "compiling template source to a method" do
|
24
23
|
template = CompilingTemplate.new { |t| "Hello World!" }
|
25
24
|
template.render(Scope.new)
|
26
|
-
|
27
|
-
|
28
|
-
assert Tilt::CompileSite.instance_methods.include?(method_name),
|
29
|
-
"CompileSite.instance_methods.include?(#{method_name.inspect})"
|
30
|
-
assert Scope.new.respond_to?(method_name),
|
31
|
-
"scope.respond_to?(#{method_name.inspect})"
|
32
|
-
end
|
33
|
-
|
34
|
-
test 'garbage collecting compiled methods' do
|
35
|
-
template = CompilingTemplate.new { '' }
|
36
|
-
method_name = template.send(:compiled_method_name, [])
|
37
|
-
template.render(Scope.new)
|
38
|
-
assert Scope.new.respond_to?(method_name)
|
39
|
-
Tilt::Template.send(
|
40
|
-
:garbage_collect_compiled_template_method,
|
41
|
-
Tilt::CompileSite,
|
42
|
-
method_name
|
43
|
-
)
|
44
|
-
assert !Scope.new.respond_to?(method_name), "compiled method not removed"
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.create_and_destroy_template
|
48
|
-
template = CompilingTemplate.new { 'Hello World' }
|
49
|
-
template.render(Scope.new)
|
50
|
-
method_name = template.send(:compiled_method_name, [])
|
51
|
-
method_name = method_name.to_sym if Symbol === Kernel.methods.first
|
52
|
-
[template.object_id, method_name]
|
53
|
-
end
|
54
|
-
|
55
|
-
finalized_object_id, finalized_method_name = create_and_destroy_template
|
56
|
-
|
57
|
-
test "triggering compiled method gc finalizer" do
|
58
|
-
assert !Tilt::CompileSite.instance_methods.include?(finalized_method_name),
|
59
|
-
"CompileSite.instance_methods.include?(#{finalized_method_name.inspect})"
|
60
|
-
assert !Scope.new.respond_to?(finalized_method_name),
|
61
|
-
"Scope.new.respond_to?(#{finalized_method_name.inspect})"
|
25
|
+
method = template.send(:compiled_method, [])
|
26
|
+
assert_kind_of UnboundMethod, method
|
62
27
|
end
|
63
28
|
|
64
29
|
# This test attempts to surface issues with compiling templates from
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require 'contest'
|
2
3
|
require 'tilt'
|
3
4
|
require 'erb'
|
5
|
+
require 'tempfile'
|
4
6
|
|
5
7
|
class ERBTemplateTest < Test::Unit::TestCase
|
6
8
|
test "registered for '.erb' files" do
|
@@ -113,18 +115,13 @@ class CompiledERBTemplateTest < Test::Unit::TestCase
|
|
113
115
|
end
|
114
116
|
|
115
117
|
class Scope
|
116
|
-
include Tilt::CompileSite
|
117
118
|
end
|
118
119
|
|
119
120
|
test "compiling template source to a method" do
|
120
121
|
template = Tilt::ERBTemplate.new { |t| "Hello World!" }
|
121
122
|
template.render(Scope.new)
|
122
|
-
|
123
|
-
|
124
|
-
assert Tilt::CompileSite.instance_methods.include?(method_name),
|
125
|
-
"CompileSite.instance_methods.include?(#{method_name.inspect})"
|
126
|
-
assert Scope.new.respond_to?(method_name),
|
127
|
-
"scope.respond_to?(#{method_name.inspect})"
|
123
|
+
method = template.send(:compiled_method, [])
|
124
|
+
assert_kind_of UnboundMethod, method
|
128
125
|
end
|
129
126
|
|
130
127
|
test "loading and evaluating templates on #render" do
|
@@ -199,6 +196,27 @@ class CompiledERBTemplateTest < Test::Unit::TestCase
|
|
199
196
|
template = Tilt.new('test.erb', :trim => '%') { "\n% if true\nhello\n%end\n" }
|
200
197
|
assert_equal "\nhello\n", template.render(Scope.new)
|
201
198
|
end
|
199
|
+
|
200
|
+
test "encoding with magic comment" do
|
201
|
+
f = Tempfile.open("template")
|
202
|
+
f.puts('<%# coding: UTF-8 %>')
|
203
|
+
f.puts('ふが <%= @hoge %>')
|
204
|
+
f.close()
|
205
|
+
@hoge = "ほげ"
|
206
|
+
erb = Tilt['erb'].new(f.path)
|
207
|
+
3.times { erb.render(self) }
|
208
|
+
f.delete
|
209
|
+
end
|
210
|
+
|
211
|
+
test "encoding with :default_encoding" do
|
212
|
+
f = Tempfile.open("template")
|
213
|
+
f.puts('ふが <%= @hoge %>')
|
214
|
+
f.close()
|
215
|
+
@hoge = "ほげ"
|
216
|
+
erb = Tilt['erb'].new(f.path, :default_encoding => 'UTF-8')
|
217
|
+
3.times { erb.render(self) }
|
218
|
+
f.delete
|
219
|
+
end
|
202
220
|
end
|
203
221
|
|
204
222
|
__END__
|
@@ -68,18 +68,13 @@ begin
|
|
68
68
|
|
69
69
|
class CompiledHamlTemplateTest < Test::Unit::TestCase
|
70
70
|
class Scope
|
71
|
-
include Tilt::CompileSite
|
72
71
|
end
|
73
72
|
|
74
73
|
test "compiling template source to a method" do
|
75
74
|
template = Tilt::HamlTemplate.new { |t| "Hello World!" }
|
76
75
|
template.render(Scope.new)
|
77
|
-
|
78
|
-
|
79
|
-
assert Tilt::CompileSite.instance_methods.include?(method_name),
|
80
|
-
"CompileSite.instance_methods.include?(#{method_name.inspect})"
|
81
|
-
assert Scope.new.respond_to?(method_name),
|
82
|
-
"scope.respond_to?(#{method_name.inspect})"
|
76
|
+
method = template.send(:compiled_method, [])
|
77
|
+
assert_kind_of UnboundMethod, method
|
83
78
|
end
|
84
79
|
|
85
80
|
test "passing locals" do
|
data/test/tilt_markaby_test.rb
CHANGED
@@ -66,6 +66,16 @@ begin
|
|
66
66
|
test "should return a new instance of the implementation class (when calling Tilt.new)" do
|
67
67
|
assert ::Tilt.new(File.dirname(__FILE__) + "/markaby/markaby.mab").kind_of?(Tilt::MarkabyTemplate)
|
68
68
|
end
|
69
|
+
|
70
|
+
test "should be able to evaluate block style templates" do
|
71
|
+
tilt = Tilt::MarkabyTemplate.new { |t| lambda { h1 "Hello World!" }}
|
72
|
+
assert_equal "<h1>Hello World!</h1>", tilt.render
|
73
|
+
end
|
74
|
+
|
75
|
+
test "should pass locals to block style templates" do
|
76
|
+
tilt = Tilt::MarkabyTemplate.new { |t| lambda { h1 "Hello #{name}!" }}
|
77
|
+
assert_equal "<h1>Hello _why!</h1>", tilt.render(nil, :name => "_why")
|
78
|
+
end
|
69
79
|
end
|
70
80
|
|
71
81
|
rescue LoadError => boom
|
@@ -44,10 +44,19 @@ begin
|
|
44
44
|
Tilt::NokogiriTemplate.new do |t|
|
45
45
|
lambda { |xml| xml.em('Hey Joe!') }
|
46
46
|
end
|
47
|
-
doc = Nokogiri.XML template.render
|
47
|
+
doc = Nokogiri.XML template.render
|
48
48
|
assert_equal 'Hey Joe!', doc.root.text
|
49
49
|
assert_equal 'em', doc.root.name
|
50
50
|
end
|
51
|
+
|
52
|
+
test "allows nesting raw XML, API-compatible to Builder" do
|
53
|
+
subtemplate = Tilt::NokogiriTemplate.new { "xml.em 'Hello World!'" }
|
54
|
+
template = Tilt::NokogiriTemplate.new { "xml.strong { xml << yield }" }
|
55
|
+
options = { :xml => Nokogiri::XML::Builder.new }
|
56
|
+
doc = Nokogiri.XML(template.render(options) { subtemplate.render(options) })
|
57
|
+
assert_equal 'Hello World!', doc.root.text.strip
|
58
|
+
assert_equal 'strong', doc.root.name
|
59
|
+
end
|
51
60
|
end
|
52
61
|
rescue LoadError
|
53
62
|
warn "Tilt::NokogiriTemplate (disabled)"
|
@@ -74,18 +74,13 @@ class CompiledStringTemplateTest < Test::Unit::TestCase
|
|
74
74
|
end
|
75
75
|
|
76
76
|
class Scope
|
77
|
-
include Tilt::CompileSite
|
78
77
|
end
|
79
78
|
|
80
79
|
test "compiling template source to a method" do
|
81
80
|
template = Tilt::StringTemplate.new { |t| "Hello World!" }
|
82
81
|
template.render(Scope.new)
|
83
|
-
|
84
|
-
|
85
|
-
assert Tilt::CompileSite.instance_methods.include?(method_name),
|
86
|
-
"CompileSite.instance_methods.include?(#{method_name.inspect})"
|
87
|
-
assert Scope.new.respond_to?(method_name),
|
88
|
-
"scope.respond_to?(#{method_name.inspect})"
|
82
|
+
method = template.send(:compiled_method, [])
|
83
|
+
assert_kind_of UnboundMethod, method
|
89
84
|
end
|
90
85
|
|
91
86
|
test "loading and evaluating templates on #render" do
|
data/test/tilt_template_test.rb
CHANGED
@@ -145,14 +145,4 @@ class TiltTemplateTest < Test::Unit::TestCase
|
|
145
145
|
inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{CONSTANT}!' }
|
146
146
|
assert_equal "Hey Bob!", inst.render(Person.new("Joe"))
|
147
147
|
end
|
148
|
-
|
149
|
-
class FastPerson < Person
|
150
|
-
include Tilt::CompileSite
|
151
|
-
end
|
152
|
-
|
153
|
-
test "template which accesses a constant with Tilt::CompileSite" do
|
154
|
-
flunk "known broken under 1.9.1" if RUBY_VERSION =~ /^1.9.1/
|
155
|
-
inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{CONSTANT}!' }
|
156
|
-
assert_equal "Hey Bob!", inst.render(FastPerson.new("Joe"))
|
157
|
-
end
|
158
148
|
end
|
data/tilt.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'tilt'
|
6
|
-
s.version = '1.
|
7
|
-
s.date = '2010-
|
6
|
+
s.version = '1.2'
|
7
|
+
s.date = '2010-12-24'
|
8
8
|
|
9
9
|
s.description = "Generic interface to multiple Ruby template engines"
|
10
10
|
s.summary = s.description
|
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
test/markaby/render_twice.mab
|
28
28
|
test/markaby/scope.mab
|
29
29
|
test/markaby/yielding.mab
|
30
|
+
test/tilt_blueclothtemplate_test.rb
|
30
31
|
test/tilt_buildertemplate_test.rb
|
31
32
|
test/tilt_cache_test.rb
|
32
33
|
test/tilt_coffeescripttemplate_test.rb
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tilt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: "1.
|
8
|
+
- 2
|
9
|
+
version: "1.2"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ryan Tomayko
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-12-24 00:00:00 -08:00
|
18
18
|
default_executable: tilt
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -195,6 +195,7 @@ files:
|
|
195
195
|
- test/markaby/render_twice.mab
|
196
196
|
- test/markaby/scope.mab
|
197
197
|
- test/markaby/yielding.mab
|
198
|
+
- test/tilt_blueclothtemplate_test.rb
|
198
199
|
- test/tilt_buildertemplate_test.rb
|
199
200
|
- test/tilt_cache_test.rb
|
200
201
|
- test/tilt_coffeescripttemplate_test.rb
|
@@ -255,6 +256,7 @@ signing_key:
|
|
255
256
|
specification_version: 2
|
256
257
|
summary: Generic interface to multiple Ruby template engines
|
257
258
|
test_files:
|
259
|
+
- test/tilt_blueclothtemplate_test.rb
|
258
260
|
- test/tilt_buildertemplate_test.rb
|
259
261
|
- test/tilt_cache_test.rb
|
260
262
|
- test/tilt_coffeescripttemplate_test.rb
|