sass 3.6.0 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTING.md +1 -1
  3. data/README.md +10 -0
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/lib/sass/script/css_parser.rb +4 -1
  7. data/lib/sass/script/functions.rb +15 -25
  8. data/lib/sass/script/lexer.rb +45 -7
  9. data/lib/sass/script/parser.rb +259 -93
  10. data/lib/sass/scss/parser.rb +43 -16
  11. data/lib/sass/scss/static_parser.rb +15 -15
  12. data/lib/sass/util.rb +31 -0
  13. metadata +8 -156
  14. data/Rakefile +0 -364
  15. data/test/sass-spec.yml +0 -3
  16. data/test/sass/cache_test.rb +0 -130
  17. data/test/sass/callbacks_test.rb +0 -60
  18. data/test/sass/compiler_test.rb +0 -225
  19. data/test/sass/conversion_test.rb +0 -2138
  20. data/test/sass/css2sass_test.rb +0 -523
  21. data/test/sass/css_variable_test.rb +0 -237
  22. data/test/sass/data/hsl-rgb.txt +0 -319
  23. data/test/sass/encoding_test.rb +0 -188
  24. data/test/sass/engine_test.rb +0 -3499
  25. data/test/sass/exec_test.rb +0 -95
  26. data/test/sass/extend_test.rb +0 -1679
  27. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  28. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  29. data/test/sass/functions_test.rb +0 -2021
  30. data/test/sass/importer_test.rb +0 -420
  31. data/test/sass/logger_test.rb +0 -57
  32. data/test/sass/mock_importer.rb +0 -49
  33. data/test/sass/more_results/more1.css +0 -9
  34. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  35. data/test/sass/more_results/more_import.css +0 -29
  36. data/test/sass/more_templates/_more_partial.sass +0 -2
  37. data/test/sass/more_templates/more1.sass +0 -23
  38. data/test/sass/more_templates/more_import.sass +0 -11
  39. data/test/sass/plugin_test.rb +0 -552
  40. data/test/sass/results/alt.css +0 -4
  41. data/test/sass/results/basic.css +0 -9
  42. data/test/sass/results/cached_import_option.css +0 -3
  43. data/test/sass/results/compact.css +0 -5
  44. data/test/sass/results/complex.css +0 -86
  45. data/test/sass/results/compressed.css +0 -1
  46. data/test/sass/results/expanded.css +0 -19
  47. data/test/sass/results/filename_fn.css +0 -3
  48. data/test/sass/results/if.css +0 -3
  49. data/test/sass/results/import.css +0 -31
  50. data/test/sass/results/import_charset.css +0 -5
  51. data/test/sass/results/import_charset_ibm866.css +0 -5
  52. data/test/sass/results/import_content.css +0 -1
  53. data/test/sass/results/line_numbers.css +0 -49
  54. data/test/sass/results/mixins.css +0 -95
  55. data/test/sass/results/multiline.css +0 -24
  56. data/test/sass/results/nested.css +0 -22
  57. data/test/sass/results/options.css +0 -1
  58. data/test/sass/results/parent_ref.css +0 -13
  59. data/test/sass/results/script.css +0 -16
  60. data/test/sass/results/scss_import.css +0 -31
  61. data/test/sass/results/scss_importee.css +0 -2
  62. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  63. data/test/sass/results/subdir/subdir.css +0 -3
  64. data/test/sass/results/units.css +0 -11
  65. data/test/sass/results/warn.css +0 -0
  66. data/test/sass/results/warn_imported.css +0 -0
  67. data/test/sass/script_conversion_test.rb +0 -365
  68. data/test/sass/script_test.rb +0 -1427
  69. data/test/sass/scss/css_test.rb +0 -1266
  70. data/test/sass/scss/rx_test.rb +0 -159
  71. data/test/sass/scss/scss_test.rb +0 -4238
  72. data/test/sass/scss/test_helper.rb +0 -37
  73. data/test/sass/source_map_test.rb +0 -1063
  74. data/test/sass/superselector_test.rb +0 -209
  75. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  76. data/test/sass/templates/_double_import_loop2.sass +0 -1
  77. data/test/sass/templates/_filename_fn_import.scss +0 -11
  78. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  79. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  80. data/test/sass/templates/_imported_content.sass +0 -3
  81. data/test/sass/templates/_partial.sass +0 -2
  82. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  83. data/test/sass/templates/alt.sass +0 -16
  84. data/test/sass/templates/basic.sass +0 -23
  85. data/test/sass/templates/bork1.sass +0 -2
  86. data/test/sass/templates/bork2.sass +0 -2
  87. data/test/sass/templates/bork3.sass +0 -2
  88. data/test/sass/templates/bork4.sass +0 -2
  89. data/test/sass/templates/bork5.sass +0 -3
  90. data/test/sass/templates/cached_import_option.scss +0 -3
  91. data/test/sass/templates/compact.sass +0 -17
  92. data/test/sass/templates/complex.sass +0 -305
  93. data/test/sass/templates/compressed.sass +0 -15
  94. data/test/sass/templates/double_import_loop1.sass +0 -1
  95. data/test/sass/templates/expanded.sass +0 -17
  96. data/test/sass/templates/filename_fn.scss +0 -18
  97. data/test/sass/templates/if.sass +0 -11
  98. data/test/sass/templates/import.sass +0 -12
  99. data/test/sass/templates/import_charset.sass +0 -9
  100. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  101. data/test/sass/templates/import_content.sass +0 -4
  102. data/test/sass/templates/importee.less +0 -2
  103. data/test/sass/templates/importee.sass +0 -19
  104. data/test/sass/templates/line_numbers.sass +0 -13
  105. data/test/sass/templates/mixin_bork.sass +0 -5
  106. data/test/sass/templates/mixins.sass +0 -76
  107. data/test/sass/templates/multiline.sass +0 -20
  108. data/test/sass/templates/nested.sass +0 -25
  109. data/test/sass/templates/nested_bork1.sass +0 -2
  110. data/test/sass/templates/nested_bork2.sass +0 -2
  111. data/test/sass/templates/nested_bork3.sass +0 -2
  112. data/test/sass/templates/nested_bork4.sass +0 -2
  113. data/test/sass/templates/nested_import.sass +0 -2
  114. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  115. data/test/sass/templates/options.sass +0 -2
  116. data/test/sass/templates/parent_ref.sass +0 -25
  117. data/test/sass/templates/same_name_different_ext.sass +0 -2
  118. data/test/sass/templates/same_name_different_ext.scss +0 -1
  119. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  120. data/test/sass/templates/script.sass +0 -101
  121. data/test/sass/templates/scss_import.scss +0 -12
  122. data/test/sass/templates/scss_importee.scss +0 -1
  123. data/test/sass/templates/single_import_loop.sass +0 -1
  124. data/test/sass/templates/subdir/import_up1.scss +0 -1
  125. data/test/sass/templates/subdir/import_up2.scss +0 -1
  126. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  127. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  128. data/test/sass/templates/subdir/subdir.sass +0 -6
  129. data/test/sass/templates/units.sass +0 -11
  130. data/test/sass/templates/warn.sass +0 -3
  131. data/test/sass/templates/warn_imported.sass +0 -4
  132. data/test/sass/test_helper.rb +0 -8
  133. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  134. data/test/sass/util/normalized_map_test.rb +0 -50
  135. data/test/sass/util/subset_map_test.rb +0 -90
  136. data/test/sass/util_test.rb +0 -393
  137. data/test/sass/value_helpers_test.rb +0 -178
  138. data/test/test_helper.rb +0 -149
@@ -1,95 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
- require 'fileutils'
3
- require 'sass/util/test'
4
- require 'tmpdir'
5
-
6
- class ExecTest < MiniTest::Test
7
- include Sass::Util::Test
8
-
9
- def setup
10
- @dir = Dir.mktmpdir
11
- end
12
-
13
- def teardown
14
- FileUtils.rm_rf(@dir)
15
- clean_up_sassc
16
- end
17
-
18
- def test_scss_t_expanded
19
- src = get_path("src.scss")
20
- dest = get_path("dest.css")
21
- write(src, ".ruleset { margin: 0 }")
22
- assert(exec(*%w[scss --sourcemap=none -t expanded --unix-newlines].push(src, dest)))
23
- assert_equal(".ruleset {\n margin: 0;\n}\n", read(dest))
24
- end
25
-
26
- def test_sass_convert_T_sass
27
- src = get_path("src.scss")
28
- dest = get_path("dest.css")
29
- write(src, ".ruleset { margin: 0 }")
30
- assert(exec(*%w[sass-convert -T sass --unix-newlines].push(src, dest)))
31
- assert_equal(".ruleset\n margin: 0\n", read(dest))
32
- end
33
-
34
- def test_sass_convert_T_sass_in_place
35
- src = get_path("src.scss")
36
- write(src, ".ruleset { margin: 0 }")
37
- assert(exec(*%w[sass-convert -T sass --in-place --unix-newlines].push(src)))
38
- assert_equal(".ruleset\n margin: 0\n", read(src))
39
- end
40
-
41
- def test_scss_t_expanded_no_unix_newlines
42
- return skip "Can be run on Windows only" unless Sass::Util.windows?
43
- src = get_path("src.scss")
44
- dest = get_path("dest.css")
45
- write(src, ".ruleset { margin: 0 }")
46
- assert(exec(*%w[scss -t expanded].push(src, dest)))
47
- assert_equal(".ruleset {\r\n margin: 0;\r\n}\r\n", read(dest))
48
- end
49
-
50
- def test_sass_convert_T_sass_no_unix_newlines
51
- return skip "Can be run on Windows only" unless Sass::Util.windows?
52
- src = get_path("src.scss")
53
- dest = get_path("dest.sass")
54
- write(src, ".ruleset { margin: 0 }")
55
- assert(exec(*%w[sass-convert -T sass].push(src, dest)))
56
- assert_equal(".ruleset\r\n margin: 0\r\n", read(dest))
57
- end
58
-
59
- def test_sass_convert_T_sass_in_place_no_unix_newlines
60
- return skip "Can be run on Windows only" unless Sass::Util.windows?
61
- src = get_path("src.scss")
62
- write(src, ".ruleset { margin: 0 }")
63
- assert(exec(*%w[sass-convert -T sass --in-place].push(src)))
64
- assert_equal(".ruleset\r\n margin: 0\r\n", read(src))
65
- end
66
-
67
- def test_sass_convert_R
68
- Dir.chdir(@dir) do
69
- src = get_path("styles/src.css")
70
- write(src, ".ruleset { margin: 0 }")
71
- assert(exec(*%w[sass-convert -Rq --from css --to scss --trace styles]))
72
- end
73
- end
74
-
75
- private
76
-
77
- def get_path(name)
78
- File.join(@dir, name)
79
- end
80
-
81
- def read(file)
82
- open(file, 'rb') {|f| f.read}
83
- end
84
-
85
- def write(file, content)
86
- FileUtils.mkdir_p(File.dirname(file))
87
- open(file, 'wb') {|f| f.write(content)}
88
- end
89
-
90
- def exec(script, *args)
91
- script = File.dirname(__FILE__) + '/../../bin/' + script
92
- ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT'])
93
- system(ruby, script, *args)
94
- end
95
- end
@@ -1,1679 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class ExtendTest < MiniTest::Test
4
- def test_basic
5
- assert_equal <<CSS, render(<<SCSS)
6
- .foo, .bar {
7
- a: b; }
8
- CSS
9
- .foo {a: b}
10
- .bar {@extend .foo}
11
- SCSS
12
-
13
- assert_equal <<CSS, render(<<SCSS)
14
- .foo, .bar {
15
- a: b; }
16
- CSS
17
- .bar {@extend .foo}
18
- .foo {a: b}
19
- SCSS
20
-
21
- assert_equal <<CSS, render(<<SCSS)
22
- .foo, .bar {
23
- a: b; }
24
-
25
- .bar {
26
- c: d; }
27
- CSS
28
- .foo {a: b}
29
- .bar {c: d; @extend .foo}
30
- SCSS
31
-
32
- assert_equal <<CSS, render(<<SCSS)
33
- .foo, .bar {
34
- a: b; }
35
-
36
- .bar {
37
- c: d; }
38
- CSS
39
- .foo {a: b}
40
- .bar {@extend .foo; c: d}
41
- SCSS
42
- end
43
-
44
- def test_indented_syntax
45
- assert_equal <<CSS, render(<<SASS, :syntax => :sass)
46
- .foo, .bar {
47
- a: b; }
48
- CSS
49
- .foo
50
- a: b
51
- .bar
52
- @extend .foo
53
- SASS
54
-
55
- assert_equal <<CSS, render(<<SASS, :syntax => :sass)
56
- .foo, .bar {
57
- a: b; }
58
- CSS
59
- .foo
60
- a: b
61
- .bar
62
- @extend \#{".foo"}
63
- SASS
64
- end
65
-
66
- def test_multiple_targets
67
- assert_equal <<CSS, render(<<SCSS)
68
- .foo, .bar {
69
- a: b; }
70
-
71
- .blip .foo, .blip .bar {
72
- c: d; }
73
- CSS
74
- .foo {a: b}
75
- .bar {@extend .foo}
76
- .blip .foo {c: d}
77
- SCSS
78
- end
79
-
80
- def test_multiple_extendees
81
- assert_equal <<CSS, render(<<SCSS)
82
- .foo, .baz {
83
- a: b; }
84
-
85
- .bar, .baz {
86
- c: d; }
87
- CSS
88
- .foo {a: b}
89
- .bar {c: d}
90
- .baz {@extend .foo; @extend .bar}
91
- SCSS
92
- end
93
-
94
- def test_multiple_extends_with_single_extender_and_single_target
95
- assert_extends('.foo .bar', '.baz {@extend .foo; @extend .bar}',
96
- '.foo .bar, .baz .bar, .foo .baz, .baz .baz')
97
- assert_extends '.foo.bar', '.baz {@extend .foo; @extend .bar}', '.foo.bar, .baz'
98
- end
99
-
100
- def test_multiple_extends_with_multiple_extenders_and_single_target
101
- assert_equal <<CSS, render(<<SCSS)
102
- .foo .bar, .baz .bar, .foo .bang, .baz .bang {
103
- a: b; }
104
- CSS
105
- .foo .bar {a: b}
106
- .baz {@extend .foo}
107
- .bang {@extend .bar}
108
- SCSS
109
-
110
- assert_equal <<CSS, render(<<SCSS)
111
- .foo.bar, .bar.baz, .baz.bang, .foo.bang {
112
- a: b; }
113
- CSS
114
- .foo.bar {a: b}
115
- .baz {@extend .foo}
116
- .bang {@extend .bar}
117
- SCSS
118
- end
119
-
120
- def test_chained_extends
121
- assert_equal <<CSS, render(<<SCSS)
122
- .foo, .bar, .baz, .bip {
123
- a: b; }
124
- CSS
125
- .foo {a: b}
126
- .bar {@extend .foo}
127
- .baz {@extend .bar}
128
- .bip {@extend .bar}
129
- SCSS
130
- end
131
-
132
- def test_dynamic_extendee
133
- assert_extends '.foo', '.bar {@extend #{".foo"}}', '.foo, .bar'
134
- assert_extends('[baz^="blip12px"]', '.bar {@extend [baz^="blip#{12px}"]}',
135
- '[baz^="blip12px"], .bar')
136
- end
137
-
138
- def test_nested_target
139
- assert_extends '.foo .bar', '.baz {@extend .bar}', '.foo .bar, .foo .baz'
140
- end
141
-
142
- def test_target_with_child
143
- assert_extends '.foo .bar', '.baz {@extend .foo}', '.foo .bar, .baz .bar'
144
- end
145
-
146
- def test_class_unification
147
- assert_unification '.foo.bar', '.baz {@extend .foo}', '.foo.bar, .bar.baz'
148
- assert_unification '.foo.baz', '.baz {@extend .foo}', '.baz'
149
- end
150
-
151
- def test_id_unification
152
- assert_unification '.foo.bar', '#baz {@extend .foo}', '.foo.bar, .bar#baz'
153
- assert_unification '.foo#baz', '#baz {@extend .foo}', '#baz'
154
- assert_unification '.foo#baz', '#bar {@extend .foo}', '.foo#baz'
155
- end
156
-
157
- def test_universal_unification_with_simple_target
158
- assert_unification '.foo', '* {@extend .foo}', '.foo, *'
159
- assert_unification '.foo', '*|* {@extend .foo}', '.foo, *|*'
160
- assert_unification '.foo.bar', '* {@extend .foo}', '.bar'
161
- assert_unification '.foo.bar', '*|* {@extend .foo}', '.bar'
162
- assert_unification '.foo.bar', 'ns|* {@extend .foo}', '.foo.bar, ns|*.bar'
163
- end
164
-
165
- def test_universal_unification_with_namespaceless_universal_target
166
- assert_unification '*.foo', 'ns|* {@extend .foo}', '*.foo'
167
- assert_unification '*.foo', '* {@extend .foo}', '*'
168
- assert_unification '*.foo', '*|* {@extend .foo}', '*'
169
- assert_unification '*|*.foo', '* {@extend .foo}', '*|*.foo, *'
170
- assert_unification '*|*.foo', '*|* {@extend .foo}', '*|*'
171
- assert_unification '*|*.foo', 'ns|* {@extend .foo}', '*|*.foo, ns|*'
172
- end
173
-
174
- def test_universal_unification_with_namespaced_universal_target
175
- assert_unification 'ns|*.foo', '* {@extend .foo}', 'ns|*.foo'
176
- assert_unification 'ns1|*.foo', 'ns2|* {@extend .foo}', 'ns1|*.foo'
177
- assert_unification 'ns|*.foo', '*|* {@extend .foo}', 'ns|*'
178
- assert_unification 'ns|*.foo', 'ns|* {@extend .foo}', 'ns|*'
179
- end
180
-
181
- def test_universal_unification_with_namespaceless_element_target
182
- assert_unification 'a.foo', 'ns|* {@extend .foo}', 'a.foo'
183
- assert_unification 'a.foo', '* {@extend .foo}', 'a'
184
- assert_unification 'a.foo', '*|* {@extend .foo}', 'a'
185
- assert_unification '*|a.foo', '* {@extend .foo}', '*|a.foo, a'
186
- assert_unification '*|a.foo', '*|* {@extend .foo}', '*|a'
187
- assert_unification '*|a.foo', 'ns|* {@extend .foo}', '*|a.foo, ns|a'
188
- end
189
-
190
- def test_universal_unification_with_namespaced_element_target
191
- assert_unification 'ns|a.foo', '* {@extend .foo}', 'ns|a.foo'
192
- assert_unification 'ns1|a.foo', 'ns2|* {@extend .foo}', 'ns1|a.foo'
193
- assert_unification 'ns|a.foo', '*|* {@extend .foo}', 'ns|a'
194
- assert_unification 'ns|a.foo', 'ns|* {@extend .foo}', 'ns|a'
195
- end
196
-
197
- def test_element_unification_with_simple_target
198
- assert_unification '.foo', 'a {@extend .foo}', '.foo, a'
199
- assert_unification '.foo.bar', 'a {@extend .foo}', '.foo.bar, a.bar'
200
- assert_unification '.foo.bar', '*|a {@extend .foo}', '.foo.bar, *|a.bar'
201
- assert_unification '.foo.bar', 'ns|a {@extend .foo}', '.foo.bar, ns|a.bar'
202
- end
203
-
204
- def test_element_unification_with_namespaceless_universal_target
205
- assert_unification '*.foo', 'ns|a {@extend .foo}', '*.foo'
206
- assert_unification '*.foo', 'a {@extend .foo}', '*.foo, a'
207
- assert_unification '*.foo', '*|a {@extend .foo}', '*.foo, a'
208
- assert_unification '*|*.foo', 'a {@extend .foo}', '*|*.foo, a'
209
- assert_unification '*|*.foo', '*|a {@extend .foo}', '*|*.foo, *|a'
210
- assert_unification '*|*.foo', 'ns|a {@extend .foo}', '*|*.foo, ns|a'
211
- end
212
-
213
- def test_element_unification_with_namespaced_universal_target
214
- assert_unification 'ns|*.foo', 'a {@extend .foo}', 'ns|*.foo'
215
- assert_unification 'ns1|*.foo', 'ns2|a {@extend .foo}', 'ns1|*.foo'
216
- assert_unification 'ns|*.foo', '*|a {@extend .foo}', 'ns|*.foo, ns|a'
217
- assert_unification 'ns|*.foo', 'ns|a {@extend .foo}', 'ns|*.foo, ns|a'
218
- end
219
-
220
- def test_element_unification_with_namespaceless_element_target
221
- assert_unification 'a.foo', 'ns|a {@extend .foo}', 'a.foo'
222
- assert_unification 'a.foo', 'h1 {@extend .foo}', 'a.foo'
223
- assert_unification 'a.foo', 'a {@extend .foo}', 'a'
224
- assert_unification 'a.foo', '*|a {@extend .foo}', 'a'
225
- assert_unification '*|a.foo', 'a {@extend .foo}', '*|a.foo, a'
226
- assert_unification '*|a.foo', '*|a {@extend .foo}', '*|a'
227
- assert_unification '*|a.foo', 'ns|a {@extend .foo}', '*|a.foo, ns|a'
228
- end
229
-
230
- def test_element_unification_with_namespaced_element_target
231
- assert_unification 'ns|a.foo', 'a {@extend .foo}', 'ns|a.foo'
232
- assert_unification 'ns1|a.foo', 'ns2|a {@extend .foo}', 'ns1|a.foo'
233
- assert_unification 'ns|a.foo', '*|a {@extend .foo}', 'ns|a'
234
- assert_unification 'ns|a.foo', 'ns|a {@extend .foo}', 'ns|a'
235
- end
236
-
237
- def test_attribute_unification
238
- assert_unification '[foo=bar].baz', '[foo=baz] {@extend .baz}', '[foo=bar].baz, [foo=bar][foo=baz]'
239
- assert_unification '[foo=bar].baz', '[foo^=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][foo^=bar]'
240
- assert_unification '[foo=bar].baz', '[foot=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][foot=bar]'
241
- assert_unification '[foo=bar].baz', '[ns|foo=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][ns|foo=bar]'
242
- assert_unification '%-a [foo=bar].bar', '[foo=bar] {@extend .bar}', '-a [foo=bar]'
243
- end
244
-
245
- def test_pseudo_unification
246
- assert_unification ':foo.baz', ':foo(2n+1) {@extend .baz}', ':foo.baz, :foo:foo(2n+1)'
247
- assert_unification ':foo.baz', '::foo {@extend .baz}', ':foo.baz, :foo::foo'
248
- assert_unification '::foo.baz', '::bar {@extend .baz}', '::foo.baz'
249
- assert_unification '::foo.baz', '::foo(2n+1) {@extend .baz}', '::foo.baz'
250
- assert_unification '::foo.baz', '::foo {@extend .baz}', '::foo'
251
- assert_unification '::foo(2n+1).baz', '::foo(2n+1) {@extend .baz}', '::foo(2n+1)'
252
- assert_unification ':foo.baz', ':bar {@extend .baz}', ':foo.baz, :foo:bar'
253
- assert_unification '.baz:foo', ':after {@extend .baz}', '.baz:foo, :foo:after'
254
- assert_unification '.baz:after', ':foo {@extend .baz}', '.baz:after, :foo:after'
255
- assert_unification ':foo.baz', ':foo {@extend .baz}', ':foo'
256
- end
257
-
258
- def test_pseudoelement_remains_at_end_of_selector
259
- assert_extends '.foo::bar', '.baz {@extend .foo}', '.foo::bar, .baz::bar'
260
- assert_extends 'a.foo::bar', '.baz {@extend .foo}', 'a.foo::bar, a.baz::bar'
261
- end
262
-
263
- def test_pseudoclass_remains_at_end_of_selector
264
- assert_extends '.foo:bar', '.baz {@extend .foo}', '.foo:bar, .baz:bar'
265
- assert_extends 'a.foo:bar', '.baz {@extend .foo}', 'a.foo:bar, a.baz:bar'
266
- end
267
-
268
- def test_id_unification_again
269
- assert_unification('#id.foo .bar', '#id.baz .qux {@extend .bar}',
270
- '#id.foo .bar, #id.baz.foo .qux')
271
- end
272
-
273
- def test_root_unification
274
- assert_extends(
275
- ".foo:root .bar",
276
- ".baz:root .qux {@extend .bar}",
277
- ".foo:root .bar, .baz.foo:root .qux")
278
- end
279
-
280
- def test_not_remains_at_end_of_selector
281
- assert_extends '.foo:not(.bar)', '.baz {@extend .foo}', '.foo:not(.bar), .baz:not(.bar)'
282
- end
283
-
284
- def test_pseudoelement_goes_lefter_than_pseudoclass
285
- assert_extends '.foo::bar', '.baz:bang {@extend .foo}', '.foo::bar, .baz:bang::bar'
286
- assert_extends '.foo:bar', '.baz::bang {@extend .foo}', '.foo:bar, .baz:bar::bang'
287
- end
288
-
289
- def test_pseudoelement_goes_lefter_than_not
290
- assert_extends '.foo::bar', '.baz:not(.bang) {@extend .foo}', '.foo::bar, .baz:not(.bang)::bar'
291
- assert_extends '.foo:not(.bang)', '.baz::bar {@extend .foo}', '.foo:not(.bang), .baz:not(.bang)::bar'
292
- end
293
-
294
- def test_negation_unification
295
- assert_extends ':not(.foo).baz', ':not(.bar) {@extend .baz}', ':not(.foo).baz, :not(.foo):not(.bar)'
296
- # Unifying to :not(.foo) here would reduce the specificity of the original selector.
297
- assert_extends ':not(.foo).baz', ':not(.foo) {@extend .baz}', ':not(.foo).baz, :not(.foo)'
298
- end
299
-
300
- def test_prefixed_pseudoclass_unification
301
- assert_unification(
302
- ':nth-child(2n+1 of .foo).baz',
303
- ':nth-child(2n of .foo) {@extend .baz}',
304
- ':nth-child(2n+1 of .foo).baz, :nth-child(2n+1 of .foo):nth-child(2n of .foo)')
305
-
306
- assert_unification(
307
- ':nth-child(2n+1 of .foo).baz',
308
- ':nth-child(2n+1 of .bar) {@extend .baz}',
309
- ':nth-child(2n+1 of .foo).baz, :nth-child(2n+1 of .foo):nth-child(2n+1 of .bar)')
310
-
311
- assert_unification(
312
- ':nth-child(2n+1 of .foo).baz',
313
- ':nth-child(2n+1 of .foo) {@extend .baz}',
314
- ':nth-child(2n+1 of .foo)')
315
- end
316
-
317
- def test_extend_into_not
318
- assert_extends(':not(.foo)', '.x {@extend .foo}', ':not(.foo):not(.x)')
319
- assert_extends(':not(.foo.bar)', '.x {@extend .bar}', ':not(.foo.bar):not(.foo.x)')
320
- assert_extends(
321
- ':not(.foo.bar, .baz.bar)',
322
- '.x {@extend .bar}',
323
- ':not(.foo.bar, .foo.x, .baz.bar, .baz.x)')
324
- end
325
-
326
- def test_extend_into_mergeable_pseudoclasses
327
- assert_extends(':matches(.foo)', '.x {@extend .foo}', ':matches(.foo, .x)')
328
- assert_extends(':matches(.foo.bar)', '.x {@extend .bar}', ':matches(.foo.bar, .foo.x)')
329
- assert_extends(
330
- ':matches(.foo.bar, .baz.bar)',
331
- '.x {@extend .bar}',
332
- ':matches(.foo.bar, .foo.x, .baz.bar, .baz.x)')
333
-
334
- assert_extends(':-moz-any(.foo)', '.x {@extend .foo}', ':-moz-any(.foo, .x)')
335
- assert_extends(':current(.foo)', '.x {@extend .foo}', ':current(.foo, .x)')
336
- assert_extends(':has(.foo)', '.x {@extend .foo}', ':has(.foo, .x)')
337
- assert_extends(':host(.foo)', '.x {@extend .foo}', ':host(.foo, .x)')
338
- assert_extends(':host-context(.foo)', '.x {@extend .foo}', ':host-context(.foo, .x)')
339
- assert_extends(':nth-child(n of .foo)', '.x {@extend .foo}', ':nth-child(n of .foo, .x)')
340
- assert_extends(
341
- ':nth-last-child(n of .foo)',
342
- '.x {@extend .foo}',
343
- ':nth-last-child(n of .foo, .x)')
344
- end
345
-
346
- def test_complex_extend_into_pseudoclass
347
- # Unlike other selectors, we don't allow complex selectors to be
348
- # added to `:not` if they weren't there before. At time of
349
- # writing, most browsers don't support that and will throw away
350
- # the entire selector if it exists.
351
- #assert_extends(':not(.bar)', '.x .y {@extend .bar}', ':not(.bar)')
352
-
353
- # If the `:not()` already has a complex selector, we won't break
354
- # anything by adding a new one.
355
- assert_extends(':not(.baz .bar)', '.x .y {@extend .bar}',
356
- ':not(.baz .bar):not(.baz .x .y):not(.x .baz .y)')
357
-
358
- # If the `:not()` would only contain complex selectors, there's no
359
- # harm in letting it continue to exist.
360
- assert_extends(':not(%bar)', '.x .y {@extend %bar}', ':not(.x .y)')
361
-
362
- assert_extends(':matches(.bar)', '.x .y {@extend .bar}', ':matches(.bar, .x .y)')
363
- assert_extends(':current(.bar)', '.x .y {@extend .bar}', ':current(.bar, .x .y)')
364
- assert_extends(':has(.bar)', '.x .y {@extend .bar}', ':has(.bar, .x .y)')
365
- assert_extends(':host(.bar)', '.x .y {@extend .bar}', ':host(.bar, .x .y)')
366
- assert_extends(':host-context(.bar)', '.x .y {@extend .bar}', ':host-context(.bar, .x .y)')
367
- assert_extends(
368
- ':-moz-any(.bar)',
369
- '.x .y {@extend .bar}',
370
- ':-moz-any(.bar, .x .y)')
371
- assert_extends(
372
- ':nth-child(n of .bar)',
373
- '.x .y {@extend .bar}',
374
- ':nth-child(n of .bar, .x .y)')
375
- assert_extends(
376
- ':nth-last-child(n of .bar)',
377
- '.x .y {@extend .bar}',
378
- ':nth-last-child(n of .bar, .x .y)')
379
- end
380
-
381
- def test_extend_over_selector_pseudoclass
382
- assert_extends(':not(.foo)', '.x {@extend :not(.foo)}', ':not(.foo), .x')
383
- assert_extends(
384
- ':matches(.foo, .bar)',
385
- '.x {@extend :matches(.foo, .bar)}',
386
- ':matches(.foo, .bar), .x')
387
- end
388
-
389
- def test_matches_within_not
390
- assert_extends(
391
- ':not(.foo, .bar)',
392
- ':matches(.x, .y) {@extend .foo}',
393
- ':not(.foo, .x, .y, .bar)')
394
- end
395
-
396
- def test_pseudoclasses_merge
397
- assert_extends(':matches(.foo)', ':matches(.bar) {@extend .foo}', ':matches(.foo, .bar)')
398
- assert_extends(':-moz-any(.foo)', ':-moz-any(.bar) {@extend .foo}', ':-moz-any(.foo, .bar)')
399
- assert_extends(':current(.foo)', ':current(.bar) {@extend .foo}', ':current(.foo, .bar)')
400
- assert_extends(
401
- ':nth-child(n of .foo)',
402
- ':nth-child(n of .bar) {@extend .foo}',
403
- ':nth-child(n of .foo, .bar)')
404
- assert_extends(
405
- ':nth-last-child(n of .foo)',
406
- ':nth-last-child(n of .bar) {@extend .foo}',
407
- ':nth-last-child(n of .foo, .bar)')
408
- end
409
-
410
- def test_nesting_pseudoclasses_merge
411
- assert_extends(':has(.foo)', ':has(.bar) {@extend .foo}', ':has(.foo, :has(.bar))')
412
- assert_extends(':host(.foo)', ':host(.bar) {@extend .foo}', ':host(.foo, :host(.bar))')
413
- assert_extends(
414
- ':host-context(.foo)',
415
- ':host-context(.bar) {@extend .foo}',
416
- ':host-context(.foo, :host-context(.bar))')
417
- end
418
-
419
- def test_not_unifies_with_unique_values
420
- assert_unification('foo', ':not(bar) {@extend foo}', ':not(bar)')
421
- assert_unification('#foo', ':not(#bar) {@extend #foo}', ':not(#bar)')
422
- end
423
-
424
- def test_not_adds_no_specificity
425
- assert_specificity_equals(':not(.foo)', '.foo')
426
- end
427
-
428
- def test_matches_has_a_specificity_range
429
- # `:matches(.foo, #bar)` has minimum specificity equal to that of `.foo`,
430
- # which means `:matches(.foo, #bar) .a` can have less specificity than
431
- # `#b.a`. Thus the selector generated by `#b.a` should be preserved.
432
- assert_equal <<CSS, render(<<SCSS)
433
- :matches(.foo, #bar) .a, :matches(.foo, #bar) #b.a {
434
- a: b; }
435
- CSS
436
- :matches(.foo, #bar) %x {a: b}
437
- .a {@extend %x}
438
- #b.a {@extend %x}
439
- SCSS
440
-
441
- # `:matches(.foo, #bar)` has maximum specificity equal to that of `#bar`,
442
- # which means `:matches(.foo, #bar).b` can have greater specificity than `.a
443
- # .b`. Thus the selector generated by `:matches(.foo, #bar).b` should be
444
- # preserved.
445
- assert_equal <<CSS, render(<<SCSS)
446
- .a .b, .a .b:matches(.foo, #bar) {
447
- a: b; }
448
- CSS
449
- .a %x {a: b}
450
- .b {@extend %x}
451
- .b:matches(.foo, #bar) {@extend %x}
452
- SCSS
453
- end
454
-
455
- def test_extend_into_not_and_normal_extend
456
- assert_equal <<CSS, render(<<SCSS)
457
- .x:not(.y):not(.bar), .foo:not(.y):not(.bar) {
458
- a: b; }
459
- CSS
460
- .x:not(.y) {a: b}
461
- .foo {@extend .x}
462
- .bar {@extend .y}
463
- SCSS
464
- end
465
-
466
- def test_extend_into_matches_and_normal_extend
467
- assert_equal <<CSS, render(<<SCSS)
468
- .x:matches(.y, .bar), .foo:matches(.y, .bar) {
469
- a: b; }
470
- CSS
471
- .x:matches(.y) {a: b}
472
- .foo {@extend .x}
473
- .bar {@extend .y}
474
- SCSS
475
- end
476
-
477
- def test_multilayer_pseudoclass_extend
478
- assert_equal <<CSS, render(<<SCSS)
479
- :matches(.x, .foo, .bar) {
480
- a: b; }
481
- CSS
482
- :matches(.x) {a: b}
483
- .foo {@extend .x}
484
- .bar {@extend .foo}
485
- SCSS
486
- end
487
-
488
- def test_root_only_allowed_at_root
489
- assert_extends(':root .foo', '.bar .baz {@extend .foo}',
490
- ':root .foo, :root .bar .baz')
491
- assert_extends('.foo:root .bar', '.baz:root .bang {@extend .bar}',
492
- '.foo:root .bar, .baz.foo:root .bang')
493
- assert_extends('html:root .bar', 'xml:root .bang {@extend .bar}', 'html:root .bar')
494
- assert_extends('.foo:root > .bar .x', '.baz:root .bang .y {@extend .x}',
495
- '.foo:root > .bar .x, .baz.foo:root > .bar .bang .y')
496
- end
497
-
498
- def test_comma_extendee
499
- assert_equal <<CSS, render(<<SCSS)
500
- .foo, .baz {
501
- a: b; }
502
-
503
- .bar, .baz {
504
- c: d; }
505
- CSS
506
- .foo {a: b}
507
- .bar {c: d}
508
- .baz {@extend .foo, .bar}
509
- SCSS
510
- end
511
-
512
- def test_redundant_selector_elimination
513
- assert_equal <<CSS, render(<<SCSS)
514
- .foo.bar, .x, .y {
515
- a: b; }
516
- CSS
517
- .foo.bar {a: b}
518
- .x {@extend .foo, .bar}
519
- .y {@extend .foo, .bar}
520
- SCSS
521
- end
522
-
523
- def test_nested_pseudo_selectors
524
- assert_equal <<CSS, render(<<SCSS)
525
- .foo .bar:not(.baz), .bang .bar:not(.baz) {
526
- a: b; }
527
- CSS
528
- .foo {
529
- .bar:not(.baz) {a: b}
530
- }
531
- .bang {@extend .foo}
532
- SCSS
533
- end
534
-
535
- ## Long Extendees
536
-
537
- def test_long_extendee
538
- assert_warning(<<WARNING) {assert_extends '.foo.bar', '.baz {@extend .foo.bar}', '.foo.bar, .baz'}
539
- DEPRECATION WARNING on line 2 of test_long_extendee_inline.scss:
540
- Extending a compound selector, .foo.bar, is deprecated and will not be supported in a future release.
541
- Consider "@extend .foo, .bar" instead.
542
- See http://bit.ly/ExtendCompound for details.
543
- WARNING
544
- end
545
-
546
- def test_long_extendee_requires_all_selectors
547
- silence_warnings do
548
- assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
549
- render_extends '.foo', '.baz {@extend .foo.bar}'
550
- end
551
- end
552
- end
553
-
554
- def test_long_extendee_matches_supersets
555
- silence_warnings {assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'}
556
- end
557
-
558
- def test_long_extendee_runs_unification
559
- silence_warnings {assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'}
560
- end
561
-
562
- ## Long Extenders
563
-
564
- def test_long_extender
565
- assert_extends '.foo.bar', '.baz.bang {@extend .foo}', '.foo.bar, .bar.baz.bang'
566
- end
567
-
568
- def test_long_extender_runs_unification
569
- assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
570
- end
571
-
572
- def test_long_extender_doesnt_unify
573
- assert_extends 'a.foo#bar', 'h1.baz {@extend .foo}', 'a.foo#bar'
574
- assert_extends 'a.foo#bar', '.bang#baz {@extend .foo}', 'a.foo#bar'
575
- end
576
-
577
- ## Nested Extenders
578
-
579
- def test_nested_extender
580
- assert_extends '.foo', 'foo bar {@extend .foo}', '.foo, foo bar'
581
- end
582
-
583
- def test_nested_extender_runs_unification
584
- assert_extends '.foo.bar', 'foo bar {@extend .foo}', '.foo.bar, foo bar.bar'
585
- end
586
-
587
- def test_nested_extender_doesnt_unify
588
- assert_extends 'baz.foo', 'foo bar {@extend .foo}', 'baz.foo'
589
- end
590
-
591
- def test_nested_extender_alternates_parents
592
- assert_extends('.baz .bip .foo', 'foo .grank bar {@extend .foo}',
593
- '.baz .bip .foo, .baz .bip foo .grank bar, foo .grank .baz .bip bar')
594
- end
595
-
596
- def test_nested_extender_unifies_identical_parents
597
- assert_extends('.baz .bip .foo', '.baz .bip bar {@extend .foo}',
598
- '.baz .bip .foo, .baz .bip bar')
599
- end
600
-
601
- def test_nested_extender_unifies_common_substring
602
- assert_extends('.baz .bip .bap .bink .foo', '.brat .bip .bap bar {@extend .foo}',
603
- '.baz .bip .bap .bink .foo, .baz .brat .bip .bap .bink bar, .brat .baz .bip .bap .bink bar')
604
- end
605
-
606
- def test_nested_extender_unifies_common_subseq
607
- assert_extends('.a .x .b .y .foo', '.a .n .b .m bar {@extend .foo}',
608
- '.a .x .b .y .foo, .a .x .n .b .y .m bar, .a .n .x .b .y .m bar, .a .x .n .b .m .y bar, .a .n .x .b .m .y bar')
609
- end
610
-
611
- def test_nested_extender_chooses_first_subseq
612
- assert_extends('.a .b .c .d .foo', '.c .d .a .b .bar {@extend .foo}',
613
- '.a .b .c .d .foo, .a .b .c .d .a .b .bar')
614
- end
615
-
616
- def test_nested_extender_counts_extended_subselectors
617
- assert_extends('.a .bip.bop .foo', '.b .bip .bar {@extend .foo}',
618
- '.a .bip.bop .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
619
- end
620
-
621
- def test_nested_extender_counts_extended_superselectors
622
- assert_extends('.a .bip .foo', '.b .bip.bop .bar {@extend .foo}',
623
- '.a .bip .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
624
- end
625
-
626
- def test_nested_extender_with_child_selector
627
- assert_extends '.baz .foo', 'foo > bar {@extend .foo}', '.baz .foo, .baz foo > bar'
628
- end
629
-
630
- def test_nested_extender_finds_common_selectors_around_child_selector
631
- assert_extends 'a > b c .c1', 'a c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
632
- assert_extends 'a > b c .c1', 'b c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
633
- end
634
-
635
- def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector
636
- assert_extends 'a + b c .c1', 'a c .c2 {@extend .c1}', 'a + b c .c1, a + b a c .c2, a a + b c .c2'
637
- assert_extends 'a + b c .c1', 'a b .c2 {@extend .c1}', 'a + b c .c1, a a + b c .c2'
638
- assert_extends 'a + b c .c1', 'b c .c2 {@extend .c1}', 'a + b c .c1, a + b c .c2'
639
- end
640
-
641
- def test_nested_extender_doesnt_find_common_selectors_around_sibling_selector
642
- assert_extends 'a ~ b c .c1', 'a c .c2 {@extend .c1}', 'a ~ b c .c1, a ~ b a c .c2, a a ~ b c .c2'
643
- assert_extends 'a ~ b c .c1', 'a b .c2 {@extend .c1}', 'a ~ b c .c1, a a ~ b c .c2'
644
- assert_extends 'a ~ b c .c1', 'b c .c2 {@extend .c1}', 'a ~ b c .c1, a ~ b c .c2'
645
- end
646
-
647
- def test_nested_extender_doesnt_find_common_selectors_around_reference_selector
648
- silence_warnings {assert_extends 'a /for/ b c .c1', 'a c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b a c .c2, a a /for/ b c .c2'}
649
- silence_warnings {assert_extends 'a /for/ b c .c1', 'a b .c2 {@extend .c1}', 'a /for/ b c .c1, a a /for/ b c .c2'}
650
- silence_warnings {assert_extends 'a /for/ b c .c1', 'b c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'}
651
- end
652
-
653
- def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
654
- assert_extends('.bip > .bap .foo', '.grip > .bap .bar {@extend .foo}',
655
- '.bip > .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar')
656
- assert_extends('.bap > .bip .foo', '.bap > .grip .bar {@extend .foo}',
657
- '.bap > .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar')
658
- end
659
-
660
- def test_nested_extender_with_child_selector_unifies
661
- assert_extends '.baz.foo', 'foo > bar {@extend .foo}', '.baz.foo, foo > bar.baz'
662
-
663
- assert_equal <<CSS, render(<<SCSS)
664
- .baz > .foo, .baz > .bar {
665
- a: b; }
666
- CSS
667
- .baz > {
668
- .foo {a: b}
669
- .bar {@extend .foo}
670
- }
671
- SCSS
672
-
673
- assert_equal <<CSS, render(<<SCSS)
674
- .foo .bar, .foo > .baz {
675
- a: b; }
676
- CSS
677
- .foo {
678
- .bar {a: b}
679
- > .baz {@extend .bar}
680
- }
681
- SCSS
682
- end
683
-
684
- def test_nested_extender_with_early_child_selector
685
- assert_equal <<CSS, render(<<SCSS)
686
- .foo .bar, .foo .bip > .baz {
687
- a: b; }
688
- CSS
689
- .foo {
690
- .bar {a: b}
691
- .bip > .baz {@extend .bar}
692
- }
693
- SCSS
694
-
695
- assert_equal <<CSS, render(<<SCSS)
696
- .foo .bip .bar, .foo .bip .foo > .baz {
697
- a: b; }
698
- CSS
699
- .foo {
700
- .bip .bar {a: b}
701
- > .baz {@extend .bar}
702
- }
703
- SCSS
704
-
705
- assert_extends '.foo > .bar', '.bip + .baz {@extend .bar}', '.foo > .bar, .foo > .bip + .baz'
706
- assert_extends '.foo + .bar', '.bip > .baz {@extend .bar}', '.foo + .bar, .bip > .foo + .baz'
707
- assert_extends '.foo > .bar', '.bip > .baz {@extend .bar}', '.foo > .bar, .bip.foo > .baz'
708
- end
709
-
710
- def test_nested_extender_with_trailing_child_selector
711
- assert_raises(Sass::SyntaxError, "bar > can't extend: invalid selector") do
712
- render("bar > {@extend .baz}")
713
- end
714
- end
715
-
716
- def test_nested_extender_with_sibling_selector
717
- assert_extends '.baz .foo', 'foo + bar {@extend .foo}', '.baz .foo, .baz foo + bar'
718
- end
719
-
720
- def test_nested_extender_with_hacky_selector
721
- assert_extends('.baz .foo', 'foo + > > + bar {@extend .foo}',
722
- '.baz .foo, .baz foo + > > + bar, foo .baz + > > + bar')
723
- assert_extends '.baz .foo', '> > bar {@extend .foo}', '.baz .foo, > > .baz bar'
724
- end
725
-
726
- def test_nested_extender_merges_with_same_selector
727
- assert_equal <<CSS, render(<<SCSS)
728
- .foo .bar, .foo .baz {
729
- a: b; }
730
- CSS
731
- .foo {
732
- .bar {a: b}
733
- .baz {@extend .bar} }
734
- SCSS
735
- end
736
-
737
- def test_nested_extender_with_child_selector_merges_with_same_selector
738
- assert_extends('.foo > .bar .baz', '.foo > .bar .bang {@extend .baz}',
739
- '.foo > .bar .baz, .foo > .bar .bang')
740
- end
741
-
742
- # Combinator Unification
743
-
744
- def test_combinator_unification_for_hacky_combinators
745
- assert_extends '.a > + x', '.b y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
746
- assert_extends '.a x', '.b > + y {@extend x}', '.a x, .a .b > + y, .b .a > + y'
747
- assert_extends '.a > + x', '.b > + y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
748
- assert_extends '.a ~ > + x', '.b > + y {@extend x}', '.a ~ > + x, .a .b ~ > + y, .b .a ~ > + y'
749
- assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
750
- assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
751
- assert_extends '.a ~ > + .b > x', '.c > + .d > y {@extend x}', '.a ~ > + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y'
752
- end
753
-
754
- def test_combinator_unification_double_tilde
755
- assert_extends '.a.b ~ x', '.a ~ y {@extend x}', '.a.b ~ x, .a.b ~ y'
756
- assert_extends '.a ~ x', '.a.b ~ y {@extend x}', '.a ~ x, .a.b ~ y'
757
- assert_extends '.a ~ x', '.b ~ y {@extend x}', '.a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y'
758
- assert_extends 'a.a ~ x', 'b.b ~ y {@extend x}', 'a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y'
759
- end
760
-
761
- def test_combinator_unification_tilde_plus
762
- assert_extends '.a.b + x', '.a ~ y {@extend x}', '.a.b + x, .a.b + y'
763
- assert_extends '.a + x', '.a.b ~ y {@extend x}', '.a + x, .a.b ~ .a + y, .a.b + y'
764
- assert_extends '.a + x', '.b ~ y {@extend x}', '.a + x, .b ~ .a + y, .b.a + y'
765
- assert_extends 'a.a + x', 'b.b ~ y {@extend x}', 'a.a + x, b.b ~ a.a + y'
766
- assert_extends '.a.b ~ x', '.a + y {@extend x}', '.a.b ~ x, .a.b ~ .a + y, .a.b + y'
767
- assert_extends '.a ~ x', '.a.b + y {@extend x}', '.a ~ x, .a.b + y'
768
- assert_extends '.a ~ x', '.b + y {@extend x}', '.a ~ x, .a ~ .b + y, .a.b + y'
769
- assert_extends 'a.a ~ x', 'b.b + y {@extend x}', 'a.a ~ x, a.a ~ b.b + y'
770
- end
771
-
772
- def test_combinator_unification_angle_sibling
773
- assert_extends '.a > x', '.b ~ y {@extend x}', '.a > x, .a > .b ~ y'
774
- assert_extends '.a > x', '.b + y {@extend x}', '.a > x, .a > .b + y'
775
- assert_extends '.a ~ x', '.b > y {@extend x}', '.a ~ x, .b > .a ~ y'
776
- assert_extends '.a + x', '.b > y {@extend x}', '.a + x, .b > .a + y'
777
- end
778
-
779
- def test_combinator_unification_double_angle
780
- assert_extends '.a.b > x', '.b > y {@extend x}', '.a.b > x, .b.a > y'
781
- assert_extends '.a > x', '.a.b > y {@extend x}', '.a > x, .a.b > y'
782
- assert_extends '.a > x', '.b > y {@extend x}', '.a > x, .b.a > y'
783
- assert_extends 'a.a > x', 'b.b > y {@extend x}', 'a.a > x'
784
- end
785
-
786
- def test_combinator_unification_double_plus
787
- assert_extends '.a.b + x', '.b + y {@extend x}', '.a.b + x, .b.a + y'
788
- assert_extends '.a + x', '.a.b + y {@extend x}', '.a + x, .a.b + y'
789
- assert_extends '.a + x', '.b + y {@extend x}', '.a + x, .b.a + y'
790
- assert_extends 'a.a + x', 'b.b + y {@extend x}', 'a.a + x'
791
- end
792
-
793
- def test_combinator_unification_angle_space
794
- assert_extends '.a.b > x', '.a y {@extend x}', '.a.b > x, .a.b > y'
795
- assert_extends '.a > x', '.a.b y {@extend x}', '.a > x, .a.b .a > y'
796
- assert_extends '.a > x', '.b y {@extend x}', '.a > x, .b .a > y'
797
- assert_extends '.a.b x', '.a > y {@extend x}', '.a.b x, .a.b .a > y'
798
- assert_extends '.a x', '.a.b > y {@extend x}', '.a x, .a.b > y'
799
- assert_extends '.a x', '.b > y {@extend x}', '.a x, .a .b > y'
800
- end
801
-
802
- def test_combinator_unification_plus_space
803
- assert_extends '.a.b + x', '.a y {@extend x}', '.a.b + x, .a .a.b + y'
804
- assert_extends '.a + x', '.a.b y {@extend x}', '.a + x, .a.b .a + y'
805
- assert_extends '.a + x', '.b y {@extend x}', '.a + x, .b .a + y'
806
- assert_extends '.a.b x', '.a + y {@extend x}', '.a.b x, .a.b .a + y'
807
- assert_extends '.a x', '.a.b + y {@extend x}', '.a x, .a .a.b + y'
808
- assert_extends '.a x', '.b + y {@extend x}', '.a x, .a .b + y'
809
- end
810
-
811
- def test_combinator_unification_nested
812
- assert_extends '.a > .b + x', '.c > .d + y {@extend x}', '.a > .b + x, .c.a > .d.b + y'
813
- assert_extends '.a > .b + x', '.c > y {@extend x}', '.a > .b + x, .c.a > .b + y'
814
- end
815
-
816
- def test_combinator_unification_with_newlines
817
- assert_equal <<CSS, render(<<SCSS)
818
- .a >
819
- .b
820
- + x, .c.a > .d.b + y {
821
- a: b; }
822
- CSS
823
- .a >
824
- .b
825
- + x {a: b}
826
- .c
827
- > .d +
828
- y {@extend x}
829
- SCSS
830
- end
831
-
832
- # Loops
833
-
834
- def test_extend_self_loop
835
- assert_equal <<CSS, render(<<SCSS)
836
- .foo {
837
- a: b; }
838
- CSS
839
- .foo {a: b; @extend .foo}
840
- SCSS
841
- end
842
-
843
- def test_basic_extend_loop
844
- assert_equal <<CSS, render(<<SCSS)
845
- .foo, .bar {
846
- a: b; }
847
-
848
- .bar, .foo {
849
- c: d; }
850
- CSS
851
- .foo {a: b; @extend .bar}
852
- .bar {c: d; @extend .foo}
853
- SCSS
854
- end
855
-
856
- def test_three_level_extend_loop
857
- assert_equal <<CSS, render(<<SCSS)
858
- .foo, .baz, .bar {
859
- a: b; }
860
-
861
- .bar, .foo, .baz {
862
- c: d; }
863
-
864
- .baz, .bar, .foo {
865
- e: f; }
866
- CSS
867
- .foo {a: b; @extend .bar}
868
- .bar {c: d; @extend .baz}
869
- .baz {e: f; @extend .foo}
870
- SCSS
871
- end
872
-
873
- def test_nested_extend_loop
874
- assert_equal <<CSS, render(<<SCSS)
875
- .bar, .bar .foo {
876
- a: b; }
877
- .bar .foo {
878
- c: d; }
879
- CSS
880
- .bar {
881
- a: b;
882
- .foo {c: d; @extend .bar}
883
- }
884
- SCSS
885
- end
886
-
887
- def test_cross_loop
888
- # The first law of extend means the selector should stick around.
889
- assert_equal <<CSS, render(<<SCSS)
890
- .foo.bar, .foo, .bar {
891
- a: b; }
892
- CSS
893
- .foo.bar {a: b}
894
- .foo {@extend .bar}
895
- .bar {@extend .foo}
896
- SCSS
897
- end
898
-
899
- def test_multiple_extender_merges_with_superset_selector
900
- assert_equal <<CSS, render(<<SCSS)
901
- a.bar.baz, a.foo {
902
- a: b; }
903
- CSS
904
- .foo {@extend .bar; @extend .baz}
905
- a.bar.baz {a: b}
906
- SCSS
907
- end
908
-
909
- def test_control_flow_if
910
- assert_equal <<CSS, render(<<SCSS)
911
- .true, .also-true {
912
- color: green; }
913
-
914
- .false, .also-false {
915
- color: red; }
916
- CSS
917
- .true { color: green; }
918
- .false { color: red; }
919
- .also-true {
920
- @if true { @extend .true; }
921
- @else { @extend .false; }
922
- }
923
- .also-false {
924
- @if false { @extend .true; }
925
- @else { @extend .false; }
926
- }
927
- SCSS
928
- end
929
-
930
- def test_control_flow_for
931
- assert_equal <<CSS, render(<<SCSS)
932
- .base-0, .added {
933
- color: green; }
934
-
935
- .base-1, .added {
936
- display: block; }
937
-
938
- .base-2, .added {
939
- border: 1px solid blue; }
940
- CSS
941
- .base-0 { color: green; }
942
- .base-1 { display: block; }
943
- .base-2 { border: 1px solid blue; }
944
- .added {
945
- @for $i from 0 to 3 {
946
- @extend .base-\#{$i};
947
- }
948
- }
949
- SCSS
950
- end
951
-
952
- def test_control_flow_while
953
- assert_equal <<CSS, render(<<SCSS)
954
- .base-0, .added {
955
- color: green; }
956
-
957
- .base-1, .added {
958
- display: block; }
959
-
960
- .base-2, .added {
961
- border: 1px solid blue; }
962
- CSS
963
- .base-0 { color: green; }
964
- .base-1 { display: block; }
965
- .base-2 { border: 1px solid blue; }
966
- .added {
967
- $i : 0;
968
- @while $i < 3 {
969
- @extend .base-\#{$i};
970
- $i : $i + 1;
971
- }
972
- }
973
- SCSS
974
- end
975
-
976
- def test_basic_placeholder_selector
977
- assert_extends '%foo', '.bar {@extend %foo}', '.bar'
978
- end
979
-
980
- def test_unused_placeholder_selector
981
- assert_equal <<CSS, render(<<SCSS)
982
- .baz {
983
- color: blue; }
984
- CSS
985
- %foo {color: blue}
986
- %bar {color: red}
987
- .baz {@extend %foo}
988
- SCSS
989
- end
990
-
991
- def test_placeholder_descendant_selector
992
- assert_extends '#context %foo a', '.bar {@extend %foo}', '#context .bar a'
993
- end
994
-
995
- def test_semi_placeholder_selector
996
- assert_equal <<CSS, render(<<SCSS)
997
- .bar .baz {
998
- color: blue; }
999
- CSS
1000
- #context %foo, .bar .baz {color: blue}
1001
- SCSS
1002
- end
1003
-
1004
- def test_placeholder_selector_with_multiple_extenders
1005
- assert_equal <<CSS, render(<<SCSS)
1006
- .bar, .baz {
1007
- color: blue; }
1008
- CSS
1009
- %foo {color: blue}
1010
- .bar {@extend %foo}
1011
- .baz {@extend %foo}
1012
- SCSS
1013
- end
1014
-
1015
- def test_placeholder_selector_as_modifier
1016
- assert_equal <<CSS, render(<<SCSS)
1017
- a.baz.bar {
1018
- color: blue; }
1019
- CSS
1020
- a%foo.baz {color: blue}
1021
- .bar {@extend %foo}
1022
- div {@extend %foo}
1023
- SCSS
1024
- end
1025
-
1026
- def test_placeholder_interpolation
1027
- assert_equal <<CSS, render(<<SCSS)
1028
- .bar {
1029
- color: blue; }
1030
- CSS
1031
- $foo: foo;
1032
-
1033
- %\#{$foo} {color: blue}
1034
- .bar {@extend %foo}
1035
- SCSS
1036
- end
1037
-
1038
- def test_placeholder_in_selector_pseudoclass
1039
- assert_equal <<CSS, render(<<SCSS)
1040
- :matches(.bar, .baz) {
1041
- color: blue; }
1042
- CSS
1043
- :matches(%foo) {color: blue}
1044
- .bar {@extend %foo}
1045
- .baz {@extend %foo}
1046
- SCSS
1047
- end
1048
-
1049
- def test_media_in_placeholder_selector
1050
- assert_equal <<CSS, render(<<SCSS)
1051
- .baz {
1052
- c: d; }
1053
- CSS
1054
- %foo {bar {@media screen {a: b}}}
1055
- .baz {c: d}
1056
- SCSS
1057
- end
1058
-
1059
- def test_extend_out_of_media
1060
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1061
- You may not @extend an outer selector from within @media.
1062
- You may only @extend selectors within the same directive.
1063
- From "@extend .foo" on line 3 of test_extend_out_of_media_inline.scss.
1064
- ERR
1065
- .foo {a: b}
1066
- @media screen {
1067
- .bar {@extend .foo}
1068
- }
1069
- SCSS
1070
- end
1071
-
1072
- def test_extend_out_of_unknown_directive
1073
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1074
- You may not @extend an outer selector from within @flooblehoof.
1075
- You may only @extend selectors within the same directive.
1076
- From "@extend .foo" on line 3 of test_extend_out_of_unknown_directive_inline.scss.
1077
- ERR
1078
- .foo {a: b}
1079
- @flooblehoof {
1080
- .bar {@extend .foo}
1081
- }
1082
- SCSS
1083
- end
1084
-
1085
- def test_extend_out_of_nested_directives
1086
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1087
- You may not @extend an outer selector from within @flooblehoof.
1088
- You may only @extend selectors within the same directive.
1089
- From "@extend .foo" on line 4 of test_extend_out_of_nested_directives_inline.scss.
1090
- ERR
1091
- @media screen {
1092
- .foo {a: b}
1093
- @flooblehoof {
1094
- .bar {@extend .foo}
1095
- }
1096
- }
1097
- SCSS
1098
- end
1099
-
1100
- def test_extend_within_media
1101
- assert_equal(<<CSS, render(<<SCSS))
1102
- @media screen {
1103
- .foo, .bar {
1104
- a: b; } }
1105
- CSS
1106
- @media screen {
1107
- .foo {a: b}
1108
- .bar {@extend .foo}
1109
- }
1110
- SCSS
1111
- end
1112
-
1113
- def test_extend_within_unknown_directive
1114
- assert_equal(<<CSS, render(<<SCSS))
1115
- @flooblehoof {
1116
- .foo, .bar {
1117
- a: b; } }
1118
- CSS
1119
- @flooblehoof {
1120
- .foo {a: b}
1121
- .bar {@extend .foo}
1122
- }
1123
- SCSS
1124
- end
1125
-
1126
- def test_extend_within_nested_directives
1127
- assert_equal(<<CSS, render(<<SCSS))
1128
- @media screen {
1129
- @flooblehoof {
1130
- .foo, .bar {
1131
- a: b; } } }
1132
- CSS
1133
- @media screen {
1134
- @flooblehoof {
1135
- .foo {a: b}
1136
- .bar {@extend .foo}
1137
- }
1138
- }
1139
- SCSS
1140
- end
1141
-
1142
- def test_extend_within_disparate_media
1143
- assert_equal(<<CSS, render(<<SCSS))
1144
- @media screen {
1145
- .foo, .bar {
1146
- a: b; } }
1147
- CSS
1148
- @media screen {.foo {a: b}}
1149
- @media screen {.bar {@extend .foo}}
1150
- SCSS
1151
- end
1152
-
1153
- def test_extend_within_disparate_unknown_directive
1154
- assert_equal(<<CSS, render(<<SCSS))
1155
- @flooblehoof {
1156
- .foo, .bar {
1157
- a: b; } }
1158
- @flooblehoof {}
1159
- CSS
1160
- @flooblehoof {.foo {a: b}}
1161
- @flooblehoof {.bar {@extend .foo}}
1162
- SCSS
1163
- end
1164
-
1165
- def test_extend_within_disparate_nested_directives
1166
- assert_equal(<<CSS, render(<<SCSS))
1167
- @media screen {
1168
- @flooblehoof {
1169
- .foo, .bar {
1170
- a: b; } } }
1171
- @media screen {
1172
- @flooblehoof {} }
1173
- CSS
1174
- @media screen {@flooblehoof {.foo {a: b}}}
1175
- @media screen {@flooblehoof {.bar {@extend .foo}}}
1176
- SCSS
1177
- end
1178
-
1179
- def test_extend_within_and_without_media
1180
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1181
- You may not @extend an outer selector from within @media.
1182
- You may only @extend selectors within the same directive.
1183
- From "@extend .foo" on line 4 of test_extend_within_and_without_media_inline.scss.
1184
- ERR
1185
- .foo {a: b}
1186
- @media screen {
1187
- .foo {c: d}
1188
- .bar {@extend .foo}
1189
- }
1190
- SCSS
1191
- end
1192
-
1193
- def test_extend_within_and_without_unknown_directive
1194
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1195
- You may not @extend an outer selector from within @flooblehoof.
1196
- You may only @extend selectors within the same directive.
1197
- From "@extend .foo" on line 4 of test_extend_within_and_without_unknown_directive_inline.scss.
1198
- ERR
1199
- .foo {a: b}
1200
- @flooblehoof {
1201
- .foo {c: d}
1202
- .bar {@extend .foo}
1203
- }
1204
- SCSS
1205
- end
1206
-
1207
- def test_extend_within_and_without_nested_directives
1208
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1209
- You may not @extend an outer selector from within @flooblehoof.
1210
- You may only @extend selectors within the same directive.
1211
- From "@extend .foo" on line 5 of test_extend_within_and_without_nested_directives_inline.scss.
1212
- ERR
1213
- @media screen {
1214
- .foo {a: b}
1215
- @flooblehoof {
1216
- .foo {c: d}
1217
- .bar {@extend .foo}
1218
- }
1219
- }
1220
- SCSS
1221
- end
1222
-
1223
- def test_extend_with_subject_transfers_subject_to_extender
1224
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1225
- foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
1226
- a: b; }
1227
- CSS
1228
- foo bar! baz {a: b}
1229
- .bip .bap {@extend bar}
1230
- SCSS
1231
-
1232
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1233
- foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
1234
- a: b; }
1235
- CSS
1236
- foo.x bar.y! baz.z {a: b}
1237
- .bip .bap {@extend .y}
1238
- SCSS
1239
- end
1240
-
1241
- def test_extend_with_subject_retains_subject_on_target
1242
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1243
- .foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
1244
- a: b; }
1245
- CSS
1246
- .foo! .bar {a: b}
1247
- .bip .bap {@extend .bar}
1248
- SCSS
1249
- end
1250
-
1251
- def test_extend_with_subject_transfers_subject_to_target
1252
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1253
- a.foo .bar, .bip a.bap! .bar {
1254
- a: b; }
1255
- CSS
1256
- a.foo .bar {a: b}
1257
- .bip .bap! {@extend .foo}
1258
- SCSS
1259
- end
1260
-
1261
- def test_extend_with_subject_retains_subject_on_extender
1262
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1263
- .foo .bar, .foo .bip! .bap, .bip! .foo .bap {
1264
- a: b; }
1265
- CSS
1266
- .foo .bar {a: b}
1267
- .bip! .bap {@extend .bar}
1268
- SCSS
1269
- end
1270
-
1271
- def test_extend_with_subject_fails_with_conflicting_subject
1272
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1273
- x! .bar {
1274
- a: b; }
1275
- CSS
1276
- x! .bar {a: b}
1277
- y! .bap {@extend .bar}
1278
- SCSS
1279
- end
1280
-
1281
- def test_extend_warns_when_extendee_doesnt_exist
1282
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1283
- ".foo" failed to @extend ".bar".
1284
- The selector ".bar" was not found.
1285
- Use "@extend .bar !optional" if the extend should be able to fail.
1286
- ERR
1287
- .foo {@extend .bar}
1288
- SCSS
1289
- end
1290
-
1291
- def test_extend_succeeds_when_one_extension_fails_but_others_dont
1292
- assert_equal(<<CSS, render(<<SCSS))
1293
- a.bar {
1294
- a: b; }
1295
-
1296
- .bar, b.foo {
1297
- c: d; }
1298
- CSS
1299
- a.bar {a: b}
1300
- .bar {c: d}
1301
- b.foo {@extend .bar}
1302
- SCSS
1303
- end
1304
-
1305
- def test_optional_extend_succeeds_when_extendee_doesnt_exist
1306
- assert_equal("", render(<<SCSS))
1307
- .foo {@extend .bar !optional}
1308
- SCSS
1309
- end
1310
-
1311
- def test_optional_extend_succeeds_when_extension_fails
1312
- assert_equal(<<CSS, render(<<SCSS))
1313
- a.bar {
1314
- a: b; }
1315
- CSS
1316
- a.bar {a: b}
1317
- b.foo {@extend .bar !optional}
1318
- SCSS
1319
- end
1320
-
1321
- # Regression Tests
1322
-
1323
- def test_extend_with_middle_pseudo
1324
- assert_equal(<<CSS, render(<<SCSS))
1325
- .btn:active.focus, :active.focus:before {
1326
- a: b; }
1327
- CSS
1328
- .btn:active.focus {a: b}
1329
- :before {@extend .btn}
1330
- SCSS
1331
- end
1332
-
1333
- def test_extend_parent_selector_suffix
1334
- assert_equal <<CSS, render(<<SCSS)
1335
- .a-b, .c {
1336
- x: y; }
1337
- CSS
1338
- .a {&-b {x: y}}
1339
- .c {@extend .a-b}
1340
- SCSS
1341
- end
1342
-
1343
- def test_pseudo_element_superselector
1344
- # Pseudo-elements shouldn't be removed in superselector calculations.
1345
- assert_equal <<CSS, render(<<SCSS)
1346
- a#bar, a#bar::fblthp {
1347
- a: b; }
1348
- CSS
1349
- %x#bar {a: b} // Add an id to make the results have high specificity
1350
- %y, %y::fblthp {@extend %x}
1351
- a {@extend %y}
1352
- SCSS
1353
-
1354
- # Pseudo-classes can be removed when the second law allows.
1355
- assert_equal <<CSS, render(<<SCSS)
1356
- a#bar {
1357
- a: b; }
1358
- CSS
1359
- %x#bar {a: b}
1360
- %y, %y:fblthp {@extend %x}
1361
- a {@extend %y}
1362
- SCSS
1363
-
1364
- # A few pseudo-elements can be written as pseudo-elements for historical
1365
- # reasons. See http://www.w3.org/TR/selectors4/#pseudo-elements.
1366
- %w[first-line first-letter before after].each do |pseudo|
1367
- assert_equal <<CSS, render(<<SCSS)
1368
- a#bar, a#bar:#{pseudo} {
1369
- a: b; }
1370
- CSS
1371
- %x#bar {a: b}
1372
- %y, %y:#{pseudo} {@extend %x}
1373
- a {@extend %y}
1374
- SCSS
1375
- end
1376
- end
1377
-
1378
- def test_multiple_source_redundancy_elimination
1379
- assert_equal <<CSS, render(<<SCSS)
1380
- .test-case, .test-case:active {
1381
- color: red; }
1382
-
1383
- .test-case:hover {
1384
- color: green; }
1385
- CSS
1386
- %default-color {color: red}
1387
- %alt-color {color: green}
1388
-
1389
- %default-style {
1390
- @extend %default-color;
1391
- &:hover {@extend %alt-color}
1392
- &:active {@extend %default-color}
1393
- }
1394
-
1395
- .test-case {@extend %default-style}
1396
- SCSS
1397
- end
1398
-
1399
- def test_nested_sibling_extend
1400
- assert_equal <<CSS, render(<<SCSS)
1401
- .parent .bar, .parent .foo {
1402
- width: 2000px; }
1403
- CSS
1404
- .foo {@extend .bar}
1405
-
1406
- .parent {
1407
- .bar {
1408
- width: 2000px;
1409
- }
1410
- .foo {
1411
- @extend .bar
1412
- }
1413
- }
1414
- SCSS
1415
- end
1416
-
1417
- def test_parent_and_sibling_extend
1418
- assert_equal <<CSS, render(<<SCSS)
1419
- .parent1 .parent2 .child1.child2, .parent2 .parent1 .child1.child2 {
1420
- c: d; }
1421
- CSS
1422
- %foo %bar%baz {c: d}
1423
-
1424
- .parent1 {
1425
- @extend %foo;
1426
- .child1 {@extend %bar}
1427
- }
1428
-
1429
- .parent2 {
1430
- @extend %foo;
1431
- .child2 {@extend %baz}
1432
- }
1433
- SCSS
1434
- end
1435
-
1436
- def test_nested_extend_specificity
1437
- assert_equal <<CSS, render(<<SCSS)
1438
- a :b, a :b:c {
1439
- a: b; }
1440
- CSS
1441
- %foo {a: b}
1442
-
1443
- a {
1444
- :b {@extend %foo}
1445
- :b:c {@extend %foo}
1446
- }
1447
- SCSS
1448
- end
1449
-
1450
- def test_nested_double_extend_optimization
1451
- assert_equal <<CSS, render(<<SCSS)
1452
- .parent1 .child {
1453
- a: b; }
1454
- CSS
1455
- %foo %bar {
1456
- a: b;
1457
- }
1458
-
1459
- .parent1 {
1460
- @extend %foo;
1461
-
1462
- .child {
1463
- @extend %bar;
1464
- }
1465
- }
1466
-
1467
- .parent2 {
1468
- @extend %foo;
1469
- }
1470
- SCSS
1471
- end
1472
-
1473
- def test_extend_in_double_nested_media_query
1474
- assert_equal <<CSS, render(<<SCSS)
1475
- @media all and (orientation: landscape) {
1476
- .bar {
1477
- color: blue; } }
1478
- CSS
1479
- @media all {
1480
- @media (orientation: landscape) {
1481
- %foo {color: blue}
1482
- .bar {@extend %foo}
1483
- }
1484
- }
1485
- SCSS
1486
- end
1487
-
1488
- def test_partially_failed_extend
1489
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1490
- .rc, test {
1491
- color: white; }
1492
-
1493
- .prices span.pill span.rc {
1494
- color: red; }
1495
- CSS
1496
- test { @extend .rc; }
1497
- .rc {color: white;}
1498
- .prices span.pill span.rc {color: red;}
1499
- SCSS
1500
- end
1501
-
1502
- def test_newline_near_combinator
1503
- assert_equal <<CSS, render(<<SCSS)
1504
- .a +
1505
- .b x, .a +
1506
- .b .c y, .c .a +
1507
- .b y {
1508
- a: b; }
1509
- CSS
1510
- .a +
1511
- .b x {a: b}
1512
- .c y {@extend x}
1513
- SCSS
1514
- end
1515
-
1516
- def test_duplicated_selector_with_newlines
1517
- assert_equal(<<CSS, render(<<SCSS))
1518
- .example-1-1,
1519
- .example-1-2,
1520
- .my-page-1 .my-module-1-1,
1521
- .example-1-3 {
1522
- a: b; }
1523
- CSS
1524
- .example-1-1,
1525
- .example-1-2,
1526
- .example-1-3 {
1527
- a: b;
1528
- }
1529
-
1530
- .my-page-1 .my-module-1-1 {@extend .example-1-2}
1531
- SCSS
1532
- end
1533
-
1534
- def test_nested_selector_with_child_selector_hack_extendee
1535
- assert_extends '> .foo', 'foo bar {@extend .foo}', '> .foo, > foo bar'
1536
- end
1537
-
1538
- def test_nested_selector_with_child_selector_hack_extender
1539
- assert_extends '.foo .bar', '> foo bar {@extend .bar}', '.foo .bar, > .foo foo bar, > foo .foo bar'
1540
- end
1541
-
1542
- def test_nested_selector_with_child_selector_hack_extender_and_extendee
1543
- assert_extends '> .foo', '> foo bar {@extend .foo}', '> .foo, > foo bar'
1544
- end
1545
-
1546
- def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee
1547
- assert_extends '~ .foo', '> foo bar {@extend .foo}', '~ .foo'
1548
- end
1549
-
1550
- def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline
1551
- assert_equal <<CSS, render(<<SCSS)
1552
- > .foo, > flip,
1553
- > foo bar {
1554
- a: b; }
1555
- CSS
1556
- > .foo {a: b}
1557
- flip,
1558
- > foo bar {@extend .foo}
1559
- SCSS
1560
- end
1561
-
1562
- def test_extended_parent_and_child_redundancy_elimination
1563
- assert_equal <<CSS, render(<<SCSS)
1564
- a b, d b, a c, d c {
1565
- a: b; }
1566
- CSS
1567
- a {
1568
- b {a: b}
1569
- c {@extend b}
1570
- }
1571
- d {@extend a}
1572
- SCSS
1573
- end
1574
-
1575
- def test_extend_redundancy_elimination_when_it_would_reduce_specificity
1576
- assert_extends 'a', 'a.foo {@extend a}', 'a, a.foo'
1577
- end
1578
-
1579
- def test_extend_redundancy_elimination_when_it_would_preserve_specificity
1580
- assert_extends '.bar a', 'a.foo {@extend a}', '.bar a'
1581
- end
1582
-
1583
- def test_extend_redundancy_elimination_never_eliminates_base_selector
1584
- assert_extends 'a.foo', '.foo {@extend a}', 'a.foo, .foo'
1585
- end
1586
-
1587
- def test_extend_cross_branch_redundancy_elimination
1588
- assert_equal <<CSS, render(<<SCSS)
1589
- .a .c .d, .b .c .a .d {
1590
- a: b; }
1591
- CSS
1592
- %x .c %y {a: b}
1593
- .a, .b {@extend %x}
1594
- .a .d {@extend %y}
1595
- SCSS
1596
-
1597
- assert_equal <<CSS, render(<<SCSS)
1598
- .e .a .c .d, .a .c .e .d, .e .b .c .a .d, .b .c .a .e .d {
1599
- a: b; }
1600
- CSS
1601
- .e %z {a: b}
1602
- %x .c %y {@extend %z}
1603
- .a, .b {@extend %x}
1604
- .a .d {@extend %y}
1605
- SCSS
1606
- end
1607
-
1608
- private
1609
-
1610
- def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
1611
- message = "\"#{extender}\" failed to @extend \"#{target}\"."
1612
- reason =
1613
- if reason == :not_found
1614
- "The selector \"#{target}\" was not found."
1615
- else
1616
- "No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
1617
- end
1618
-
1619
- assert_raise_message(Sass::SyntaxError, <<ERR) {yield}
1620
- #{message}
1621
- #{reason}
1622
- Use "@extend #{target} !optional" if the extend should be able to fail.
1623
- ERR
1624
- end
1625
-
1626
- def assert_unification(selector, extension, unified, nested = true)
1627
- # Do some trickery so the first law of extend doesn't get in our way.
1628
- assert_extends(
1629
- "%-a #{selector}",
1630
- extension + " -a {@extend %-a}",
1631
- unified.split(', ').map {|s| "-a #{s}"}.join(', '))
1632
- end
1633
-
1634
- def assert_specificity_equals(sel1, sel2)
1635
- assert_specificity_gte(sel1, sel2)
1636
- assert_specificity_gte(sel2, sel1)
1637
- end
1638
-
1639
- def assert_specificity_gte(sel1, sel2)
1640
- assert_equal <<CSS, render(<<SCSS)
1641
- #{sel1} .a {
1642
- a: b; }
1643
- CSS
1644
- #{sel1} %-a {a: b}
1645
- .a {@extend %-a}
1646
- #{sel2}.a {@extend %-a}
1647
- SCSS
1648
- end
1649
-
1650
- def render_unification(selector, extension)
1651
- render_extends(
1652
- "%-a #{selector}",
1653
- extension + " -a {@extend %-a}")
1654
- end
1655
-
1656
- def assert_extends(selector, extension, result)
1657
- assert_equal <<CSS, render_extends(selector, extension)
1658
- #{result} {
1659
- a: b; }
1660
- CSS
1661
- end
1662
-
1663
- def assert_extends_to_nothing(selector, extension)
1664
- assert_equal '', render_extends(selector, extension)
1665
- end
1666
-
1667
- def render_extends(selector, extension)
1668
- render(<<SCSS)
1669
- #{selector} {a: b}
1670
- #{extension}
1671
- SCSS
1672
- end
1673
-
1674
- def render(sass, options = {})
1675
- options = {:syntax => :scss}.merge(options)
1676
- munge_filename options
1677
- Sass::Engine.new(sass, options).render
1678
- end
1679
- end