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 +29 -18
- data/lib/slim/command.rb +15 -1
- data/lib/slim/compiler.rb +11 -8
- data/lib/slim/embedded_engine.rb +75 -47
- data/lib/slim/end_inserter.rb +1 -1
- data/lib/slim/engine.rb +23 -4
- data/lib/slim/filter.rb +10 -13
- data/lib/slim/interpolation.rb +3 -1
- data/lib/slim/parser.rb +9 -4
- data/lib/slim/rails.rb +2 -31
- data/lib/slim/sections.rb +5 -5
- data/lib/slim/template.rb +12 -4
- data/lib/slim/version.rb +1 -1
- data/lib/slim.rb +0 -1
- data/test/helper.rb +0 -1
- data/test/integration/rails/dummy/config/application.rb +6 -6
- data/test/slim/test_chain_manipulation.rb +42 -0
- data/test/slim/test_embedded_engines.rb +30 -3
- data/test/slim/test_html_structure.rb +16 -0
- data/test/slim/test_pretty.rb +45 -0
- data/test/slim/test_ruby_errors.rb +1 -1
- data/test/slim/test_text_interpolation.rb +7 -0
- metadata +21 -8
- data/lib/slim/validator.rb +0 -16
- data/test/slim/test_validator.rb +0 -47
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.
|
292
|
-
(1) erubis 0.
|
293
|
-
(1) fast erubis 0.
|
294
|
-
(1) slim 3.
|
295
|
-
(1) haml 2.
|
296
|
-
(1) haml ugly 2.
|
297
|
-
(2) erb 0.
|
298
|
-
(2) erubis 0.
|
299
|
-
(2) fast erubis 0.
|
300
|
-
(2) slim 0.
|
301
|
-
(2) haml 0.
|
302
|
-
(2) haml ugly 0.
|
303
|
-
(3) erb 0.010000 0.000000 0.010000 ( 0.
|
304
|
-
(3) erubis 0.010000 0.000000 0.010000 ( 0.
|
305
|
-
(3) fast erubis 0.010000 0.000000 0.010000 ( 0.
|
306
|
-
(3) slim 0.010000 0.000000 0.010000 ( 0.
|
307
|
-
(3) haml 0.
|
308
|
-
(3) haml ugly 0.
|
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]
|
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
|
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
|
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]
|
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(
|
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
|
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
|
-
|
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
|
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
|
100
|
+
[:html, :staticattrs, *attrs.map {|k, v| [k.to_s, compile(v)] }]
|
98
101
|
end
|
99
102
|
end
|
100
103
|
end
|
data/lib/slim/embedded_engine.rb
CHANGED
@@ -4,21 +4,26 @@ module Slim
|
|
4
4
|
class EmbeddedEngine < Filter
|
5
5
|
@engines = {}
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
7
|
+
class << self
|
8
|
+
attr_reader :engines
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
18
|
-
|
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.
|
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
|
36
|
-
|
37
|
-
engine
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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).
|
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,
|
78
|
-
register :textile,
|
79
|
-
register :rdoc,
|
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,
|
83
|
-
register :
|
84
|
-
register :
|
85
|
-
register :
|
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,
|
89
|
-
register :haml,
|
90
|
-
register :nokogiri,
|
91
|
-
register :builder,
|
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,
|
95
|
-
register :radius,
|
96
|
-
register :markaby,
|
122
|
+
register :liquid, DynamicTiltEngine
|
123
|
+
register :radius, DynamicTiltEngine
|
124
|
+
register :markaby, DynamicTiltEngine
|
97
125
|
|
98
126
|
# Embedded javascript/css
|
99
|
-
register :javascript, TagEngine,
|
100
|
-
register :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,
|
131
|
+
register :ruby, RubyEngine
|
104
132
|
end
|
105
133
|
end
|
data/lib/slim/end_inserter.rb
CHANGED
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 (
|
37
|
-
|
38
|
-
|
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
|
-
|
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
|
14
|
+
[:slim, :control, code, compile(content)]
|
10
15
|
end
|
11
16
|
|
12
17
|
def on_slim_comment(content)
|
13
|
-
[:slim, :comment, compile
|
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
|
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
|
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
|
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
|
data/lib/slim/interpolation.rb
CHANGED
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
|
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
|
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(
|
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
|
44
|
+
compile(content),
|
45
45
|
[:block, 'end']]
|
46
46
|
end
|
47
47
|
|
48
48
|
def on_slim_section(name, content)
|
49
|
-
content = compile
|
50
|
-
tmp1, tmp2 = tmp_var(
|
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
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
data/lib/slim.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require File.expand_path('../boot', __FILE__)
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
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
|
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
|
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
|
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
|
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
|
@@ -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
|
-
-
|
9
|
-
version: 0.9.
|
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-
|
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
|
-
-
|
33
|
-
-
|
34
|
-
version: 0.
|
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
|
data/lib/slim/validator.rb
DELETED
data/test/slim/test_validator.rb
DELETED
@@ -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
|