tilt 1.3.7 → 1.4.1
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/CHANGELOG.md +8 -0
- data/README.md +21 -0
- data/TEMPLATES.md +2 -2
- data/lib/tilt/template.rb +70 -24
- data/lib/tilt.rb +1 -1
- data/test/tilt_markdown_test.rb +1 -1
- data/test/tilt_template_test.rb +144 -0
- data/tilt.gemspec +2 -2
- metadata +3 -2
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -194,6 +194,27 @@ template, but if you depend on a specific implementation, you should use #prefer
|
|
|
194
194
|
When a file extension has a preferred template class, Tilt will *always* use
|
|
195
195
|
that class, even if it raises an exception.
|
|
196
196
|
|
|
197
|
+
Encodings
|
|
198
|
+
---------
|
|
199
|
+
|
|
200
|
+
Tilt needs to know the encoding of the template in order to work properly:
|
|
201
|
+
|
|
202
|
+
Tilt will use `Encoding.default_external` as the encoding when reading external
|
|
203
|
+
files. If you're mostly working with one encoding (e.g. UTF-8) we *highly*
|
|
204
|
+
recommend setting this option. When providing a custom reader block (`Tilt.new
|
|
205
|
+
{ custom_string }`) you'll have ensure the string is properly encoded yourself.
|
|
206
|
+
|
|
207
|
+
Most of the template engines in Tilt also allows you to override the encoding
|
|
208
|
+
using the `:default_encoding`-option:
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
tmpl = Tilt.new('hello.erb', :default_encoding => 'Big5')
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Ultimately it's up to the template engine how to handle the encoding: It might
|
|
215
|
+
respect `:default_encoding`, it might always assume it's UTF-8 (like
|
|
216
|
+
CoffeScript), or it can do its own encoding detection.
|
|
217
|
+
|
|
197
218
|
Template Compilation
|
|
198
219
|
--------------------
|
|
199
220
|
|
data/TEMPLATES.md
CHANGED
|
@@ -305,9 +305,9 @@ time when using this template engine within a threaded environment.
|
|
|
305
305
|
|
|
306
306
|
### See also
|
|
307
307
|
|
|
308
|
-
* [Liquid for Programmers](
|
|
308
|
+
* [Liquid for Programmers](https://wiki.github.com/Shopify/liquid/liquid-for-programmers)
|
|
309
309
|
* [Liquid Docs](http://liquid.rubyforge.org/)
|
|
310
|
-
* GitHub: [
|
|
310
|
+
* GitHub: [Shopify/liquid](https://github.com/Shopify/liquid/)
|
|
311
311
|
|
|
312
312
|
|
|
313
313
|
<a name='radius'></a>
|
data/lib/tilt/template.rb
CHANGED
|
@@ -65,11 +65,37 @@ module Tilt
|
|
|
65
65
|
@default_encoding = @options.delete :default_encoding
|
|
66
66
|
|
|
67
67
|
# load template data and prepare (uses binread to avoid encoding issues)
|
|
68
|
-
@reader = block || lambda { |t|
|
|
68
|
+
@reader = block || lambda { |t| read_template_file }
|
|
69
69
|
@data = @reader.call(self)
|
|
70
|
+
|
|
71
|
+
if @data.respond_to?(:force_encoding)
|
|
72
|
+
@data.force_encoding(default_encoding) if default_encoding
|
|
73
|
+
|
|
74
|
+
if !@data.valid_encoding?
|
|
75
|
+
raise Encoding::InvalidByteSequenceError, "#{eval_file} is not valid #{@data.encoding}"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
70
79
|
prepare
|
|
71
80
|
end
|
|
72
81
|
|
|
82
|
+
# The encoding of the source data. Defaults to the
|
|
83
|
+
# default_encoding-option if present. You may override this method
|
|
84
|
+
# in your template class if you have a better hint of the data's
|
|
85
|
+
# encoding.
|
|
86
|
+
def default_encoding
|
|
87
|
+
@default_encoding
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def read_template_file
|
|
91
|
+
data = File.open(file, 'rb') { |io| io.read }
|
|
92
|
+
if data.respond_to?(:force_encoding)
|
|
93
|
+
# Set it to the default external (without verifying)
|
|
94
|
+
data.force_encoding(Encoding.default_external) if Encoding.default_external
|
|
95
|
+
end
|
|
96
|
+
data
|
|
97
|
+
end
|
|
98
|
+
|
|
73
99
|
# Render the template in the given scope with the locals specified. If a
|
|
74
100
|
# block is given, it is typically available within the template via
|
|
75
101
|
# +yield+.
|
|
@@ -156,26 +182,32 @@ module Tilt
|
|
|
156
182
|
def precompiled(locals)
|
|
157
183
|
preamble = precompiled_preamble(locals)
|
|
158
184
|
template = precompiled_template(locals)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
185
|
+
postamble = precompiled_postamble(locals)
|
|
186
|
+
source = ''
|
|
187
|
+
|
|
188
|
+
# Ensure that our generated source code has the same encoding as the
|
|
189
|
+
# the source code generated by the template engine.
|
|
190
|
+
if source.respond_to?(:force_encoding)
|
|
191
|
+
template_encoding = extract_encoding(template)
|
|
192
|
+
|
|
193
|
+
source.force_encoding(template_encoding)
|
|
194
|
+
template.force_encoding(template_encoding)
|
|
164
195
|
end
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
]
|
|
170
|
-
|
|
196
|
+
|
|
197
|
+
# https://github.com/rtomayko/tilt/issues/193
|
|
198
|
+
warn "precompiled_preamble should return String (not Array)" if preamble.is_a?(Array)
|
|
199
|
+
warn "precompiled_postamble should return String (not Array)" if postamble.is_a?(Array)
|
|
200
|
+
source << [preamble, template, postamble].join("\n")
|
|
201
|
+
|
|
202
|
+
[source, preamble.count("\n")+1]
|
|
171
203
|
end
|
|
172
204
|
|
|
173
205
|
# A string containing the (Ruby) source code for the template. The
|
|
174
|
-
# default Template#evaluate implementation requires either this
|
|
175
|
-
# or the #precompiled method be overridden. When defined,
|
|
176
|
-
# Template guarantees correct file/line handling, locals
|
|
177
|
-
# scopes, and support for template
|
|
178
|
-
#
|
|
206
|
+
# default Template#evaluate implementation requires either this
|
|
207
|
+
# method or the #precompiled method be overridden. When defined,
|
|
208
|
+
# the base Template guarantees correct file/line handling, locals
|
|
209
|
+
# support, custom scopes, proper encoding, and support for template
|
|
210
|
+
# compilation.
|
|
179
211
|
def precompiled_template(locals)
|
|
180
212
|
raise NotImplementedError
|
|
181
213
|
end
|
|
@@ -212,8 +244,13 @@ module Tilt
|
|
|
212
244
|
def compile_template_method(locals)
|
|
213
245
|
source, offset = precompiled(locals)
|
|
214
246
|
method_name = "__tilt_#{Thread.current.object_id.abs}"
|
|
215
|
-
method_source =
|
|
216
|
-
|
|
247
|
+
method_source = ""
|
|
248
|
+
|
|
249
|
+
if method_source.respond_to?(:force_encoding)
|
|
250
|
+
method_source.force_encoding(source.encoding)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
method_source << <<-RUBY
|
|
217
254
|
TOPOBJECT.class_eval do
|
|
218
255
|
def #{method_name}(locals)
|
|
219
256
|
Thread.current[:tilt_vars] = [self, locals]
|
|
@@ -234,13 +271,22 @@ module Tilt
|
|
|
234
271
|
method
|
|
235
272
|
end
|
|
236
273
|
|
|
274
|
+
def extract_encoding(script)
|
|
275
|
+
extract_magic_comment(script) || script.encoding
|
|
276
|
+
end
|
|
277
|
+
|
|
237
278
|
def extract_magic_comment(script)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
comment
|
|
241
|
-
elsif @default_encoding
|
|
242
|
-
"# coding: #{@default_encoding}"
|
|
279
|
+
binary script do
|
|
280
|
+
script[/\A[ \t]*\#.*coding\s*[=:]\s*([[:alnum:]\-_]+).*$/n, 1]
|
|
243
281
|
end
|
|
244
282
|
end
|
|
283
|
+
|
|
284
|
+
def binary(string)
|
|
285
|
+
original_encoding = string.encoding
|
|
286
|
+
string.force_encoding(Encoding::BINARY)
|
|
287
|
+
yield
|
|
288
|
+
ensure
|
|
289
|
+
string.force_encoding(original_encoding)
|
|
290
|
+
end
|
|
245
291
|
end
|
|
246
292
|
end
|
data/lib/tilt.rb
CHANGED
data/test/tilt_markdown_test.rb
CHANGED
data/test/tilt_template_test.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# coding: utf-8
|
|
1
2
|
require 'contest'
|
|
2
3
|
require 'tilt'
|
|
3
4
|
require 'tempfile'
|
|
@@ -152,6 +153,53 @@ class TiltTemplateTest < Test::Unit::TestCase
|
|
|
152
153
|
assert_equal "1 + 2 = 3", inst.render(Object.new, '_answer' => 3)
|
|
153
154
|
end
|
|
154
155
|
|
|
156
|
+
class CustomGeneratingMockTemplate < PreparingMockTemplate
|
|
157
|
+
def precompiled_template(locals)
|
|
158
|
+
data
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def precompiled_preamble(locals)
|
|
162
|
+
options.fetch(:preamble)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def precompiled_postamble(locals)
|
|
166
|
+
options.fetch(:postamble)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
test "supports pre/postamble" do
|
|
171
|
+
inst = CustomGeneratingMockTemplate.new(
|
|
172
|
+
:preamble => 'buf = []',
|
|
173
|
+
:postamble => 'buf.join'
|
|
174
|
+
) { 'buf << 1' }
|
|
175
|
+
|
|
176
|
+
assert_equal "1", inst.render
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Special-case for Haml
|
|
180
|
+
# https://github.com/rtomayko/tilt/issues/193
|
|
181
|
+
test "supports Array pre/postambles" do
|
|
182
|
+
inst = CustomGeneratingMockTemplate.new(
|
|
183
|
+
:preamble => ['buf = ', '[]'],
|
|
184
|
+
:postamble => ['buf.', 'join']
|
|
185
|
+
) { 'buf << 1' }
|
|
186
|
+
|
|
187
|
+
# TODO: Use assert_output when we swicth to MiniTest
|
|
188
|
+
warns = <<-EOF
|
|
189
|
+
precompiled_preamble should return String (not Array)
|
|
190
|
+
precompiled_postamble should return String (not Array)
|
|
191
|
+
EOF
|
|
192
|
+
|
|
193
|
+
begin
|
|
194
|
+
require 'stringio'
|
|
195
|
+
$stderr = StringIO.new
|
|
196
|
+
assert_equal "1", inst.render
|
|
197
|
+
assert_equal warns, $stderr.string
|
|
198
|
+
ensure
|
|
199
|
+
$stderr = STDERR
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
155
203
|
class Person
|
|
156
204
|
CONSTANT = "Bob"
|
|
157
205
|
|
|
@@ -176,4 +224,100 @@ class TiltTemplateTest < Test::Unit::TestCase
|
|
|
176
224
|
inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{CONSTANT}!' }
|
|
177
225
|
assert_equal "Hey Bob!", inst.render(Person.new("Joe"))
|
|
178
226
|
end
|
|
227
|
+
|
|
228
|
+
##
|
|
229
|
+
# Encodings
|
|
230
|
+
|
|
231
|
+
class DynamicMockTemplate < MockTemplate
|
|
232
|
+
def precompiled_template(locals)
|
|
233
|
+
options[:code]
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
class UTF8Template < MockTemplate
|
|
238
|
+
def default_encoding
|
|
239
|
+
Encoding::UTF_8
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
if ''.respond_to?(:encoding)
|
|
244
|
+
original_encoding = Encoding.default_external
|
|
245
|
+
|
|
246
|
+
setup do
|
|
247
|
+
@file = Tempfile.open('template')
|
|
248
|
+
@file.puts "stuff"
|
|
249
|
+
@file.close
|
|
250
|
+
@template = @file.path
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
teardown do
|
|
254
|
+
Encoding.default_external = original_encoding
|
|
255
|
+
Encoding.default_internal = nil
|
|
256
|
+
@file.delete
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
test "reading from file assumes default external encoding" do
|
|
260
|
+
Encoding.default_external = 'Big5'
|
|
261
|
+
inst = MockTemplate.new(@template)
|
|
262
|
+
assert_equal 'Big5', inst.data.encoding.to_s
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
test "reading from file with a :default_encoding overrides default external" do
|
|
266
|
+
Encoding.default_external = 'Big5'
|
|
267
|
+
inst = MockTemplate.new(@template, :default_encoding => 'GBK')
|
|
268
|
+
assert_equal 'GBK', inst.data.encoding.to_s
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
test "reading from file with default_internal set does no transcoding" do
|
|
272
|
+
Encoding.default_internal = 'utf-8'
|
|
273
|
+
Encoding.default_external = 'Big5'
|
|
274
|
+
inst = MockTemplate.new(@template)
|
|
275
|
+
assert_equal 'Big5', inst.data.encoding.to_s
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
test "using provided template data verbatim when given as string" do
|
|
279
|
+
Encoding.default_internal = 'Big5'
|
|
280
|
+
inst = MockTemplate.new(@template) { "blah".force_encoding('GBK') }
|
|
281
|
+
assert_equal 'GBK', inst.data.encoding.to_s
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
test "uses the template from the generated source code" do
|
|
285
|
+
tmpl = "ふが"
|
|
286
|
+
code = tmpl.inspect.encode('Shift_JIS')
|
|
287
|
+
inst = DynamicMockTemplate.new(:code => code) { '' }
|
|
288
|
+
res = inst.render
|
|
289
|
+
assert_equal 'Shift_JIS', res.encoding.to_s
|
|
290
|
+
assert_equal tmpl, res.encode(tmpl.encoding)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
test "uses the magic comment from the generated source code" do
|
|
294
|
+
tmpl = "ふが"
|
|
295
|
+
code = ("# coding: Shift_JIS\n" + tmpl.inspect).encode('Shift_JIS')
|
|
296
|
+
# Set it to an incorrect encoding
|
|
297
|
+
code.force_encoding('UTF-8')
|
|
298
|
+
|
|
299
|
+
inst = DynamicMockTemplate.new(:code => code) { '' }
|
|
300
|
+
res = inst.render
|
|
301
|
+
assert_equal 'Shift_JIS', res.encoding.to_s
|
|
302
|
+
assert_equal tmpl, res.encode(tmpl.encoding)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
test "uses #default_encoding instead of default_external" do
|
|
306
|
+
Encoding.default_external = 'Big5'
|
|
307
|
+
inst = UTF8Template.new(@template)
|
|
308
|
+
assert_equal 'UTF-8', inst.data.encoding.to_s
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
test "uses #default_encoding instead of current encoding" do
|
|
312
|
+
tmpl = "".force_encoding('Big5')
|
|
313
|
+
inst = UTF8Template.new(@template) { tmpl }
|
|
314
|
+
assert_equal 'UTF-8', inst.data.encoding.to_s
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
test "raises error if the encoding is not valid" do
|
|
318
|
+
assert_raises(Encoding::InvalidByteSequenceError) do
|
|
319
|
+
UTF8Template.new(@template) { "\xe4" }
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
179
323
|
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 = '2013-
|
|
6
|
+
s.version = '1.4.1'
|
|
7
|
+
s.date = '2013-05-08'
|
|
8
8
|
|
|
9
9
|
s.description = "Generic interface to multiple Ruby template engines"
|
|
10
10
|
s.summary = s.description
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tilt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.1
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-
|
|
12
|
+
date: 2013-05-08 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: asciidoctor
|
|
@@ -518,3 +518,4 @@ test_files:
|
|
|
518
518
|
- test/tilt_test.rb
|
|
519
519
|
- test/tilt_wikiclothtemplate_test.rb
|
|
520
520
|
- test/tilt_yajltemplate_test.rb
|
|
521
|
+
has_rdoc:
|