slim 0.9.1 → 0.9.2
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/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
|