tilt 0.6 → 0.9

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.
@@ -33,6 +34,12 @@ Support for these template engines is included with the package:
33
34
  RDiscount .markdown rdiscount
34
35
  RedCloth .textile redcloth
35
36
 
37
+ See [TEMPLATES.md][t] for detailed information on template engine
38
+ options and supported features.
39
+
40
+ [t]: http://github.com/rtomayko/tilt/blob/master/TEMPLATES.md
41
+ "Tilt Template Engine Documentation"
42
+
36
43
  Basic Usage
37
44
  -----------
38
45
 
@@ -139,8 +146,49 @@ Or, use BlueCloth for markdown instead of RDiscount:
139
146
 
140
147
  Tilt.register 'markdown', Tilt::BlueClothTemplate
141
148
 
149
+ Template Compilation
150
+ --------------------
151
+
152
+ Tilt can compile generated Ruby source code produced by template engines and
153
+ reuse on subsequent template invocations. Benchmarks show this yields a 5x-10x
154
+ performance increase over evaluating the Ruby source on each invocation.
155
+
156
+ Template compilation is currently supported for these template engines:
157
+ StringTemplate, ERB, Erubis, Haml, and Builder.
158
+
159
+ To enable template compilation, the `Tilt::CompileSite` module must be mixed in
160
+ to the scope object passed to the template's `#render` method. This can be
161
+ accomplished by including (with `Module#include`) the module in the class used
162
+ for scope objects or by extending (with `Object#extend`) scope objects before
163
+ passing to `Template#render`:
164
+
165
+ require 'tilt'
166
+
167
+ template = Tilt::ERBTemplate.new('foo.erb')
168
+
169
+ # Slow. Uses Object#instance_eval to process template
170
+ class Scope
171
+ end
172
+ scope = Scope.new
173
+ template.render(scope)
174
+
175
+ # Fast. Uses compiled template and Object#send to process template
176
+ class Scope
177
+ include Tilt::CompileSite
178
+ end
179
+ scope = Scope.new
180
+ template.render(scope)
181
+
182
+ # Also fast, though a bit a slower due to having to extend each time
183
+ scope = Object.new
184
+ scope.extend Tilt::CompileSite
185
+ template.render(scope)
186
+
187
+ When the `Tilt::CompileSite` module is not present, template execution falls
188
+ back to evaluating the template from source on each invocation.
189
+
142
190
  LICENSE
143
191
  -------
144
192
 
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.
193
+ Tilt is Copyright (c) 2010 [Ryan Tomayko](http://tomayko.com/about) and
194
+ distributed under the MIT license. See the `COPYING` file for more info.
data/Rakefile CHANGED
@@ -16,38 +16,44 @@ end
16
16
 
17
17
  # PACKAGING =================================================================
18
18
 
19
- require 'rubygems/specification'
20
- $spec ||= eval(File.read('tilt.gemspec'))
21
-
22
- def package(ext='')
23
- "dist/tilt-#{$spec.version}" + ext
19
+ begin
20
+ require 'rubygems'
21
+ rescue LoadError
24
22
  end
25
23
 
26
- desc 'Build packages'
27
- task :package => %w[.gem .tar.gz].map {|e| package(e)}
24
+ if defined?(Gem)
25
+ SPEC = eval(File.read('tilt.gemspec'))
28
26
 
29
- desc 'Build and install as local gem'
30
- task :install => package('.gem') do
31
- sh "gem install #{package('.gem')}"
32
- end
27
+ def package(ext='')
28
+ "pkg/tilt-#{SPEC.version}" + ext
29
+ end
33
30
 
34
- directory 'dist/'
31
+ desc 'Build packages'
32
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
35
33
 
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
34
+ desc 'Build and install as local gem'
35
+ task :install => package('.gem') do
36
+ sh "gem install #{package('.gem')}"
37
+ end
40
38
 
41
- file package('.tar.gz') => %w[dist/] + $spec.files do |f|
42
- sh "git archive --format=tar HEAD | gzip > #{f.name}"
43
- end
39
+ directory 'pkg/'
40
+
41
+ file package('.gem') => %w[pkg/ tilt.gemspec] + SPEC.files do |f|
42
+ sh "gem build tilt.gemspec"
43
+ mv File.basename(f.name), f.name
44
+ end
44
45
 
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
46
+ file package('.tar.gz') => %w[pkg/] + 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
51
57
  end
52
58
 
53
59
  # GEMSPEC ===================================================================
@@ -71,26 +77,3 @@ file 'tilt.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f|
71
77
  File.open(f.name, 'w') { |io| io.write(spec) }
72
78
  puts "updated #{f.name}"
73
79
  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
@@ -67,6 +67,12 @@ of any combination of the following characters:
67
67
  The `$SAFE` level; when set, ERB code will be run in a
68
68
  separate thread with `$SAFE` set to the provided level.
69
69
 
70
+ #### `:outvar => '_erbout'`
71
+
72
+ The name of the variable used to accumulate template output. This can be
73
+ any valid Ruby expression but must be assignable. By default a local
74
+ variable named `_erbout` is used.
75
+
70
76
  ### See also
71
77
 
72
78
  * [ERB documentation](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html)
@@ -88,9 +94,22 @@ the extensions as follows:
88
94
 
89
95
  ### Options
90
96
 
91
- #### `:trim => true`
97
+ #### `:engine_class => Erubis::Eruby`
92
98
 
93
- Delete spaces around '<% %>'. (But, spaces around '<%= %>' are preserved.)
99
+ Allows you to specify a custom engine class to use instead of the
100
+ default which is `Erubis::Eruby`.
101
+
102
+ #### `:escape_html => false`
103
+
104
+ When `true`, `Erubis::EscapedEruby` will be used as the engine class
105
+ instead of the default. All content within `<%= %>` blocks will be
106
+ automatically html escaped.
107
+
108
+ #### `:outvar => '_erbout'`
109
+
110
+ The name of the variable used to accumulate template output. This can be
111
+ any valid Ruby expression but must be assignable. By default a local
112
+ variable named `_erbout` is used.
94
113
 
95
114
  #### `:pattern => '<% %>'`
96
115
 
@@ -98,14 +117,17 @@ Set pattern for embedded Ruby code.
98
117
 
99
118
  See the [ERB](#erb) template documentation for examples, usage, and options.
100
119
 
101
- __NOTE:__ It's suggested that your program `require 'erubis'` at load time when
102
- using this template engine within a threaded environment.
120
+ #### `:trim => true`
121
+
122
+ Delete spaces around '<% %>'. (But, spaces around '<%= %>' are preserved.)
103
123
 
104
124
  ### See also
105
125
 
106
126
  * [Erubis Home](http://www.kuwata-lab.com/erubis/)
107
127
  * [Erubis User's Guide](http://www.kuwata-lab.com/erubis/users-guide.html)
108
128
 
129
+ __NOTE:__ It's suggested that your program `require 'erubis'` at load time when
130
+ using this template engine within a threaded environment.
109
131
 
110
132
  <a name='haml'></a>
111
133
  Haml (`haml`)
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)