tilt 1.3.3 → 1.3.4
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/COPYING +1 -1
- data/Gemfile +31 -1
- data/HACKING +16 -0
- data/README.md +5 -2
- data/Rakefile +25 -1
- data/TEMPLATES.md +13 -13
- data/bin/tilt +8 -6
- data/lib/tilt.rb +15 -1
- data/lib/tilt/asciidoc.rb +34 -0
- data/lib/tilt/coffee.rb +4 -0
- data/lib/tilt/css.rb +10 -2
- data/lib/tilt/csv.rb +71 -0
- data/lib/tilt/erb.rb +1 -1
- data/lib/tilt/etanni.rb +27 -0
- data/lib/tilt/liquid.rb +4 -0
- data/lib/tilt/markdown.rb +35 -11
- data/lib/tilt/nokogiri.rb +4 -4
- data/lib/tilt/plain.rb +20 -0
- data/lib/tilt/radius.rb +4 -0
- data/lib/tilt/rdoc.rb +20 -5
- data/lib/tilt/template.rb +35 -74
- data/lib/tilt/textile.rb +5 -0
- data/lib/tilt/wiki.rb +8 -0
- data/test/tilt_asciidoctor_test.rb +44 -0
- data/test/tilt_blueclothtemplate_test.rb +1 -1
- data/test/tilt_coffeescripttemplate_test.rb +64 -11
- data/test/tilt_creoletemplate_test.rb +1 -1
- data/test/tilt_csv_test.rb +73 -0
- data/test/tilt_erbtemplate_test.rb +5 -0
- data/test/tilt_erubistemplate_test.rb +1 -1
- data/test/tilt_etannitemplate_test.rb +173 -0
- data/test/tilt_fallback_test.rb +6 -6
- data/test/tilt_hamltemplate_test.rb +1 -1
- data/test/tilt_kramdown_test.rb +1 -1
- data/test/tilt_lesstemplate_test.less +1 -0
- data/test/tilt_lesstemplate_test.rb +19 -3
- data/test/tilt_liquidtemplate_test.rb +1 -1
- data/test/tilt_markaby_test.rb +1 -1
- data/test/tilt_markdown_test.rb +15 -4
- data/test/tilt_marukutemplate_test.rb +1 -1
- data/test/tilt_radiustemplate_test.rb +1 -1
- data/test/tilt_rdiscounttemplate_test.rb +1 -1
- data/test/tilt_rdoctemplate_test.rb +10 -3
- data/test/tilt_redcarpettemplate_test.rb +15 -3
- data/test/tilt_redclothtemplate_test.rb +13 -1
- data/test/tilt_sasstemplate_test.rb +1 -1
- data/test/tilt_stringtemplate_test.rb +1 -1
- data/test/tilt_template_test.rb +13 -0
- data/test/tilt_wikiclothtemplate_test.rb +1 -1
- data/test/tilt_yajltemplate_test.rb +13 -4
- data/tilt.gemspec +27 -17
- metadata +203 -75
data/lib/tilt/erb.rb
CHANGED
@@ -24,7 +24,7 @@ module Tilt
|
|
24
24
|
|
25
25
|
def prepare
|
26
26
|
@outvar = options[:outvar] || self.class.default_output_variable
|
27
|
-
options[:trim] = '<>' if options[:trim].nil? || options[:trim] == true
|
27
|
+
options[:trim] = '<>' if !(options[:trim] == false) && (options[:trim].nil? || options[:trim] == true)
|
28
28
|
@engine = ::ERB.new(data, options[:safe], options[:trim], @outvar)
|
29
29
|
end
|
30
30
|
|
data/lib/tilt/etanni.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'tilt/template'
|
2
|
+
|
3
|
+
module Tilt
|
4
|
+
class EtanniTemplate < Template
|
5
|
+
def prepare
|
6
|
+
separator = data.hash.abs
|
7
|
+
chomp = "<<#{separator}.chomp!"
|
8
|
+
start = "\n_out_ << #{chomp}\n"
|
9
|
+
stop = "\n#{separator}\n"
|
10
|
+
replacement = "#{stop}\\1#{start}"
|
11
|
+
|
12
|
+
temp = data.strip
|
13
|
+
temp.gsub!(/<\?r\s+(.*?)\s+\?>/m, replacement)
|
14
|
+
|
15
|
+
@code = "_out_ = [<<#{separator}.chomp!]\n#{temp}#{stop}_out_.join"
|
16
|
+
end
|
17
|
+
|
18
|
+
def precompiled_template(locals)
|
19
|
+
@code
|
20
|
+
end
|
21
|
+
|
22
|
+
def precompiled(locals)
|
23
|
+
source, offset = super
|
24
|
+
[source, offset + 1]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/tilt/liquid.rb
CHANGED
data/lib/tilt/markdown.rb
CHANGED
@@ -37,6 +37,10 @@ module Tilt
|
|
37
37
|
def evaluate(scope, locals, &block)
|
38
38
|
@output ||= @engine.to_html
|
39
39
|
end
|
40
|
+
|
41
|
+
def allows_script?
|
42
|
+
false
|
43
|
+
end
|
40
44
|
end
|
41
45
|
|
42
46
|
# Upskirt Markdown implementation. See:
|
@@ -53,7 +57,7 @@ module Tilt
|
|
53
57
|
end
|
54
58
|
|
55
59
|
def prepare
|
56
|
-
klass = [
|
60
|
+
klass = [Redcarpet2, Redcarpet1].detect { |e| e.engine_initialized? }
|
57
61
|
@engine = klass.new(file, line, options) { data }
|
58
62
|
end
|
59
63
|
|
@@ -61,6 +65,10 @@ module Tilt
|
|
61
65
|
@engine.evaluate(scope, locals, &block)
|
62
66
|
end
|
63
67
|
|
68
|
+
def allows_script?
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
64
72
|
# Compatibility mode for Redcarpet 1.x
|
65
73
|
class Redcarpet1 < RDiscountTemplate
|
66
74
|
self.default_mime_type = 'text/html'
|
@@ -80,22 +88,22 @@ module Tilt
|
|
80
88
|
self.default_mime_type = 'text/html'
|
81
89
|
|
82
90
|
def self.engine_initialized?
|
83
|
-
defined? ::Redcarpet::Render
|
91
|
+
defined? ::Redcarpet::Render and defined? ::Redcarpet::Markdown
|
84
92
|
end
|
85
93
|
|
86
94
|
def generate_renderer
|
87
|
-
renderer = options.delete(:renderer) || Redcarpet::Render::HTML
|
95
|
+
renderer = options.delete(:renderer) || ::Redcarpet::Render::HTML
|
88
96
|
return renderer unless options.delete(:smartypants)
|
89
|
-
return renderer if renderer <= Redcarpet::Render::SmartyPants
|
97
|
+
return renderer if renderer.is_a?(Class) && renderer <= ::Redcarpet::Render::SmartyPants
|
90
98
|
|
91
|
-
if renderer == Redcarpet::Render::XHTML
|
92
|
-
Redcarpet::Render::SmartyHTML.new(:xhtml => true)
|
93
|
-
elsif renderer == Redcarpet::Render::HTML
|
94
|
-
Redcarpet::Render::SmartyHTML
|
99
|
+
if renderer == ::Redcarpet::Render::XHTML
|
100
|
+
::Redcarpet::Render::SmartyHTML.new(:xhtml => true)
|
101
|
+
elsif renderer == ::Redcarpet::Render::HTML
|
102
|
+
::Redcarpet::Render::SmartyHTML
|
95
103
|
elsif renderer.is_a? Class
|
96
|
-
Class.new(renderer) { include Redcarpet::Render::SmartyPants }
|
104
|
+
Class.new(renderer) { include ::Redcarpet::Render::SmartyPants }
|
97
105
|
else
|
98
|
-
renderer.extend Redcarpet::Render::SmartyPants
|
106
|
+
renderer.extend ::Redcarpet::Render::SmartyPants
|
99
107
|
end
|
100
108
|
end
|
101
109
|
|
@@ -109,13 +117,17 @@ module Tilt
|
|
109
117
|
# only raise an exception if someone is trying to enable :escape_html
|
110
118
|
options.delete(:escape_html) unless options[:escape_html]
|
111
119
|
|
112
|
-
@engine = Redcarpet::Markdown.new(generate_renderer, options)
|
120
|
+
@engine = ::Redcarpet::Markdown.new(generate_renderer, options)
|
113
121
|
@output = nil
|
114
122
|
end
|
115
123
|
|
116
124
|
def evaluate(scope, locals, &block)
|
117
125
|
@output ||= @engine.render(data)
|
118
126
|
end
|
127
|
+
|
128
|
+
def allows_script?
|
129
|
+
false
|
130
|
+
end
|
119
131
|
end
|
120
132
|
end
|
121
133
|
|
@@ -140,6 +152,10 @@ module Tilt
|
|
140
152
|
def evaluate(scope, locals, &block)
|
141
153
|
@output ||= @engine.to_html
|
142
154
|
end
|
155
|
+
|
156
|
+
def allows_script?
|
157
|
+
false
|
158
|
+
end
|
143
159
|
end
|
144
160
|
|
145
161
|
# Maruku markdown implementation. See:
|
@@ -161,6 +177,10 @@ module Tilt
|
|
161
177
|
def evaluate(scope, locals, &block)
|
162
178
|
@output ||= @engine.to_html
|
163
179
|
end
|
180
|
+
|
181
|
+
def allows_script?
|
182
|
+
false
|
183
|
+
end
|
164
184
|
end
|
165
185
|
|
166
186
|
# Kramdown Markdown implementation. See:
|
@@ -185,6 +205,10 @@ module Tilt
|
|
185
205
|
def evaluate(scope, locals, &block)
|
186
206
|
@output ||= @engine.to_html
|
187
207
|
end
|
208
|
+
|
209
|
+
def allows_script?
|
210
|
+
false
|
211
|
+
end
|
188
212
|
end
|
189
213
|
end
|
190
214
|
|
data/lib/tilt/nokogiri.rb
CHANGED
@@ -4,6 +4,7 @@ module Tilt
|
|
4
4
|
# Nokogiri template implementation. See:
|
5
5
|
# http://nokogiri.org/
|
6
6
|
class NokogiriTemplate < Template
|
7
|
+
DOCUMENT_HEADER = /^<\?xml version=\"1\.0\"\?>\n?/
|
7
8
|
self.default_mime_type = 'text/xml'
|
8
9
|
|
9
10
|
def self.engine_initialized?
|
@@ -16,11 +17,10 @@ module Tilt
|
|
16
17
|
|
17
18
|
def prepare; end
|
18
19
|
|
19
|
-
def evaluate(scope, locals
|
20
|
-
block &&= proc { yield.gsub(/^<\?xml version=\"1\.0\"\?>\n?/, "") }
|
21
|
-
|
20
|
+
def evaluate(scope, locals)
|
22
21
|
if data.respond_to?(:to_str)
|
23
|
-
|
22
|
+
wrapper = proc { yield.sub(DOCUMENT_HEADER, "") } if block_given?
|
23
|
+
super(scope, locals, &wrapper)
|
24
24
|
else
|
25
25
|
::Nokogiri::XML::Builder.new.tap(&data).to_xml
|
26
26
|
end
|
data/lib/tilt/plain.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'tilt/template'
|
2
|
+
|
3
|
+
|
4
|
+
module Tilt
|
5
|
+
# Raw text (no template functionality).
|
6
|
+
class PlainTemplate < Template
|
7
|
+
self.default_mime_type = 'text/html'
|
8
|
+
|
9
|
+
def self.engine_initialized?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def prepare
|
14
|
+
end
|
15
|
+
|
16
|
+
def evaluate(scope, locals, &block)
|
17
|
+
@output ||= data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/tilt/radius.rb
CHANGED
data/lib/tilt/rdoc.rb
CHANGED
@@ -4,23 +4,34 @@ module Tilt
|
|
4
4
|
# RDoc template. See:
|
5
5
|
# http://rdoc.rubyforge.org/
|
6
6
|
#
|
7
|
-
# It's suggested that your program require 'rdoc/markup' and
|
8
|
-
# 'rdoc/markup/to_html' at load time when using this template
|
9
|
-
# engine.
|
7
|
+
# It's suggested that your program `require 'rdoc/markup'` and
|
8
|
+
# `require 'rdoc/markup/to_html'` at load time when using this template
|
9
|
+
# engine in a threaded environment.
|
10
10
|
class RDocTemplate < Template
|
11
11
|
self.default_mime_type = 'text/html'
|
12
12
|
|
13
13
|
def self.engine_initialized?
|
14
|
-
defined? ::RDoc::Markup
|
14
|
+
defined? ::RDoc::Markup::ToHtml
|
15
15
|
end
|
16
16
|
|
17
17
|
def initialize_engine
|
18
|
+
require_template_library 'rdoc'
|
18
19
|
require_template_library 'rdoc/markup'
|
19
20
|
require_template_library 'rdoc/markup/to_html'
|
20
21
|
end
|
21
22
|
|
23
|
+
def markup
|
24
|
+
begin
|
25
|
+
# RDoc 4.0
|
26
|
+
require 'rdoc/options'
|
27
|
+
RDoc::Markup::ToHtml.new(RDoc::Options.new, nil)
|
28
|
+
rescue ArgumentError
|
29
|
+
# RDoc < 4.0
|
30
|
+
RDoc::Markup::ToHtml.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
22
34
|
def prepare
|
23
|
-
markup = RDoc::Markup::ToHtml.new
|
24
35
|
@engine = markup.convert(data)
|
25
36
|
@output = nil
|
26
37
|
end
|
@@ -28,5 +39,9 @@ module Tilt
|
|
28
39
|
def evaluate(scope, locals, &block)
|
29
40
|
@output ||= @engine.to_s
|
30
41
|
end
|
42
|
+
|
43
|
+
def allows_script?
|
44
|
+
false
|
45
|
+
end
|
31
46
|
end
|
32
47
|
end
|
data/lib/tilt/template.rb
CHANGED
@@ -41,6 +41,7 @@ module Tilt
|
|
41
41
|
[options, line, file].compact.each do |arg|
|
42
42
|
case
|
43
43
|
when arg.respond_to?(:to_str) ; @file = arg.to_str
|
44
|
+
when arg.respond_to?(:path) ; @file = arg.path
|
44
45
|
when arg.respond_to?(:to_int) ; @line = arg.to_int
|
45
46
|
when arg.respond_to?(:to_hash) ; @options = arg.to_hash.dup
|
46
47
|
else raise TypeError
|
@@ -91,6 +92,15 @@ module Tilt
|
|
91
92
|
file || '(__TEMPLATE__)'
|
92
93
|
end
|
93
94
|
|
95
|
+
# Whether or not this template engine allows executing Ruby script
|
96
|
+
# within the template. If this is false, +scope+ and +locals+ will
|
97
|
+
# generally not be used, nor will the provided block be avaiable
|
98
|
+
# via +yield+.
|
99
|
+
# This should be overridden by template subclasses.
|
100
|
+
def allows_script?
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
94
104
|
protected
|
95
105
|
# Called once and only once for each template subclass the first time
|
96
106
|
# the template class is initialized. This should be used to require the
|
@@ -98,7 +108,7 @@ module Tilt
|
|
98
108
|
def initialize_engine
|
99
109
|
end
|
100
110
|
|
101
|
-
# Like Kernel
|
111
|
+
# Like Kernel#require but issues a warning urging a manual require when
|
102
112
|
# running under a threaded environment.
|
103
113
|
def require_template_library(name)
|
104
114
|
if Thread.list.size > 1
|
@@ -123,25 +133,15 @@ module Tilt
|
|
123
133
|
end
|
124
134
|
end
|
125
135
|
|
136
|
+
# Execute the compiled template and return the result string. Template
|
137
|
+
# evaluation is guaranteed to be performed in the scope object with the
|
138
|
+
# locals specified and with support for yielding to the block.
|
139
|
+
#
|
140
|
+
# This method is only used by source generating templates. Subclasses that
|
141
|
+
# override render() may not support all features.
|
126
142
|
def evaluate(scope, locals, &block)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
# Process the template and return the result. The first time this
|
131
|
-
# method is called, the template source is evaluated with instance_eval.
|
132
|
-
# On the sequential method calls it will compile the template to an
|
133
|
-
# unbound method which will lead to better performance. In any case,
|
134
|
-
# template executation is guaranteed to be performed in the scope object
|
135
|
-
# with the locals specified and with support for yielding to the block.
|
136
|
-
def cached_evaluate(scope, locals, &block)
|
137
|
-
# Redefine itself to use method compilation the next time:
|
138
|
-
def self.cached_evaluate(scope, locals, &block)
|
139
|
-
method = compiled_method(locals.keys)
|
140
|
-
method.bind(scope).call(locals, &block)
|
141
|
-
end
|
142
|
-
|
143
|
-
# Use instance_eval the first time:
|
144
|
-
evaluate_source(scope, locals, &block)
|
143
|
+
method = compiled_method(locals.keys)
|
144
|
+
method.bind(scope).call(locals, &block)
|
145
145
|
end
|
146
146
|
|
147
147
|
# Generates all template source by combining the preamble, template, and
|
@@ -186,7 +186,13 @@ module Tilt
|
|
186
186
|
# source line offset, so adding code to the preamble does not effect line
|
187
187
|
# reporting in Kernel::caller and backtraces.
|
188
188
|
def precompiled_preamble(locals)
|
189
|
-
locals.map
|
189
|
+
locals.map do |k,v|
|
190
|
+
if k.to_s =~ /\A[a-z]\w*\z/
|
191
|
+
"#{k} = locals[#{k.inspect}]"
|
192
|
+
else
|
193
|
+
raise "invalid locals key: #{k.inspect} (keys must be variable names)"
|
194
|
+
end
|
195
|
+
end.join("\n")
|
190
196
|
end
|
191
197
|
|
192
198
|
# Generates postamble code for the precompiled template source. The
|
@@ -203,34 +209,10 @@ module Tilt
|
|
203
209
|
end
|
204
210
|
|
205
211
|
private
|
206
|
-
# Evaluate the template source in the context of the scope object.
|
207
|
-
def evaluate_source(scope, locals, &block)
|
208
|
-
source, offset = precompiled(locals)
|
209
|
-
scope.instance_eval(source, eval_file, line - offset)
|
210
|
-
end
|
211
|
-
|
212
|
-
# JRuby doesn't allow Object#instance_eval to yield to the block it's
|
213
|
-
# closed over. This is by design and (ostensibly) something that will
|
214
|
-
# change in MRI, though no current MRI version tested (1.8.6 - 1.9.2)
|
215
|
-
# exhibits the behavior. More info here:
|
216
|
-
#
|
217
|
-
# http://jira.codehaus.org/browse/JRUBY-2599
|
218
|
-
#
|
219
|
-
# We redefine evaluate_source to work around this issues.
|
220
|
-
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
221
|
-
undef evaluate_source
|
222
|
-
def evaluate_source(scope, locals, &block)
|
223
|
-
source, offset = precompiled(locals)
|
224
|
-
file, lineno = eval_file, (line - offset)
|
225
|
-
scope.instance_eval { Kernel::eval(source, binding, file, lineno) }
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
212
|
def compile_template_method(locals)
|
230
213
|
source, offset = precompiled(locals)
|
231
|
-
offset += 5
|
232
214
|
method_name = "__tilt_#{Thread.current.object_id.abs}"
|
233
|
-
|
215
|
+
method_source = <<-RUBY
|
234
216
|
#{extract_magic_comment source}
|
235
217
|
TOPOBJECT.class_eval do
|
236
218
|
def #{method_name}(locals)
|
@@ -238,12 +220,11 @@ module Tilt
|
|
238
220
|
class << self
|
239
221
|
this, locals = Thread.current[:tilt_vars]
|
240
222
|
this.instance_eval do
|
241
|
-
#{source}
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
223
|
RUBY
|
224
|
+
offset += method_source.count("\n")
|
225
|
+
method_source << source
|
226
|
+
method_source << "\nend;end;end;end"
|
227
|
+
Object.class_eval method_source, eval_file, line - offset
|
247
228
|
unbind_compiled_method(method_name)
|
248
229
|
end
|
249
230
|
|
@@ -255,30 +236,10 @@ module Tilt
|
|
255
236
|
|
256
237
|
def extract_magic_comment(script)
|
257
238
|
comment = script.slice(/\A[ \t]*\#.*coding\s*[=:]\s*([[:alnum:]\-_]+).*$/)
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
# Special case Ruby 1.9.1's broken yield.
|
263
|
-
#
|
264
|
-
# http://github.com/rtomayko/tilt/commit/20c01a5
|
265
|
-
# http://redmine.ruby-lang.org/issues/show/3601
|
266
|
-
#
|
267
|
-
# Remove when 1.9.2 dominates 1.9.1 installs in the wild.
|
268
|
-
if RUBY_VERSION =~ /^1.9.1/
|
269
|
-
undef compile_template_method
|
270
|
-
def compile_template_method(locals)
|
271
|
-
source, offset = precompiled(locals)
|
272
|
-
offset += 1
|
273
|
-
method_name = "__tilt_#{Thread.current.object_id}"
|
274
|
-
Object.class_eval <<-RUBY, eval_file, line - offset
|
275
|
-
TOPOBJECT.class_eval do
|
276
|
-
def #{method_name}(locals)
|
277
|
-
#{source}
|
278
|
-
end
|
279
|
-
end
|
280
|
-
RUBY
|
281
|
-
unbind_compiled_method(method_name)
|
239
|
+
if comment && !%w[ascii-8bit binary].include?($1.downcase)
|
240
|
+
comment
|
241
|
+
elsif @default_encoding
|
242
|
+
"# coding: #{@default_encoding}"
|
282
243
|
end
|
283
244
|
end
|
284
245
|
end
|
data/lib/tilt/textile.rb
CHANGED
@@ -14,12 +14,17 @@ module Tilt
|
|
14
14
|
|
15
15
|
def prepare
|
16
16
|
@engine = RedCloth.new(data)
|
17
|
+
options.each {|k, v| @engine.send("#{k}=", v) if @engine.respond_to? "#{k}="}
|
17
18
|
@output = nil
|
18
19
|
end
|
19
20
|
|
20
21
|
def evaluate(scope, locals, &block)
|
21
22
|
@output ||= @engine.to_html
|
22
23
|
end
|
24
|
+
|
25
|
+
def allows_script?
|
26
|
+
false
|
27
|
+
end
|
23
28
|
end
|
24
29
|
end
|
25
30
|
|