haml 3.0.0.beta.3 → 3.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/.yardopts +2 -0
- data/REMEMBER +4 -11
- data/Rakefile +24 -2
- data/VERSION +1 -1
- data/lib/haml.rb +5 -2
- data/lib/haml/exec.rb +11 -4
- data/lib/haml/filters.rb +3 -0
- data/lib/haml/helpers.rb +2 -10
- data/lib/haml/helpers/action_view_extensions.rb +4 -2
- data/lib/haml/helpers/action_view_mods.rb +6 -4
- data/lib/haml/html.rb +0 -1
- data/lib/haml/precompiler.rb +37 -30
- data/lib/haml/railtie.rb +6 -2
- data/lib/haml/root.rb +4 -0
- data/lib/haml/template.rb +2 -0
- data/lib/haml/util.rb +74 -0
- data/lib/haml/util/subset_map.rb +101 -0
- data/lib/sass.rb +1 -0
- data/lib/sass/engine.rb +36 -31
- data/lib/sass/files.rb +1 -1
- data/lib/sass/plugin.rb +21 -0
- data/lib/sass/plugin/staleness_checker.rb +9 -9
- data/lib/sass/script.rb +1 -2
- data/lib/sass/script/color.rb +4 -3
- data/lib/sass/script/css_lexer.rb +11 -1
- data/lib/sass/script/css_parser.rb +4 -1
- data/lib/sass/script/funcall.rb +9 -0
- data/lib/sass/script/interpolation.rb +21 -0
- data/lib/sass/script/lexer.rb +30 -13
- data/lib/sass/script/node.rb +1 -1
- data/lib/sass/script/number.rb +4 -5
- data/lib/sass/script/parser.rb +13 -14
- data/lib/sass/script/string.rb +8 -2
- data/lib/sass/script/string_interpolation.rb +27 -4
- data/lib/sass/scss.rb +3 -0
- data/lib/sass/scss/css_parser.rb +5 -3
- data/lib/sass/scss/parser.rb +146 -64
- data/lib/sass/scss/rx.rb +9 -1
- data/lib/sass/scss/sass_parser.rb +11 -0
- data/lib/sass/scss/script_lexer.rb +2 -0
- data/lib/sass/scss/static_parser.rb +48 -0
- data/lib/sass/selector.rb +353 -0
- data/lib/sass/selector/abstract_sequence.rb +40 -0
- data/lib/sass/selector/comma_sequence.rb +80 -0
- data/lib/sass/selector/sequence.rb +194 -0
- data/lib/sass/selector/simple.rb +107 -0
- data/lib/sass/selector/simple_sequence.rb +161 -0
- data/lib/sass/tree/comment_node.rb +1 -0
- data/lib/sass/tree/debug_node.rb +1 -0
- data/lib/sass/tree/directive_node.rb +1 -0
- data/lib/sass/tree/extend_node.rb +60 -0
- data/lib/sass/tree/for_node.rb +1 -0
- data/lib/sass/tree/if_node.rb +2 -0
- data/lib/sass/tree/import_node.rb +2 -0
- data/lib/sass/tree/mixin_def_node.rb +1 -0
- data/lib/sass/tree/mixin_node.rb +21 -5
- data/lib/sass/tree/node.rb +59 -12
- data/lib/sass/tree/prop_node.rb +20 -21
- data/lib/sass/tree/root_node.rb +8 -17
- data/lib/sass/tree/rule_node.rb +49 -100
- data/lib/sass/tree/variable_node.rb +1 -0
- data/lib/sass/tree/warn_node.rb +1 -0
- data/lib/sass/tree/while_node.rb +1 -0
- data/test/haml/engine_test.rb +185 -3
- data/test/haml/helper_test.rb +25 -2
- data/test/haml/template_test.rb +2 -2
- data/test/haml/templates/helpers.haml +13 -0
- data/test/haml/util/subset_map_test.rb +91 -0
- data/test/haml/util_test.rb +25 -0
- data/test/sass/conversion_test.rb +23 -3
- data/test/sass/engine_test.rb +50 -7
- data/test/sass/extend_test.rb +1045 -0
- data/test/sass/results/complex.css +0 -1
- data/test/sass/results/script.css +1 -1
- data/test/sass/script_conversion_test.rb +16 -0
- data/test/sass/script_test.rb +37 -4
- data/test/sass/scss/css_test.rb +17 -3
- data/test/sass/scss/rx_test.rb +1 -1
- data/test/sass/scss/scss_test.rb +30 -0
- data/test/sass/templates/complex.sass +0 -2
- data/test/test_helper.rb +5 -0
- metadata +18 -4
data/test/haml/helper_test.rb
CHANGED
@@ -15,7 +15,18 @@ module Haml::Helpers
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class HelperTest < Test::Unit::TestCase
|
18
|
-
Post = Struct.new('Post', :body)
|
18
|
+
Post = Struct.new('Post', :body, :error_field, :errors)
|
19
|
+
class PostErrors
|
20
|
+
def on(name)
|
21
|
+
return unless name == 'error_field'
|
22
|
+
["Really bad error"]
|
23
|
+
end
|
24
|
+
alias_method :full_messages, :on
|
25
|
+
|
26
|
+
def [](name)
|
27
|
+
on(name) || []
|
28
|
+
end
|
29
|
+
end
|
19
30
|
|
20
31
|
def setup
|
21
32
|
@base = ActionView::Base.new
|
@@ -26,7 +37,7 @@ class HelperTest < Test::Unit::TestCase
|
|
26
37
|
@base.controller.response = ActionController::Response.new
|
27
38
|
end
|
28
39
|
|
29
|
-
@base.instance_variable_set('@post', Post.new("Foo bar\nbaz"))
|
40
|
+
@base.instance_variable_set('@post', Post.new("Foo bar\nbaz", nil, PostErrors.new))
|
30
41
|
end
|
31
42
|
|
32
43
|
def render(text, options = {})
|
@@ -153,6 +164,18 @@ HTML
|
|
153
164
|
HAML
|
154
165
|
end
|
155
166
|
|
167
|
+
def test_content_tag_error_wrapping
|
168
|
+
def @base.protect_against_forgery?; false; end
|
169
|
+
assert_equal(<<HTML, render(<<HAML, :action_view))
|
170
|
+
<form action="" method="post">
|
171
|
+
<div class="fieldWithErrors"><label for="post_error_field">Error field</label></div>
|
172
|
+
</form>
|
173
|
+
HTML
|
174
|
+
#{rails_block_helper_char} form_for #{form_for_calling_convention('post')}, :url => '' do |f|
|
175
|
+
= f.label 'error_field'
|
176
|
+
HAML
|
177
|
+
end
|
178
|
+
|
156
179
|
def test_haml_tag_name_attribute_with_id
|
157
180
|
assert_equal("<p id='some_id'></p>\n", render("- haml_tag 'p#some_id'"))
|
158
181
|
end
|
data/test/haml/template_test.rb
CHANGED
@@ -288,7 +288,7 @@ END
|
|
288
288
|
<input id="article_body" name="article[body]" size="30" type="text" value="World" />
|
289
289
|
</form>
|
290
290
|
HTML
|
291
|
-
- form_for :article,
|
291
|
+
- form_for #{form_for_calling_convention(:article)}, :url => '' do |f|
|
292
292
|
Title:
|
293
293
|
= f.text_field :title
|
294
294
|
Body:
|
@@ -387,7 +387,7 @@ HAML
|
|
387
387
|
<input id="article_body" name="article[body]" size="30" type="text" value="World" />
|
388
388
|
</form>
|
389
389
|
HTML
|
390
|
-
#{rails_block_helper_char} form_for :article,
|
390
|
+
#{rails_block_helper_char} form_for #{form_for_calling_convention(:article)}, :url => '' do |f|
|
391
391
|
Title:
|
392
392
|
= f.text_field :title
|
393
393
|
Body:
|
@@ -62,6 +62,19 @@ click
|
|
62
62
|
<input id="article_body" name="article[body]" size="30" type="text" value="World" />
|
63
63
|
</form>
|
64
64
|
</div>
|
65
|
+
- elsif Haml::Util.ap_geq_3_beta_3?
|
66
|
+
%p
|
67
|
+
= form_tag ''
|
68
|
+
%div
|
69
|
+
= form_tag '' do
|
70
|
+
%div= submit_tag 'save'
|
71
|
+
- @foo = 'value one'
|
72
|
+
= test_partial 'partial'
|
73
|
+
= form_for @article, :as => :article, :url => '', :html => {:class => nil, :id => nil} do |f|
|
74
|
+
Title:
|
75
|
+
= f.text_field :title
|
76
|
+
Body:
|
77
|
+
= f.text_field :body
|
65
78
|
- elsif Haml::Util.ap_geq_3?
|
66
79
|
%p
|
67
80
|
= form_tag ''
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
3
|
+
|
4
|
+
class SubsetMapTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@ssm = Haml::Util::SubsetMap.new
|
7
|
+
@ssm[Set[1, 2]] = "Foo"
|
8
|
+
@ssm[Set["fizz", "fazz"]] = "Bar"
|
9
|
+
|
10
|
+
@ssm[Set[:foo, :bar]] = "Baz"
|
11
|
+
@ssm[Set[:foo, :bar, :baz]] = "Bang"
|
12
|
+
|
13
|
+
@ssm[Set[:bip, :bop, :blip]] = "Qux"
|
14
|
+
@ssm[Set[:bip, :bop]] = "Thram"
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_equal_keys
|
18
|
+
assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2])
|
19
|
+
assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"])
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_subset_keys
|
23
|
+
assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"])
|
24
|
+
assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3])
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_superset_keys
|
28
|
+
assert_equal [], @ssm.get(Set[1])
|
29
|
+
assert_equal [], @ssm.get(Set[2])
|
30
|
+
assert_equal [], @ssm.get(Set["fizz"])
|
31
|
+
assert_equal [], @ssm.get(Set["fazz"])
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_disjoint_keys
|
35
|
+
assert_equal [], @ssm.get(Set[3, 4])
|
36
|
+
assert_equal [], @ssm.get(Set["fuzz", "frizz"])
|
37
|
+
assert_equal [], @ssm.get(Set["gran", 15])
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_semi_disjoint_keys
|
41
|
+
assert_equal [], @ssm.get(Set[2, 3])
|
42
|
+
assert_equal [], @ssm.get(Set["fizz", "fuzz"])
|
43
|
+
assert_equal [], @ssm.get(Set[1, "fazz"])
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_empty_key_set
|
47
|
+
assert_raise(ArgumentError) {@ssm[Set[]] = "Fail"}
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_empty_key_get
|
51
|
+
assert_equal [], @ssm.get(Set[])
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_multiple_subsets
|
55
|
+
assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"])
|
56
|
+
assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", "fuzz"])
|
57
|
+
|
58
|
+
assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar])
|
59
|
+
assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz])
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_bracket_bracket
|
63
|
+
assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]]
|
64
|
+
assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]]
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_order_preserved
|
68
|
+
@ssm[Set[10, 11, 12]] = 1
|
69
|
+
@ssm[Set[10, 11]] = 2
|
70
|
+
@ssm[Set[11]] = 3
|
71
|
+
@ssm[Set[11, 12]] = 4
|
72
|
+
@ssm[Set[9, 10, 11, 12, 13]] = 5
|
73
|
+
@ssm[Set[10, 13]] = 6
|
74
|
+
|
75
|
+
assert_equal(
|
76
|
+
[[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]],
|
77
|
+
[5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]],
|
78
|
+
@ssm.get(Set[9, 10, 11, 12, 13]))
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_multiple_equal_values
|
82
|
+
@ssm[Set[11, 12]] = 1
|
83
|
+
@ssm[Set[12, 13]] = 2
|
84
|
+
@ssm[Set[13, 14]] = 1
|
85
|
+
@ssm[Set[14, 15]] = 1
|
86
|
+
|
87
|
+
assert_equal(
|
88
|
+
[[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]],
|
89
|
+
@ssm.get(Set[11, 12, 13, 14, 15]))
|
90
|
+
end
|
91
|
+
end
|
data/test/haml/util_test.rb
CHANGED
@@ -66,6 +66,24 @@ class UtilTest < Test::Unit::TestCase
|
|
66
66
|
merge_adjacent_strings(["foo ", "bar ", "baz", :bang, "biz", " bop", 12]))
|
67
67
|
end
|
68
68
|
|
69
|
+
def test_intersperse
|
70
|
+
assert_equal(["foo", " ", "bar", " ", "baz"],
|
71
|
+
intersperse(%w[foo bar baz], " "))
|
72
|
+
assert_equal([], intersperse([], " "))
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_substitute
|
76
|
+
assert_equal(["foo", "bar", "baz", 3, 4],
|
77
|
+
substitute([1, 2, 3, 4], [1, 2], ["foo", "bar", "baz"]))
|
78
|
+
assert_equal([1, "foo", "bar", "baz", 4],
|
79
|
+
substitute([1, 2, 3, 4], [2, 3], ["foo", "bar", "baz"]))
|
80
|
+
assert_equal([1, 2, "foo", "bar", "baz"],
|
81
|
+
substitute([1, 2, 3, 4], [3, 4], ["foo", "bar", "baz"]))
|
82
|
+
|
83
|
+
assert_equal([1, "foo", "bar", "baz", 2, 3, 4],
|
84
|
+
substitute([1, 2, 2, 2, 3, 4], [2, 2], ["foo", "bar", "baz"]))
|
85
|
+
end
|
86
|
+
|
69
87
|
def test_strip_string_array
|
70
88
|
assert_equal(["foo ", " bar ", " baz"],
|
71
89
|
strip_string_array([" foo ", " bar ", " baz "]))
|
@@ -75,6 +93,13 @@ class UtilTest < Test::Unit::TestCase
|
|
75
93
|
strip_string_array([" foo ", " bar ", :baz]))
|
76
94
|
end
|
77
95
|
|
96
|
+
def test_paths
|
97
|
+
assert_equal([[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5]],
|
98
|
+
paths([[1, 2], [3, 4], [5]]))
|
99
|
+
assert_equal([[]], paths([]))
|
100
|
+
assert_equal([[1, 2, 3]], paths([[1], [2], [3]]))
|
101
|
+
end
|
102
|
+
|
78
103
|
def test_silence_warnings
|
79
104
|
old_stderr, $stderr = $stderr, StringIO.new
|
80
105
|
warn "Out"
|
@@ -183,7 +183,7 @@ SASS
|
|
183
183
|
def test_multiline_properties
|
184
184
|
assert_scss_to_sass <<SASS, <<SCSS
|
185
185
|
foo bar
|
186
|
-
baz: bip
|
186
|
+
baz: bip bam boon
|
187
187
|
SASS
|
188
188
|
foo bar {
|
189
189
|
baz:
|
@@ -194,7 +194,7 @@ SCSS
|
|
194
194
|
|
195
195
|
assert_scss_to_scss <<OUT, <<IN
|
196
196
|
foo bar {
|
197
|
-
baz: bip
|
197
|
+
baz: bip bam boon; }
|
198
198
|
OUT
|
199
199
|
foo bar {
|
200
200
|
baz:
|
@@ -915,7 +915,7 @@ SCSS
|
|
915
915
|
assert_selector_renders['> E']
|
916
916
|
assert_selector_renders['+ E']
|
917
917
|
assert_selector_renders['~ E']
|
918
|
-
assert_selector_renders['
|
918
|
+
assert_selector_renders['> > E']
|
919
919
|
|
920
920
|
assert_selector_renders['E*']
|
921
921
|
assert_selector_renders['E*.foo']
|
@@ -1031,6 +1031,26 @@ div
|
|
1031
1031
|
SASS
|
1032
1032
|
end
|
1033
1033
|
|
1034
|
+
def test_sass2_var_in_property_interpolation
|
1035
|
+
assert_sass_to_scss <<SCSS, <<SASS
|
1036
|
+
foo {
|
1037
|
+
a: b \#{$c} d; }
|
1038
|
+
SCSS
|
1039
|
+
foo
|
1040
|
+
a: b \#{!c} d
|
1041
|
+
SASS
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
def test_sass2_var_in_selector_interpolation
|
1045
|
+
assert_sass_to_scss <<SCSS, <<SASS
|
1046
|
+
foo-\#{$c} {
|
1047
|
+
a: b; }
|
1048
|
+
SCSS
|
1049
|
+
foo-\#{!c}
|
1050
|
+
a: b
|
1051
|
+
SASS
|
1052
|
+
end
|
1053
|
+
|
1034
1054
|
private
|
1035
1055
|
|
1036
1056
|
def assert_sass_to_sass(sass, options = {})
|
data/test/sass/engine_test.rb
CHANGED
@@ -592,6 +592,36 @@ END
|
|
592
592
|
assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
|
593
593
|
end
|
594
594
|
|
595
|
+
def test_property_hacks
|
596
|
+
assert_equal(<<CSS, render(<<SASS))
|
597
|
+
foo {
|
598
|
+
_name: val;
|
599
|
+
*name: val;
|
600
|
+
#name: val;
|
601
|
+
.name: val;
|
602
|
+
name: val; }
|
603
|
+
CSS
|
604
|
+
foo
|
605
|
+
_name: val
|
606
|
+
*name: val
|
607
|
+
#name: val
|
608
|
+
.name: val
|
609
|
+
name: val
|
610
|
+
SASS
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_properties_with_space_after_colon
|
614
|
+
assert_equal <<CSS, render(<<SASS)
|
615
|
+
foo {
|
616
|
+
bar: baz;
|
617
|
+
bizz: bap; }
|
618
|
+
CSS
|
619
|
+
foo
|
620
|
+
bar : baz
|
621
|
+
bizz : bap
|
622
|
+
SASS
|
623
|
+
end
|
624
|
+
|
595
625
|
def test_line_annotations
|
596
626
|
assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
|
597
627
|
/* line 2, test_line_annotations_inline.sass */
|
@@ -980,6 +1010,19 @@ a-\#{$a}
|
|
980
1010
|
SASS
|
981
1011
|
end
|
982
1012
|
|
1013
|
+
def test_complex_property_interpolation
|
1014
|
+
assert_equal(<<CSS, render(<<SASS))
|
1015
|
+
a-1 {
|
1016
|
+
b-2 3-fizzap18: c-3; }
|
1017
|
+
CSS
|
1018
|
+
$a: 1
|
1019
|
+
$b: 2
|
1020
|
+
$c: 3
|
1021
|
+
a-\#{$a}
|
1022
|
+
b-\#{$b $c}-\#{fizzap + ($c + 15)}: c-\#{$a + $b}
|
1023
|
+
SASS
|
1024
|
+
end
|
1025
|
+
|
983
1026
|
def test_if_directive
|
984
1027
|
assert_equal("a {\n b: 1; }\n", render(<<SASS))
|
985
1028
|
$var: true
|
@@ -994,16 +1037,16 @@ SASS
|
|
994
1037
|
def test_for
|
995
1038
|
assert_equal(<<CSS, render(<<SASS))
|
996
1039
|
a-0 {
|
997
|
-
|
1040
|
+
two-i: 0; }
|
998
1041
|
|
999
1042
|
a-1 {
|
1000
|
-
|
1043
|
+
two-i: 2; }
|
1001
1044
|
|
1002
1045
|
a-2 {
|
1003
|
-
|
1046
|
+
two-i: 4; }
|
1004
1047
|
|
1005
1048
|
a-3 {
|
1006
|
-
|
1049
|
+
two-i: 6; }
|
1007
1050
|
|
1008
1051
|
b-1 {
|
1009
1052
|
j-1: 0; }
|
@@ -1020,7 +1063,7 @@ CSS
|
|
1020
1063
|
$a: 3
|
1021
1064
|
@for $i from 0 to $a + 1
|
1022
1065
|
a-\#{$i}
|
1023
|
-
|
1066
|
+
two-i: 2 * $i
|
1024
1067
|
|
1025
1068
|
@for $j from 1 through 4
|
1026
1069
|
b-\#{$j}
|
@@ -1348,7 +1391,7 @@ SASS
|
|
1348
1391
|
|
1349
1392
|
def test_attribute_selector_with_spaces
|
1350
1393
|
assert_equal(<<CSS, render(<<SASS))
|
1351
|
-
a b[foo
|
1394
|
+
a b[foo=bar] {
|
1352
1395
|
c: d; }
|
1353
1396
|
CSS
|
1354
1397
|
a
|
@@ -1542,7 +1585,7 @@ SASS
|
|
1542
1585
|
|
1543
1586
|
def test_interpolation_doesnt_deep_unquote_strings
|
1544
1587
|
assert_equal(<<CSS, render(<<SASS))
|
1545
|
-
.foo-"bar" "baz" {
|
1588
|
+
.foo- "bar" "baz" {
|
1546
1589
|
a: b; }
|
1547
1590
|
CSS
|
1548
1591
|
.foo-\#{"bar" "baz"}
|
@@ -0,0 +1,1045 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
3
|
+
|
4
|
+
class ExtendTest < Test::Unit::TestCase
|
5
|
+
def test_basic
|
6
|
+
assert_equal <<CSS, render(<<SCSS)
|
7
|
+
.foo, .bar {
|
8
|
+
a: b; }
|
9
|
+
CSS
|
10
|
+
.foo {a: b}
|
11
|
+
.bar {@extend .foo}
|
12
|
+
SCSS
|
13
|
+
|
14
|
+
assert_equal <<CSS, render(<<SCSS)
|
15
|
+
.foo, .bar {
|
16
|
+
a: b; }
|
17
|
+
CSS
|
18
|
+
.bar {@extend .foo}
|
19
|
+
.foo {a: b}
|
20
|
+
SCSS
|
21
|
+
|
22
|
+
assert_equal <<CSS, render(<<SCSS)
|
23
|
+
.foo, .bar {
|
24
|
+
a: b; }
|
25
|
+
|
26
|
+
.bar {
|
27
|
+
c: d; }
|
28
|
+
CSS
|
29
|
+
.foo {a: b}
|
30
|
+
.bar {c: d; @extend .foo}
|
31
|
+
SCSS
|
32
|
+
|
33
|
+
assert_equal <<CSS, render(<<SCSS)
|
34
|
+
.foo, .bar {
|
35
|
+
a: b; }
|
36
|
+
|
37
|
+
.bar {
|
38
|
+
c: d; }
|
39
|
+
CSS
|
40
|
+
.foo {a: b}
|
41
|
+
.bar {@extend .foo; c: d}
|
42
|
+
SCSS
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_indented_syntax
|
46
|
+
assert_equal <<CSS, render(<<SASS, :syntax => :sass)
|
47
|
+
.foo, .bar {
|
48
|
+
a: b; }
|
49
|
+
CSS
|
50
|
+
.foo
|
51
|
+
a: b
|
52
|
+
.bar
|
53
|
+
@extend .foo
|
54
|
+
SASS
|
55
|
+
|
56
|
+
assert_equal <<CSS, render(<<SASS, :syntax => :sass)
|
57
|
+
.foo, .bar {
|
58
|
+
a: b; }
|
59
|
+
CSS
|
60
|
+
.foo
|
61
|
+
a: b
|
62
|
+
.bar
|
63
|
+
@extend \#{".foo"}
|
64
|
+
SASS
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_multiple_targets
|
68
|
+
assert_equal <<CSS, render(<<SCSS)
|
69
|
+
.foo, .bar {
|
70
|
+
a: b; }
|
71
|
+
|
72
|
+
.blip .foo, .blip .bar {
|
73
|
+
c: d; }
|
74
|
+
CSS
|
75
|
+
.foo {a: b}
|
76
|
+
.bar {@extend .foo}
|
77
|
+
.blip .foo {c: d}
|
78
|
+
SCSS
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_multiple_extendees
|
82
|
+
assert_equal <<CSS, render(<<SCSS)
|
83
|
+
.foo, .baz {
|
84
|
+
a: b; }
|
85
|
+
|
86
|
+
.bar, .baz {
|
87
|
+
c: d; }
|
88
|
+
CSS
|
89
|
+
.foo {a: b}
|
90
|
+
.bar {c: d}
|
91
|
+
.baz {@extend .foo; @extend .bar}
|
92
|
+
SCSS
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_multiple_extends_with_single_extender_and_single_target
|
96
|
+
assert_equal <<CSS, render(<<SCSS)
|
97
|
+
.foo .bar, .baz .bar, .foo .baz, .baz .baz {
|
98
|
+
a: b; }
|
99
|
+
CSS
|
100
|
+
.foo .bar {a: b}
|
101
|
+
.baz {@extend .foo; @extend .bar}
|
102
|
+
SCSS
|
103
|
+
|
104
|
+
assert_equal <<CSS, render(<<SCSS)
|
105
|
+
.foo.bar, .bar.baz, .foo.baz, .baz {
|
106
|
+
a: b; }
|
107
|
+
CSS
|
108
|
+
.foo.bar {a: b}
|
109
|
+
.baz {@extend .foo; @extend .bar}
|
110
|
+
SCSS
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_multiple_extends_with_multiple_extenders_and_single_target
|
114
|
+
assert_equal <<CSS, render(<<SCSS)
|
115
|
+
.foo .bar, .baz .bar, .foo .bang, .baz .bang {
|
116
|
+
a: b; }
|
117
|
+
CSS
|
118
|
+
.foo .bar {a: b}
|
119
|
+
.baz {@extend .foo}
|
120
|
+
.bang {@extend .bar}
|
121
|
+
SCSS
|
122
|
+
|
123
|
+
assert_equal <<CSS, render(<<SCSS)
|
124
|
+
.foo.bar, .bar.baz, .foo.bang, .baz.bang {
|
125
|
+
a: b; }
|
126
|
+
CSS
|
127
|
+
.foo.bar {a: b}
|
128
|
+
.baz {@extend .foo}
|
129
|
+
.bang {@extend .bar}
|
130
|
+
SCSS
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_chained_extends
|
134
|
+
assert_equal <<CSS, render(<<SCSS)
|
135
|
+
.foo, .bar, .baz, .bip {
|
136
|
+
a: b; }
|
137
|
+
CSS
|
138
|
+
.foo {a: b}
|
139
|
+
.bar {@extend .foo}
|
140
|
+
.baz {@extend .bar}
|
141
|
+
.bip {@extend .bar}
|
142
|
+
SCSS
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_dynamic_extendee
|
146
|
+
assert_equal <<CSS, render(<<SCSS)
|
147
|
+
.foo, .bar {
|
148
|
+
a: b; }
|
149
|
+
CSS
|
150
|
+
.foo {a: b}
|
151
|
+
.bar {@extend \#{".foo"}}
|
152
|
+
SCSS
|
153
|
+
|
154
|
+
assert_equal <<CSS, render(<<SCSS)
|
155
|
+
[baz^="blip12px"], .bar {
|
156
|
+
a: b; }
|
157
|
+
CSS
|
158
|
+
[baz^="blip12px"] {a: b}
|
159
|
+
.bar {@extend [baz^="blip\#{12px}"]}
|
160
|
+
SCSS
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_nested_target
|
164
|
+
assert_equal <<CSS, render(<<SCSS)
|
165
|
+
.foo .bar, .foo .baz {
|
166
|
+
a: b; }
|
167
|
+
CSS
|
168
|
+
.foo .bar {a: b}
|
169
|
+
.baz {@extend .bar}
|
170
|
+
SCSS
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_target_with_child
|
174
|
+
assert_equal <<CSS, render(<<SCSS)
|
175
|
+
.foo .bar, .baz .bar {
|
176
|
+
a: b; }
|
177
|
+
CSS
|
178
|
+
.foo .bar {a: b}
|
179
|
+
.baz {@extend .foo}
|
180
|
+
SCSS
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_class_unification
|
184
|
+
assert_equal <<CSS, render(<<SCSS)
|
185
|
+
.foo.bar, .bar.baz {
|
186
|
+
a: b; }
|
187
|
+
CSS
|
188
|
+
.foo.bar {a: b}
|
189
|
+
.baz {@extend .foo}
|
190
|
+
SCSS
|
191
|
+
|
192
|
+
assert_equal <<CSS, render(<<SCSS)
|
193
|
+
.foo.baz, .baz {
|
194
|
+
a: b; }
|
195
|
+
CSS
|
196
|
+
.foo.baz {a: b}
|
197
|
+
.baz {@extend .foo}
|
198
|
+
SCSS
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_id_unification
|
202
|
+
assert_equal <<CSS, render(<<SCSS)
|
203
|
+
.foo.bar, .bar#baz {
|
204
|
+
a: b; }
|
205
|
+
CSS
|
206
|
+
.foo.bar {a: b}
|
207
|
+
#baz {@extend .foo}
|
208
|
+
SCSS
|
209
|
+
|
210
|
+
assert_equal <<CSS, render(<<SCSS)
|
211
|
+
.foo#baz, #baz {
|
212
|
+
a: b; }
|
213
|
+
CSS
|
214
|
+
.foo#baz {a: b}
|
215
|
+
#baz {@extend .foo}
|
216
|
+
SCSS
|
217
|
+
|
218
|
+
assert_equal <<CSS, render(<<SCSS)
|
219
|
+
.foo#baz {
|
220
|
+
a: b; }
|
221
|
+
CSS
|
222
|
+
.foo#baz {a: b}
|
223
|
+
#bar {@extend .foo}
|
224
|
+
SCSS
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_universal_unification_with_simple_target
|
228
|
+
assert_equal <<CSS, render(<<SCSS)
|
229
|
+
.foo, * {
|
230
|
+
a: b; }
|
231
|
+
CSS
|
232
|
+
.foo {a: b}
|
233
|
+
* {@extend .foo}
|
234
|
+
SCSS
|
235
|
+
|
236
|
+
assert_equal <<CSS, render(<<SCSS)
|
237
|
+
.foo, *|* {
|
238
|
+
a: b; }
|
239
|
+
CSS
|
240
|
+
.foo {a: b}
|
241
|
+
*|* {@extend .foo}
|
242
|
+
SCSS
|
243
|
+
|
244
|
+
assert_equal <<CSS, render(<<SCSS)
|
245
|
+
.foo.bar, .bar {
|
246
|
+
a: b; }
|
247
|
+
CSS
|
248
|
+
.foo.bar {a: b}
|
249
|
+
* {@extend .foo}
|
250
|
+
SCSS
|
251
|
+
|
252
|
+
assert_equal <<CSS, render(<<SCSS)
|
253
|
+
.foo.bar, .bar {
|
254
|
+
a: b; }
|
255
|
+
CSS
|
256
|
+
.foo.bar {a: b}
|
257
|
+
*|* {@extend .foo}
|
258
|
+
SCSS
|
259
|
+
|
260
|
+
assert_equal <<CSS, render(<<SCSS)
|
261
|
+
.foo.bar, ns|*.bar {
|
262
|
+
a: b; }
|
263
|
+
CSS
|
264
|
+
.foo.bar {a: b}
|
265
|
+
ns|* {@extend .foo}
|
266
|
+
SCSS
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_universal_unification_with_namespaceless_universal_target
|
270
|
+
assert_equal <<CSS, render(<<SCSS)
|
271
|
+
*.foo, * {
|
272
|
+
a: b; }
|
273
|
+
CSS
|
274
|
+
*.foo {a: b}
|
275
|
+
* {@extend .foo}
|
276
|
+
SCSS
|
277
|
+
|
278
|
+
assert_equal <<CSS, render(<<SCSS)
|
279
|
+
*.foo, * {
|
280
|
+
a: b; }
|
281
|
+
CSS
|
282
|
+
*.foo {a: b}
|
283
|
+
*|* {@extend .foo}
|
284
|
+
SCSS
|
285
|
+
|
286
|
+
assert_equal <<CSS, render(<<SCSS)
|
287
|
+
*|*.foo, * {
|
288
|
+
a: b; }
|
289
|
+
CSS
|
290
|
+
*|*.foo {a: b}
|
291
|
+
* {@extend .foo}
|
292
|
+
SCSS
|
293
|
+
|
294
|
+
assert_equal <<CSS, render(<<SCSS)
|
295
|
+
*|*.foo, *|* {
|
296
|
+
a: b; }
|
297
|
+
CSS
|
298
|
+
*|*.foo {a: b}
|
299
|
+
*|* {@extend .foo}
|
300
|
+
SCSS
|
301
|
+
|
302
|
+
assert_equal <<CSS, render(<<SCSS)
|
303
|
+
*.foo, ns|* {
|
304
|
+
a: b; }
|
305
|
+
CSS
|
306
|
+
*.foo {a: b}
|
307
|
+
ns|* {@extend .foo}
|
308
|
+
SCSS
|
309
|
+
|
310
|
+
assert_equal <<CSS, render(<<SCSS)
|
311
|
+
*|*.foo, ns|* {
|
312
|
+
a: b; }
|
313
|
+
CSS
|
314
|
+
*|*.foo {a: b}
|
315
|
+
ns|* {@extend .foo}
|
316
|
+
SCSS
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_universal_unification_with_namespaced_universal_target
|
320
|
+
assert_equal <<CSS, render(<<SCSS)
|
321
|
+
ns|*.foo, ns|* {
|
322
|
+
a: b; }
|
323
|
+
CSS
|
324
|
+
ns|*.foo {a: b}
|
325
|
+
* {@extend .foo}
|
326
|
+
SCSS
|
327
|
+
|
328
|
+
assert_equal <<CSS, render(<<SCSS)
|
329
|
+
ns|*.foo, ns|* {
|
330
|
+
a: b; }
|
331
|
+
CSS
|
332
|
+
ns|*.foo {a: b}
|
333
|
+
*|* {@extend .foo}
|
334
|
+
SCSS
|
335
|
+
|
336
|
+
assert_equal <<CSS, render(<<SCSS)
|
337
|
+
ns1|*.foo {
|
338
|
+
a: b; }
|
339
|
+
CSS
|
340
|
+
ns1|*.foo {a: b}
|
341
|
+
ns2|* {@extend .foo}
|
342
|
+
SCSS
|
343
|
+
|
344
|
+
assert_equal <<CSS, render(<<SCSS)
|
345
|
+
ns|*.foo, ns|* {
|
346
|
+
a: b; }
|
347
|
+
CSS
|
348
|
+
ns|*.foo {a: b}
|
349
|
+
ns|* {@extend .foo}
|
350
|
+
SCSS
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_universal_unification_with_namespaceless_element_target
|
354
|
+
assert_equal <<CSS, render(<<SCSS)
|
355
|
+
a.foo, a {
|
356
|
+
a: b; }
|
357
|
+
CSS
|
358
|
+
a.foo {a: b}
|
359
|
+
* {@extend .foo}
|
360
|
+
SCSS
|
361
|
+
|
362
|
+
assert_equal <<CSS, render(<<SCSS)
|
363
|
+
a.foo, a {
|
364
|
+
a: b; }
|
365
|
+
CSS
|
366
|
+
a.foo {a: b}
|
367
|
+
*|* {@extend .foo}
|
368
|
+
SCSS
|
369
|
+
|
370
|
+
assert_equal <<CSS, render(<<SCSS)
|
371
|
+
*|a.foo, a {
|
372
|
+
a: b; }
|
373
|
+
CSS
|
374
|
+
*|a.foo {a: b}
|
375
|
+
* {@extend .foo}
|
376
|
+
SCSS
|
377
|
+
|
378
|
+
assert_equal <<CSS, render(<<SCSS)
|
379
|
+
*|a.foo, *|a {
|
380
|
+
a: b; }
|
381
|
+
CSS
|
382
|
+
*|a.foo {a: b}
|
383
|
+
*|* {@extend .foo}
|
384
|
+
SCSS
|
385
|
+
|
386
|
+
assert_equal <<CSS, render(<<SCSS)
|
387
|
+
a.foo, ns|a {
|
388
|
+
a: b; }
|
389
|
+
CSS
|
390
|
+
a.foo {a: b}
|
391
|
+
ns|* {@extend .foo}
|
392
|
+
SCSS
|
393
|
+
|
394
|
+
assert_equal <<CSS, render(<<SCSS)
|
395
|
+
*|a.foo, ns|a {
|
396
|
+
a: b; }
|
397
|
+
CSS
|
398
|
+
*|a.foo {a: b}
|
399
|
+
ns|* {@extend .foo}
|
400
|
+
SCSS
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_universal_unification_with_namespaced_element_target
|
404
|
+
assert_equal <<CSS, render(<<SCSS)
|
405
|
+
ns|a.foo, ns|a {
|
406
|
+
a: b; }
|
407
|
+
CSS
|
408
|
+
ns|a.foo {a: b}
|
409
|
+
* {@extend .foo}
|
410
|
+
SCSS
|
411
|
+
|
412
|
+
assert_equal <<CSS, render(<<SCSS)
|
413
|
+
ns|a.foo, ns|a {
|
414
|
+
a: b; }
|
415
|
+
CSS
|
416
|
+
ns|a.foo {a: b}
|
417
|
+
*|* {@extend .foo}
|
418
|
+
SCSS
|
419
|
+
|
420
|
+
assert_equal <<CSS, render(<<SCSS)
|
421
|
+
ns1|a.foo {
|
422
|
+
a: b; }
|
423
|
+
CSS
|
424
|
+
ns1|a.foo {a: b}
|
425
|
+
ns2|* {@extend .foo}
|
426
|
+
SCSS
|
427
|
+
|
428
|
+
assert_equal <<CSS, render(<<SCSS)
|
429
|
+
ns|a.foo, ns|a {
|
430
|
+
a: b; }
|
431
|
+
CSS
|
432
|
+
ns|a.foo {a: b}
|
433
|
+
ns|* {@extend .foo}
|
434
|
+
SCSS
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_element_unification_with_simple_target
|
438
|
+
assert_equal <<CSS, render(<<SCSS)
|
439
|
+
.foo, a {
|
440
|
+
a: b; }
|
441
|
+
CSS
|
442
|
+
.foo {a: b}
|
443
|
+
a {@extend .foo}
|
444
|
+
SCSS
|
445
|
+
|
446
|
+
assert_equal <<CSS, render(<<SCSS)
|
447
|
+
.foo.bar, a.bar {
|
448
|
+
a: b; }
|
449
|
+
CSS
|
450
|
+
.foo.bar {a: b}
|
451
|
+
a {@extend .foo}
|
452
|
+
SCSS
|
453
|
+
|
454
|
+
assert_equal <<CSS, render(<<SCSS)
|
455
|
+
.foo.bar, *|a.bar {
|
456
|
+
a: b; }
|
457
|
+
CSS
|
458
|
+
.foo.bar {a: b}
|
459
|
+
*|a {@extend .foo}
|
460
|
+
SCSS
|
461
|
+
|
462
|
+
assert_equal <<CSS, render(<<SCSS)
|
463
|
+
.foo.bar, ns|a.bar {
|
464
|
+
a: b; }
|
465
|
+
CSS
|
466
|
+
.foo.bar {a: b}
|
467
|
+
ns|a {@extend .foo}
|
468
|
+
SCSS
|
469
|
+
end
|
470
|
+
|
471
|
+
def test_element_unification_with_namespaceless_universal_target
|
472
|
+
assert_equal <<CSS, render(<<SCSS)
|
473
|
+
*.foo, a {
|
474
|
+
a: b; }
|
475
|
+
CSS
|
476
|
+
*.foo {a: b}
|
477
|
+
a {@extend .foo}
|
478
|
+
SCSS
|
479
|
+
|
480
|
+
assert_equal <<CSS, render(<<SCSS)
|
481
|
+
*.foo, a {
|
482
|
+
a: b; }
|
483
|
+
CSS
|
484
|
+
*.foo {a: b}
|
485
|
+
*|a {@extend .foo}
|
486
|
+
SCSS
|
487
|
+
|
488
|
+
assert_equal <<CSS, render(<<SCSS)
|
489
|
+
*|*.foo, a {
|
490
|
+
a: b; }
|
491
|
+
CSS
|
492
|
+
*|*.foo {a: b}
|
493
|
+
a {@extend .foo}
|
494
|
+
SCSS
|
495
|
+
|
496
|
+
assert_equal <<CSS, render(<<SCSS)
|
497
|
+
*|*.foo, *|a {
|
498
|
+
a: b; }
|
499
|
+
CSS
|
500
|
+
*|*.foo {a: b}
|
501
|
+
*|a {@extend .foo}
|
502
|
+
SCSS
|
503
|
+
|
504
|
+
assert_equal <<CSS, render(<<SCSS)
|
505
|
+
*.foo, ns|a {
|
506
|
+
a: b; }
|
507
|
+
CSS
|
508
|
+
*.foo {a: b}
|
509
|
+
ns|a {@extend .foo}
|
510
|
+
SCSS
|
511
|
+
|
512
|
+
assert_equal <<CSS, render(<<SCSS)
|
513
|
+
*|*.foo, ns|a {
|
514
|
+
a: b; }
|
515
|
+
CSS
|
516
|
+
*|*.foo {a: b}
|
517
|
+
ns|a {@extend .foo}
|
518
|
+
SCSS
|
519
|
+
end
|
520
|
+
|
521
|
+
def test_element_unification_with_namespaced_universal_target
|
522
|
+
assert_equal <<CSS, render(<<SCSS)
|
523
|
+
ns|*.foo, ns|a {
|
524
|
+
a: b; }
|
525
|
+
CSS
|
526
|
+
ns|*.foo {a: b}
|
527
|
+
a {@extend .foo}
|
528
|
+
SCSS
|
529
|
+
|
530
|
+
assert_equal <<CSS, render(<<SCSS)
|
531
|
+
ns|*.foo, ns|a {
|
532
|
+
a: b; }
|
533
|
+
CSS
|
534
|
+
ns|*.foo {a: b}
|
535
|
+
*|a {@extend .foo}
|
536
|
+
SCSS
|
537
|
+
|
538
|
+
assert_equal <<CSS, render(<<SCSS)
|
539
|
+
ns1|*.foo {
|
540
|
+
a: b; }
|
541
|
+
CSS
|
542
|
+
ns1|*.foo {a: b}
|
543
|
+
ns2|a {@extend .foo}
|
544
|
+
SCSS
|
545
|
+
|
546
|
+
assert_equal <<CSS, render(<<SCSS)
|
547
|
+
ns|*.foo, ns|a {
|
548
|
+
a: b; }
|
549
|
+
CSS
|
550
|
+
ns|*.foo {a: b}
|
551
|
+
ns|a {@extend .foo}
|
552
|
+
SCSS
|
553
|
+
end
|
554
|
+
|
555
|
+
def test_element_unification_with_namespaceless_element_target
|
556
|
+
assert_equal <<CSS, render(<<SCSS)
|
557
|
+
a.foo, a {
|
558
|
+
a: b; }
|
559
|
+
CSS
|
560
|
+
a.foo {a: b}
|
561
|
+
a {@extend .foo}
|
562
|
+
SCSS
|
563
|
+
|
564
|
+
assert_equal <<CSS, render(<<SCSS)
|
565
|
+
a.foo, a {
|
566
|
+
a: b; }
|
567
|
+
CSS
|
568
|
+
a.foo {a: b}
|
569
|
+
*|a {@extend .foo}
|
570
|
+
SCSS
|
571
|
+
|
572
|
+
assert_equal <<CSS, render(<<SCSS)
|
573
|
+
*|a.foo, a {
|
574
|
+
a: b; }
|
575
|
+
CSS
|
576
|
+
*|a.foo {a: b}
|
577
|
+
a {@extend .foo}
|
578
|
+
SCSS
|
579
|
+
|
580
|
+
assert_equal <<CSS, render(<<SCSS)
|
581
|
+
*|a.foo, *|a {
|
582
|
+
a: b; }
|
583
|
+
CSS
|
584
|
+
*|a.foo {a: b}
|
585
|
+
*|a {@extend .foo}
|
586
|
+
SCSS
|
587
|
+
|
588
|
+
assert_equal <<CSS, render(<<SCSS)
|
589
|
+
a.foo, ns|a {
|
590
|
+
a: b; }
|
591
|
+
CSS
|
592
|
+
a.foo {a: b}
|
593
|
+
ns|a {@extend .foo}
|
594
|
+
SCSS
|
595
|
+
|
596
|
+
assert_equal <<CSS, render(<<SCSS)
|
597
|
+
*|a.foo, ns|a {
|
598
|
+
a: b; }
|
599
|
+
CSS
|
600
|
+
*|a.foo {a: b}
|
601
|
+
ns|a {@extend .foo}
|
602
|
+
SCSS
|
603
|
+
|
604
|
+
assert_equal <<CSS, render(<<SCSS)
|
605
|
+
a.foo {
|
606
|
+
a: b; }
|
607
|
+
CSS
|
608
|
+
a.foo {a: b}
|
609
|
+
h1 {@extend .foo}
|
610
|
+
SCSS
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_element_unification_with_namespaced_element_target
|
614
|
+
assert_equal <<CSS, render(<<SCSS)
|
615
|
+
ns|a.foo, ns|a {
|
616
|
+
a: b; }
|
617
|
+
CSS
|
618
|
+
ns|a.foo {a: b}
|
619
|
+
a {@extend .foo}
|
620
|
+
SCSS
|
621
|
+
|
622
|
+
assert_equal <<CSS, render(<<SCSS)
|
623
|
+
ns|a.foo, ns|a {
|
624
|
+
a: b; }
|
625
|
+
CSS
|
626
|
+
ns|a.foo {a: b}
|
627
|
+
*|a {@extend .foo}
|
628
|
+
SCSS
|
629
|
+
|
630
|
+
assert_equal <<CSS, render(<<SCSS)
|
631
|
+
ns1|a.foo {
|
632
|
+
a: b; }
|
633
|
+
CSS
|
634
|
+
ns1|a.foo {a: b}
|
635
|
+
ns2|a {@extend .foo}
|
636
|
+
SCSS
|
637
|
+
|
638
|
+
assert_equal <<CSS, render(<<SCSS)
|
639
|
+
ns|a.foo, ns|a {
|
640
|
+
a: b; }
|
641
|
+
CSS
|
642
|
+
ns|a.foo {a: b}
|
643
|
+
ns|a {@extend .foo}
|
644
|
+
SCSS
|
645
|
+
end
|
646
|
+
|
647
|
+
def test_attribute_unification
|
648
|
+
assert_equal <<CSS, render(<<SCSS)
|
649
|
+
[foo=bar].baz, [foo=bar][foo=baz] {
|
650
|
+
a: b; }
|
651
|
+
CSS
|
652
|
+
[foo=bar].baz {a: b}
|
653
|
+
[foo=baz] {@extend .baz}
|
654
|
+
SCSS
|
655
|
+
|
656
|
+
assert_equal <<CSS, render(<<SCSS)
|
657
|
+
[foo=bar].baz, [foo=bar][foo^=bar] {
|
658
|
+
a: b; }
|
659
|
+
CSS
|
660
|
+
[foo=bar].baz {a: b}
|
661
|
+
[foo^=bar] {@extend .baz}
|
662
|
+
SCSS
|
663
|
+
|
664
|
+
assert_equal <<CSS, render(<<SCSS)
|
665
|
+
[foo=bar].baz, [foo=bar][foot=bar] {
|
666
|
+
a: b; }
|
667
|
+
CSS
|
668
|
+
[foo=bar].baz {a: b}
|
669
|
+
[foot=bar] {@extend .baz}
|
670
|
+
SCSS
|
671
|
+
|
672
|
+
assert_equal <<CSS, render(<<SCSS)
|
673
|
+
[foo=bar].baz, [foo=bar][ns|foo=bar] {
|
674
|
+
a: b; }
|
675
|
+
CSS
|
676
|
+
[foo=bar].baz {a: b}
|
677
|
+
[ns|foo=bar] {@extend .baz}
|
678
|
+
SCSS
|
679
|
+
|
680
|
+
assert_equal <<CSS, render(<<SCSS)
|
681
|
+
[foo=bar].baz, [foo=bar] {
|
682
|
+
a: b; }
|
683
|
+
CSS
|
684
|
+
[foo=bar].baz {a: b}
|
685
|
+
[foo=bar] {@extend .baz}
|
686
|
+
SCSS
|
687
|
+
end
|
688
|
+
|
689
|
+
def test_pseudo_unification
|
690
|
+
assert_equal <<CSS, render(<<SCSS)
|
691
|
+
:foo.baz, :foo:foo(2n+1) {
|
692
|
+
a: b; }
|
693
|
+
CSS
|
694
|
+
:foo.baz {a: b}
|
695
|
+
:foo(2n+1) {@extend .baz}
|
696
|
+
SCSS
|
697
|
+
|
698
|
+
assert_equal <<CSS, render(<<SCSS)
|
699
|
+
:foo.baz, :foo::foo {
|
700
|
+
a: b; }
|
701
|
+
CSS
|
702
|
+
:foo.baz {a: b}
|
703
|
+
::foo {@extend .baz}
|
704
|
+
SCSS
|
705
|
+
|
706
|
+
assert_equal <<CSS, render(<<SCSS)
|
707
|
+
::foo.baz {
|
708
|
+
a: b; }
|
709
|
+
CSS
|
710
|
+
::foo.baz {a: b}
|
711
|
+
::bar {@extend .baz}
|
712
|
+
SCSS
|
713
|
+
|
714
|
+
assert_equal <<CSS, render(<<SCSS)
|
715
|
+
::foo.baz {
|
716
|
+
a: b; }
|
717
|
+
CSS
|
718
|
+
::foo.baz {a: b}
|
719
|
+
::foo(2n+1) {@extend .baz}
|
720
|
+
SCSS
|
721
|
+
|
722
|
+
assert_equal <<CSS, render(<<SCSS)
|
723
|
+
::foo.baz, ::foo {
|
724
|
+
a: b; }
|
725
|
+
CSS
|
726
|
+
::foo.baz {a: b}
|
727
|
+
::foo {@extend .baz}
|
728
|
+
SCSS
|
729
|
+
|
730
|
+
assert_equal <<CSS, render(<<SCSS)
|
731
|
+
::foo(2n+1).baz, ::foo(2n+1) {
|
732
|
+
a: b; }
|
733
|
+
CSS
|
734
|
+
::foo(2n+1).baz {a: b}
|
735
|
+
::foo(2n+1) {@extend .baz}
|
736
|
+
SCSS
|
737
|
+
|
738
|
+
assert_equal <<CSS, render(<<SCSS)
|
739
|
+
:foo.baz, :foo:bar {
|
740
|
+
a: b; }
|
741
|
+
CSS
|
742
|
+
:foo.baz {a: b}
|
743
|
+
:bar {@extend .baz}
|
744
|
+
SCSS
|
745
|
+
|
746
|
+
assert_equal <<CSS, render(<<SCSS)
|
747
|
+
:foo.baz, :foo {
|
748
|
+
a: b; }
|
749
|
+
CSS
|
750
|
+
:foo.baz {a: b}
|
751
|
+
:foo {@extend .baz}
|
752
|
+
SCSS
|
753
|
+
end
|
754
|
+
|
755
|
+
def test_pseudoelement_remains_at_end_of_selector
|
756
|
+
assert_equal <<CSS, render(<<SCSS)
|
757
|
+
.foo::bar, .baz::bar {
|
758
|
+
a: b; }
|
759
|
+
CSS
|
760
|
+
.foo::bar {a: b}
|
761
|
+
.baz {@extend .foo}
|
762
|
+
SCSS
|
763
|
+
|
764
|
+
assert_equal <<CSS, render(<<SCSS)
|
765
|
+
a.foo::bar, a.baz::bar {
|
766
|
+
a: b; }
|
767
|
+
CSS
|
768
|
+
a.foo::bar {a: b}
|
769
|
+
.baz {@extend .foo}
|
770
|
+
SCSS
|
771
|
+
end
|
772
|
+
|
773
|
+
def test_negation_unification
|
774
|
+
assert_equal <<CSS, render(<<SCSS)
|
775
|
+
:not(.foo).baz, :not(.foo):not(.bar) {
|
776
|
+
a: b; }
|
777
|
+
CSS
|
778
|
+
:not(.foo).baz {a: b}
|
779
|
+
:not(.bar) {@extend .baz}
|
780
|
+
SCSS
|
781
|
+
|
782
|
+
assert_equal <<CSS, render(<<SCSS)
|
783
|
+
:not(.foo).baz, :not(.foo) {
|
784
|
+
a: b; }
|
785
|
+
CSS
|
786
|
+
:not(.foo).baz {a: b}
|
787
|
+
:not(.foo) {@extend .baz}
|
788
|
+
SCSS
|
789
|
+
|
790
|
+
assert_equal <<CSS, render(<<SCSS)
|
791
|
+
:not([a=b]).baz, :not([a=b]) {
|
792
|
+
a: b; }
|
793
|
+
CSS
|
794
|
+
:not([a=b]).baz {a: b}
|
795
|
+
:not([a = b]) {@extend .baz}
|
796
|
+
SCSS
|
797
|
+
end
|
798
|
+
|
799
|
+
## Long Extendees
|
800
|
+
|
801
|
+
def test_long_extendee
|
802
|
+
assert_equal <<CSS, render(<<SCSS)
|
803
|
+
.foo.bar, .baz {
|
804
|
+
a: b; }
|
805
|
+
CSS
|
806
|
+
.foo.bar {a: b}
|
807
|
+
.baz {@extend .foo.bar}
|
808
|
+
SCSS
|
809
|
+
end
|
810
|
+
|
811
|
+
def test_long_extendee_requires_all_selectors
|
812
|
+
assert_equal <<CSS, render(<<SCSS)
|
813
|
+
.foo {
|
814
|
+
a: b; }
|
815
|
+
CSS
|
816
|
+
.foo {a: b}
|
817
|
+
.baz {@extend .foo.bar}
|
818
|
+
SCSS
|
819
|
+
end
|
820
|
+
|
821
|
+
def test_long_extendee_matches_supersets
|
822
|
+
assert_equal <<CSS, render(<<SCSS)
|
823
|
+
.foo.bar.bap, .bap.baz {
|
824
|
+
a: b; }
|
825
|
+
CSS
|
826
|
+
.foo.bar.bap {a: b}
|
827
|
+
.baz {@extend .foo.bar}
|
828
|
+
SCSS
|
829
|
+
end
|
830
|
+
|
831
|
+
def test_long_extendee_runs_unification
|
832
|
+
assert_equal <<CSS, render(<<SCSS)
|
833
|
+
ns|*.foo.bar, ns|a.baz {
|
834
|
+
a: b; }
|
835
|
+
CSS
|
836
|
+
ns|*.foo.bar {a: b}
|
837
|
+
a.baz {@extend .foo.bar}
|
838
|
+
SCSS
|
839
|
+
end
|
840
|
+
|
841
|
+
## Long Extenders
|
842
|
+
|
843
|
+
def test_long_extender
|
844
|
+
assert_equal <<CSS, render(<<SCSS)
|
845
|
+
.foo.bar, .bar.baz.bang {
|
846
|
+
a: b; }
|
847
|
+
CSS
|
848
|
+
.foo.bar {a: b}
|
849
|
+
.baz.bang {@extend .foo}
|
850
|
+
SCSS
|
851
|
+
end
|
852
|
+
|
853
|
+
def test_long_extender_runs_unification
|
854
|
+
assert_equal <<CSS, render(<<SCSS)
|
855
|
+
ns|*.foo.bar, ns|a.bar.baz {
|
856
|
+
a: b; }
|
857
|
+
CSS
|
858
|
+
ns|*.foo.bar {a: b}
|
859
|
+
a.baz {@extend .foo}
|
860
|
+
SCSS
|
861
|
+
end
|
862
|
+
|
863
|
+
def test_long_extender_aborts_unification
|
864
|
+
assert_equal <<CSS, render(<<SCSS)
|
865
|
+
a.foo#bar {
|
866
|
+
a: b; }
|
867
|
+
CSS
|
868
|
+
a.foo#bar {a: b}
|
869
|
+
h1.baz {@extend .foo}
|
870
|
+
SCSS
|
871
|
+
|
872
|
+
assert_equal <<CSS, render(<<SCSS)
|
873
|
+
a.foo#bar {
|
874
|
+
a: b; }
|
875
|
+
CSS
|
876
|
+
a.foo#bar {a: b}
|
877
|
+
.bang#baz {@extend .foo}
|
878
|
+
SCSS
|
879
|
+
end
|
880
|
+
|
881
|
+
## Nested Extenders
|
882
|
+
|
883
|
+
def test_nested_extender
|
884
|
+
assert_equal <<CSS, render(<<SCSS)
|
885
|
+
.foo, foo bar {
|
886
|
+
a: b; }
|
887
|
+
CSS
|
888
|
+
.foo {a: b}
|
889
|
+
foo bar {@extend .foo}
|
890
|
+
SCSS
|
891
|
+
end
|
892
|
+
|
893
|
+
def test_nested_extender_runs_unification
|
894
|
+
assert_equal <<CSS, render(<<SCSS)
|
895
|
+
.foo.bar, foo bar.bar {
|
896
|
+
a: b; }
|
897
|
+
CSS
|
898
|
+
.foo.bar {a: b}
|
899
|
+
foo bar {@extend .foo}
|
900
|
+
SCSS
|
901
|
+
end
|
902
|
+
|
903
|
+
def test_nested_extender_aborts_unification
|
904
|
+
assert_equal <<CSS, render(<<SCSS)
|
905
|
+
baz.foo {
|
906
|
+
a: b; }
|
907
|
+
CSS
|
908
|
+
baz.foo {a: b}
|
909
|
+
foo bar {@extend .foo}
|
910
|
+
SCSS
|
911
|
+
end
|
912
|
+
|
913
|
+
def test_nested_extender_interleaves_parents_with_unification
|
914
|
+
assert_equal <<CSS, render(<<SCSS)
|
915
|
+
.baz .foo, .baz foo bar, foo.baz bar, foo .baz bar {
|
916
|
+
a: b; }
|
917
|
+
CSS
|
918
|
+
.baz .foo {a: b}
|
919
|
+
foo bar {@extend .foo}
|
920
|
+
SCSS
|
921
|
+
end
|
922
|
+
|
923
|
+
def test_nested_extender_interleaves_parents_with_aborted_unification
|
924
|
+
assert_equal <<CSS, render(<<SCSS)
|
925
|
+
baz .foo, baz foo bar, foo baz bar {
|
926
|
+
a: b; }
|
927
|
+
CSS
|
928
|
+
baz .foo {a: b}
|
929
|
+
foo bar {@extend .foo}
|
930
|
+
SCSS
|
931
|
+
end
|
932
|
+
|
933
|
+
def test_nested_extender_with_lots_of_interleaving
|
934
|
+
# Please, never ever do this in a real stylesheet
|
935
|
+
assert_equal <<CSS, render(<<SCSS)
|
936
|
+
.foo .bar .baz .bang, .foo .bar .baz .foo2 .bar2 .baz2 .bang2, .foo .bar .foo2.baz .bar2 .baz2 .bang2, .foo .bar .foo2 .baz .bar2 .baz2 .bang2, .foo .bar .foo2 .bar2.baz .baz2 .bang2, .foo .bar .foo2 .bar2 .baz .baz2 .bang2, .foo .bar .foo2 .bar2 .baz2.baz .bang2, .foo .bar .foo2 .bar2 .baz2 .baz .bang2, .foo .foo2.bar .baz .bar2 .baz2 .bang2, .foo .foo2.bar .bar2.baz .baz2 .bang2, .foo .foo2.bar .bar2 .baz .baz2 .bang2, .foo .foo2.bar .bar2 .baz2.baz .bang2, .foo .foo2.bar .bar2 .baz2 .baz .bang2, .foo .foo2 .bar .baz .bar2 .baz2 .bang2, .foo .foo2 .bar .bar2.baz .baz2 .bang2, .foo .foo2 .bar .bar2 .baz .baz2 .bang2, .foo .foo2 .bar .bar2 .baz2.baz .bang2, .foo .foo2 .bar .bar2 .baz2 .baz .bang2, .foo .foo2 .bar2.bar .baz .baz2 .bang2, .foo .foo2 .bar2.bar .baz2.baz .bang2, .foo .foo2 .bar2.bar .baz2 .baz .bang2, .foo .foo2 .bar2 .bar .baz .baz2 .bang2, .foo .foo2 .bar2 .bar .baz2.baz .bang2, .foo .foo2 .bar2 .bar .baz2 .baz .bang2, .foo .foo2 .bar2 .baz2.bar .baz .bang2, .foo .foo2 .bar2 .baz2 .bar .baz .bang2, .foo2.foo .bar .baz .bar2 .baz2 .bang2, .foo2.foo .bar .bar2.baz .baz2 .bang2, .foo2.foo .bar .bar2 .baz .baz2 .bang2, .foo2.foo .bar .bar2 .baz2.baz .bang2, .foo2.foo .bar .bar2 .baz2 .baz .bang2, .foo2.foo .bar2.bar .baz .baz2 .bang2, .foo2.foo .bar2.bar .baz2.baz .bang2, .foo2.foo .bar2.bar .baz2 .baz .bang2, .foo2.foo .bar2 .bar .baz .baz2 .bang2, .foo2.foo .bar2 .bar .baz2.baz .bang2, .foo2.foo .bar2 .bar .baz2 .baz .bang2, .foo2.foo .bar2 .baz2.bar .baz .bang2, .foo2.foo .bar2 .baz2 .bar .baz .bang2, .foo2 .foo .bar .baz .bar2 .baz2 .bang2, .foo2 .foo .bar .bar2.baz .baz2 .bang2, .foo2 .foo .bar .bar2 .baz .baz2 .bang2, .foo2 .foo .bar .bar2 .baz2.baz .bang2, .foo2 .foo .bar .bar2 .baz2 .baz .bang2, .foo2 .foo .bar2.bar .baz .baz2 .bang2, .foo2 .foo .bar2.bar .baz2.baz .bang2, .foo2 .foo .bar2.bar .baz2 .baz .bang2, .foo2 .foo .bar2 .bar .baz .baz2 .bang2, .foo2 .foo .bar2 .bar .baz2.baz .bang2, .foo2 .foo .bar2 .bar .baz2 .baz .bang2, .foo2 .foo .bar2 .baz2.bar .baz .bang2, .foo2 .foo .bar2 .baz2 .bar .baz .bang2, .foo2 .bar2.foo .bar .baz .baz2 .bang2, .foo2 .bar2.foo .bar .baz2.baz .bang2, .foo2 .bar2.foo .bar .baz2 .baz .bang2, .foo2 .bar2.foo .baz2.bar .baz .bang2, .foo2 .bar2.foo .baz2 .bar .baz .bang2, .foo2 .bar2 .foo .bar .baz .baz2 .bang2, .foo2 .bar2 .foo .bar .baz2.baz .bang2, .foo2 .bar2 .foo .bar .baz2 .baz .bang2, .foo2 .bar2 .foo .baz2.bar .baz .bang2, .foo2 .bar2 .foo .baz2 .bar .baz .bang2, .foo2 .bar2 .baz2.foo .bar .baz .bang2, .foo2 .bar2 .baz2 .foo .bar .baz .bang2 {
|
937
|
+
a: b; }
|
938
|
+
CSS
|
939
|
+
.foo .bar .baz .bang {a: b}
|
940
|
+
.foo2 .bar2 .baz2 .bang2 {@extend .bang}
|
941
|
+
SCSS
|
942
|
+
end
|
943
|
+
|
944
|
+
def test_nested_extender_with_child_selector
|
945
|
+
assert_equal <<CSS, render(<<SCSS)
|
946
|
+
.baz .foo, .baz foo > bar {
|
947
|
+
a: b; }
|
948
|
+
CSS
|
949
|
+
.baz .foo {a: b}
|
950
|
+
foo > bar {@extend .foo}
|
951
|
+
SCSS
|
952
|
+
end
|
953
|
+
|
954
|
+
def test_nested_extender_with_descendant_and_child_selector
|
955
|
+
assert_equal <<CSS, render(<<SCSS)
|
956
|
+
.baz .foo, .baz bang foo > bar, bang.baz foo > bar, bang .baz foo > bar {
|
957
|
+
a: b; }
|
958
|
+
CSS
|
959
|
+
.baz .foo {a: b}
|
960
|
+
bang foo > bar {@extend .foo}
|
961
|
+
SCSS
|
962
|
+
end
|
963
|
+
|
964
|
+
def test_nested_extender_with_child_selector_unifies
|
965
|
+
assert_equal <<CSS, render(<<SCSS)
|
966
|
+
.baz.foo, foo > bar.baz {
|
967
|
+
a: b; }
|
968
|
+
CSS
|
969
|
+
.baz.foo {a: b}
|
970
|
+
foo > bar {@extend .foo}
|
971
|
+
SCSS
|
972
|
+
end
|
973
|
+
|
974
|
+
def test_nested_extender_with_child_selector_and_more
|
975
|
+
assert_equal <<CSS, render(<<SCSS)
|
976
|
+
.foo .bar, .foo foo > bar baz, foo > bar.foo baz, foo > bar .foo baz {
|
977
|
+
a: b; }
|
978
|
+
CSS
|
979
|
+
.foo .bar {a: b}
|
980
|
+
foo > bar baz {@extend .bar}
|
981
|
+
SCSS
|
982
|
+
end
|
983
|
+
|
984
|
+
def test_nested_extender_with_trailing_child_selector
|
985
|
+
assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do
|
986
|
+
render("bar > {@extend .baz}")
|
987
|
+
end
|
988
|
+
end
|
989
|
+
|
990
|
+
def test_nested_extender_with_sibling_selector
|
991
|
+
assert_equal <<CSS, render(<<SCSS)
|
992
|
+
.baz .foo, .baz foo + bar {
|
993
|
+
a: b; }
|
994
|
+
CSS
|
995
|
+
.baz .foo {a: b}
|
996
|
+
foo + bar {@extend .foo}
|
997
|
+
SCSS
|
998
|
+
end
|
999
|
+
|
1000
|
+
def test_nested_extender_with_hacky_selector
|
1001
|
+
assert_equal <<CSS, render(<<SCSS)
|
1002
|
+
.baz .foo, .baz foo + > > + bar {
|
1003
|
+
a: b; }
|
1004
|
+
CSS
|
1005
|
+
.baz .foo {a: b}
|
1006
|
+
foo + > > + bar {@extend .foo}
|
1007
|
+
SCSS
|
1008
|
+
|
1009
|
+
assert_equal <<CSS, render(<<SCSS)
|
1010
|
+
.baz .foo, .baz > > bar {
|
1011
|
+
a: b; }
|
1012
|
+
CSS
|
1013
|
+
.baz .foo {a: b}
|
1014
|
+
> > bar {@extend .foo}
|
1015
|
+
SCSS
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
def test_nested_extender_merges_with_same_selector
|
1019
|
+
assert_equal <<CSS, render(<<SCSS)
|
1020
|
+
.foo .bar, .foo .baz {
|
1021
|
+
a: b; }
|
1022
|
+
CSS
|
1023
|
+
.foo {
|
1024
|
+
.bar {a: b}
|
1025
|
+
.baz {@extend .bar} }
|
1026
|
+
SCSS
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
def test_nested_extender_with_child_selector_merges_with_same_selector
|
1030
|
+
assert_equal <<CSS, render(<<SCSS)
|
1031
|
+
.foo > .bar .baz, .foo > .bar .bang {
|
1032
|
+
a: b; }
|
1033
|
+
CSS
|
1034
|
+
.foo > .bar .baz {a: b}
|
1035
|
+
.foo > .bar .bang {@extend .baz}
|
1036
|
+
SCSS
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
private
|
1040
|
+
|
1041
|
+
def render(sass, options = {})
|
1042
|
+
munge_filename options
|
1043
|
+
Sass::Engine.new(sass, {:syntax => :scss}.merge(options)).render
|
1044
|
+
end
|
1045
|
+
end
|