tilt 0.5 → 1.0

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 CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Ryan Tomayko <http://tomayko.com/about>
1
+ Copyright (c) 2010 Ryan Tomayko <http://tomayko.com/about>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
data/README.md CHANGED
@@ -13,7 +13,8 @@ feature is relevant to the engine):
13
13
  * Ability to pass locals to template evaluation
14
14
  * Support for passing a block to template evaluation for "yield"
15
15
  * Backtraces with correct filenames and line numbers
16
- * Template compilation caching and reloading
16
+ * Template file caching and reloading
17
+ * Fast, method-based template source compilation
17
18
 
18
19
  The primary goal is to get all of the things listed above right for all
19
20
  template engines included in the distribution.
@@ -29,9 +30,16 @@ Support for these template engines is included with the package:
29
30
  Less CSS .less less
30
31
  Builder .builder builder
31
32
  Liquid .liquid liquid
32
- Mustache .mustache mustache
33
33
  RDiscount .markdown rdiscount
34
34
  RedCloth .textile redcloth
35
+ RDoc .rdoc rdoc
36
+ Radius .radius radius
37
+
38
+ See [TEMPLATES.md][t] for detailed information on template engine
39
+ options and supported features.
40
+
41
+ [t]: http://github.com/rtomayko/tilt/blob/master/TEMPLATES.md
42
+ "Tilt Template Engine Documentation"
35
43
 
36
44
  Basic Usage
37
45
  -----------
@@ -139,8 +147,49 @@ Or, use BlueCloth for markdown instead of RDiscount:
139
147
 
140
148
  Tilt.register 'markdown', Tilt::BlueClothTemplate
141
149
 
150
+ Template Compilation
151
+ --------------------
152
+
153
+ Tilt can compile generated Ruby source code produced by template engines and
154
+ reuse on subsequent template invocations. Benchmarks show this yields a 5x-10x
155
+ performance increase over evaluating the Ruby source on each invocation.
156
+
157
+ Template compilation is currently supported for these template engines:
158
+ StringTemplate, ERB, Erubis, Haml, and Builder.
159
+
160
+ To enable template compilation, the `Tilt::CompileSite` module must be mixed in
161
+ to the scope object passed to the template's `#render` method. This can be
162
+ accomplished by including (with `Module#include`) the module in the class used
163
+ for scope objects or by extending (with `Object#extend`) scope objects before
164
+ passing to `Template#render`:
165
+
166
+ require 'tilt'
167
+
168
+ template = Tilt::ERBTemplate.new('foo.erb')
169
+
170
+ # Slow. Uses Object#instance_eval to process template
171
+ class Scope
172
+ end
173
+ scope = Scope.new
174
+ template.render(scope)
175
+
176
+ # Fast. Uses compiled template and Object#send to process template
177
+ class Scope
178
+ include Tilt::CompileSite
179
+ end
180
+ scope = Scope.new
181
+ template.render(scope)
182
+
183
+ # Also fast, though a bit a slower due to having to extend each time
184
+ scope = Object.new
185
+ scope.extend Tilt::CompileSite
186
+ template.render(scope)
187
+
188
+ When the `Tilt::CompileSite` module is not present, template execution falls
189
+ back to evaluating the template from source on each invocation.
190
+
142
191
  LICENSE
143
192
  -------
144
193
 
145
- Tilt is Copyright (c) 2009 [Ryan Tomayko](http://tomayko.com/about) and
146
- distributed under the MIT license. See the COPYING file for more info.
194
+ Tilt is Copyright (c) 2010 [Ryan Tomayko](http://tomayko.com/about) and
195
+ distributed under the MIT license. See the `COPYING` file for more info.
data/Rakefile CHANGED
@@ -11,43 +11,50 @@ end
11
11
  desc 'Run tests (default)'
12
12
  Rake::TestTask.new(:test) do |t|
13
13
  t.test_files = FileList['test/*_test.rb']
14
- t.ruby_opts = ['-rubygems'] if defined? Gem
14
+ t.ruby_opts = ['-Itest']
15
+ t.ruby_opts << '-rubygems' if defined? Gem
15
16
  end
16
17
 
17
18
  # PACKAGING =================================================================
18
19
 
19
- require 'rubygems/specification'
20
- $spec ||= eval(File.read('tilt.gemspec'))
21
-
22
- def package(ext='')
23
- "dist/tilt-#{$spec.version}" + ext
20
+ begin
21
+ require 'rubygems'
22
+ rescue LoadError
24
23
  end
25
24
 
26
- desc 'Build packages'
27
- task :package => %w[.gem .tar.gz].map {|e| package(e)}
25
+ if defined?(Gem)
26
+ SPEC = eval(File.read('tilt.gemspec'))
28
27
 
29
- desc 'Build and install as local gem'
30
- task :install => package('.gem') do
31
- sh "gem install #{package('.gem')}"
32
- end
28
+ def package(ext='')
29
+ "pkg/tilt-#{SPEC.version}" + ext
30
+ end
33
31
 
34
- directory 'dist/'
32
+ desc 'Build packages'
33
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
35
34
 
36
- file package('.gem') => %w[dist/ tilt.gemspec] + $spec.files do |f|
37
- sh "gem build tilt.gemspec"
38
- mv File.basename(f.name), f.name
39
- end
35
+ desc 'Build and install as local gem'
36
+ task :install => package('.gem') do
37
+ sh "gem install #{package('.gem')}"
38
+ end
40
39
 
41
- file package('.tar.gz') => %w[dist/] + $spec.files do |f|
42
- sh "git archive --format=tar HEAD | gzip > #{f.name}"
43
- end
40
+ directory 'pkg/'
41
+
42
+ file package('.gem') => %w[pkg/ tilt.gemspec] + SPEC.files do |f|
43
+ sh "gem build tilt.gemspec"
44
+ mv File.basename(f.name), f.name
45
+ end
44
46
 
45
- desc 'Upload gem and tar.gz distributables to rubyforge'
46
- task :release => [package('.gem'), package('.tar.gz')] do |t|
47
- sh <<-SH
48
- rubyforge add_release sinatra tilt #{$spec.version} #{package('.gem')} &&
49
- rubyforge add_file sinatra tilt #{$spec.version} #{package('.tar.gz')}
50
- SH
47
+ file package('.tar.gz') => %w[pkg/] + SPEC.files do |f|
48
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
49
+ end
50
+
51
+ desc 'Upload gem and tar.gz distributables to rubyforge'
52
+ task :release => [package('.gem'), package('.tar.gz')] do |t|
53
+ sh <<-SH
54
+ rubyforge add_release sinatra tilt #{SPEC.version} #{package('.gem')} &&
55
+ rubyforge add_file sinatra tilt #{SPEC.version} #{package('.tar.gz')}
56
+ SH
57
+ end
51
58
  end
52
59
 
53
60
  # GEMSPEC ===================================================================
@@ -71,26 +78,3 @@ file 'tilt.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f|
71
78
  File.open(f.name, 'w') { |io| io.write(spec) }
72
79
  puts "updated #{f.name}"
73
80
  end
74
-
75
- # DOC =======================================================================
76
-
77
- # requires the hanna gem:
78
- # gem install mislav-hanna --source=http://gems.github.com
79
- desc 'Build API documentation (doc/api)'
80
- task 'rdoc' => 'rdoc/index.html'
81
- file 'rdoc/index.html' => FileList['lib/**/*.rb'] do |f|
82
- rm_rf 'rdoc'
83
- sh((<<-SH).gsub(/[\s\n]+/, ' ').strip)
84
- hanna
85
- --op doc/api
86
- --promiscuous
87
- --charset utf8
88
- --fmt html
89
- --inline-source
90
- --line-numbers
91
- --accessor option_accessor=RW
92
- --main Tilt
93
- --title 'Tilt API Documentation'
94
- #{f.prerequisites.join(' ')}
95
- SH
96
- end
data/TEMPLATES.md CHANGED
@@ -9,7 +9,6 @@ documentation on each supported template engine is provided below.
9
9
  * [Erubis](#erubis) - `Tilt::ErubisTemplate`
10
10
  * [Haml](#haml) - `Tilt::HamlTemplate`
11
11
  * [Liquid](#liquid) - `Tilt::LiquidTemplate`
12
- * [Mustache](#mustache) - `Tilt::MustachTemplate`
13
12
 
14
13
  Tilt includes support for CSS processors like [lesscss](http://lesscss.org)
15
14
  and [sass](http://sass-lang.com/), in addition, it also supports simple
@@ -67,6 +66,12 @@ of any combination of the following characters:
67
66
  The `$SAFE` level; when set, ERB code will be run in a
68
67
  separate thread with `$SAFE` set to the provided level.
69
68
 
69
+ #### `:outvar => '_erbout'`
70
+
71
+ The name of the variable used to accumulate template output. This can be
72
+ any valid Ruby expression but must be assignable. By default a local
73
+ variable named `_erbout` is used.
74
+
70
75
  ### See also
71
76
 
72
77
  * [ERB documentation](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html)
@@ -88,9 +93,22 @@ the extensions as follows:
88
93
 
89
94
  ### Options
90
95
 
91
- #### `:trim => true`
96
+ #### `:engine_class => Erubis::Eruby`
92
97
 
93
- Delete spaces around '<% %>'. (But, spaces around '<%= %>' are preserved.)
98
+ Allows you to specify a custom engine class to use instead of the
99
+ default which is `Erubis::Eruby`.
100
+
101
+ #### `:escape_html => false`
102
+
103
+ When `true`, `Erubis::EscapedEruby` will be used as the engine class
104
+ instead of the default. All content within `<%= %>` blocks will be
105
+ automatically html escaped.
106
+
107
+ #### `:outvar => '_erbout'`
108
+
109
+ The name of the variable used to accumulate template output. This can be
110
+ any valid Ruby expression but must be assignable. By default a local
111
+ variable named `_erbout` is used.
94
112
 
95
113
  #### `:pattern => '<% %>'`
96
114
 
@@ -98,14 +116,17 @@ Set pattern for embedded Ruby code.
98
116
 
99
117
  See the [ERB](#erb) template documentation for examples, usage, and options.
100
118
 
101
- __NOTE:__ It's suggested that your program `require 'erubis'` at load time when
102
- using this template engine within a threaded environment.
119
+ #### `:trim => true`
120
+
121
+ Delete spaces around '<% %>'. (But, spaces around '<%= %>' are preserved.)
103
122
 
104
123
  ### See also
105
124
 
106
125
  * [Erubis Home](http://www.kuwata-lab.com/erubis/)
107
126
  * [Erubis User's Guide](http://www.kuwata-lab.com/erubis/users-guide.html)
108
127
 
128
+ __NOTE:__ It's suggested that your program `require 'erubis'` at load time when
129
+ using this template engine within a threaded environment.
109
130
 
110
131
  <a name='haml'></a>
111
132
  Haml (`haml`)
@@ -282,53 +303,6 @@ time when using this template engine within a threaded environment.
282
303
  * [Liquid Docs](http://liquid.rubyforge.org/)
283
304
  * GitHub: [tobi/liquid](http://github.com/tobi/liquid/)
284
305
 
285
- <a name='mustache'></a>
286
- Mustache (`mustache`)
287
- ---------------------
288
-
289
- Mustache is a framework-agnostic way to render logic-free views.
290
-
291
- __NOTE:__ It's suggested that your program `require 'mustache'` at load time
292
- when using this template engine in a threaded environment.
293
-
294
- ### Options
295
-
296
- #### `:path => Dir.pwd`
297
-
298
- The base path where mustache templates (`.html` files) are located. Defaults to
299
- the current working directory.
300
-
301
- #### `:template_extension => 'html'`
302
-
303
- The file extension used on mustache templates. Default is `'html'`.
304
-
305
- #### `:namespace => Object`
306
-
307
- The class or module where View classes are located. If you have
308
- `Hurl::App::Views`, namespace should be `Hurl:App`. This defaults to `Object`,
309
- causing `::Views` to be searched for classes.
310
-
311
- #### `:mustaches => nil`
312
-
313
- Where mustache views (.rb files) are located, or nil to disable auto-requiring
314
- of views based on template names. By default, the view file is assumed to be in
315
- the same directory as the template file.
316
-
317
- All other options are assumed to be attribute writer's on the Mustache
318
- class and are set when a template is compiled. They are:
319
-
320
- #### `:view => nil`
321
-
322
- The Mustache subclass that should be used a the view. When this option is
323
- specified, the template file will be determined from the view class, and the
324
- `:namespace` and `:mustaches` options are irrelevant.
325
-
326
- ### See also
327
-
328
- * [Mustache Docs](http://defunkt.github.com/mustache/)
329
- * GitHub: [defunkt/mustache](http://github.com/defunkt/mustache)
330
-
331
-
332
306
  <a name='markdown'></a>
333
307
  Markdown (`markdown`, `md`, `mkd`)
334
308
  ----------------------------------
@@ -410,3 +384,56 @@ engine in a threaded environment.
410
384
  ### See also
411
385
 
412
386
  * [RDoc](http://rdoc.sourceforge.net/doc/index.html)
387
+
388
+
389
+ <a name='radius'></a>
390
+ Radius (`radius`)
391
+ -----------------
392
+
393
+ Radius is the template language used by Radiant CMS. It is a tag
394
+ language designed to be valid XML/HTML.
395
+
396
+ ### Example
397
+
398
+ <html>
399
+ <body>
400
+ <h1><r:title /></h1>
401
+ <ul class="<r:type />">
402
+ <r:repeat times="3">
403
+ <li><r:hello />!</li>
404
+ </r:repeat>
405
+ </ul>
406
+ <r:yield />
407
+ </body>
408
+ </html>
409
+
410
+ ### Usage
411
+
412
+ To render a template such as the one above.
413
+
414
+ scope = OpenStruct.new
415
+ scope.title = "Radius Example"
416
+ scope.hello = "Hello, World!"
417
+
418
+ require 'radius'
419
+ template = Tilt::RadiusTemplate.new('example.radius', :tag_prefix=>'r')
420
+ template.render(scope, :type=>'hlist'){ "Jackpot!" }
421
+
422
+ The result will be:
423
+
424
+ <html>
425
+ <body>
426
+ <h1>Radius Example</h1>
427
+ <ul class="hlist">
428
+ <li>Hello, World!</li>
429
+ <li>Hello, World!</li>
430
+ <li>Hello, World!</li>
431
+ </ul>
432
+ Jackpot!
433
+ </body>
434
+ </html>
435
+
436
+ ### See also
437
+
438
+ * [Radius](http://radius.rubyforge.org/)
439
+ * [Radiant](http://radiantcms.org/)
data/bin/tilt CHANGED
@@ -3,17 +3,21 @@ require 'ostruct'
3
3
  require 'optparse'
4
4
  require 'tilt'
5
5
 
6
- usage = <<EOF
7
- Usage: tilt [OPTIONS] [FILE]
8
- Process template FILE and generate output. With no FILE or when FILE
9
- is '-', read template from stdin and use the --type option to determine
10
- the template's type.
6
+ usage = <<USAGE
7
+ Usage: tilt <options> <file>
8
+ Process template <file> and write output to stdout. With no <file> or
9
+ when <file> is '-', read template from stdin and use the --type option
10
+ to determine the template's type.
11
11
 
12
12
  Options
13
- -l, --list List supported template engines + file patterns and exit.
14
- -t, --type=PATTERN Use this template engine; required when FILE is stdin.
13
+ -l, --list List template engines + file patterns and exit
14
+ -t, --type=<pattern> Use this template engine; required if no <file>
15
+ -y, --layout=<file> Use <file> as a layout template
15
16
 
16
- -h, --help Show this help message.
17
+ -D<name>=<value> Define variable <name> as <value>
18
+ -o, --vars=<ruby> Evaluate <ruby> to Hash and use for variables
19
+
20
+ -h, --help Show this help message
17
21
 
18
22
  Convert markdown to HTML:
19
23
  $ tilt foo.markdown > foo.html
@@ -21,11 +25,18 @@ Convert markdown to HTML:
21
25
  Process ERB template:
22
26
  $ echo "Answer: <%= 2 + 2 %>" | tilt -t erb
23
27
  Answer: 4
24
- EOF
28
+
29
+ Define variables:
30
+ $ echo "Answer: <%= 2 + n %>" | tilt --locals="{:n=>40, :x=>0}"
31
+ Answer: 42
32
+ $ echo "Answer: <%= 2 + n %>" | tilt -Dn=40 -Dx=0
33
+ Answer: 42
34
+ USAGE
25
35
 
26
36
  script_name = File.basename($0)
27
37
  pattern = nil
28
38
  layout = nil
39
+ locals = {}
29
40
 
30
41
  ARGV.options do |o|
31
42
  o.program_name = script_name
@@ -44,18 +55,31 @@ ARGV.options do |o|
44
55
  end
45
56
 
46
57
  # the template type / pattern
47
- o.on("-t", "--type=PATTERN") do |val|
48
- fail "unknown template type: #{val}" if Tilt[val].nil?
58
+ o.on("-t", "--type=PATTERN", String) do |val|
59
+ abort "unknown template type: #{val}" if Tilt[val].nil?
49
60
  pattern = val
50
61
  end
51
62
 
52
63
  # pass template output into the specified layout template
53
- o.on("-y", "--layout=FILE") do |file|
64
+ o.on("-y", "--layout=FILE", String) do |file|
54
65
  paths = [file, "~/.tilt/#{file}", "/etc/tilt/#{file}"]
55
66
  layout = paths.
56
67
  map { |p| File.expand_path(p) }.
57
68
  find { |p| File.exist?(p) }
58
- fail "no such layout: #{file}" if layout.nil?
69
+ abort "no such layout: #{file}" if layout.nil?
70
+ end
71
+
72
+ # define a local variable
73
+ o.on("-D", "--define=PAIR", String) do |pair|
74
+ key, value = pair.split(/[=:]/, 2)
75
+ locals[key.to_sym] = value
76
+ end
77
+
78
+ # define local variables using a Ruby hash
79
+ o.on("--vars=RUBY") do |ruby|
80
+ hash = eval(ruby)
81
+ abort "vars must be a Hash, not #{hash.inspect}" if !hash.is_a?(Hash)
82
+ hash.each { |key, value| locals[key.to_sym] = value }
59
83
  end
60
84
 
61
85
  o.on_tail("-h", "--help") { puts usage; exit }
@@ -65,17 +89,22 @@ end
65
89
 
66
90
  file = ARGV.first || '-'
67
91
  pattern = file if pattern.nil?
92
+ abort "template type not given. see: #{$0} --help" if ['-', ''].include?(pattern)
93
+
94
+ engine = Tilt[pattern]
95
+ abort "template engine not found for: #{pattern}" if engine.nil?
96
+
68
97
  template =
69
- Tilt[pattern].new(file) {
98
+ engine.new(file) {
70
99
  if file == '-'
71
100
  $stdin.read
72
101
  else
73
102
  File.read(file)
74
103
  end
75
104
  }
76
- output = template.render
105
+ output = template.render(self, locals)
77
106
 
78
107
  # process layout
79
- output = Tilt.new(layout).render { output } if layout
108
+ output = Tilt.new(layout).render(self, locals) { output } if layout
80
109
 
81
110
  $stdout.write(output)