tilt 1.1 → 1.2
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/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
|