slim 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -288,24 +288,29 @@ There are two helpers you could use to validate your Slim syntax:
288
288
  # OS X 10.6 + Ruby 1.9.2, 1000 iterations
289
289
 
290
290
  user system total real
291
- (1) erb 0.420000 0.000000 0.420000 ( 0.429334)
292
- (1) erubis 0.350000 0.000000 0.350000 ( 0.356078)
293
- (1) fast erubis 0.350000 0.000000 0.350000 ( 0.355976)
294
- (1) slim 3.300000 0.010000 3.310000 ( 3.340637)
295
- (1) haml 2.950000 0.000000 2.950000 ( 2.970671)
296
- (1) haml ugly 2.840000 0.010000 2.850000 ( 2.856405)
297
- (2) erb 0.150000 0.000000 0.150000 ( 0.151098)
298
- (2) erubis 0.130000 0.000000 0.130000 ( 0.130713)
299
- (2) fast erubis 0.100000 0.000000 0.100000 ( 0.112199)
300
- (2) slim 0.030000 0.000000 0.030000 ( 0.027752)
301
- (2) haml 0.320000 0.000000 0.320000 ( 0.332581)
302
- (2) haml ugly 0.280000 0.000000 0.280000 ( 0.305250)
303
- (3) erb 0.010000 0.000000 0.010000 ( 0.014402)
304
- (3) erubis 0.010000 0.000000 0.010000 ( 0.015365)
305
- (3) fast erubis 0.010000 0.000000 0.010000 ( 0.012789)
306
- (3) slim 0.010000 0.000000 0.010000 ( 0.015583)
307
- (3) haml 0.120000 0.000000 0.120000 ( 0.120017)
308
- (3) haml ugly 0.100000 0.010000 0.110000 ( 0.117665)
291
+ (1) erb 0.310000 0.000000 0.310000 ( 0.311769)
292
+ (1) erubis 0.250000 0.000000 0.250000 ( 0.252026)
293
+ (1) fast erubis 0.250000 0.000000 0.250000 ( 0.257639)
294
+ (1) slim 3.250000 0.040000 3.290000 ( 3.282734)
295
+ (1) haml 2.230000 0.000000 2.230000 ( 2.237396)
296
+ (1) haml ugly 2.160000 0.000000 2.160000 ( 2.154061)
297
+ (2) erb 0.100000 0.000000 0.100000 ( 0.107232)
298
+ (2) erubis 0.090000 0.000000 0.090000 ( 0.087301)
299
+ (2) fast erubis 0.080000 0.000000 0.080000 ( 0.073382)
300
+ (2) slim 0.020000 0.000000 0.020000 ( 0.017364)
301
+ (2) haml 0.240000 0.010000 0.250000 ( 0.234680)
302
+ (2) haml ugly 0.200000 0.000000 0.200000 ( 0.209600)
303
+ (3) erb 0.010000 0.000000 0.010000 ( 0.010558)
304
+ (3) erubis 0.010000 0.000000 0.010000 ( 0.008676)
305
+ (3) fast erubis 0.010000 0.000000 0.010000 ( 0.009134)
306
+ (3) slim 0.010000 0.000000 0.010000 ( 0.012114)
307
+ (3) haml 0.090000 0.000000 0.090000 ( 0.086450)
308
+ (3) haml ugly 0.070000 0.000000 0.070000 ( 0.078825)
309
+ (4) erb 0.020000 0.000000 0.020000 ( 0.015715)
310
+ (4) erubis 0.010000 0.000000 0.010000 ( 0.014027)
311
+ (4) slim 0.020000 0.000000 0.020000 ( 0.017591)
312
+ (4) haml 0.100000 0.000000 0.100000 ( 0.098249)
313
+ (4) haml ugly 0.090000 0.000000 0.090000 ( 0.089413)
309
314
 
310
315
  1. Uncached benchmark. Template is parsed every time.
311
316
  Activate this benchmark with slow=1.
@@ -319,6 +324,11 @@ There are two helpers you could use to validate your Slim syntax:
319
324
  This is the fastest evaluation strategy because it benchmarks
320
325
  pure execution speed of the generated ruby code.
321
326
 
327
+ 4. Compiled Tilt benchmark. Template is compiled with Tilt, which gives a more
328
+ accurate result of the performance in production mode in frameworks like
329
+ Sinatra, Ramaze and Camping. (Rails still uses its own template
330
+ compilation.)
331
+
322
332
  ## License
323
333
 
324
334
  This project is released under the MIT license.
@@ -335,6 +345,7 @@ This project is released under the MIT license.
335
345
 
336
346
  ## Slim related projects
337
347
 
348
+ * [Vim files](https://github.com/bbommarito/vim-slim)
338
349
  * [Textmate bundle](https://github.com/fredwu/ruby-slim-textmate-bundle)
339
350
  * [Haml2Slim converter](https://github.com/fredwu/haml2slim)
340
351
  * [Rails 3 Generators](https://github.com/leogalmeida/slim-rails)
data/lib/slim/command.rb CHANGED
@@ -40,6 +40,10 @@ module Slim
40
40
  @options[:compile] = true
41
41
  end
42
42
 
43
+ opts.on('-r', '--rails', :NONE, 'Generate rails compatible code (combine with -c)') do
44
+ @options[:rails] = true
45
+ end
46
+
43
47
  opts.on('-S', '--sections', :NONE, 'Logic-less sections mode') do
44
48
  @options[:sections] = true
45
49
  end
@@ -48,6 +52,10 @@ module Slim
48
52
  @options[:pretty] = true
49
53
  end
50
54
 
55
+ opts.on('-d', '--debug', :NONE, 'Debugging output') do
56
+ @options[:debug] = true
57
+ end
58
+
51
59
  opts.on_tail('-h', '--help', 'Show this message') do
52
60
  puts opts
53
61
  exit
@@ -81,10 +89,16 @@ module Slim
81
89
  if @options[:compile]
82
90
  @options[:output].puts(Slim::Engine.new(:file => @options[:file],
83
91
  :pretty => @options[:pretty],
84
- :sections => @options[:sections]).compile(@options[:input].read))
92
+ :sections => @options[:sections],
93
+ :disable_capture => @options[:rails],
94
+ :debug => @options[:debug],
95
+ :generator => @options[:rails] ?
96
+ Temple::Generators::RailsOutputBuffer :
97
+ Temple::Generators::ArrayBuffer).call(@options[:input].read))
85
98
  else
86
99
  @options[:output].puts(Slim::Template.new(@options[:file],
87
100
  :pretty => @options[:pretty],
101
+ :debug => @options[:debug],
88
102
  :sections => @options[:sections]) { @options[:input].read }.render)
89
103
  end
90
104
  end
data/lib/slim/compiler.rb CHANGED
@@ -12,7 +12,7 @@ module Slim
12
12
  def on_slim_control(code, content)
13
13
  [:multi,
14
14
  [:block, code],
15
- compile!(content)]
15
+ compile(content)]
16
16
  end
17
17
 
18
18
  # Handle comment expression `[:slim, :comment, content]`
@@ -20,7 +20,7 @@ module Slim
20
20
  # @param [Array] content Temple expression
21
21
  # @return [Array] Compiled temple expression
22
22
  def on_slim_comment(content)
23
- [:html, :comment, compile!(content)]
23
+ [:html, :comment, compile(content)]
24
24
  end
25
25
 
26
26
  # Handle output expression `[:slim, :output, escape, code, content]`
@@ -31,7 +31,7 @@ module Slim
31
31
  # @return [Array] Compiled temple expression
32
32
  def on_slim_output(escape, code, content)
33
33
  if empty_exp?(content)
34
- [:multi, escape && options[:auto_escape] ? [:escape, :dynamic, code] : [:dynamic, code], content]
34
+ [:multi, [:escape, escape && options[:auto_escape], [:dynamic, code]], content]
35
35
  else
36
36
  on_slim_output_block(escape, code, content)
37
37
  end
@@ -45,7 +45,7 @@ module Slim
45
45
  # @param [Array] content Temple expression
46
46
  # @return [Array] Compiled temple expression
47
47
  def on_slim_output_block(escape, code, content)
48
- tmp = tmp_var('capture')
48
+ tmp = tmp_var(:output)
49
49
 
50
50
  [:multi,
51
51
  # Capture the result of the code in a variable. We can't do
@@ -60,7 +60,7 @@ module Slim
60
60
  # The capturing can be disabled with the option :disable_capture.
61
61
  # Output code in the block writes directly to the output buffer then.
62
62
  # Rails handles this by replacing the output buffer for helpers (with_output_buffer - braindead!).
63
- options[:disable_capture] ? compile!(content) : [:capture, tmp_var('capture'), compile!(content)],
63
+ options[:disable_capture] ? compile(content) : [:capture, tmp_var(:output), compile(content)],
64
64
 
65
65
  # Close the block.
66
66
  [:block, 'end'],
@@ -74,8 +74,11 @@ module Slim
74
74
  # @param [String] type Directive type
75
75
  # @return [Array] Compiled temple expression
76
76
  def on_slim_directive(type, args)
77
- if type == 'doctype'
77
+ case type
78
+ when 'doctype'
78
79
  [:html, :doctype, args]
80
+ else
81
+ raise "Invalid directive #{type}"
79
82
  end
80
83
  end
81
84
 
@@ -86,7 +89,7 @@ module Slim
86
89
  # @param [Array] content Temple expression
87
90
  # @return [Array] Compiled temple expression
88
91
  def on_slim_tag(name, attrs, closed, content)
89
- [:html, :tag, name, compile!(attrs), closed, compile!(content)]
92
+ [:html, :tag, name, compile(attrs), closed, compile(content)]
90
93
  end
91
94
 
92
95
  # Handle tag attributes expression `[:slim, :attrs, *attrs]`
@@ -94,7 +97,7 @@ module Slim
94
97
  # @param [Array] attrs Attributes
95
98
  # @return [Array] Compiled temple expression
96
99
  def on_slim_attrs(*attrs)
97
- [:html, :staticattrs, *attrs.map {|k, v| [k.to_s, compile!(v)] }]
100
+ [:html, :staticattrs, *attrs.map {|k, v| [k.to_s, compile(v)] }]
98
101
  end
99
102
  end
100
103
  end
@@ -4,21 +4,26 @@ module Slim
4
4
  class EmbeddedEngine < Filter
5
5
  @engines = {}
6
6
 
7
- def self.register(name, klass, options = {})
8
- @engines[name.to_s] = klass.new(options)
9
- end
7
+ class << self
8
+ attr_reader :engines
10
9
 
11
- def self.[](name)
12
- engine = @engines[name.to_s]
13
- raise "Invalid embedded engine #{name}" if !engine
14
- engine.dup
10
+ def register(name, klass, *option_filter)
11
+ local_options = Hash === option_filter.last ? option_filter.pop : nil
12
+ @engines[name.to_s] = [klass, option_filter, local_options]
13
+ end
15
14
  end
16
15
 
17
- def on_slim_embedded(name, *body)
18
- engine = EmbeddedEngine[name]
16
+ def new_engine(name)
17
+ name = name.to_s
19
18
  raise "Embedded engine #{name} is disabled" if (options[:enable_engines] && !options[:enable_engines].include?(name)) ||
20
19
  (options[:disable_engines] && options[:disable_engines].include?(name))
21
- engine.on_slim_embedded(name, *body)
20
+ engine, option_filter, local_options = self.class.engines[name] || raise("Embedded engine #{name} not found")
21
+ filtered_options = Hash[*option_filter.select {|k| options.include?(k) }.map {|k| [k, options[k]] }.flatten]
22
+ engine.new(Temple::Utils::ImmutableHash.new(local_options, filtered_options))
23
+ end
24
+
25
+ def on_slim_embedded(name, *body)
26
+ new_engine(name).on_slim_embedded(name, *body)
22
27
  end
23
28
 
24
29
  def collect_text(body)
@@ -29,40 +34,62 @@ module Slim
29
34
  end
30
35
 
31
36
  class TiltEngine < EmbeddedEngine
37
+ def on_slim_embedded(engine, *body)
38
+ text = collect_text(body)
39
+ engine = Tilt[engine] || raise("Tilt engine #{engine} is not available.")
40
+ tilt_render(engine, text)
41
+ end
42
+
43
+ def tilt_render(engine, text)
44
+ # Static template
45
+ [:static, engine.new { text }.render]
46
+ end
47
+ end
48
+
49
+ class SassEngine < TiltEngine
50
+ def tilt_render(engine, text)
51
+ text = engine.new(:style => (options[:pretty] ? :expanded : :compressed)) { text }.render
52
+ text.chomp!
53
+ [:static, options[:pretty] ? "\n#{text}\n" : text]
54
+ end
55
+ end
56
+
57
+ class DynamicTiltEngine < TiltEngine
32
58
  # Code to collect local variables
33
59
  COLLECT_LOCALS = %q{eval('{' + local_variables.select {|v| v[0] != ?_ }.map {|v| ":#{v}=>#{v}" }.join(',') + '}')}
34
60
 
35
- def on_slim_embedded(engine, *body)
36
- text = collect_text(body)
37
- engine = Tilt[engine]
38
- if options[:precompiled]
39
- # Wrap precompiled code in proc, local variables from out the proc are accessible
40
- # WARNING: This is a bit of a hack. Tilt::Engine#precompiled is protected
41
- precompiled = engine.new { text }.send(:precompiled, {}).first
42
- [:dynamic, "proc { #{precompiled} }.call"]
43
- elsif options[:dynamic]
44
- # Fully dynamic evaluation of the template during runtime (Slow and uncached)
45
- [:dynamic, "#{engine.name}.new { #{text.inspect} }.render(self, #{COLLECT_LOCALS})"]
46
- elsif options[:interpolate]
47
- # Static template with interpolated ruby code
48
- [:slim, :text, engine.new { text }.render]
49
- else
50
- # Static template
51
- [:static, engine.new { text }.render]
52
- end
61
+ def tilt_render(engine, text)
62
+ # Fully dynamic evaluation of the template during runtime (Slow and uncached)
63
+ [:dynamic, "#{engine.name}.new { #{text.inspect} }.render(self, #{COLLECT_LOCALS})"]
64
+ end
65
+ end
66
+
67
+ class PrecompiledTiltEngine < TiltEngine
68
+ def tilt_render(engine, text)
69
+ # Wrap precompiled code in proc, local variables from out the proc are accessible
70
+ # WARNING: This is a bit of a hack. Tilt::Engine#precompiled is protected
71
+ precompiled = engine.new { text }.send(:precompiled, {}).first
72
+ [:dynamic, "proc { #{precompiled} }.call"]
73
+ end
74
+ end
75
+
76
+ class InterpolateTiltEngine < TiltEngine
77
+ def tilt_render(engine, text)
78
+ # Static template with interpolated ruby code
79
+ [:slim, :text, engine.new { text }.render]
53
80
  end
54
81
  end
55
82
 
56
83
  class ERBEngine < EmbeddedEngine
57
84
  def on_slim_embedded(engine, *body)
58
85
  text = collect_text(body)
59
- Temple::ERB::Parser.new(:auto_escape => true).compile(text)
86
+ Temple::ERB::Parser.new(:auto_escape => true).call(text)
60
87
  end
61
88
  end
62
89
 
63
90
  class TagEngine < EmbeddedEngine
64
91
  def on_slim_embedded(engine, *body)
65
- content = options[:engine] ? options[:engine].new.on_slim_embedded(engine, *body) : [:multi, *body]
92
+ content = options[:engine] ? options[:engine].new(options).on_slim_embedded(engine, *body) : [:multi, *body]
66
93
  [:slim, :tag, options[:tag], [:slim, :attrs, *options[:attributes].map {|k, v| [k, [:static, v]] }], false, content]
67
94
  end
68
95
  end
@@ -74,32 +101,33 @@ module Slim
74
101
  end
75
102
 
76
103
  # These engines are executed at compile time, embedded ruby is interpolated
77
- register :markdown, TiltEngine, :interpolate => true
78
- register :textile, TiltEngine, :interpolate => true
79
- register :rdoc, TiltEngine, :interpolate => true
104
+ register :markdown, InterpolateTiltEngine
105
+ register :textile, InterpolateTiltEngine
106
+ register :rdoc, InterpolateTiltEngine
107
+ register :creole, InterpolateTiltEngine
80
108
 
81
109
  # These engines are executed at compile time
82
- register :coffee, TagEngine, :tag => 'script', :attributes => { :type => 'text/javascript' }, :engine => TiltEngine
83
- register :sass, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }, :engine => TiltEngine
84
- register :scss, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }, :engine => TiltEngine
85
- register :less, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }, :engine => TiltEngine
110
+ register :coffee, TagEngine, :tag => 'script', :attributes => { :type => 'text/javascript' }, :engine => TiltEngine
111
+ register :less, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }, :engine => TiltEngine
112
+ register :sass, TagEngine, :pretty, :tag => 'style', :attributes => { :type => 'text/css' }, :engine => SassEngine
113
+ register :scss, TagEngine, :pretty, :tag => 'style', :attributes => { :type => 'text/css' }, :engine => SassEngine
86
114
 
87
115
  # These engines are precompiled, code is embedded
88
- register :erb, ERBEngine
89
- register :haml, TiltEngine, :precompiled => true
90
- register :nokogiri, TiltEngine, :precompiled => true
91
- register :builder, TiltEngine, :precompiled => true
116
+ register :erb, ERBEngine
117
+ register :haml, PrecompiledTiltEngine
118
+ register :nokogiri, PrecompiledTiltEngine
119
+ register :builder, PrecompiledTiltEngine
92
120
 
93
121
  # These engines are completely executed at runtime (Usage not recommended, no caching!)
94
- register :liquid, TiltEngine, :dynamic => true
95
- register :radius, TiltEngine, :dynamic => true
96
- register :markaby, TiltEngine, :dynamic => true
122
+ register :liquid, DynamicTiltEngine
123
+ register :radius, DynamicTiltEngine
124
+ register :markaby, DynamicTiltEngine
97
125
 
98
126
  # Embedded javascript/css
99
- register :javascript, TagEngine, :tag => 'script', :attributes => { :type => 'text/javascript' }
100
- register :css, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }
127
+ register :javascript, TagEngine, :tag => 'script', :attributes => { :type => 'text/javascript' }
128
+ register :css, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }
101
129
 
102
130
  # Embedded ruby code
103
- register :ruby, RubyEngine
131
+ register :ruby, RubyEngine
104
132
  end
105
133
  end
@@ -37,7 +37,7 @@ module Slim
37
37
  prev_indent = false
38
38
  end
39
39
 
40
- result << compile!(exp)
40
+ result << compile(exp)
41
41
  end
42
42
 
43
43
  # The last line can be a control code too.
data/lib/slim/engine.rb CHANGED
@@ -14,12 +14,14 @@ module Slim
14
14
  :id_delimiter => nil,
15
15
  :generator => Temple::Generators::ArrayBuffer
16
16
 
17
+ #
17
18
  # Document all supported options with purpose, type etc.
18
19
  #
19
20
  # Type | Name | Default value | Purpose
20
21
  # --------------------------------------------------------------------------------------------------------------------------------------------
21
22
  # String | :file | nil | Name of parsed file, set automatically by Slim::Template
22
23
  # Integer | :tabsize | 4 | Number of whitespaces per tab (used by the parser)
24
+ # String | :encoding | utf-8 | Set encoding of template
23
25
  # String list | :enable_engines | All enabled | List of enabled embedded engines (whitelist)
24
26
  # String list | :disable_engines | None disabled | List of disabled embedded engines (blacklist)
25
27
  # Boolean | :sections | false | Enable sections mode (logic-less)
@@ -33,9 +35,26 @@ module Slim
33
35
  # String | :attr_wrapper | '"' | Character to wrap attributes in html (can be ' or ")
34
36
  # String | :id_delimiter | '_' | Joining character used if multiple html ids are supplied (e.g. #id1#id2)
35
37
  # Boolean | :pretty | false | Pretty html indenting (This is slower!)
36
- # Class | :generator | ArrayBuffer/RailsOutputBuffer | Temple code generator (defaults generates array buffer)
37
- use Slim::Parser, :file, :tabsize
38
- use Slim::EmbeddedEngine, :enable_engines, :disable_engines
38
+ # Class | :generator | ArrayBuffer/RailsOutputBuffer | Temple code generator (default generator generates array buffer)
39
+ #
40
+ # It is also possible to set all options supported by the generator (option :generator). The standard generators
41
+ # support the options :buffer and :capture_generator.
42
+ #
43
+ # Options can be set at multiple positions. Slim/Temple uses a inheritance mechanism to allow
44
+ # subclasses to overwrite options of the superclass. The option priorities are as follows:
45
+ #
46
+ # Custom (Options passed by the user) > Slim::Template > Slim::Engine > Parser/Filter/Generator (e.g Slim::Parser, Slim::Compiler)
47
+ #
48
+ # It is also possible to set options for superclasses like Temple::Engine. But this will affect all temple template engines then.
49
+ #
50
+ # Slim::Engine > Temple::Engine
51
+ # Slim::Compiler > Temple::Filter
52
+ #
53
+ # It is recommended to set the default settings only once in the code and avoid duplication. Only use
54
+ # `set_default_options` when you have to override some default settings.
55
+ #
56
+ use Slim::Parser, :file, :tabsize, :encoding
57
+ use Slim::EmbeddedEngine, :enable_engines, :disable_engines, :pretty
39
58
  use Slim::Interpolation
40
59
  use Slim::Sections, :sections, :dictionary, :dictionary_access
41
60
  use Slim::EndInserter
@@ -47,6 +66,6 @@ module Slim
47
66
  filter :StaticMerger
48
67
  filter :DynamicInliner
49
68
  filter :Debugger, :debug, :debug_prefix => 'Optimized code'
50
- chain << proc {|options| options[:generator].new }
69
+ use(:Generator) {|exp| options[:generator].new(options).call(exp) }
51
70
  end
52
71
  end
data/lib/slim/filter.rb CHANGED
@@ -1,36 +1,33 @@
1
1
  module Slim
2
2
  # Base class for Temple filters used in Slim
3
+ #
4
+ # This base filter passes everything through and allows
5
+ # to override only some methods without affecting the rest
6
+ # of the expression.
7
+ #
3
8
  # @api private
4
9
  class Filter < Temple::Filter
5
10
  # Dispatch on_slim_*
6
11
  temple_dispatch :slim
7
12
 
8
13
  def on_slim_control(code, content)
9
- [:slim, :control, code, compile!(content)]
14
+ [:slim, :control, code, compile(content)]
10
15
  end
11
16
 
12
17
  def on_slim_comment(content)
13
- [:slim, :comment, compile!(content)]
18
+ [:slim, :comment, compile(content)]
14
19
  end
15
20
 
16
21
  def on_slim_output(code, escape, content)
17
- [:slim, :output, code, escape, compile!(content)]
22
+ [:slim, :output, code, escape, compile(content)]
18
23
  end
19
24
 
20
25
  def on_slim_tag(name, attrs, closed, content)
21
- [:slim, :tag, name, compile!(attrs), closed, compile!(content)]
26
+ [:slim, :tag, name, compile(attrs), closed, compile(content)]
22
27
  end
23
28
 
24
29
  def on_slim_attrs(*attrs)
25
- [:slim, :attrs, *attrs.map {|k, v| [k, compile!(v)] }]
26
- end
27
-
28
- # Generate unique temporary variable name
29
- #
30
- # @return [String] Variable name
31
- def tmp_var(prefix)
32
- @tmp_var ||= 0
33
- "_slim#{prefix}#{@tmp_var += 1}"
30
+ [:slim, :attrs, *attrs.map {|k, v| [k, compile(v)] }]
34
31
  end
35
32
  end
36
33
  end
@@ -1,5 +1,7 @@
1
1
  module Slim
2
- # Perform interpolation of #{var_name}
2
+ # Perform interpolation of #{var_name} in the
3
+ # expressions `[:slim, :text, string]`.
4
+ #
3
5
  # @api private
4
6
  class Interpolation < Filter
5
7
  # Handle text expression `[:slim, :text, string]`
data/lib/slim/parser.rb CHANGED
@@ -4,6 +4,9 @@ module Slim
4
4
  class Parser
5
5
  include Temple::Mixins::Options
6
6
 
7
+ set_default_options :tabsize => 4,
8
+ :encoding => 'utf-8'
9
+
7
10
  class SyntaxError < StandardError
8
11
  attr_reader :error, :file, :line, :lineno, :column
9
12
 
@@ -24,8 +27,6 @@ module Slim
24
27
  end
25
28
  end
26
29
 
27
- default_options[:tabsize] = 4
28
-
29
30
  def initialize(options = {})
30
31
  super
31
32
  @tab = ' ' * @options[:tabsize]
@@ -35,7 +36,9 @@ module Slim
35
36
  #
36
37
  # @param [String] str Slim code
37
38
  # @return [Array] Temple expression representing the code
38
- def compile(str)
39
+ def call(str)
40
+ str.force_encoding(options[:encoding]) if options[:encoding] && str.respond_to?(:force_encoding)
41
+
39
42
  lineno = 0
40
43
  result = [:multi]
41
44
 
@@ -245,7 +248,7 @@ module Slim
245
248
  private
246
249
 
247
250
  ATTR_REGEX = /^\s+(\w[:\w-]*)=/
248
- QUOTED_VALUE_REGEX = /^("[^"]+"|'[^']+')/
251
+ QUOTED_VALUE_REGEX = /^("[^"]*"|'[^']*')/
249
252
  ATTR_SHORTHAND = {
250
253
  '#' => 'id',
251
254
  '.' => 'class',
@@ -277,6 +280,8 @@ module Slim
277
280
 
278
281
  # Find any literal class/id attributes
279
282
  while line =~ CLASS_ID_REGEX
283
+ # The class/id attribute is :static instead of :slim :text,
284
+ # because we don't want text interpolation in .class or #id shortcut
280
285
  attributes << [ATTR_SHORTHAND[$1], [:static, $2]]
281
286
  line = $'
282
287
  end
data/lib/slim/rails.rb CHANGED
@@ -1,32 +1,3 @@
1
+ # TODO: I would say we remove when we reach 1.0
1
2
  require 'slim'
2
-
3
- Slim::Engine.default_options[:generator] = Temple::Generators::RailsOutputBuffer
4
- Slim::Engine.default_options[:disable_capture] = true
5
-
6
- module ActionView
7
- module TemplateHandlers
8
- if Rails::VERSION::MAJOR < 3
9
- raise "Slim supports only Rails 3.x and greater, your Rails version is #{Rails::VERSION::STRING}"
10
- end
11
-
12
- if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR < 1
13
- # Slim handler for Rails 3.0
14
- class SlimHandler < TemplateHandler
15
- include Compilable
16
-
17
- def compile(template)
18
- Slim::Engine.new.compile(template.source)
19
- end
20
- end
21
- else
22
- # Slim handler for Rails 3.1 and greater
23
- class SlimHandler
24
- def self.call(template)
25
- Slim::Engine.new.compile(template.source)
26
- end
27
- end
28
- end
29
- end
30
-
31
- Template.register_template_handler :slim, TemplateHandlers::SlimHandler
32
- end
3
+ puts 'Deprecated: Use `require \'slim\'` instead of `require \'slim/rails\'`'
data/lib/slim/sections.rb CHANGED
@@ -14,7 +14,7 @@ module Slim
14
14
  end
15
15
  end
16
16
 
17
- def compile(exp)
17
+ def call(exp)
18
18
  if options[:sections]
19
19
  # Store the dictionary in the _slimdict variable
20
20
  dictionary = options[:dictionary]
@@ -37,17 +37,17 @@ module Slim
37
37
  end
38
38
 
39
39
  def on_slim_inverted_section(name, content)
40
- tmp = tmp_var('section')
40
+ tmp = tmp_var(:section)
41
41
  [:multi,
42
42
  [:block, "#{tmp} = #{access name}"],
43
43
  [:block, "if !#{tmp} || #{tmp}.respond_to?(:empty) && #{tmp}.empty?"],
44
- compile!(content),
44
+ compile(content),
45
45
  [:block, 'end']]
46
46
  end
47
47
 
48
48
  def on_slim_section(name, content)
49
- content = compile!(content)
50
- tmp1, tmp2 = tmp_var('dict'), tmp_var('dict')
49
+ content = compile(content)
50
+ tmp1, tmp2 = tmp_var(:dict), tmp_var(:dict)
51
51
 
52
52
  [:multi,
53
53
  [:block, "if #{tmp1} = #{access name}"],
data/lib/slim/template.rb CHANGED
@@ -1,9 +1,17 @@
1
1
  module Slim
2
2
  # Tilt template implementation for Slim
3
3
  # @api public
4
- class Template < Temple::Template
5
- engine Slim::Engine
6
- end
4
+ Template = Temple::Templates::Tilt(Slim::Engine, :register_as => :slim)
5
+
6
+ if Object.const_defined?(:Rails)
7
+ # Rails template implementation for Slim
8
+ # @api public
9
+ RailsTemplate = Temple::Templates::Rails(Slim::Engine, :register_as => :slim)
7
10
 
8
- Tilt.register 'slim', Template
11
+ # Use rails-specific generator. This is necessary
12
+ # to support block capturing. Disable the internal slim capturing.
13
+ # Rails takes care of the capturing by itself.
14
+ RailsTemplate.set_default_options :generator => Temple::Generators::RailsOutputBuffer,
15
+ :disable_capture => true
16
+ end
9
17
  end
data/lib/slim/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Slim
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.2'
3
3
  end
data/lib/slim.rb CHANGED
@@ -12,4 +12,3 @@ require 'slim/engine'
12
12
  require 'slim/template'
13
13
  require 'slim/version'
14
14
  require 'slim/wrapper'
15
- require 'slim/validator'
data/test/helper.rb CHANGED
@@ -14,7 +14,6 @@ class TestSlim < MiniTest::Unit::TestCase
14
14
 
15
15
  def teardown
16
16
  Slim::Sections.set_default_options(:dictionary_access => :wrapped)
17
- Temple::Filters::EscapeHTML.default_options.delete(:use_html_safe)
18
17
  end
19
18
 
20
19
  def render(source, options = {}, &block)
@@ -1,12 +1,12 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
- require "active_model/railtie"
4
- require "active_record/railtie"
5
- require "action_controller/railtie"
6
- require "action_view/railtie"
7
- require "action_mailer/railtie"
3
+ require 'active_model/railtie'
4
+ require 'active_record/railtie'
5
+ require 'action_controller/railtie'
6
+ require 'action_view/railtie'
7
+ require 'action_mailer/railtie'
8
8
 
9
- require "slim/rails"
9
+ require 'slim'
10
10
 
11
11
  module Dummy
12
12
  class Application < Rails::Application
@@ -0,0 +1,42 @@
1
+ require 'helper'
2
+
3
+ class TestSlimChainManipulation < TestSlim
4
+ def test_replace
5
+ source = %q{
6
+ p Test
7
+ }
8
+ chain = proc do |engine|
9
+ engine.replace(Temple::HTML::Pretty, :ReplacementFilter) do |exp|
10
+ [:dynamic, '1+1']
11
+ end
12
+ end
13
+
14
+ assert_html '2', source, :chain => chain
15
+ end
16
+
17
+ def test_before
18
+ source = %q{
19
+ p Test
20
+ }
21
+ chain = proc do |engine|
22
+ engine.before(Slim::Parser, :WrapInput) do |input|
23
+ "p Header\n#{input}\np Footer"
24
+ end
25
+ end
26
+
27
+ assert_html '<p>Header</p><p>Test</p><p>Footer</p>', source, :chain => chain
28
+ end
29
+
30
+ def test_after
31
+ source = %q{
32
+ p Test
33
+ }
34
+ chain = proc do |engine|
35
+ engine.after(Slim::Parser, :ReplaceParsedExp) do |exp|
36
+ [:slim, :output, false, '1+1', [:multi]]
37
+ end
38
+ end
39
+
40
+ assert_html '2', source, :chain => chain
41
+ end
42
+ end
@@ -1,7 +1,25 @@
1
1
  require 'helper'
2
+ begin
3
+ require('creole/template')
4
+ rescue LoadError
5
+ end
2
6
 
3
7
  class TestSlimEmbeddedEngines < TestSlim
4
- def test_render_with_embedded_template
8
+ def test_render_with_haml
9
+ source = %q{
10
+ p
11
+ - text = 'haml'
12
+ haml:
13
+ %b Hello from #{text.upcase}!
14
+ Second Line!
15
+ - if true
16
+ = true
17
+ }
18
+
19
+ assert_html "<p><b>Hello from HAML!</b>\nSecond Line!\ntrue\n</p>", source
20
+ end
21
+
22
+ def test_render_with_erb
5
23
  source = %q{
6
24
  p
7
25
  - text = 'before erb block'
@@ -14,7 +32,7 @@ p
14
32
  assert_html "<p><b>Hello from BEFORE ERB BLOCK!</b>\nSecond Line!\ntrue</p>", source
15
33
  end
16
34
 
17
- def test_render_with_interpolated_embedded_template
35
+ def test_render_with_markdown
18
36
  source = %q{
19
37
  markdown:
20
38
  #Header
@@ -24,6 +42,15 @@ markdown:
24
42
  assert_html "<h1>Header</h1>\n\n<p>Hello from Markdown!\n\"Second Line!\"</p>\n", source
25
43
  end
26
44
 
45
+ def test_render_with_creole
46
+ source = %q{
47
+ creole:
48
+ = head1
49
+ == head2
50
+ }
51
+ assert_html "<h1>head1</h1><h2>head2</h2>", source
52
+ end
53
+
27
54
  def test_render_with_javascript
28
55
  # Keep the trailing space behind "javascript: "!
29
56
  source = %q{
@@ -59,7 +86,7 @@ scss:
59
86
  $color: #f00;
60
87
  body { color: $color; }
61
88
  }
62
- assert_html "<style type=\"text/css\">body {\n color: red; }\n</style>", source
89
+ assert_html "<style type=\"text/css\">body{color:red}</style>", source
63
90
  end
64
91
 
65
92
  def test_disabled_embedded_engine
@@ -262,6 +262,22 @@ p(id="marvin" class="martian" data-info="Illudium Q-36")= output_number
262
262
  assert_html '<p class="martian" data-info="Illudium Q-36" id="marvin">1337</p>', source
263
263
  end
264
264
 
265
+ def test_empty_attribute
266
+ source = %q{
267
+ p(id="marvin" class="" data-info="Illudium Q-36")= output_number
268
+ }
269
+
270
+ assert_html '<p data-info="Illudium Q-36" id="marvin">1337</p>', source
271
+ end
272
+
273
+ def test_dynamic_empty_attribute
274
+ source = %q{
275
+ p(id="marvin" class=nil data-info="Illudium Q-36")= output_number
276
+ }
277
+
278
+ assert_html '<p data-info="Illudium Q-36" id="marvin">1337</p>', source
279
+ end
280
+
265
281
  def test_closed_tag
266
282
  source = %q{
267
283
  closed/
@@ -0,0 +1,45 @@
1
+ require 'helper'
2
+
3
+ class TestSlimPretty < TestSlim
4
+ def setup
5
+ Slim::Engine.set_default_options :pretty => true
6
+ end
7
+
8
+ def teardown
9
+ Slim::Engine.set_default_options :pretty => false
10
+ end
11
+
12
+ def test_pretty_sass
13
+ source = %q{
14
+ doctype 5
15
+ html
16
+ head
17
+ title Hello World!
18
+ sass:
19
+ body
20
+ background-color: red
21
+ body
22
+ #container
23
+ p Hello!
24
+ }
25
+
26
+ result = %q{<!DOCTYPE html>
27
+ <html>
28
+ <head>
29
+ <title>Hello World!</title>
30
+ <style type="text/css">
31
+ body {
32
+ background-color: red;
33
+ }
34
+ </style>
35
+ </head>
36
+ <body>
37
+ <div id="container">
38
+ <p>Hello!</p>
39
+ </div>
40
+ </body>
41
+ </html>}
42
+
43
+ assert_html result, source
44
+ end
45
+ end
@@ -121,7 +121,7 @@ p
121
121
  1+1
122
122
  }
123
123
 
124
- assert_runtime_error 'Invalid embedded engine embed_unknown', source
124
+ assert_runtime_error 'Embedded engine embed_unknown not found', source
125
125
  end
126
126
 
127
127
  def test_explicit_end
@@ -1,6 +1,13 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestSlimTextInterpolation < TestSlim
4
+ def test_interpolation_in_attribute
5
+ source = %q{
6
+ p id="a#{id_helper}b" = hello_world
7
+ }
8
+
9
+ assert_html '<p id="anoticeb">Hello World from @env</p>', source
10
+ end
4
11
 
5
12
  def test_interpolation_in_text
6
13
  source = %q{
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 1
9
- version: 0.9.1
8
+ - 2
9
+ version: 0.9.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Andrew Stone
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-03-10 00:00:00 -05:00
19
+ date: 2011-03-30 00:00:00 -04:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -29,9 +29,9 @@ dependencies:
29
29
  - !ruby/object:Gem::Version
30
30
  segments:
31
31
  - 0
32
- - 1
33
- - 8
34
- version: 0.1.8
32
+ - 2
33
+ - 0
34
+ version: 0.2.0
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -141,6 +141,19 @@ dependencies:
141
141
  version: "0"
142
142
  type: :development
143
143
  version_requirements: *id009
144
+ - !ruby/object:Gem::Dependency
145
+ name: creole
146
+ prerelease: false
147
+ requirement: &id010 !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ type: :development
156
+ version_requirements: *id010
144
157
  description: Slim is a template language whose goal is reduce the syntax to the essential parts without becoming cryptic.
145
158
  email:
146
159
  - andy@stonean.com
@@ -169,7 +182,6 @@ files:
169
182
  - lib/slim/rails.rb
170
183
  - lib/slim/sections.rb
171
184
  - lib/slim/template.rb
172
- - lib/slim/validator.rb
173
185
  - lib/slim/version.rb
174
186
  - lib/slim/wrapper.rb
175
187
  - test/helper.rb
@@ -213,6 +225,7 @@ files:
213
225
  - test/integration/rails/dummy/script/rails
214
226
  - test/integration/rails/test_helper.rb
215
227
  - test/integration/rails/test_slim_rails.rb
228
+ - test/slim/test_chain_manipulation.rb
216
229
  - test/slim/test_code_blocks.rb
217
230
  - test/slim/test_code_escaping.rb
218
231
  - test/slim/test_code_evaluation.rb
@@ -222,11 +235,11 @@ files:
222
235
  - test/slim/test_html_escaping.rb
223
236
  - test/slim/test_html_structure.rb
224
237
  - test/slim/test_parser_errors.rb
238
+ - test/slim/test_pretty.rb
225
239
  - test/slim/test_ruby_errors.rb
226
240
  - test/slim/test_sections.rb
227
241
  - test/slim/test_slim_template.rb
228
242
  - test/slim/test_text_interpolation.rb
229
- - test/slim/test_validator.rb
230
243
  - test/slim/test_wrapper.rb
231
244
  has_rdoc: true
232
245
  homepage: http://github.com/stonean/slim
@@ -1,16 +0,0 @@
1
- module Slim
2
- module Validator
3
- class << self
4
- def validate!(source)
5
- Slim::Engine.new.compile(source.to_s)
6
- true
7
- rescue Exception => ex
8
- ex
9
- end
10
-
11
- def valid?(source)
12
- validate!(source) === true
13
- end
14
- end
15
- end
16
- end
@@ -1,47 +0,0 @@
1
- require 'helper'
2
-
3
- class TestSlimValidator < TestSlim
4
- def test_valid_true?
5
- source = %q{
6
- p Slim
7
- }
8
- assert_valid? true, source
9
- end
10
-
11
- def test_valid_false?
12
- source = %q{
13
- p
14
- Slim
15
- }
16
- assert_valid? false, source
17
- end
18
-
19
- def test_valid!
20
- source = %q{
21
- p Slim
22
- }
23
- assert_valid! false, source
24
- end
25
-
26
- def test_invalid!
27
- source = %q{
28
- p
29
- Slim
30
- }
31
- assert_invalid! Slim::Parser::SyntaxError, source
32
- end
33
-
34
- private
35
-
36
- def assert_valid?(expected, source)
37
- assert_equal expected, Slim::Validator.valid?(source)
38
- end
39
-
40
- def assert_valid!(expected, source)
41
- assert_equal true, Slim::Validator.validate!(source)
42
- end
43
-
44
- def assert_invalid!(expected, source)
45
- assert_equal expected, Slim::Validator.validate!(source).class
46
- end
47
- end