tilt 0.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/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
|