tilt 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +18 -0
- data/README.md +75 -0
- data/Rakefile +97 -0
- data/lib/tilt.rb +297 -0
- data/test/.bacon +0 -0
- data/test/spec_tilt.rb +44 -0
- data/test/spec_tilt_buildertemplate.rb +40 -0
- data/test/spec_tilt_erbtemplate.rb +78 -0
- data/test/spec_tilt_hamltemplate.rb +79 -0
- data/test/spec_tilt_liquid_template.rb +24 -0
- data/test/spec_tilt_rdiscount.rb +18 -0
- data/test/spec_tilt_sasstemplate.rb +19 -0
- data/test/spec_tilt_stringtemplate.rb +77 -0
- data/test/spec_tilt_template.rb +100 -0
- data/tilt.gemspec +45 -0
- metadata +80 -0
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2009 Ryan Tomayko <http://tomayko.com/about>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
Tilt
|
2
|
+
====
|
3
|
+
|
4
|
+
Tilt provides a thin interface over a bunch of different template engines to
|
5
|
+
make their usage as generic possible. This is useful for web frameworks,
|
6
|
+
static site generators, and other systems that support multiple template
|
7
|
+
engines but don't want to code for each of them explicitly.
|
8
|
+
|
9
|
+
The following features are supported for all template engines (assuming the
|
10
|
+
feature is relevant to the engine):
|
11
|
+
|
12
|
+
* Custom template evaluation scopes / bindings
|
13
|
+
* Ability to pass locals to template evaluation
|
14
|
+
* Support for passing a block to template evaluation for "yield"
|
15
|
+
* Backtraces with correct filenames and line numbers
|
16
|
+
* Template compilation caching and reloading
|
17
|
+
|
18
|
+
These template engines are currently supported with (many) more on the way:
|
19
|
+
|
20
|
+
* ERB
|
21
|
+
* Interpolated Ruby String
|
22
|
+
* Haml (with the `haml` gem/library)
|
23
|
+
* Sass (with the `haml` gem/library)
|
24
|
+
* Builder (with the `builder` gem/library)
|
25
|
+
* Liquid (with the `liquid` gem/library)
|
26
|
+
|
27
|
+
Usage
|
28
|
+
-----
|
29
|
+
|
30
|
+
All supported templates have an implementation class under the `Tilt` module.
|
31
|
+
Each template implementation follows the exact same interface for creation
|
32
|
+
and rendering:
|
33
|
+
|
34
|
+
template = Tilt::HamlTemplate.new('templates/foo.haml')
|
35
|
+
output = template.render
|
36
|
+
|
37
|
+
The `render` method takes an optional evaluation scope and locals hash
|
38
|
+
arguments. In the following example, the template is evaluated within the
|
39
|
+
context of the person object and can access the locals `x` and `y`:
|
40
|
+
|
41
|
+
template = Tilt::ERBTemplate.new('templates/foo.erb')
|
42
|
+
joe = Person.find('joe')
|
43
|
+
output = template.render(joe, :x => 35, :y => 42)
|
44
|
+
|
45
|
+
The `render` method may be called multiple times without creating a new
|
46
|
+
template object. Continuing the previous example, we can render in Jane's
|
47
|
+
scope with a different set of locals:
|
48
|
+
|
49
|
+
jane = Person.find('jane')
|
50
|
+
output = template.render(jane, :x => 22, :y => nil)
|
51
|
+
|
52
|
+
Blocks can be passed to the render method for templates that support running
|
53
|
+
arbitrary ruby code and using `yield`. Assuming the following was in a file
|
54
|
+
named `foo.erb`:
|
55
|
+
|
56
|
+
Hey <%= yield %>!
|
57
|
+
|
58
|
+
The block passed to the `render` method is invoked on `yield`:
|
59
|
+
|
60
|
+
template = Tilt::ERBTemplate.new('foo.erb')
|
61
|
+
template.render { 'Joe' }
|
62
|
+
# => "Hey Joe!"
|
63
|
+
|
64
|
+
There's also a lightweight file extension to template engine mapping layer.
|
65
|
+
You can pass a filename or extension to `Tilt::[]` to retrieve the
|
66
|
+
corresponding implementation class:
|
67
|
+
|
68
|
+
Tilt['hello.erb']
|
69
|
+
# => Tilt::ERBTemplate
|
70
|
+
|
71
|
+
The `Tilt.new` works similarly but returns a new instance of the underlying
|
72
|
+
implementation class:
|
73
|
+
|
74
|
+
template = Tilt.new('templates/foo.erb')
|
75
|
+
output = template.render
|
data/Rakefile
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
task :default => :spec
|
2
|
+
|
3
|
+
# SPECS =====================================================================
|
4
|
+
|
5
|
+
desc 'Generate test coverage report'
|
6
|
+
task :rcov do
|
7
|
+
sh "rcov -Ilib:test test/*_test.rb"
|
8
|
+
end
|
9
|
+
desc 'Run specs with unit test style output'
|
10
|
+
task :test do |t|
|
11
|
+
sh 'bacon -qa'
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Run specs with story style output'
|
15
|
+
task :spec do |t|
|
16
|
+
sh 'bacon -a'
|
17
|
+
end
|
18
|
+
|
19
|
+
# PACKAGING =================================================================
|
20
|
+
|
21
|
+
# load gemspec like github's gem builder to surface any SAFE issues.
|
22
|
+
Thread.new do
|
23
|
+
require 'rubygems/specification'
|
24
|
+
$spec = eval("$SAFE=3\n#{File.read('tilt.gemspec')}")
|
25
|
+
end.join
|
26
|
+
|
27
|
+
def package(ext='')
|
28
|
+
"dist/tilt-#{$spec.version}" + ext
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Build packages'
|
32
|
+
task :package => %w[.gem .tar.gz].map {|e| package(e)}
|
33
|
+
|
34
|
+
desc 'Build and install as local gem'
|
35
|
+
task :install => package('.gem') do
|
36
|
+
sh "gem install #{package('.gem')}"
|
37
|
+
end
|
38
|
+
|
39
|
+
directory 'dist/'
|
40
|
+
|
41
|
+
file package('.gem') => %w[dist/ tilt.gemspec] + $spec.files do |f|
|
42
|
+
sh "gem build tilt.gemspec"
|
43
|
+
mv File.basename(f.name), f.name
|
44
|
+
end
|
45
|
+
|
46
|
+
file package('.tar.gz') => %w[dist/] + $spec.files do |f|
|
47
|
+
sh "git archive --format=tar HEAD | gzip > #{f.name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'Upload gem and tar.gz distributables to rubyforge'
|
51
|
+
task :release => [package('.gem'), package('.tar.gz')] do |t|
|
52
|
+
sh <<-SH
|
53
|
+
rubyforge add_release sinatra tilt #{$spec.version} #{package('.gem')} &&
|
54
|
+
rubyforge add_file sinatra tilt #{$spec.version} #{package('.tar.gz')}
|
55
|
+
SH
|
56
|
+
end
|
57
|
+
|
58
|
+
# GEMSPEC ===================================================================
|
59
|
+
|
60
|
+
file 'tilt.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f|
|
61
|
+
# read spec file and split out manifest section
|
62
|
+
spec = File.read(f.name)
|
63
|
+
parts = spec.split(" # = MANIFEST =\n")
|
64
|
+
# determine file list from git ls-files
|
65
|
+
files = `git ls-files`.
|
66
|
+
split("\n").sort.reject{ |file| file =~ /^\./ }.
|
67
|
+
map{ |file| " #{file}" }.join("\n")
|
68
|
+
# piece file back together and write...
|
69
|
+
parts[1] = " s.files = %w[\n#{files}\n ]\n"
|
70
|
+
spec = parts.join(" # = MANIFEST =\n")
|
71
|
+
spec.sub!(/s.date = '.*'/, "s.date = '#{Time.now.strftime("%Y-%m-%d")}'")
|
72
|
+
File.open(f.name, 'w') { |io| io.write(spec) }
|
73
|
+
puts "updated #{f.name}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# DOC =======================================================================
|
77
|
+
|
78
|
+
# requires the hanna gem:
|
79
|
+
# gem install mislav-hanna --source=http://gems.github.com
|
80
|
+
desc 'Build API documentation (doc/api)'
|
81
|
+
task 'rdoc' => 'rdoc/index.html'
|
82
|
+
file 'rdoc/index.html' => FileList['lib/**/*.rb'] do |f|
|
83
|
+
rm_rf 'rdoc'
|
84
|
+
sh((<<-SH).gsub(/[\s\n]+/, ' ').strip)
|
85
|
+
hanna
|
86
|
+
--op doc/api
|
87
|
+
--promiscuous
|
88
|
+
--charset utf8
|
89
|
+
--fmt html
|
90
|
+
--inline-source
|
91
|
+
--line-numbers
|
92
|
+
--accessor option_accessor=RW
|
93
|
+
--main Tilt
|
94
|
+
--title 'Tilt API Documentation'
|
95
|
+
#{f.prerequisites.join(' ')}
|
96
|
+
SH
|
97
|
+
end
|
data/lib/tilt.rb
ADDED
@@ -0,0 +1,297 @@
|
|
1
|
+
module Tilt
|
2
|
+
@template_mappings = {}
|
3
|
+
|
4
|
+
# Register a template implementation by file extension.
|
5
|
+
def self.register(ext, template_class)
|
6
|
+
ext = ext.sub(/^\./, '')
|
7
|
+
@template_mappings[ext.downcase] = template_class
|
8
|
+
end
|
9
|
+
|
10
|
+
# Create a new template for the given file using the file's extension
|
11
|
+
# to determine the the template mapping.
|
12
|
+
def self.new(file, line=nil, options={}, &block)
|
13
|
+
if template_class = self[File.basename(file)]
|
14
|
+
template_class.new(file, line, options, &block)
|
15
|
+
else
|
16
|
+
fail "No template engine registered for #{File.basename(file)}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Lookup a template class given for the given filename or file
|
21
|
+
# extension. Return nil when no implementation is found.
|
22
|
+
def self.[](filename)
|
23
|
+
ext = filename.to_s.downcase
|
24
|
+
until ext.empty?
|
25
|
+
return @template_mappings[ext] if @template_mappings.key?(ext)
|
26
|
+
ext = ext.sub(/^[^.]*\.?/, '')
|
27
|
+
end
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Base class for template implementations. Subclasses must implement
|
32
|
+
# the #compile! method and one of the #evaluate or #template_source
|
33
|
+
# methods.
|
34
|
+
class Template
|
35
|
+
# Template source; loaded from a file or given directly.
|
36
|
+
attr_reader :data
|
37
|
+
|
38
|
+
# The name of the file where the template data was loaded from.
|
39
|
+
attr_reader :file
|
40
|
+
|
41
|
+
# The line number in #file where template data was loaded from.
|
42
|
+
attr_reader :line
|
43
|
+
|
44
|
+
# A Hash of template engine specific options. This is passed directly
|
45
|
+
# to the underlying engine and is not used by the generic template
|
46
|
+
# interface.
|
47
|
+
attr_reader :options
|
48
|
+
|
49
|
+
# Create a new template with the file, line, and options specified. By
|
50
|
+
# default, template data is read from the file specified. When a block
|
51
|
+
# is given, it should read template data and return as a String. When
|
52
|
+
# file is nil, a block is required.
|
53
|
+
def initialize(file=nil, line=1, options={}, &block)
|
54
|
+
raise ArgumentError, "file or block required" if file.nil? && block.nil?
|
55
|
+
@file = file
|
56
|
+
@line = line || 1
|
57
|
+
@options = options || {}
|
58
|
+
@reader = block || lambda { |t| File.read(file) }
|
59
|
+
end
|
60
|
+
|
61
|
+
# Render the template in the given scope with the locals specified. If a
|
62
|
+
# block is given, it is typically available within the template via
|
63
|
+
# +yield+.
|
64
|
+
def render(scope=Object.new, locals={}, &block)
|
65
|
+
if @data.nil?
|
66
|
+
@data = @reader.call(self)
|
67
|
+
compile!
|
68
|
+
end
|
69
|
+
evaluate scope, locals || {}, &block
|
70
|
+
end
|
71
|
+
|
72
|
+
# The filename used in backtraces to describe the template.
|
73
|
+
def eval_file
|
74
|
+
@file || '(__TEMPLATE__)'
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
# Do whatever preparation is necessary to "compile" the template.
|
79
|
+
# Called immediately after template #data is loaded. Instance variables
|
80
|
+
# set in this method are available when #evaluate is called.
|
81
|
+
#
|
82
|
+
# Subclasses must provide an implementation of this method.
|
83
|
+
def compile!
|
84
|
+
raise NotImplementedError
|
85
|
+
end
|
86
|
+
|
87
|
+
# Process the template and return the result. Subclasses should override
|
88
|
+
# this method unless they implement the #template_source.
|
89
|
+
def evaluate(scope, locals, &block)
|
90
|
+
source, offset = local_assignment_code(locals)
|
91
|
+
source = [source, template_source].join("\n")
|
92
|
+
scope.instance_eval source, eval_file, line - offset
|
93
|
+
end
|
94
|
+
|
95
|
+
# Return a string containing the (Ruby) source code for the template. The
|
96
|
+
# default Template#evaluate implementation requires this method be
|
97
|
+
# defined.
|
98
|
+
def template_source
|
99
|
+
raise NotImplementedError
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def local_assignment_code(locals)
|
104
|
+
return ['', 1] if locals.empty?
|
105
|
+
source = locals.collect { |k,v| "#{k} = locals[:#{k}]" }
|
106
|
+
[source.join("\n"), source.length]
|
107
|
+
end
|
108
|
+
|
109
|
+
def require_template_library(name)
|
110
|
+
warn "WARN: loading '#{name}' library in a non thread-safe way; " +
|
111
|
+
"explicit require '#{name}' suggested."
|
112
|
+
require name
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Extremely simple template cache implementation.
|
117
|
+
class Cache
|
118
|
+
def initialize
|
119
|
+
@cache = {}
|
120
|
+
end
|
121
|
+
|
122
|
+
def fetch(*key)
|
123
|
+
key = key.map { |part| part.to_s }.join(":")
|
124
|
+
@cache[key] ||= yield
|
125
|
+
end
|
126
|
+
|
127
|
+
def clear
|
128
|
+
@cache = {}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Template Implementations ================================================
|
133
|
+
|
134
|
+
# The template source is evaluated as a Ruby string. The #{} interpolation
|
135
|
+
# syntax can be used to generated dynamic output.
|
136
|
+
class StringTemplate < Template
|
137
|
+
def compile!
|
138
|
+
@code = "%Q{#{data}}"
|
139
|
+
end
|
140
|
+
|
141
|
+
def template_source
|
142
|
+
@code
|
143
|
+
end
|
144
|
+
end
|
145
|
+
register 'str', StringTemplate
|
146
|
+
|
147
|
+
# ERB template implementation. See:
|
148
|
+
# http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html
|
149
|
+
#
|
150
|
+
# It's suggested that your program require 'erb' at load
|
151
|
+
# time when using this template engine.
|
152
|
+
class ERBTemplate < Template
|
153
|
+
def compile!
|
154
|
+
require_template_library 'erb' unless defined?(::ERB)
|
155
|
+
@engine = ::ERB.new(data, nil, nil, '@_out_buf')
|
156
|
+
end
|
157
|
+
|
158
|
+
def template_source
|
159
|
+
@engine.src
|
160
|
+
end
|
161
|
+
|
162
|
+
def evaluate(scope, locals, &block)
|
163
|
+
source, offset = local_assignment_code(locals)
|
164
|
+
source = [source, template_source].join("\n")
|
165
|
+
|
166
|
+
original_out_buf =
|
167
|
+
scope.instance_variables.any? { |var| var.to_sym == :@_out_buf } &&
|
168
|
+
scope.instance_variable_get(:@_out_buf)
|
169
|
+
|
170
|
+
scope.instance_eval source, eval_file, line - offset
|
171
|
+
|
172
|
+
output = scope.instance_variable_get(:@_out_buf)
|
173
|
+
scope.instance_variable_set(:@_out_buf, original_out_buf)
|
174
|
+
|
175
|
+
output
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
# ERB generates a line to specify the character coding of the generated
|
181
|
+
# source in 1.9. Account for this in the line offset.
|
182
|
+
if RUBY_VERSION >= '1.9.0'
|
183
|
+
def local_assignment_code(locals)
|
184
|
+
source, offset = super
|
185
|
+
[source, offset + 1]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
%w[erb rhtml].each { |ext| register ext, ERBTemplate }
|
190
|
+
|
191
|
+
# Haml template implementation. See:
|
192
|
+
# http://haml.hamptoncatlin.com/
|
193
|
+
#
|
194
|
+
# It's suggested that your program require 'haml' at load
|
195
|
+
# time when using this template engine.
|
196
|
+
class HamlTemplate < Template
|
197
|
+
def compile!
|
198
|
+
require_template_library 'haml' unless defined?(::Haml::Engine)
|
199
|
+
@engine = ::Haml::Engine.new(data, haml_options)
|
200
|
+
end
|
201
|
+
|
202
|
+
def evaluate(scope, locals, &block)
|
203
|
+
@engine.render(scope, locals, &block)
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
def haml_options
|
208
|
+
options.merge(:filename => eval_file, :line => line)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
register 'haml', HamlTemplate
|
212
|
+
|
213
|
+
# Sass template implementation. See:
|
214
|
+
# http://haml.hamptoncatlin.com/
|
215
|
+
#
|
216
|
+
# Sass templates do not support object scopes, locals, or yield.
|
217
|
+
#
|
218
|
+
# It's suggested that your program require 'sass' at load
|
219
|
+
# time when using this template engine.
|
220
|
+
class SassTemplate < Template
|
221
|
+
def compile!
|
222
|
+
require_template_library 'sass' unless defined?(::Sass::Engine)
|
223
|
+
@engine = ::Sass::Engine.new(data, sass_options)
|
224
|
+
end
|
225
|
+
|
226
|
+
def evaluate(scope, locals, &block)
|
227
|
+
@engine.render
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
def sass_options
|
232
|
+
options.merge(:filename => eval_file, :line => line)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
register 'sass', SassTemplate
|
236
|
+
|
237
|
+
# Builder template implementation. See:
|
238
|
+
# http://builder.rubyforge.org/
|
239
|
+
#
|
240
|
+
# It's suggested that your program require 'builder' at load
|
241
|
+
# time when using this template engine.
|
242
|
+
class BuilderTemplate < Template
|
243
|
+
def compile!
|
244
|
+
require_template_library 'builder' unless defined?(::Builder)
|
245
|
+
end
|
246
|
+
|
247
|
+
def evaluate(scope, locals, &block)
|
248
|
+
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
249
|
+
if data.respond_to?(:to_str)
|
250
|
+
locals[:xml] = xml
|
251
|
+
super(scope, locals, &block)
|
252
|
+
elsif data.kind_of?(Proc)
|
253
|
+
data.call(xml)
|
254
|
+
end
|
255
|
+
xml.target!
|
256
|
+
end
|
257
|
+
|
258
|
+
def template_source
|
259
|
+
data.to_str
|
260
|
+
end
|
261
|
+
end
|
262
|
+
register 'builder', BuilderTemplate
|
263
|
+
|
264
|
+
# Liquid template implementation. See:
|
265
|
+
# http://liquid.rubyforge.org/
|
266
|
+
#
|
267
|
+
# LiquidTemplate does not support scopes or yield blocks.
|
268
|
+
#
|
269
|
+
# It's suggested that your program require 'liquid' at load
|
270
|
+
# time when using this template engine.
|
271
|
+
class LiquidTemplate < Template
|
272
|
+
def compile!
|
273
|
+
require_template_library 'liquid' unless defined?(::Liquid::Template)
|
274
|
+
@engine = ::Liquid::Template.parse(data)
|
275
|
+
end
|
276
|
+
|
277
|
+
def evaluate(scope, locals, &block)
|
278
|
+
locals = locals.inject({}) { |hash,(k,v)| hash[k.to_s] = v ; hash }
|
279
|
+
@engine.render(locals)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
register 'liquid', LiquidTemplate
|
283
|
+
|
284
|
+
# Discount Markdown implementation.
|
285
|
+
class RDiscountTemplate < Template
|
286
|
+
def compile!
|
287
|
+
require_template_library 'rdiscount' unless defined?(::RDiscount)
|
288
|
+
@engine = RDiscount.new(data)
|
289
|
+
end
|
290
|
+
|
291
|
+
def evaluate(scope, locals, &block)
|
292
|
+
@engine.to_html
|
293
|
+
end
|
294
|
+
end
|
295
|
+
register 'markdown', RDiscountTemplate
|
296
|
+
|
297
|
+
end
|
data/test/.bacon
ADDED
File without changes
|
data/test/spec_tilt.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
describe "Tilt" do
|
5
|
+
class MockTemplate
|
6
|
+
attr_reader :args, :block
|
7
|
+
def initialize(*args, &block)
|
8
|
+
@args = args
|
9
|
+
@block = block
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "registers template implementation classes by file extension" do
|
14
|
+
lambda { Tilt.register('mock', MockTemplate) }.should.not.raise
|
15
|
+
end
|
16
|
+
|
17
|
+
it "looks up template implementation classes by file extension" do
|
18
|
+
impl = Tilt['mock']
|
19
|
+
impl.should.equal MockTemplate
|
20
|
+
|
21
|
+
impl = Tilt['.mock']
|
22
|
+
impl.should.equal MockTemplate
|
23
|
+
end
|
24
|
+
|
25
|
+
it "looks up template implementation classes with multiple file extensions" do
|
26
|
+
impl = Tilt['index.html.mock']
|
27
|
+
impl.should.equal MockTemplate
|
28
|
+
end
|
29
|
+
|
30
|
+
it "looks up template implementation classes by file name" do
|
31
|
+
impl = Tilt['templates/test.mock']
|
32
|
+
impl.should.equal MockTemplate
|
33
|
+
end
|
34
|
+
|
35
|
+
it "gives nil when no template implementation classes exist for a filename" do
|
36
|
+
Tilt['none'].should.be.nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it "creates a new template instance given a filename" do
|
40
|
+
template = Tilt.new('foo.mock', 1, :key => 'val') { 'Hello World!' }
|
41
|
+
template.args.should.equal ['foo.mock', 1, {:key => 'val'}]
|
42
|
+
template.block.call.should.equal 'Hello World!'
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
describe "Tilt::BuilderTemplate" do
|
6
|
+
it "is registered for '.builder' files" do
|
7
|
+
Tilt['test.builder'].should.equal Tilt::BuilderTemplate
|
8
|
+
Tilt['test.xml.builder'].should.equal Tilt::BuilderTemplate
|
9
|
+
end
|
10
|
+
|
11
|
+
it "compiles and evaluates the template on #render" do
|
12
|
+
template = Tilt::BuilderTemplate.new { |t| "xml.em 'Hello World!'" }
|
13
|
+
template.render.should.equal "<em>Hello World!</em>\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "supports locals" do
|
17
|
+
template = Tilt::BuilderTemplate.new { "xml.em('Hey ' + name + '!')" }
|
18
|
+
template.render(Object.new, :name => 'Joe').should.equal "<em>Hey Joe!</em>\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is evaluated in the object scope provided" do
|
22
|
+
template = Tilt::BuilderTemplate.new { "xml.em('Hey ' + @name + '!')" }
|
23
|
+
scope = Object.new
|
24
|
+
scope.instance_variable_set :@name, 'Joe'
|
25
|
+
template.render(scope).should.equal "<em>Hey Joe!</em>\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "evaluates template_source with yield support" do
|
29
|
+
template = Tilt::BuilderTemplate.new { "xml.em('Hey ' + yield + '!')" }
|
30
|
+
template.render { 'Joe' }.should.equal "<em>Hey Joe!</em>\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "calls a block directly when" do
|
34
|
+
template =
|
35
|
+
Tilt::BuilderTemplate.new do |t|
|
36
|
+
lambda { |xml| xml.em('Hey Joe!') }
|
37
|
+
end
|
38
|
+
template.render.should.equal "<em>Hey Joe!</em>\n"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
describe "Tilt::ERBTemplate" do
|
6
|
+
it "is registered for '.erb' files" do
|
7
|
+
Tilt['test.erb'].should.equal Tilt::ERBTemplate
|
8
|
+
Tilt['test.html.erb'].should.equal Tilt::ERBTemplate
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is registered for '.rhtml' files" do
|
12
|
+
Tilt['test.rhtml'].should.equal Tilt::ERBTemplate
|
13
|
+
end
|
14
|
+
|
15
|
+
it "compiles and evaluates the template on #render" do
|
16
|
+
template = Tilt::ERBTemplate.new { |t| "Hello World!" }
|
17
|
+
template.render.should.equal "Hello World!"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "supports locals" do
|
21
|
+
template = Tilt::ERBTemplate.new { 'Hey <%= name %>!' }
|
22
|
+
template.render(Object.new, :name => 'Joe').should.equal "Hey Joe!"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is evaluated in the object scope provided" do
|
26
|
+
template = Tilt::ERBTemplate.new { 'Hey <%= @name %>!' }
|
27
|
+
scope = Object.new
|
28
|
+
scope.instance_variable_set :@name, 'Joe'
|
29
|
+
template.render(scope).should.equal "Hey Joe!"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "evaluates template_source with yield support" do
|
33
|
+
template = Tilt::ERBTemplate.new { 'Hey <%= yield %>!' }
|
34
|
+
template.render { 'Joe' }.should.equal "Hey Joe!"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "reports the file and line properly in backtraces without locals" do
|
38
|
+
data = File.read(__FILE__).split("\n__END__\n").last
|
39
|
+
fail unless data[0] == ?<
|
40
|
+
template = Tilt::ERBTemplate.new('test.erb', 11) { data }
|
41
|
+
begin
|
42
|
+
template.render
|
43
|
+
flunk 'should have raised an exception'
|
44
|
+
rescue => boom
|
45
|
+
boom.should.be.kind_of NameError
|
46
|
+
line = boom.backtrace.first
|
47
|
+
file, line, meth = line.split(":")
|
48
|
+
file.should.equal 'test.erb'
|
49
|
+
line.should.equal '13'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "reports the file and line properly in backtraces with locals" do
|
54
|
+
data = File.read(__FILE__).split("\n__END__\n").last
|
55
|
+
fail unless data[0] == ?<
|
56
|
+
template = Tilt::ERBTemplate.new('test.erb', 1) { data }
|
57
|
+
begin
|
58
|
+
template.render(nil, :name => 'Joe', :foo => 'bar')
|
59
|
+
flunk 'should have raised an exception'
|
60
|
+
rescue => boom
|
61
|
+
boom.should.be.kind_of RuntimeError
|
62
|
+
line = boom.backtrace.first
|
63
|
+
file, line, meth = line.split(":")
|
64
|
+
file.should.equal 'test.erb'
|
65
|
+
line.should.equal '6'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
__END__
|
71
|
+
<html>
|
72
|
+
<body>
|
73
|
+
<h1>Hey <%= name %>!</h1>
|
74
|
+
|
75
|
+
|
76
|
+
<p><% fail %></p>
|
77
|
+
</body>
|
78
|
+
</html>
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
begin
|
5
|
+
class ::MockError < NameError
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'haml'
|
9
|
+
describe "Tilt::HamlTemplate" do
|
10
|
+
it "is registered for '.haml' files" do
|
11
|
+
Tilt['test.haml'].should.equal Tilt::HamlTemplate
|
12
|
+
end
|
13
|
+
|
14
|
+
it "compiles and evaluates the template on #render" do
|
15
|
+
template = Tilt::HamlTemplate.new { |t| "%p Hello World!" }
|
16
|
+
template.render.should.equal "<p>Hello World!</p>\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "supports locals" do
|
20
|
+
template = Tilt::HamlTemplate.new { "%p= 'Hey ' + name + '!'" }
|
21
|
+
template.render(Object.new, :name => 'Joe').should.equal "<p>Hey Joe!</p>\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is evaluated in the object scope provided" do
|
25
|
+
template = Tilt::HamlTemplate.new { "%p= 'Hey ' + @name + '!'" }
|
26
|
+
scope = Object.new
|
27
|
+
scope.instance_variable_set :@name, 'Joe'
|
28
|
+
template.render(scope).should.equal "<p>Hey Joe!</p>\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "evaluates template_source with yield support" do
|
32
|
+
template = Tilt::HamlTemplate.new { "%p= 'Hey ' + yield + '!'" }
|
33
|
+
template.render { 'Joe' }.should.equal "<p>Hey Joe!</p>\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "reports the file and line properly in backtraces without locals" do
|
37
|
+
data = File.read(__FILE__).split("\n__END__\n").last
|
38
|
+
fail unless data[0] == ?%
|
39
|
+
template = Tilt::HamlTemplate.new('test.haml', 10) { data }
|
40
|
+
begin
|
41
|
+
template.render
|
42
|
+
fail 'should have raised an exception'
|
43
|
+
rescue => boom
|
44
|
+
boom.should.be.kind_of NameError
|
45
|
+
line = boom.backtrace.first
|
46
|
+
file, line, meth = line.split(":")
|
47
|
+
file.should.equal 'test.haml'
|
48
|
+
line.should.equal '12'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "reports the file and line properly in backtraces with locals" do
|
53
|
+
data = File.read(__FILE__).split("\n__END__\n").last
|
54
|
+
fail unless data[0] == ?%
|
55
|
+
template = Tilt::HamlTemplate.new('test.haml') { data }
|
56
|
+
begin
|
57
|
+
res = template.render(Object.new, :name => 'Joe', :foo => 'bar')
|
58
|
+
rescue => boom
|
59
|
+
boom.should.be.kind_of ::MockError
|
60
|
+
line = boom.backtrace.first
|
61
|
+
file, line, meth = line.split(":")
|
62
|
+
file.should.equal 'test.haml'
|
63
|
+
line.should.equal '5'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
rescue LoadError => boom
|
69
|
+
warn "Tilt::HamlTemplate (disabled)\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
__END__
|
73
|
+
%html
|
74
|
+
%body
|
75
|
+
%h1= "Hey #{name}"
|
76
|
+
|
77
|
+
= raise MockError
|
78
|
+
|
79
|
+
%p we never get here
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'liquid'
|
6
|
+
describe "Tilt::LiquidTemplate" do
|
7
|
+
it "is registered for '.liquid' files" do
|
8
|
+
Tilt['test.liquid'].should.equal Tilt::LiquidTemplate
|
9
|
+
end
|
10
|
+
|
11
|
+
it "compiles and evaluates the template on #render" do
|
12
|
+
template = Tilt::LiquidTemplate.new { |t| "Hello World!" }
|
13
|
+
template.render.should.equal "Hello World!"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "supports locals" do
|
17
|
+
template = Tilt::LiquidTemplate.new { "Hey {{ name }}!" }
|
18
|
+
template.render(nil, :name => 'Joe').should.equal "Hey Joe!"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue LoadError => boom
|
23
|
+
warn "Tilt::LiquidTemplate (disabled)\n"
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rdiscount'
|
6
|
+
describe "Tilt::RDiscountTemplate" do
|
7
|
+
it "is registered for '.markdown' files" do
|
8
|
+
Tilt['test.markdown'].should.equal Tilt::RDiscountTemplate
|
9
|
+
end
|
10
|
+
|
11
|
+
it "compiles and evaluates the template on #render" do
|
12
|
+
template = Tilt::RDiscountTemplate.new { |t| "# Hello World!" }
|
13
|
+
template.render.should.equal "<h1>Hello World!</h1>\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
rescue LoadError => boom
|
17
|
+
warn "Tilt::RDiscountTemplate (disabled)\n"
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'haml'
|
6
|
+
describe "Tilt::SassTemplate" do
|
7
|
+
it "is registered for '.sass' files" do
|
8
|
+
Tilt['test.sass'].should.equal Tilt::SassTemplate
|
9
|
+
end
|
10
|
+
|
11
|
+
it "compiles and evaluates the template on #render" do
|
12
|
+
template = Tilt::SassTemplate.new { |t| "#main\n :background-color #0000ff" }
|
13
|
+
template.render.should.equal "#main {\n background-color: #0000ff; }\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
rescue LoadError => boom
|
18
|
+
warn "Tilt::SassTemplate (disabled)\n"
|
19
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
describe "Tilt::StringTemplate" do
|
5
|
+
it "is registered for '.str' files" do
|
6
|
+
Tilt['test.str'].should.equal Tilt::StringTemplate
|
7
|
+
end
|
8
|
+
|
9
|
+
it "compiles and evaluates the template on #render" do
|
10
|
+
template = Tilt::StringTemplate.new { |t| "Hello World!" }
|
11
|
+
template.render.should.equal "Hello World!"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "supports locals" do
|
15
|
+
template = Tilt::StringTemplate.new { 'Hey #{name}!' }
|
16
|
+
template.render(Object.new, :name => 'Joe').should.equal "Hey Joe!"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "is evaluated in the object scope provided" do
|
20
|
+
template = Tilt::StringTemplate.new { 'Hey #{@name}!' }
|
21
|
+
scope = Object.new
|
22
|
+
scope.instance_variable_set :@name, 'Joe'
|
23
|
+
template.render(scope).should.equal "Hey Joe!"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "evaluates template_source with yield support" do
|
27
|
+
template = Tilt::StringTemplate.new { 'Hey #{yield}!' }
|
28
|
+
template.render { 'Joe' }.should.equal "Hey Joe!"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "renders multiline templates" do
|
32
|
+
template = Tilt::StringTemplate.new { "Hello\nWorld!\n" }
|
33
|
+
template.render.should.equal "Hello\nWorld!\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "reports the file and line properly in backtraces without locals" do
|
37
|
+
data = File.read(__FILE__).split("\n__END__\n").last
|
38
|
+
fail unless data[0] == ?<
|
39
|
+
template = Tilt::StringTemplate.new('test.str', 11) { data }
|
40
|
+
begin
|
41
|
+
template.render
|
42
|
+
flunk 'should have raised an exception'
|
43
|
+
rescue => boom
|
44
|
+
boom.should.be.kind_of NameError
|
45
|
+
line = boom.backtrace.first
|
46
|
+
file, line, meth = line.split(":")
|
47
|
+
file.should.equal 'test.str'
|
48
|
+
line.should.equal '13'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "reports the file and line properly in backtraces with locals" do
|
53
|
+
data = File.read(__FILE__).split("\n__END__\n").last
|
54
|
+
fail unless data[0] == ?<
|
55
|
+
template = Tilt::StringTemplate.new('test.str', 1) { data }
|
56
|
+
begin
|
57
|
+
template.render(nil, :name => 'Joe', :foo => 'bar')
|
58
|
+
flunk 'should have raised an exception'
|
59
|
+
rescue => boom
|
60
|
+
boom.should.be.kind_of RuntimeError
|
61
|
+
line = boom.backtrace.first
|
62
|
+
file, line, meth = line.split(":")
|
63
|
+
file.should.equal 'test.str'
|
64
|
+
line.should.equal '6'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
__END__
|
70
|
+
<html>
|
71
|
+
<body>
|
72
|
+
<h1>Hey #{name}!</h1>
|
73
|
+
|
74
|
+
|
75
|
+
<p>#{fail}</p>
|
76
|
+
</body>
|
77
|
+
</html>
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
describe "Tilt::Template" do
|
5
|
+
it "raises ArgumentError when a file or block not given" do
|
6
|
+
lambda { Tilt::Template.new }.should.raise ArgumentError
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can be constructed with a file" do
|
10
|
+
inst = Tilt::Template.new('foo.erb')
|
11
|
+
inst.file.should.equal 'foo.erb'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can be constructed with a file and line" do
|
15
|
+
inst = Tilt::Template.new('foo.erb', 55)
|
16
|
+
inst.file.should.equal 'foo.erb'
|
17
|
+
inst.line.should.equal 55
|
18
|
+
end
|
19
|
+
|
20
|
+
it "uses the filename provided for #eval_file" do
|
21
|
+
inst = Tilt::Template.new('foo.erb', 55)
|
22
|
+
inst.eval_file.should.equal 'foo.erb'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "uses a default filename for #eval_file when no file provided" do
|
26
|
+
inst = Tilt::Template.new { 'Hi' }
|
27
|
+
inst.eval_file.should.not.be.nil
|
28
|
+
inst.eval_file.should.not.include "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can be constructed with a data loading block" do
|
32
|
+
lambda {
|
33
|
+
Tilt::Template.new { |template| "Hello World!" }
|
34
|
+
}.should.not.raise
|
35
|
+
end
|
36
|
+
|
37
|
+
it "raises NotImplementedError when #compile! not defined" do
|
38
|
+
inst = Tilt::Template.new { |template| "Hello World!" }
|
39
|
+
lambda { inst.render }.should.raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
class CompilingMockTemplate < Tilt::Template
|
43
|
+
def compile!
|
44
|
+
data.should.not.be.nil
|
45
|
+
@compiled = true
|
46
|
+
end
|
47
|
+
def compiled? ; @compiled ; end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "raises NotImplementedError when #evaluate or #template_source not defined" do
|
51
|
+
inst = CompilingMockTemplate.new { |t| "Hello World!" }
|
52
|
+
lambda { inst.render }.should.raise NotImplementedError
|
53
|
+
inst.should.be.compiled
|
54
|
+
end
|
55
|
+
|
56
|
+
class SimpleMockTemplate < CompilingMockTemplate
|
57
|
+
def evaluate(scope, locals, &block)
|
58
|
+
should.be.compiled
|
59
|
+
scope.should.not.be.nil
|
60
|
+
locals.should.not.be.nil
|
61
|
+
"<em>#{@data}</em>"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "compiles and evaluates the template on #render" do
|
66
|
+
inst = SimpleMockTemplate.new { |t| "Hello World!" }
|
67
|
+
inst.render.should.equal "<em>Hello World!</em>"
|
68
|
+
inst.should.be.compiled
|
69
|
+
end
|
70
|
+
|
71
|
+
class SourceGeneratingMockTemplate < CompilingMockTemplate
|
72
|
+
def template_source
|
73
|
+
"foo = [] ; foo << %Q{#{data}} ; foo.join"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "evaluates template_source with locals support" do
|
78
|
+
inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{name}!' }
|
79
|
+
inst.render(Object.new, :name => 'Joe').should.equal "Hey Joe!"
|
80
|
+
inst.should.be.compiled
|
81
|
+
end
|
82
|
+
|
83
|
+
class Person
|
84
|
+
attr_accessor :name
|
85
|
+
def initialize(name)
|
86
|
+
@name = name
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "evaluates template_source in the object scope provided" do
|
91
|
+
inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{@name}!' }
|
92
|
+
scope = Person.new('Joe')
|
93
|
+
inst.render(scope).should.equal "Hey Joe!"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "evaluates template_source with yield support" do
|
97
|
+
inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{yield}!' }
|
98
|
+
inst.render(Object.new){ 'Joe' }.should.equal "Hey Joe!"
|
99
|
+
end
|
100
|
+
end
|
data/tilt.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
+
|
5
|
+
s.name = 'tilt'
|
6
|
+
s.version = '0.2'
|
7
|
+
s.date = '2009-06-07'
|
8
|
+
|
9
|
+
s.description = "Generic interface to multiple Ruby template engines"
|
10
|
+
s.summary = s.description
|
11
|
+
|
12
|
+
s.authors = ["Ryan Tomayko"]
|
13
|
+
s.email = "r@tomayko.com"
|
14
|
+
|
15
|
+
# = MANIFEST =
|
16
|
+
s.files = %w[
|
17
|
+
COPYING
|
18
|
+
README.md
|
19
|
+
Rakefile
|
20
|
+
lib/tilt.rb
|
21
|
+
test/.bacon
|
22
|
+
test/spec_tilt.rb
|
23
|
+
test/spec_tilt_buildertemplate.rb
|
24
|
+
test/spec_tilt_erbtemplate.rb
|
25
|
+
test/spec_tilt_hamltemplate.rb
|
26
|
+
test/spec_tilt_liquid_template.rb
|
27
|
+
test/spec_tilt_rdiscount.rb
|
28
|
+
test/spec_tilt_sasstemplate.rb
|
29
|
+
test/spec_tilt_stringtemplate.rb
|
30
|
+
test/spec_tilt_template.rb
|
31
|
+
tilt.gemspec
|
32
|
+
]
|
33
|
+
# = MANIFEST =
|
34
|
+
|
35
|
+
s.test_files = s.files.select {|path| path =~ /^test\/spec_.*.rb/}
|
36
|
+
|
37
|
+
s.extra_rdoc_files = %w[COPYING]
|
38
|
+
|
39
|
+
s.has_rdoc = true
|
40
|
+
s.homepage = "http://github.com/rtomayko/tilt/"
|
41
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tilt", "--main", "Tilt"]
|
42
|
+
s.require_paths = %w[lib]
|
43
|
+
s.rubyforge_project = 'wink'
|
44
|
+
s.rubygems_version = '1.1.1'
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tilt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.2"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Tomayko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-07 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Generic interface to multiple Ruby template engines
|
17
|
+
email: r@tomayko.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- COPYING
|
24
|
+
files:
|
25
|
+
- COPYING
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- lib/tilt.rb
|
29
|
+
- test/.bacon
|
30
|
+
- test/spec_tilt.rb
|
31
|
+
- test/spec_tilt_buildertemplate.rb
|
32
|
+
- test/spec_tilt_erbtemplate.rb
|
33
|
+
- test/spec_tilt_hamltemplate.rb
|
34
|
+
- test/spec_tilt_liquid_template.rb
|
35
|
+
- test/spec_tilt_rdiscount.rb
|
36
|
+
- test/spec_tilt_sasstemplate.rb
|
37
|
+
- test/spec_tilt_stringtemplate.rb
|
38
|
+
- test/spec_tilt_template.rb
|
39
|
+
- tilt.gemspec
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/rtomayko/tilt/
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options:
|
44
|
+
- --line-numbers
|
45
|
+
- --inline-source
|
46
|
+
- --title
|
47
|
+
- Tilt
|
48
|
+
- --main
|
49
|
+
- Tilt
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project: wink
|
67
|
+
rubygems_version: 1.3.1
|
68
|
+
signing_key:
|
69
|
+
specification_version: 2
|
70
|
+
summary: Generic interface to multiple Ruby template engines
|
71
|
+
test_files:
|
72
|
+
- test/spec_tilt.rb
|
73
|
+
- test/spec_tilt_buildertemplate.rb
|
74
|
+
- test/spec_tilt_erbtemplate.rb
|
75
|
+
- test/spec_tilt_hamltemplate.rb
|
76
|
+
- test/spec_tilt_liquid_template.rb
|
77
|
+
- test/spec_tilt_rdiscount.rb
|
78
|
+
- test/spec_tilt_sasstemplate.rb
|
79
|
+
- test/spec_tilt_stringtemplate.rb
|
80
|
+
- test/spec_tilt_template.rb
|