slim 1.3.2 → 1.3.3
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/.yardopts +3 -2
- data/CHANGES +12 -0
- data/README.md +56 -10
- data/Rakefile +7 -1
- data/lib/slim.rb +1 -1
- data/lib/slim/code_attributes.rb +67 -0
- data/lib/slim/engine.rb +2 -1
- data/lib/slim/parser.rb +27 -9
- data/lib/slim/splat_attributes.rb +21 -20
- data/lib/slim/version.rb +1 -1
- data/slim.gemspec +1 -3
- data/test/core/test_encoding.rb +6 -0
- data/test/core/test_html_attributes.rb +21 -5
- data/test/core/test_html_structure.rb +0 -16
- data/test/core/test_pretty.rb +2 -2
- data/test/literate/TESTS.md +830 -0
- data/test/literate/helper.rb +15 -0
- data/test/literate/run.rb +96 -0
- metadata +66 -27
- data/lib/slim/boolean_attributes.rb +0 -67
data/.yardopts
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
--
|
2
|
-
--
|
1
|
+
--markup-provider redcarpet
|
2
|
+
--markup markdown
|
3
|
+
- README.md CHANGES LICENSE test/literate/TESTS.md
|
data/CHANGES
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
1.3.3
|
2
|
+
|
3
|
+
* Attribute handling made consistent:
|
4
|
+
- Splat attributes, static and dynamic attributes are now all handled the same
|
5
|
+
- Merged attributes are removed if empty (in the default configuration this is only "class")
|
6
|
+
- Dynamic attributes which are not merged are checked for false or nil and removed if this is the case
|
7
|
+
- Dynamic attributes which are not merged are checked for true and generated as attribute-name="attribute-name"
|
8
|
+
* Rename class BooleanAttributes to CodeAttributes
|
9
|
+
* Add literate test suite (still incomplete), run with `rake test:literate`
|
10
|
+
* Remove UTF BOM when parsing Slim code
|
11
|
+
* Fixed issue #303
|
12
|
+
|
1
13
|
1.3.2
|
2
14
|
|
3
15
|
* Fix boolean attributes #299
|
data/README.md
CHANGED
@@ -119,9 +119,9 @@ You can also embed html in the text line
|
|
119
119
|
- articles.each do |a|
|
120
120
|
| <tr><td>#{a.name}</td><td>#{a.description}</td></tr>
|
121
121
|
|
122
|
-
### Text with trailing space `'`
|
122
|
+
### Text with trailing white space `'`
|
123
123
|
|
124
|
-
The single quote tells Slim to copy the line (similar to `|`), but makes sure that a single trailing space is appended.
|
124
|
+
The single quote tells Slim to copy the line (similar to `|`), but makes sure that a single trailing white space is appended.
|
125
125
|
|
126
126
|
### Inline html `<` (HTML style)
|
127
127
|
|
@@ -148,7 +148,7 @@ If your ruby code needs to use multiple lines, append a backslash `\` at the end
|
|
148
148
|
- if articles.empty?
|
149
149
|
| No inventory
|
150
150
|
|
151
|
-
###
|
151
|
+
### Output `=`
|
152
152
|
|
153
153
|
The equal sign tells Slim it's a Ruby call that produces output to add to the buffer. If your ruby code needs to use multiple lines, append a backslash `\` at the end of the lines, for example:
|
154
154
|
|
@@ -158,7 +158,7 @@ The equal sign tells Slim it's a Ruby call that produces output to add to the bu
|
|
158
158
|
|
159
159
|
### Output with trailing white space `='`
|
160
160
|
|
161
|
-
Same as the single equal sign (`=`), except that it adds a trailing
|
161
|
+
Same as the single equal sign (`=`), except that it adds a trailing white space.
|
162
162
|
|
163
163
|
### Output without HTML escaping `==`
|
164
164
|
|
@@ -166,7 +166,7 @@ Same as the single equal sign (`=`), but does not go through the `escape_html` m
|
|
166
166
|
|
167
167
|
### Output without HTML escaping and trailing ws `=='`
|
168
168
|
|
169
|
-
Same as the double equal sign (`==`), except that it adds a trailing
|
169
|
+
Same as the double equal sign (`==`), except that it adds a trailing white space.
|
170
170
|
|
171
171
|
### Code comment `/`
|
172
172
|
|
@@ -321,7 +321,6 @@ you can use the characters `{...}`, `(...)`, `[...]` to wrap the attributes.
|
|
321
321
|
h1(id="logo") = page_logo
|
322
322
|
h2[id="tagline" class="small tagline"] = page_tagline
|
323
323
|
|
324
|
-
|
325
324
|
If you wrap the attributes, you can spread them across multiple lines:
|
326
325
|
|
327
326
|
h2[id="tagline"
|
@@ -337,7 +336,7 @@ You can use text interpolation in the quoted attributes:
|
|
337
336
|
|
338
337
|
a href="http://#{url}" Goto the #{url}
|
339
338
|
|
340
|
-
The attribute value will be escaped
|
339
|
+
The attribute value will be escaped if the option `:escape_quoted_attrs` is set. Use == if you want to disable escaping in the attribute.
|
341
340
|
|
342
341
|
a href=="&"
|
343
342
|
|
@@ -370,17 +369,44 @@ as booleans. If you use the attribut wrapper you can omit the attribute assigmen
|
|
370
369
|
input type="text" disabled=false
|
371
370
|
input type="text" disabled=nil
|
372
371
|
|
372
|
+
#### Attribute merging
|
373
|
+
|
374
|
+
You can configure attributes to be merged if multiple are given (See option `:attr_delimiter`). In the default configuration
|
375
|
+
this is done for class attributes with the white space as delimiter.
|
376
|
+
|
377
|
+
a.menu class="highlight" href="http://slim-lang.com/" Slim-lang.com
|
378
|
+
|
379
|
+
This renders as
|
380
|
+
|
381
|
+
<a class="menu highlight" href="http://slim-lang.com/">Slim-lang.com</a>
|
382
|
+
|
383
|
+
You can also use an `Array` as attribute value and the array elements will be merged using the delimiter.
|
384
|
+
|
385
|
+
a class=["menu","highlight"]
|
386
|
+
a class=:menu,:highlight
|
387
|
+
|
373
388
|
#### Splat attributes `*`
|
374
389
|
|
375
390
|
The splat shortcut allows you turn a hash in to attribute/value pairs
|
376
391
|
|
377
392
|
.card*{'data-url'=>place_path(place), 'data-id'=>place.id} = place.name
|
393
|
+
|
394
|
+
renders as
|
395
|
+
|
396
|
+
<div class="card" data-id="1234" data-url="/place/1234">Slim's house</div>
|
397
|
+
|
398
|
+
You can also use methods or instance variables which return a hash as shown here:
|
399
|
+
|
378
400
|
.card *method_which_returns_hash = place.name
|
379
401
|
.card *@hash_instance_variable = place.name
|
380
402
|
|
403
|
+
The hash attributes which support attribute merging (see Slim option `:attr_delimiter`) can be given as an `Array`
|
404
|
+
|
405
|
+
.first *{:class => [:second, :third]} Text
|
406
|
+
|
381
407
|
renders as
|
382
408
|
|
383
|
-
|
409
|
+
div class="first second third"
|
384
410
|
|
385
411
|
#### ID shortcut `#` and class shortcut `.`
|
386
412
|
|
@@ -408,7 +434,23 @@ This is the same as
|
|
408
434
|
|
409
435
|
You can define custom shortcuts (Similar to `#` for id and `.` for class).
|
410
436
|
|
411
|
-
In this example we add
|
437
|
+
In this example we add `&` to create a shortcut for the input elements with type attribute.
|
438
|
+
|
439
|
+
Slim::Engine.set_default_options :shortcut => {'&' => 'input type', '#' => 'id', '.' => 'class'}
|
440
|
+
|
441
|
+
We can use it in Slim code like this
|
442
|
+
|
443
|
+
&text name="user"
|
444
|
+
&password name="pw"
|
445
|
+
&submit
|
446
|
+
|
447
|
+
which renders to
|
448
|
+
|
449
|
+
<input type="text" name="user" />
|
450
|
+
<input type="password" name="pw" />
|
451
|
+
<input type="submit" />
|
452
|
+
|
453
|
+
In another example we add `@` to create a shortcut for the role attribute.
|
412
454
|
|
413
455
|
Slim::Engine.set_default_options :shortcut => {'@' => 'role', '#' => 'id', '.' => 'class'}
|
414
456
|
|
@@ -528,7 +570,7 @@ There are a lot of them but the good thing is, that Slim checks the configuratio
|
|
528
570
|
<thead style="font-weight:bold"><tr><td>Type</td><td>Name</td><td>Default</td><td>Purpose</td></tr></thead>
|
529
571
|
<tbody>
|
530
572
|
<tr><td>String</td><td>:file</td><td>nil</td><td>Name of parsed file, set automatically by Slim::Template</td></tr>
|
531
|
-
<tr><td>Integer</td><td>:tabsize</td><td>4</td><td>Number of
|
573
|
+
<tr><td>Integer</td><td>:tabsize</td><td>4</td><td>Number of white spaces per tab (used by the parser)</td></tr>
|
532
574
|
<tr><td>String</td><td>:encoding</td><td>"utf-8"</td><td>Set encoding of template</td></tr>
|
533
575
|
<tr><td>String</td><td>:default_tag</td><td>"div"</td><td>Default tag to be used if tag name is omitted</td></tr>
|
534
576
|
<tr><td>Hash</td><td>:shortcut</td><td>\{'.' => 'class', '#' => 'id'}</td><td>Attribute shortcuts</td></tr>
|
@@ -792,6 +834,7 @@ There are plugins for various text editors (including the most important ones -
|
|
792
834
|
* [Emacs](https://github.com/minad/emacs-slim)
|
793
835
|
* [Textmate / Sublime Text](https://github.com/fredwu/ruby-slim-tmbundle)
|
794
836
|
* [Espresso text editor](https://github.com/CiiDub/Slim-Sugar)
|
837
|
+
* [Coda](https://github.com/nwalton3/Coda-2-Slim.mode)
|
795
838
|
|
796
839
|
### Template Converters (HAML, ERB, ...)
|
797
840
|
|
@@ -875,6 +918,8 @@ overhead added by the Temple framework compared to ERB.
|
|
875
918
|
Slim provides an extensive test-suite based on minitest. You can run the tests
|
876
919
|
with 'rake test' and the rails integration tests with 'rake test:rails'.
|
877
920
|
|
921
|
+
We are currently experimenting with human-readable literate tests which are written as markdown files: {file:test/literate/TESTS.md TESTS.md}
|
922
|
+
|
878
923
|
Travis-CI is used for continous integration testing: {http://travis-ci.org/#!/stonean/slim}
|
879
924
|
|
880
925
|
Slim is working well on all major Ruby implementations:
|
@@ -934,6 +979,7 @@ Syntax highlighting:
|
|
934
979
|
* [Emacs](https://github.com/minad/emacs-slim)
|
935
980
|
* [Textmate / Sublime Text](https://github.com/fredwu/ruby-slim-tmbundle)
|
936
981
|
* [Espresso text editor](https://github.com/CiiDub/Slim-Sugar)
|
982
|
+
* [Coda](https://github.com/nwalton3/Coda-2-Slim.mode)
|
937
983
|
|
938
984
|
Template Converters (HAML, ERB, ...):
|
939
985
|
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ end
|
|
14
14
|
task 'test' => %w(test:core_and_plugins)
|
15
15
|
|
16
16
|
namespace 'test' do
|
17
|
-
task 'core_and_plugins' => %w(core logic_less translator)
|
17
|
+
task 'core_and_plugins' => %w(core literate logic_less translator)
|
18
18
|
|
19
19
|
Rake::TestTask.new('core') do |t|
|
20
20
|
t.libs << 'lib' << 'test/core'
|
@@ -22,6 +22,12 @@ namespace 'test' do
|
|
22
22
|
t.verbose = true
|
23
23
|
end
|
24
24
|
|
25
|
+
Rake::TestTask.new('literate') do |t|
|
26
|
+
t.libs << 'lib' << 'test/literate'
|
27
|
+
t.test_files = FileList['test/literate/run.rb']
|
28
|
+
t.verbose = true
|
29
|
+
end
|
30
|
+
|
25
31
|
Rake::TestTask.new('logic_less') do |t|
|
26
32
|
t.libs << 'lib' << 'test/core'
|
27
33
|
t.test_files = FileList['test/logic_less/test_*.rb']
|
data/lib/slim.rb
CHANGED
@@ -6,7 +6,7 @@ require 'slim/embedded_engine'
|
|
6
6
|
require 'slim/interpolation'
|
7
7
|
require 'slim/control_structures'
|
8
8
|
require 'slim/splat_attributes'
|
9
|
-
require 'slim/
|
9
|
+
require 'slim/code_attributes'
|
10
10
|
require 'slim/engine'
|
11
11
|
require 'slim/template'
|
12
12
|
require 'slim/version'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Slim
|
2
|
+
# @api private
|
3
|
+
class CodeAttributes < Filter
|
4
|
+
define_options :attr_delimiter
|
5
|
+
|
6
|
+
# Handle attributes expression `[:html, :attrs, *attrs]`
|
7
|
+
#
|
8
|
+
# @param [Array] attrs Array of temple expressions
|
9
|
+
# @return [Array] Compiled temple expression
|
10
|
+
def on_html_attrs(*attrs)
|
11
|
+
[:multi, *attrs.map {|a| compile(a) }]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Handle attribute expression `[:slim, :attr, escape, code]`
|
15
|
+
#
|
16
|
+
# @param [String] name Attribute name
|
17
|
+
# @param [Array] value Value expression
|
18
|
+
# @return [Array] Compiled temple expression
|
19
|
+
def on_html_attr(name, value)
|
20
|
+
unless value[0] == :slim && value[1] == :attrvalue && !options[:attr_delimiter][name]
|
21
|
+
# We perform merging on the attribute
|
22
|
+
@attr = name
|
23
|
+
return super
|
24
|
+
end
|
25
|
+
|
26
|
+
# We handle the attribute as a boolean attribute
|
27
|
+
escape, code = value[2], value[3]
|
28
|
+
case code
|
29
|
+
when 'true'
|
30
|
+
[:html, :attr, name, [:static, name]]
|
31
|
+
when 'false', 'nil'
|
32
|
+
[:multi]
|
33
|
+
else
|
34
|
+
tmp = unique_name
|
35
|
+
[:multi,
|
36
|
+
[:code, "#{tmp} = #{code}"],
|
37
|
+
[:case, tmp,
|
38
|
+
['true', [:html, :attr, name, [:static, name]]],
|
39
|
+
['false, nil', [:multi]],
|
40
|
+
[:else, [:html, :attr, name, [:escape, escape, [:dynamic, tmp]]]]]]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Handle attribute expression `[:slim, :attrvalue, escape, code]`
|
45
|
+
#
|
46
|
+
# @param [Boolean] escape Escape html
|
47
|
+
# @param [String] code Ruby code
|
48
|
+
# @return [Array] Compiled temple expression
|
49
|
+
def on_slim_attrvalue(escape, code)
|
50
|
+
# We perform attribute merging on Array values
|
51
|
+
if delimiter = options[:attr_delimiter][@attr]
|
52
|
+
tmp = unique_name
|
53
|
+
[:multi,
|
54
|
+
[:code, "#{tmp} = #{code}"],
|
55
|
+
[:if, "Array === #{tmp}",
|
56
|
+
[:multi,
|
57
|
+
[:code, "#{tmp}.flatten!"],
|
58
|
+
[:code, "#{tmp}.map!(&:to_s)"],
|
59
|
+
[:code, "#{tmp}.reject!(&:empty?)"],
|
60
|
+
[:escape, escape, [:dynamic, "#{tmp}.join(#{delimiter.inspect})"]]],
|
61
|
+
[:escape, escape, [:dynamic, tmp]]]]
|
62
|
+
else
|
63
|
+
[:escape, escape, [:dynamic, code]]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/slim/engine.rb
CHANGED
@@ -23,7 +23,8 @@ module Slim
|
|
23
23
|
use Slim::SplatAttributes, :attr_delimiter, :attr_wrapper, :sort_attrs, :default_tag
|
24
24
|
html :AttributeSorter, :sort_attrs
|
25
25
|
html :AttributeMerger, :attr_delimiter
|
26
|
-
use Slim::
|
26
|
+
use Slim::CodeAttributes, :attr_delimiter
|
27
|
+
use(:AttributeRemover) { Temple::HTML::AttributeRemover.new(:remove_empty_attrs => options[:attr_delimiter].keys) }
|
27
28
|
html :Pretty, :format, :attr_wrapper, :pretty, :indent
|
28
29
|
filter :Escapable, :use_html_safe, :disable_escape
|
29
30
|
filter :ControlFlow
|
data/lib/slim/parser.rb
CHANGED
@@ -55,14 +55,7 @@ module Slim
|
|
55
55
|
# @param [String] str Slim code
|
56
56
|
# @return [Array] Temple expression representing the code]]
|
57
57
|
def call(str)
|
58
|
-
|
59
|
-
if options[:encoding] && str.respond_to?(:encoding)
|
60
|
-
old_enc = str.encoding
|
61
|
-
str = str.dup if str.frozen?
|
62
|
-
str.force_encoding(options[:encoding])
|
63
|
-
# Fall back to old encoding if new encoding is invalid
|
64
|
-
str.force_encoding(old_enc) unless str.valid_encoding?
|
65
|
-
end
|
58
|
+
str = remove_bom(set_encoding(str))
|
66
59
|
|
67
60
|
result = [:multi]
|
68
61
|
reset(str.split(/\r?\n/), [result])
|
@@ -86,6 +79,31 @@ module Slim
|
|
86
79
|
QUOTED_ATTR_REGEX = /#{ATTR_NAME}=(=?)("|')/
|
87
80
|
CODE_ATTR_REGEX = /#{ATTR_NAME}=(=?)/
|
88
81
|
|
82
|
+
# Set string encoding if option is set
|
83
|
+
def set_encoding(s)
|
84
|
+
if options[:encoding] && s.respond_to?(:encoding)
|
85
|
+
old_enc = s.encoding
|
86
|
+
s = s.dup if s.frozen?
|
87
|
+
s.force_encoding(options[:encoding])
|
88
|
+
# Fall back to old encoding if new encoding is invalid
|
89
|
+
s.force_encoding(old_enc) unless s.valid_encoding?
|
90
|
+
end
|
91
|
+
s
|
92
|
+
end
|
93
|
+
|
94
|
+
# Remove unicode byte order mark from string
|
95
|
+
def remove_bom(s)
|
96
|
+
if s.respond_to?(:encoding)
|
97
|
+
if s.encoding.name =~ /^UTF-(8|16|32)(BE|LE)?/
|
98
|
+
s.gsub(Regexp.new("\\A\uFEFF".encode(s.encoding.name)), '')
|
99
|
+
else
|
100
|
+
s
|
101
|
+
end
|
102
|
+
else
|
103
|
+
s.gsub(/\A\xEF\xBB\xBF/, '')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
89
107
|
def reset(lines = nil, stacks = nil)
|
90
108
|
# Since you can indent however you like in Slim, we need to keep a list
|
91
109
|
# of how deeply indented you are. For instance, in a template like this:
|
@@ -347,7 +365,7 @@ module Slim
|
|
347
365
|
end
|
348
366
|
|
349
367
|
if delimiter
|
350
|
-
boolean_attr_regex = /#{ATTR_NAME}(?=(\s|#{Regexp.escape delimiter}))/
|
368
|
+
boolean_attr_regex = /#{ATTR_NAME}(?=(\s|#{Regexp.escape delimiter}|\Z))/
|
351
369
|
end_regex = /\A\s*#{Regexp.escape delimiter}/
|
352
370
|
end
|
353
371
|
|
@@ -79,30 +79,31 @@ module Slim
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
merger << [:block, "#{hash}.each do |#{name}
|
82
|
+
merger << [:block, "#{hash}.keys.each do |#{name}|",
|
83
83
|
[:multi,
|
84
|
-
[:code, "#{value}
|
85
|
-
[:if, "#{
|
86
|
-
[:
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
[:
|
91
|
-
|
84
|
+
[:code, "#{value} = #{hash}[#{name}]"],
|
85
|
+
[:if, "#{@attr_delimiter}[#{name}]",
|
86
|
+
[:multi,
|
87
|
+
[:code, "#{value}.flatten!"],
|
88
|
+
[:code, "#{value}.map!(&:to_s)"],
|
89
|
+
[:code, "#{value}.reject!(&:empty?)"],
|
90
|
+
[:if, "#{value}.empty?",
|
91
|
+
[:code, "#{hash}.delete(#{name})"],
|
92
|
+
[:code, "#{hash}[#{name}] = #{value}.join(#{@attr_delimiter}[#{name}].to_s)"]]],
|
93
|
+
[:multi,
|
94
|
+
[:if, "#{value}.size > 1",
|
95
|
+
[:code, %{raise("Multiple #\{#{name}\} attributes specified")}]],
|
92
96
|
[:case, "#{value}.first",
|
93
97
|
['true', [:code, "#{hash}[#{name}] = #{name}"]],
|
94
|
-
['false, nil', [:code, "#{hash}
|
95
|
-
[:else, [:code, "#{hash}[#{name}] = #{value}.first"]]]]
|
96
|
-
[:else,
|
97
|
-
[:code, "#{hash}[#{name}] = #{value}.join(#{@attr_delimiter}[#{name}].to_s)"]]]]]
|
98
|
+
['false, nil', [:code, "#{hash}.delete(#{name})"]],
|
99
|
+
[:else, [:code, "#{hash}[#{name}] = #{value}.first"]]]]]]]
|
98
100
|
|
99
|
-
attr = [:
|
100
|
-
[:
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
[:static, options[:attr_wrapper]]]]
|
101
|
+
attr = [:multi,
|
102
|
+
[:static, ' '],
|
103
|
+
[:dynamic, name],
|
104
|
+
[:static, "=#{options[:attr_wrapper]}"],
|
105
|
+
[:escape, true, [:dynamic, value]],
|
106
|
+
[:static, options[:attr_wrapper]]]
|
106
107
|
enumerator = options[:sort_attrs] ? "#{hash}.sort_by {|#{name},#{value}| #{name} }" : hash
|
107
108
|
formatter = [:block, "#{enumerator}.each do |#{name},#{value}|", attr]
|
108
109
|
|
data/lib/slim/version.rb
CHANGED
data/slim.gemspec
CHANGED
@@ -11,15 +11,13 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.summary = 'Slim is a template language.'
|
12
12
|
s.description = 'Slim is a template language whose goal is reduce the syntax to the essential parts without becoming cryptic.'
|
13
13
|
s.homepage = 'http://slim-lang.com/'
|
14
|
-
s.extra_rdoc_files = %w(README.md LICENSE CHANGES)
|
15
|
-
s.rdoc_options = %w(--charset=UTF-8)
|
16
14
|
s.rubyforge_project = s.name
|
17
15
|
|
18
16
|
s.files = `git ls-files`.split("\n")
|
19
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
18
|
s.require_paths = %w(lib)
|
21
19
|
|
22
|
-
s.add_runtime_dependency('temple', ['~> 0.5.
|
20
|
+
s.add_runtime_dependency('temple', ['~> 0.5.5'])
|
23
21
|
s.add_runtime_dependency('tilt', ['~> 1.3.3'])
|
24
22
|
|
25
23
|
s.add_development_dependency('rake', ['>= 0.8.7'])
|
data/test/core/test_encoding.rb
CHANGED
@@ -99,15 +99,15 @@ option(selected class="clazz") Text
|
|
99
99
|
assert_html '<option class="clazz" selected="selected">Text</option><option class="clazz" selected="selected">Text</option>', source
|
100
100
|
end
|
101
101
|
|
102
|
-
def
|
102
|
+
def test_array_attribute_merging
|
103
103
|
source = %{
|
104
|
-
.alpha class="beta" class=[:gamma, nil, :delta, [true, false]]
|
104
|
+
.alpha class="beta" class=[[""], :gamma, nil, :delta, [true, false]]
|
105
|
+
.alpha class=:beta,:gamma
|
105
106
|
}
|
106
107
|
|
107
|
-
assert_html '<div class="alpha beta gamma delta true false"></div>', source
|
108
|
+
assert_html '<div class="alpha beta gamma delta true false"></div><div class="alpha beta gamma"></div>', source
|
108
109
|
end
|
109
110
|
|
110
|
-
|
111
111
|
def test_shortcut_splat
|
112
112
|
source = %q{
|
113
113
|
*hash This is my title
|
@@ -213,6 +213,22 @@ a class=true
|
|
213
213
|
a class=false
|
214
214
|
}
|
215
215
|
|
216
|
-
assert_html '<a class="true false"></a><a class="false true"></a><a class="
|
216
|
+
assert_html '<a class="true false"></a><a class="false true"></a><a class="true"></a><a class="false"></a>', source
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_static_empty_attribute
|
220
|
+
source = %q{
|
221
|
+
p(id="marvin" name="" class="" data-info="Illudium Q-36")= output_number
|
222
|
+
}
|
223
|
+
|
224
|
+
assert_html '<p data-info="Illudium Q-36" id="marvin" name="">1337</p>', source
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_dynamic_empty_attribute
|
228
|
+
source = %q{
|
229
|
+
p(id="marvin" class=nil nonempty=("".to_s) data-info="Illudium Q-36")= output_number
|
230
|
+
}
|
231
|
+
|
232
|
+
assert_html '<p data-info="Illudium Q-36" id="marvin" nonempty="">1337</p>', source
|
217
233
|
end
|
218
234
|
end
|