slim 2.0.2 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +16 -13
- data/CHANGES +9 -0
- data/Gemfile +8 -2
- data/README.jp.md +968 -0
- data/README.md +25 -4
- data/lib/slim/code_attributes.rb +1 -1
- data/lib/slim/command.rb +13 -13
- data/lib/slim/controls.rb +5 -3
- data/lib/slim/end_inserter.rb +7 -6
- data/lib/slim/engine.rb +2 -1
- data/lib/slim/parser.rb +4 -3
- data/lib/slim/splat/builder.rb +13 -15
- data/lib/slim/splat/filter.rb +1 -1
- data/lib/slim/version.rb +1 -1
- data/test/core/test_code_blocks.rb +53 -0
- data/test/core/test_embedded_engines.rb +1 -0
- data/test/literate/TESTS.md +64 -2
- data/test/rails/test/test_slim.rb +4 -2
- metadata +15 -14
data/README.md
CHANGED
@@ -555,7 +555,7 @@ This is the same as
|
|
555
555
|
div class="content"
|
556
556
|
= show_content
|
557
557
|
|
558
|
-
## Helpers and
|
558
|
+
## Helpers, capturing and includes
|
559
559
|
|
560
560
|
If you use Slim you might want to extend your template with some helpers. Assume that you have the following helper
|
561
561
|
|
@@ -574,7 +574,7 @@ module Helpers
|
|
574
574
|
end
|
575
575
|
~~~
|
576
576
|
|
577
|
-
which can be used in Slim as follows
|
577
|
+
which is included in the scope that executes the Slim template code. The helper can then be used in the Slim template as follows
|
578
578
|
|
579
579
|
p
|
580
580
|
= headline do
|
@@ -589,6 +589,25 @@ sugar you can omit the `do` keyword and write only
|
|
589
589
|
' Hello
|
590
590
|
= user.name
|
591
591
|
|
592
|
+
It has been requested many times to support includes of subtemplates in Slim. Up to now this has not been implemented as a core feature
|
593
|
+
but you can easily get it by writing your own helper. The includes will be executed at runtime.
|
594
|
+
|
595
|
+
~~~ruby
|
596
|
+
module Helpers
|
597
|
+
def include_slim(name, options = {}, &block)
|
598
|
+
Slim::Template.new("#{name}.slim", options).render(self, &block)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
~~~
|
602
|
+
|
603
|
+
This helper can then be used as follows
|
604
|
+
|
605
|
+
nav= include_slim 'menu'
|
606
|
+
section= include_slim 'content'
|
607
|
+
|
608
|
+
However this helper doesn't do any caching. You should therefore implement a more intelligent version of the helper which
|
609
|
+
fits your purposes. You should also be aware that most frameworks already bring their own include helper, e.g. Rails has `render`.
|
610
|
+
|
592
611
|
## Text interpolation
|
593
612
|
|
594
613
|
Use standard Ruby interpolation. The text will be html escaped by default.
|
@@ -754,7 +773,8 @@ Slim uses [Tilt](https://github.com/rtomayko/tilt) to compile the generated code
|
|
754
773
|
Slim::Template.new('template.slim', optional_option_hash).render(scope)
|
755
774
|
Slim::Template.new(optional_option_hash) { source }.render(scope)
|
756
775
|
|
757
|
-
The optional option hash can have to options which were documented in the section above.
|
776
|
+
The optional option hash can have to options which were documented in the section above. The scope is the object in which the template
|
777
|
+
code is executed.
|
758
778
|
|
759
779
|
### Sinatra
|
760
780
|
|
@@ -805,7 +825,7 @@ Usage: slimrb [options]
|
|
805
825
|
-v, --version Print version
|
806
826
|
</pre>
|
807
827
|
|
808
|
-
Start 'slimrb', type your code and press Ctrl-d to send EOF. Example usage:
|
828
|
+
Start 'slimrb', type your code and press Ctrl-d to send EOF. In Windows Command Prompt press Ctrl-z, Enter to send EOF. Example usage:
|
809
829
|
|
810
830
|
<pre>
|
811
831
|
$ slimrb
|
@@ -930,6 +950,7 @@ Syntax highlighting:
|
|
930
950
|
* [Textmate / Sublime Text](https://github.com/slim-template/ruby-slim.tmbundle)
|
931
951
|
* [Espresso text editor](https://github.com/slim-template/Slim-Sugar)
|
932
952
|
* [Coda](https://github.com/slim-template/Coda-2-Slim.mode)
|
953
|
+
* [Atom](https://github.com/slim-template/language-slim)
|
933
954
|
|
934
955
|
Template Converters (HAML, ERB, ...):
|
935
956
|
|
data/lib/slim/code_attributes.rb
CHANGED
data/lib/slim/command.rb
CHANGED
@@ -17,13 +17,6 @@ module Slim
|
|
17
17
|
@opts = OptionParser.new(&method(:set_opts))
|
18
18
|
@opts.parse!(@args)
|
19
19
|
process
|
20
|
-
exit 0
|
21
|
-
rescue Exception => ex
|
22
|
-
raise ex if @options[:trace] || SystemExit === ex
|
23
|
-
$stderr.print "#{ex.class}: " if ex.class != RuntimeError
|
24
|
-
$stderr.puts ex.message
|
25
|
-
$stderr.puts ' Use --trace for backtrace.'
|
26
|
-
exit 1
|
27
20
|
end
|
28
21
|
|
29
22
|
private
|
@@ -93,11 +86,6 @@ module Slim
|
|
93
86
|
end
|
94
87
|
end
|
95
88
|
|
96
|
-
unless @options[:output]
|
97
|
-
file = args.shift
|
98
|
-
@options[:output] = file ? File.open(file, 'w') : $stdout
|
99
|
-
end
|
100
|
-
|
101
89
|
result =
|
102
90
|
if @options[:erb]
|
103
91
|
require 'slim/erb_converter'
|
@@ -108,7 +96,19 @@ module Slim
|
|
108
96
|
Template.new(@options[:file]) { @options[:input].read }.render
|
109
97
|
end
|
110
98
|
|
111
|
-
|
99
|
+
rescue Exception => ex
|
100
|
+
raise ex if @options[:trace] || SystemExit === ex
|
101
|
+
$stderr.print "#{ex.class}: " if ex.class != RuntimeError
|
102
|
+
$stderr.puts ex.message
|
103
|
+
$stderr.puts ' Use --trace for backtrace.'
|
104
|
+
exit 1
|
105
|
+
else
|
106
|
+
unless @options[:output]
|
107
|
+
file = args.shift
|
108
|
+
@options[:output] = file ? File.open(file, 'w') : $stdout
|
109
|
+
end
|
110
|
+
@options[:output].puts(result)
|
111
|
+
exit 0
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
data/lib/slim/controls.rb
CHANGED
@@ -3,6 +3,8 @@ module Slim
|
|
3
3
|
class Controls < Filter
|
4
4
|
define_options :disable_capture
|
5
5
|
|
6
|
+
IF_RE = /\A(if|unless)\b|do\s*(\|[^\|]*\|)?\s*$/
|
7
|
+
|
6
8
|
# Handle control expression `[:slim, :control, code, content]`
|
7
9
|
#
|
8
10
|
# @param [String] code Ruby code
|
@@ -21,9 +23,7 @@ module Slim
|
|
21
23
|
# @param [Array] content Temple expression
|
22
24
|
# @return [Array] Compiled temple expression
|
23
25
|
def on_slim_output(escape, code, content)
|
24
|
-
if
|
25
|
-
[:multi, [:escape, escape, [:dynamic, code]], content]
|
26
|
-
else
|
26
|
+
if code =~ IF_RE
|
27
27
|
tmp = unique_name
|
28
28
|
|
29
29
|
[:multi,
|
@@ -43,6 +43,8 @@ module Slim
|
|
43
43
|
|
44
44
|
# Output the content.
|
45
45
|
[:escape, escape, [:dynamic, tmp]]]
|
46
|
+
else
|
47
|
+
[:multi, [:escape, escape, [:dynamic, code]], content]
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
data/lib/slim/end_inserter.rb
CHANGED
@@ -10,8 +10,9 @@ module Slim
|
|
10
10
|
#
|
11
11
|
# @api private
|
12
12
|
class EndInserter < Filter
|
13
|
-
|
14
|
-
|
13
|
+
IF_RE = /\A(if|unless|else|elsif|when|rescue|ensure)\b|do\s*(\|[^\|]*\|)?\s*$/
|
14
|
+
ELSE_RE = /\A(else|elsif|when|rescue|ensure)\b/
|
15
|
+
END_RE = /\Aend\b/
|
15
16
|
|
16
17
|
# Handle multi expression `[:multi, *exps]`
|
17
18
|
#
|
@@ -24,14 +25,14 @@ module Slim
|
|
24
25
|
|
25
26
|
exps.each do |exp|
|
26
27
|
if control?(exp)
|
27
|
-
raise(Temple::FilterError, 'Explicit end statements are forbidden') if exp[2] =~
|
28
|
+
raise(Temple::FilterError, 'Explicit end statements are forbidden') if exp[2] =~ END_RE
|
28
29
|
|
29
30
|
# Two control code in a row. If this one is *not*
|
30
31
|
# an else block, we should close the previous one.
|
31
|
-
append_end(result) if prev_indent && exp[2] !~
|
32
|
+
append_end(result) if prev_indent && exp[2] !~ ELSE_RE
|
32
33
|
|
33
|
-
# Indent if the control code
|
34
|
-
prev_indent =
|
34
|
+
# Indent if the control code starts a block.
|
35
|
+
prev_indent = exp[2] =~ IF_RE
|
35
36
|
elsif exp[0] != :newline && prev_indent
|
36
37
|
# This is *not* a control code, so we should close the previous one.
|
37
38
|
# Ignores newlines because they will be inserted after each line.
|
data/lib/slim/engine.rb
CHANGED
@@ -7,6 +7,7 @@ module Slim
|
|
7
7
|
# `define_options` when you have to override some default settings.
|
8
8
|
define_options :pretty => false,
|
9
9
|
:sort_attrs => true,
|
10
|
+
:format => :xhtml,
|
10
11
|
:attr_quote => '"',
|
11
12
|
:merge_attrs => {'class' => ' '},
|
12
13
|
:generator => Temple::Generators::ArrayBuffer,
|
@@ -17,7 +18,7 @@ module Slim
|
|
17
18
|
use Slim::Parser, :file, :tabsize, :shortcut, :default_tag, :attr_delims
|
18
19
|
use Slim::Embedded, :enable_engines, :disable_engines, :pretty
|
19
20
|
use Slim::Interpolation
|
20
|
-
use Slim::Splat::Filter, :merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs
|
21
|
+
use Slim::Splat::Filter, :merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs, :format
|
21
22
|
use Slim::DoInserter
|
22
23
|
use Slim::EndInserter
|
23
24
|
use Slim::Controls, :disable_capture
|
data/lib/slim/parser.rb
CHANGED
@@ -58,7 +58,7 @@ module Slim
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
keys = Regexp.union @attr_shortcut.keys.sort_by {|k| -k.size }
|
61
|
-
@attr_shortcut_re = /\A(#{keys}+)(
|
61
|
+
@attr_shortcut_re = /\A(#{keys}+)((?:#{WORD_RE}|-)*)/
|
62
62
|
keys = Regexp.union @tag_shortcut.keys.sort_by {|k| -k.size }
|
63
63
|
@tag_re = /\A(?:#{keys}|\*(?=[^\s]+)|(#{WORD_RE}(?:#{WORD_RE}|:|-)*#{WORD_RE}|#{WORD_RE}+))/
|
64
64
|
keys = Regexp.escape options[:attr_delims].keys.join
|
@@ -338,8 +338,9 @@ module Slim
|
|
338
338
|
# Handle output code
|
339
339
|
@line = $'
|
340
340
|
trailing_ws2 = $2.include?('\'') || $2.include?('>')
|
341
|
+
leading_ws2 = $2.include?('<')
|
341
342
|
block = [:multi]
|
342
|
-
@stacks.last
|
343
|
+
@stacks.last.insert(-2, [:static, ' ']) if !leading_ws && $2.include?('<')
|
343
344
|
tag << [:slim, :output, $1 != '=', parse_broken_line, block]
|
344
345
|
@stacks.last << [:static, ' '] if !trailing_ws && trailing_ws2
|
345
346
|
@stacks << block
|
@@ -397,7 +398,7 @@ module Slim
|
|
397
398
|
when boolean_attr_re
|
398
399
|
# Boolean attribute
|
399
400
|
@line = $'
|
400
|
-
attributes << [:html, :attr, $1, [:
|
401
|
+
attributes << [:html, :attr, $1, [:multi]]
|
401
402
|
when end_re
|
402
403
|
# Find ending delimiter
|
403
404
|
@line = $'
|
data/lib/slim/splat/builder.rb
CHANGED
@@ -13,18 +13,8 @@ module Slim
|
|
13
13
|
attr(name, escape ? Temple::Utils.escape_html(value) : value) unless value.empty?
|
14
14
|
elsif @options[:hyphen_attrs].include?(name) && Hash === value
|
15
15
|
hyphen_attr(name, escape, value)
|
16
|
-
|
17
|
-
|
18
|
-
when false, nil
|
19
|
-
# Boolean false attribute
|
20
|
-
return
|
21
|
-
when true
|
22
|
-
# Boolean true attribute
|
23
|
-
value = ''
|
24
|
-
else
|
25
|
-
value = value.to_s
|
26
|
-
end
|
27
|
-
attr(name, escape ? Temple::Utils.escape_html(value) : value)
|
16
|
+
elsif value != false && value != nil
|
17
|
+
attr(name, value != true && escape ? Temple::Utils.escape_html(value) : value)
|
28
18
|
end
|
29
19
|
end
|
30
20
|
|
@@ -37,7 +27,7 @@ module Slim
|
|
37
27
|
def attr(name, value)
|
38
28
|
if @attrs[name]
|
39
29
|
if delim = @options[:merge_attrs][name]
|
40
|
-
@attrs[name] << delim << value
|
30
|
+
@attrs[name] << delim << value.to_s
|
41
31
|
else
|
42
32
|
raise("Multiple #{name} attributes specified")
|
43
33
|
end
|
@@ -59,7 +49,15 @@ module Slim
|
|
59
49
|
def build_attrs
|
60
50
|
attrs = @options[:sort_attrs] ? @attrs.sort_by(&:first) : @attrs
|
61
51
|
attrs.map do |k, v|
|
62
|
-
|
52
|
+
if v == true
|
53
|
+
if @options[:format] == :xhtml
|
54
|
+
" #{k}=#{@options[:attr_quote]}#{@options[:attr_quote]}"
|
55
|
+
else
|
56
|
+
" #{k}"
|
57
|
+
end
|
58
|
+
else
|
59
|
+
" #{k}=#{@options[:attr_quote]}#{v}#{@options[:attr_quote]}"
|
60
|
+
end
|
63
61
|
end.join
|
64
62
|
end
|
65
63
|
|
@@ -71,7 +69,7 @@ module Slim
|
|
71
69
|
hyphen_attr("#{name}-#{n.to_s.gsub('_', '-')}", escape, v)
|
72
70
|
end
|
73
71
|
else
|
74
|
-
attr(name, escape ? Temple::Utils.escape_html(value) : value
|
72
|
+
attr(name, value != true && escape ? Temple::Utils.escape_html(value) : value)
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
data/lib/slim/splat/filter.rb
CHANGED
@@ -2,7 +2,7 @@ module Slim
|
|
2
2
|
module Splat
|
3
3
|
# @api private
|
4
4
|
class Filter < ::Slim::Filter
|
5
|
-
OPTIONS = [:merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs]
|
5
|
+
OPTIONS = [:merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs, :format]
|
6
6
|
define_options OPTIONS
|
7
7
|
default_options[:hyphen_attrs] = %w(data aria)
|
8
8
|
|
data/lib/slim/version.rb
CHANGED
@@ -116,4 +116,57 @@ p
|
|
116
116
|
|
117
117
|
assert_html 'Hello Ruby! Hello from within a block! Hello Ruby!', source
|
118
118
|
end
|
119
|
+
|
120
|
+
def test_if_without_content
|
121
|
+
source = %q{
|
122
|
+
- if true
|
123
|
+
}
|
124
|
+
assert_html '', source
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_unless_without_content
|
128
|
+
source = %q{
|
129
|
+
- unless true
|
130
|
+
}
|
131
|
+
assert_html '', source
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_if_with_comment
|
135
|
+
source = %q{
|
136
|
+
- if true
|
137
|
+
/ comment
|
138
|
+
}
|
139
|
+
assert_html '', source
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_control_do_with_comment
|
143
|
+
source = %q{
|
144
|
+
- hello_world "Hello"
|
145
|
+
/ comment
|
146
|
+
}
|
147
|
+
assert_html '', source
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_output_do_with_comment
|
151
|
+
source = %q{
|
152
|
+
= hello_world "Hello"
|
153
|
+
/ comment
|
154
|
+
}
|
155
|
+
assert_html 'Hello', source
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_output_if_without_content
|
159
|
+
source = %q{
|
160
|
+
= if true
|
161
|
+
}
|
162
|
+
assert_html '', source
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_output_if_with_comment
|
166
|
+
source = %q{
|
167
|
+
= if true
|
168
|
+
/ comment
|
169
|
+
}
|
170
|
+
assert_html '', source
|
171
|
+
end
|
119
172
|
end
|
data/test/literate/TESTS.md
CHANGED
@@ -410,6 +410,16 @@ renders as
|
|
410
410
|
49
|
411
411
|
~~~
|
412
412
|
|
413
|
+
~~~ slim
|
414
|
+
=< 7*7
|
415
|
+
~~~
|
416
|
+
|
417
|
+
renders as
|
418
|
+
|
419
|
+
~~~ html
|
420
|
+
49
|
421
|
+
~~~
|
422
|
+
|
413
423
|
The legacy syntax `='` is also supported.
|
414
424
|
|
415
425
|
~~~ slim
|
@@ -705,13 +715,14 @@ You can force a trailing whitespace behind a tag by adding `>`. The legacy synta
|
|
705
715
|
a#closed> class="test" /
|
706
716
|
a#closed> class="test"/
|
707
717
|
a> href='url1' Link1
|
718
|
+
a< href='url1' Link1
|
708
719
|
a' href='url2' Link2
|
709
720
|
~~~
|
710
721
|
|
711
722
|
renders as
|
712
723
|
|
713
724
|
~~~ html
|
714
|
-
<a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a>
|
725
|
+
<a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a> <a href="url1">Link1</a><a href="url2">Link2</a>
|
715
726
|
~~~
|
716
727
|
|
717
728
|
If you combine > and =' only one trailing whitespace is added.
|
@@ -721,12 +732,15 @@ a> =' 'Text1'
|
|
721
732
|
a =' 'Text2'
|
722
733
|
a> = 'Text3'
|
723
734
|
a>= 'Text4'
|
735
|
+
a=> 'Text5'
|
736
|
+
a<= 'Text6'
|
737
|
+
a=< 'Text7'
|
724
738
|
~~~
|
725
739
|
|
726
740
|
renders as
|
727
741
|
|
728
742
|
~~~ html
|
729
|
-
<a>Text1</a> <a>Text2</a> <a>Text3</a> <a>Text4</a>
|
743
|
+
<a>Text1</a> <a>Text2</a> <a>Text3</a> <a>Text4</a> <a>Text5</a> <a>Text6</a> <a>Text7</a>
|
730
744
|
~~~
|
731
745
|
|
732
746
|
You can force a leading whitespace before a tag by adding `<`.
|
@@ -1008,6 +1022,28 @@ renders as
|
|
1008
1022
|
<input type="text" /><input type="text" /><input type="text" /><input type="text" /><input type="text" />
|
1009
1023
|
~~~
|
1010
1024
|
|
1025
|
+
If html5 is activated the attributes are written as standalone.
|
1026
|
+
|
1027
|
+
~~~ options
|
1028
|
+
:format => :html
|
1029
|
+
~~~
|
1030
|
+
|
1031
|
+
~~~ slim
|
1032
|
+
- true_value1 = ""
|
1033
|
+
- true_value2 = true
|
1034
|
+
input type="text" disabled=true_value1
|
1035
|
+
input type="text" disabled=true_value2
|
1036
|
+
input type="text" disabled="disabled"
|
1037
|
+
input type="text" disabled=true
|
1038
|
+
input(type="text" disabled)
|
1039
|
+
~~~
|
1040
|
+
|
1041
|
+
renders as
|
1042
|
+
|
1043
|
+
~~~ html
|
1044
|
+
<input disabled="" type="text"><input disabled type="text"><input disabled="disabled" type="text"><input disabled type="text"><input disabled type="text">
|
1045
|
+
~~~
|
1046
|
+
|
1011
1047
|
#### Attribute merging
|
1012
1048
|
|
1013
1049
|
You can configure attributes to be merged if multiple are given (See option `:merge_attrs`). In the default configuration
|
@@ -1160,6 +1196,32 @@ renders to
|
|
1160
1196
|
|
1161
1197
|
#### ID shortcut and class shortcut `.`
|
1162
1198
|
|
1199
|
+
ID and class shortcuts can contain dashes.
|
1200
|
+
|
1201
|
+
~~~ slim
|
1202
|
+
.-test text
|
1203
|
+
#test- text
|
1204
|
+
.--a#b- text
|
1205
|
+
.a--test-123#--b text
|
1206
|
+
~~~
|
1207
|
+
|
1208
|
+
renders as
|
1209
|
+
|
1210
|
+
~~~ html
|
1211
|
+
<div class="-test">
|
1212
|
+
text
|
1213
|
+
</div>
|
1214
|
+
<div id="test-">
|
1215
|
+
text
|
1216
|
+
</div>
|
1217
|
+
<div class="--a" id="b-">
|
1218
|
+
text
|
1219
|
+
</div>
|
1220
|
+
<div class="a--test-123" id="--b">
|
1221
|
+
text
|
1222
|
+
</div>
|
1223
|
+
~~~
|
1224
|
+
|
1163
1225
|
## Text interpolation
|
1164
1226
|
|
1165
1227
|
Use standard Ruby interpolation. The text will be html escaped by default.
|