sass 3.6.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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