slim 1.2.2 → 1.3.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/Rakefile CHANGED
@@ -11,20 +11,36 @@ task :bench, :iterations, :slow do
11
11
  ruby('benchmarks/run-benchmarks.rb')
12
12
  end
13
13
 
14
- Rake::TestTask.new('test') do |t|
15
- t.libs << 'lib' << 'test/slim'
16
- t.test_files = FileList['test/slim/test_*.rb']
17
- t.verbose = true
18
- end
14
+ task 'test' => %w(test:core test:logic_less test:translator)
19
15
 
20
- Rake::TestTask.new('test:rails') do |t|
21
- t.libs << 'lib'
22
- t.test_files = FileList['test/rails/test/test_*.rb']
23
- t.verbose = true
24
- end
16
+ namespace 'test' do
17
+ Rake::TestTask.new('core') do |t|
18
+ t.libs << 'lib' << 'test/slim'
19
+ t.test_files = FileList['test/slim/test_*.rb']
20
+ t.verbose = true
21
+ end
22
+
23
+ Rake::TestTask.new('logic_less') do |t|
24
+ t.libs << 'lib' << 'test/slim'
25
+ t.test_files = FileList['test/slim/logic_less/test_*.rb']
26
+ t.verbose = true
27
+ end
28
+
29
+ Rake::TestTask.new('translator') do |t|
30
+ t.libs << 'lib' << 'test/slim'
31
+ t.test_files = FileList['test/slim/translator/test_*.rb']
32
+ t.verbose = true
33
+ end
25
34
 
26
- task 'test:ci' do |t|
27
- Rake::Task[ENV['TASK']].execute
35
+ Rake::TestTask.new('rails') do |t|
36
+ t.libs << 'lib'
37
+ t.test_files = FileList['test/rails/test/test_*.rb']
38
+ t.verbose = true
39
+ end
40
+
41
+ task 'ci' do |t|
42
+ Rake::Task[ENV['TASK']].execute
43
+ end
28
44
  end
29
45
 
30
46
  begin
@@ -3,10 +3,10 @@
3
3
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
4
 
5
5
  require 'slim'
6
- require 'complex_view'
6
+ require 'context'
7
7
 
8
8
  content = File.read(File.dirname(__FILE__) + '/view.slim')
9
9
  slim = Slim::Template.new { content }
10
- view = ComplexView.new
10
+ context = Context.new
11
11
 
12
- 10000.times { slim.render(view) }
12
+ 10000.times { slim.render(context) }
@@ -6,6 +6,7 @@ require 'slim'
6
6
  require 'context'
7
7
 
8
8
  require 'benchmark'
9
+ require 'tilt'
9
10
  require 'erubis'
10
11
  require 'erb'
11
12
  require 'haml'
@@ -15,63 +16,101 @@ class SlimBenchmarks
15
16
  @iterations = (iterations || 1000).to_i
16
17
  @benches = []
17
18
 
18
- tpl_erb = File.read(File.dirname(__FILE__) + '/view.erb')
19
- tpl_haml = File.read(File.dirname(__FILE__) + '/view.haml')
20
- tpl_slim = File.read(File.dirname(__FILE__) + '/view.slim')
19
+ @erb_code = File.read(File.dirname(__FILE__) + '/view.erb')
20
+ @haml_code = File.read(File.dirname(__FILE__) + '/view.haml')
21
+ @slim_code = File.read(File.dirname(__FILE__) + '/view.slim')
21
22
 
22
- context = Context.new
23
- context_binding = context.instance_eval { binding }
23
+ init_compiled_benches
24
+ init_tilt_benches
25
+ init_cached_benches
26
+ init_parsing_benches if slow
27
+ end
24
28
 
25
- erb = ERB.new(tpl_erb)
26
- erubis = Erubis::Eruby.new(tpl_erb)
27
- fast_erubis = Erubis::FastEruby.new(tpl_erb)
28
- haml = Haml::Engine.new(tpl_haml, :format => :html5)
29
- haml_ugly = Haml::Engine.new(tpl_haml, :format => :html5, :ugly => true)
30
- slim = Slim::Template.new { tpl_slim }
29
+ def init_compiled_benches
30
+ erb = ERB.new(@erb_code)
31
+ erubis = Erubis::Eruby.new(@erb_code)
32
+ fast_erubis = Erubis::FastEruby.new(@erb_code)
33
+ haml_pretty = Haml::Engine.new(@haml_code, :format => :html5)
34
+ haml_ugly = Haml::Engine.new(@haml_code, :format => :html5, :ugly => true)
31
35
 
32
- tilt_erb = Tilt::ERBTemplate.new { tpl_erb }
33
- tilt_erubis = Tilt::ErubisTemplate.new { tpl_erb }
34
- tilt_haml = Tilt::HamlTemplate.new(:format => :html5){ tpl_haml }
35
- tilt_haml_ugly = Tilt::HamlTemplate.new(:format => :html5, :ugly => true){ tpl_haml }
36
- tilt_slim = Slim::Template.new { tpl_slim }
36
+ context = Context.new
37
37
 
38
- haml.def_method(context, :run_haml)
38
+ haml_pretty.def_method(context, :run_haml_pretty)
39
39
  haml_ugly.def_method(context, :run_haml_ugly)
40
40
  context.instance_eval %{
41
41
  def run_erb; #{erb.src}; end
42
42
  def run_erubis; #{erubis.src}; end
43
+ def run_temple_erb; #{Temple::ERB::Engine.new.call @erb_code}; end
43
44
  def run_fast_erubis; #{fast_erubis.src}; end
44
- def run_slim; #{slim.precompiled_template}; end
45
+ def run_slim_pretty; #{Slim::Engine.new(:pretty => true).call @slim_code}; end
46
+ def run_slim_ugly; #{Slim::Engine.new.call @slim_code}; end
45
47
  }
46
48
 
47
- if slow
48
- bench('(1) erb') { ERB.new(tpl_erb).result(context_binding) }
49
- bench('(1) erubis') { Erubis::Eruby.new(tpl_erb).result(context_binding) }
50
- bench('(1) fast erubis') { Erubis::Eruby.new(tpl_erb).result(context_binding) }
51
- bench('(1) slim') { Slim::Template.new { tpl_slim }.render(context) }
52
- bench('(1) haml') { Haml::Engine.new(tpl_haml, :format => :html5).render(context) }
53
- bench('(1) haml ugly') { Haml::Engine.new(tpl_haml, :format => :html5, :ugly => true).render(context) }
54
- end
49
+ bench('(1) erb') { context.run_erb }
50
+ bench('(1) erubis') { context.run_erubis }
51
+ bench('(1) fast erubis') { context.run_fast_erubis }
52
+ bench('(1) temple erb') { context.run_temple_erb }
53
+ bench('(1) slim pretty') { context.run_slim_pretty }
54
+ bench('(1) slim ugly') { context.run_slim_ugly }
55
+ bench('(1) haml pretty') { context.run_haml_pretty }
56
+ bench('(1) haml ugly') { context.run_haml_ugly }
57
+ end
55
58
 
56
- bench('(2) erb') { erb.result(context_binding) }
57
- bench('(2) erubis') { erubis.result(context_binding) }
58
- bench('(2) fast erubis') { fast_erubis.result(context_binding) }
59
- bench('(2) slim') { slim.render(context) }
60
- bench('(2) haml') { haml.render(context) }
61
- bench('(2) haml ugly') { haml_ugly.render(context) }
62
-
63
- bench('(3) erb') { context.run_erb }
64
- bench('(3) erubis') { context.run_erubis }
65
- bench('(3) fast erubis') { context.run_fast_erubis }
66
- bench('(3) slim') { context.run_slim }
67
- bench('(3) haml') { context.run_haml }
68
- bench('(3) haml ugly') { context.run_haml_ugly }
69
-
70
- bench('(4) erb') { tilt_erb.render(context) }
71
- bench('(4) erubis') { tilt_erubis.render(context) }
72
- bench('(4) slim') { tilt_slim.render(context) }
73
- bench('(4) haml') { tilt_haml.render(context) }
74
- bench('(4) haml ugly') { tilt_haml_ugly.render(context) }
59
+ def init_tilt_benches
60
+ tilt_erb = Tilt::ERBTemplate.new { @erb_code }
61
+ tilt_erubis = Tilt::ErubisTemplate.new { @erb_code }
62
+ tilt_temple_erb = Temple::ERB::Template.new { @erb_code }
63
+ tilt_haml_pretty= Tilt::HamlTemplate.new(:format => :html5){ @haml_code }
64
+ tilt_haml_ugly = Tilt::HamlTemplate.new(:format => :html5, :ugly => true){ @haml_code }
65
+ tilt_slim_pretty= Slim::Template.new(:pretty => true) { @slim_code }
66
+ tilt_slim_ugly = Slim::Template.new { @slim_code }
67
+
68
+ context = Context.new
69
+
70
+ bench('(2) erb') { tilt_erb.render(context) }
71
+ bench('(2) erubis') { tilt_erubis.render(context) }
72
+ bench('(2) temple erb') { tilt_temple_erb.render(context) }
73
+ bench('(2) slim pretty') { tilt_slim_pretty.render(context) }
74
+ bench('(2) slim ugly') { tilt_slim_ugly.render(context) }
75
+ bench('(2) haml pretty') { tilt_haml_pretty.render(context) }
76
+ bench('(2) haml ugly') { tilt_haml_ugly.render(context) }
77
+ end
78
+
79
+ def init_cached_benches
80
+ context = Context.new
81
+ context_binding = context.instance_eval { binding }
82
+
83
+ erb = ERB.new(@erb_code)
84
+ erubis = Erubis::Eruby.new(@erb_code)
85
+ fast_erubis = Erubis::FastEruby.new(@erb_code)
86
+ temple_erb = Temple::ERB::Template.new { @erb_code }
87
+ haml_pretty = Haml::Engine.new(@haml_code, :format => :html5)
88
+ haml_ugly = Haml::Engine.new(@haml_code, :format => :html5, :ugly => true)
89
+ slim_pretty = Slim::Template.new(:pretty => true) { @slim_code }
90
+ slim_ugly = Slim::Template.new { @slim_code }
91
+
92
+ bench('(3) erb') { erb.result(context_binding) }
93
+ bench('(3) erubis') { erubis.result(context_binding) }
94
+ bench('(3) fast erubis') { fast_erubis.result(context_binding) }
95
+ bench('(3) temple erb') { temple_erb.render(context) }
96
+ bench('(3) slim pretty') { slim_pretty.render(context) }
97
+ bench('(3) slim ugly') { slim_ugly.render(context) }
98
+ bench('(3) haml pretty') { haml_pretty.render(context) }
99
+ bench('(3) haml ugly') { haml_ugly.render(context) }
100
+ end
101
+
102
+ def init_parsing_benches
103
+ context = Context.new
104
+ context_binding = context.instance_eval { binding }
105
+
106
+ bench('(4) erb') { ERB.new(@erb_code).result(context_binding) }
107
+ bench('(4) erubis') { Erubis::Eruby.new(@erb_code).result(context_binding) }
108
+ bench('(4) fast erubis') { Erubis::FastEruby.new(@erb_code).result(context_binding) }
109
+ bench('(4) temple erb') { Temple::ERB::Template.new { @erb_code }.render(context) }
110
+ bench('(4) slim pretty') { Slim::Template.new(:pretty => true) { @slim_code }.render(context) }
111
+ bench('(4) slim ugly') { Slim::Template.new { @slim_code }.render(context) }
112
+ bench('(4) haml pretty') { Haml::Engine.new(@haml_code, :format => :html5).render(context) }
113
+ bench('(4) haml ugly') { Haml::Engine.new(@haml_code, :format => :html5, :ugly => true).render(context) }
75
114
  end
76
115
 
77
116
  def run
@@ -84,23 +123,26 @@ class SlimBenchmarks
84
123
  end
85
124
  end
86
125
  puts "
87
- 1. Uncached benchmark. Template is parsed every time.
88
- Activate this benchmark with 'rake bench slow=1'.
89
-
90
- 2. Cached benchmark. Template is parsed before the benchmark.
91
- The ruby code generated by the template engine might be evaluated every time.
92
- This benchmark uses the standard API of the template engine.
93
-
94
- 3. Compiled benchmark. Template is parsed before the benchmark and
95
- generated ruby code is compiled into a method.
96
- This is the fastest evaluation strategy because it benchmarks
97
- pure execution speed of the generated ruby code.
98
-
99
- 4. Compiled Tilt benchmark. Template is compiled with Tilt, which gives a more
100
- accurate result of the performance in production mode in frameworks like
101
- Sinatra, Ramaze and Camping. (Rails still uses its own template
102
- compilation.)
103
-
126
+ (1) Compiled benchmark. Template is parsed before the benchmark and
127
+ generated ruby code is compiled into a method.
128
+ This is the fastest evaluation strategy because it benchmarks
129
+ pure execution speed of the generated ruby code.
130
+
131
+ (2) Compiled Tilt benchmark. Template is compiled with Tilt, which gives a more
132
+ accurate result of the performance in production mode in frameworks like
133
+ Sinatra, Ramaze and Camping. (Rails still uses its own template
134
+ compilation.)
135
+
136
+ (3) Cached benchmark. Template is parsed before the benchmark.
137
+ The ruby code generated by the template engine might be evaluated every time.
138
+ This benchmark uses the standard API of the template engine.
139
+
140
+ (4) Parsing benchmark. Template is parsed every time.
141
+ This is not the recommended way to use the template engine
142
+ and Slim is not optimized for it. Activate this benchmark with 'rake bench slow=1'.
143
+
144
+ Temple ERB is the ERB implementation using the Temple framework. It shows the
145
+ overhead added by the Temple framework compared to ERB.
104
146
  "
105
147
  end
106
148
 
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
+
5
+ require 'slim'
6
+ require 'context'
7
+ require 'diffbench'
8
+
9
+ content = File.read(File.dirname(__FILE__) + '/view.slim')
10
+ engine = Slim::Engine.new
11
+ template = Slim::Template.new { content }
12
+ context = Context.new
13
+
14
+ DiffBench.bm do
15
+ report("Parse") do
16
+ 2000.times { engine.call(content) }
17
+ end
18
+ report("Render") do
19
+ 100000.times { template.render(context) }
20
+ end
21
+ end
data/bin/slimrb CHANGED
@@ -3,5 +3,4 @@
3
3
  $:.unshift File.dirname(__FILE__) + '/../lib'
4
4
  require 'slim/command'
5
5
 
6
- cmd = Slim::Command.new(ARGV)
7
- cmd.run
6
+ Slim::Command.new(ARGV).run
@@ -6,9 +6,7 @@ require 'slim/filter'
6
6
  require 'slim/end_inserter'
7
7
  require 'slim/embedded_engine'
8
8
  require 'slim/interpolation'
9
- require 'slim/sections'
10
9
  require 'slim/compiler'
11
10
  require 'slim/engine'
12
11
  require 'slim/template'
13
12
  require 'slim/version'
14
- require 'slim/wrapper'
@@ -1,4 +1,5 @@
1
- require 'slim'
1
+ require 'slim/logic_less'
2
+ require 'slim/translator'
2
3
  require 'optparse'
3
4
 
4
5
  module Slim
@@ -44,8 +45,12 @@ module Slim
44
45
  @options[:rails] = true
45
46
  end
46
47
 
47
- opts.on('-S', '--sections', :NONE, 'Logic-less sections mode') do
48
- @options[:sections] = true
48
+ opts.on('-t', '--translator', :NONE, 'Enable translator plugin') do
49
+ @options[:translator] = true
50
+ end
51
+
52
+ opts.on('-l', '--logic-less', :NONE, 'Enable logic-less plugin') do
53
+ @options[:logic_less] = true
49
54
  end
50
55
 
51
56
  opts.on('-p', '--pretty', :NONE, 'Produce pretty html') do
@@ -85,15 +90,17 @@ module Slim
85
90
  if @options[:compile]
86
91
  @options[:output].puts(Slim::Engine.new(:file => @options[:file],
87
92
  :pretty => @options[:pretty],
88
- :sections => @options[:sections],
93
+ :logic_less => @options[:logic_less],
89
94
  :disable_capture => @options[:rails],
95
+ :tr => @options[:translator],
90
96
  :generator => @options[:rails] ?
91
97
  Temple::Generators::RailsOutputBuffer :
92
98
  Temple::Generators::ArrayBuffer).call(@options[:input].read))
93
99
  else
94
100
  @options[:output].puts(Slim::Template.new(@options[:file],
95
101
  :pretty => @options[:pretty],
96
- :sections => @options[:sections]) { @options[:input].read }.render)
102
+ :tr => @options[:translator],
103
+ :logic_less => @options[:logic_less]) { @options[:input].read }.render)
97
104
  end
98
105
  end
99
106
  end
@@ -13,7 +13,7 @@ module Slim
13
13
 
14
14
  # Handle control expression `[:slim, :control, code, content]`
15
15
  #
16
- # @param [String] ruby code
16
+ # @param [String] code Ruby code
17
17
  # @param [Array] content Temple expression
18
18
  # @return [Array] Compiled temple expression
19
19
  def on_slim_control(code, content)
@@ -22,19 +22,6 @@ module Slim
22
22
  compile(content)]
23
23
  end
24
24
 
25
- # Handle conditional comment expression
26
- # `[:slim, :conditional_comment, conditional, content]`
27
- #
28
- # @param [Array] content Temple expression
29
- # @return [Array] Compiled temple expression
30
- def on_slim_condcomment(condition, content)
31
- [:html, :comment,
32
- [:multi,
33
- [:static, "[#{condition}]>"],
34
- compile(content),
35
- [:static, '<![endif]']]]
36
- end
37
-
38
25
  # Handle output expression `[:slim, :output, escape, code, content]`
39
26
  #
40
27
  # @param [Boolean] escape Escape html
@@ -67,6 +54,14 @@ module Slim
67
54
  end
68
55
  end
69
56
 
57
+ # Handle text expression `[:slim, :text, content]`
58
+ #
59
+ # @param [Array] content Temple expression
60
+ # @return [Array] Compiled temple expression
61
+ def on_slim_text(content)
62
+ compile(content)
63
+ end
64
+
70
65
  # Handle tag expression `[:slim, :tag, name, attrs, content]`
71
66
  #
72
67
  # @param [String] name Tag name
@@ -103,7 +98,7 @@ module Slim
103
98
 
104
99
  # Handle attributes expression `[:slim, :attrs, *attrs]`
105
100
  #
106
- # @param [Array] *attrs Array of temple expressions
101
+ # @param [Array] attrs Array of temple expressions
107
102
  # @return [Array] Compiled temple expression
108
103
  def on_slim_attrs(*attrs)
109
104
  if attrs.any? {|attr| attr[1] == :splat}
@@ -1,6 +1,6 @@
1
1
  module Slim
2
2
  # @api private
3
- class CollectText < Filter
3
+ class TextCollector < Filter
4
4
  def call(exp)
5
5
  @collected = ''
6
6
  super(exp)
@@ -14,7 +14,7 @@ module Slim
14
14
  end
15
15
 
16
16
  # @api private
17
- class CollectNewlines < Filter
17
+ class NewlineCollector < Filter
18
18
  def call(exp)
19
19
  @collected = [:multi]
20
20
  super(exp)
@@ -28,7 +28,7 @@ module Slim
28
28
  end
29
29
 
30
30
  # @api private
31
- class ProtectOutput < Filter
31
+ class OutputProtector < Filter
32
32
  def call(exp)
33
33
  @protect = []
34
34
  @collected = ''
@@ -87,18 +87,26 @@ module Slim
87
87
  engine.new(Temple::ImmutableHash.new(local_options, filtered_options)).on_slim_embedded(name, body)
88
88
  end
89
89
 
90
+ protected
91
+
92
+ def collect_text(body)
93
+ @text_collector ||= TextCollector.new
94
+ @text_collector.call(body)
95
+ end
96
+
90
97
  # Basic tilt engine
91
98
  class TiltEngine < EmbeddedEngine
92
99
  def on_slim_embedded(engine, body)
93
100
  tilt_engine = Tilt[engine] || raise("Tilt engine #{engine} is not available.")
94
101
  tilt_options = options[engine.to_sym] || {}
95
- [:multi, tilt_render(tilt_engine, tilt_options, collect_text(body)), CollectNewlines.new.call(body)]
102
+ [:multi, tilt_render(tilt_engine, tilt_options, collect_text(body)), collect_newlines(body)]
96
103
  end
97
104
 
98
105
  protected
99
106
 
100
- def collect_text(body)
101
- CollectText.new.call(body)
107
+ def collect_newlines(body)
108
+ @newline_collector ||= NewlineCollector.new
109
+ @newline_collector.call(body)
102
110
  end
103
111
  end
104
112
 
@@ -135,25 +143,35 @@ module Slim
135
143
 
136
144
  # Static template with interpolated ruby code
137
145
  class InterpolateTiltEngine < TiltEngine
138
- def initialize(opts = {})
139
- super
140
- @protect = ProtectOutput.new
141
- end
142
-
143
146
  def collect_text(body)
144
- text = Interpolation.new.call(body)
145
- @protect.call(text)
147
+ output_protector.call(interpolation.call(body))
146
148
  end
147
149
 
148
150
  def tilt_render(tilt_engine, tilt_options, text)
149
- @protect.unprotect(tilt_engine.new(tilt_options) { text }.render)
151
+ output_protector.unprotect(tilt_engine.new(tilt_options) { text }.render)
152
+ end
153
+
154
+ private
155
+
156
+ def interpolation
157
+ @interpolation ||= Interpolation.new
158
+ end
159
+
160
+ def output_protector
161
+ @output_protector ||= OutputProtector.new
150
162
  end
151
163
  end
152
164
 
153
165
  # ERB engine (uses the Temple ERB implementation)
154
166
  class ERBEngine < EmbeddedEngine
155
167
  def on_slim_embedded(engine, body)
156
- [:multi, [:newline], Temple::ERB::Parser.new.call(CollectText.new.call(body))]
168
+ [:multi, [:newline], erb_parser.call(collect_text(body))]
169
+ end
170
+
171
+ protected
172
+
173
+ def erb_parser
174
+ @erb_parser ||= Temple::ERB::Parser.new
157
175
  end
158
176
  end
159
177
 
@@ -169,7 +187,7 @@ module Slim
169
187
  # Embeds ruby code
170
188
  class RubyEngine < EmbeddedEngine
171
189
  def on_slim_embedded(engine, body)
172
- [:multi, [:newline], [:code, CollectText.new.call(body)]]
190
+ [:multi, [:newline], [:code, collect_text(body)]]
173
191
  end
174
192
  end
175
193