sass 3.5.2 → 3.7.4

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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +1 -1
  3. data/CONTRIBUTING.md +3 -3
  4. data/README.md +17 -9
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/extra/sass-spec-ref.sh +9 -1
  8. data/lib/sass/engine.rb +1 -9
  9. data/lib/sass/exec/base.rb +0 -2
  10. data/lib/sass/exec/sass_scss.rb +1 -5
  11. data/lib/sass/importers/filesystem.rb +4 -2
  12. data/lib/sass/logger/base.rb +11 -0
  13. data/lib/sass/script/css_parser.rb +4 -1
  14. data/lib/sass/script/functions.rb +76 -41
  15. data/lib/sass/script/lexer.rb +62 -19
  16. data/lib/sass/script/parser.rb +260 -93
  17. data/lib/sass/script/tree/funcall.rb +0 -4
  18. data/lib/sass/script/tree/interpolation.rb +0 -3
  19. data/lib/sass/script/tree/operation.rb +1 -1
  20. data/lib/sass/script/value/color.rb +3 -2
  21. data/lib/sass/script/value/helpers.rb +8 -2
  22. data/lib/sass/script/value/number.rb +2 -1
  23. data/lib/sass/scss/css_parser.rb +6 -1
  24. data/lib/sass/scss/parser.rb +48 -18
  25. data/lib/sass/scss/rx.rb +1 -1
  26. data/lib/sass/scss/static_parser.rb +15 -18
  27. data/lib/sass/selector/comma_sequence.rb +2 -1
  28. data/lib/sass/selector/pseudo.rb +1 -1
  29. data/lib/sass/selector/sequence.rb +0 -4
  30. data/lib/sass/source/map.rb +0 -4
  31. data/lib/sass/tree/rule_node.rb +3 -6
  32. data/lib/sass/tree/visitors/perform.rb +2 -6
  33. data/lib/sass/tree/visitors/to_css.rb +4 -11
  34. data/lib/sass/util.rb +60 -20
  35. data/lib/sass/version.rb +0 -2
  36. metadata +38 -162
  37. data/Rakefile +0 -338
  38. data/lib/test.css +0 -4
  39. data/lib/test.css.map +0 -7
  40. data/test/sass-spec.yml +0 -3
  41. data/test/sass/cache_test.rb +0 -130
  42. data/test/sass/callbacks_test.rb +0 -60
  43. data/test/sass/compiler_test.rb +0 -225
  44. data/test/sass/conversion_test.rb +0 -2138
  45. data/test/sass/css2sass_test.rb +0 -523
  46. data/test/sass/css_variable_test.rb +0 -237
  47. data/test/sass/data/hsl-rgb.txt +0 -319
  48. data/test/sass/encoding_test.rb +0 -188
  49. data/test/sass/engine_test.rb +0 -3499
  50. data/test/sass/exec_test.rb +0 -95
  51. data/test/sass/extend_test.rb +0 -1678
  52. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  53. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  54. data/test/sass/functions_test.rb +0 -2021
  55. data/test/sass/importer_test.rb +0 -420
  56. data/test/sass/logger_test.rb +0 -57
  57. data/test/sass/mock_importer.rb +0 -49
  58. data/test/sass/more_results/more1.css +0 -9
  59. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  60. data/test/sass/more_results/more_import.css +0 -29
  61. data/test/sass/more_templates/_more_partial.sass +0 -2
  62. data/test/sass/more_templates/more1.sass +0 -23
  63. data/test/sass/more_templates/more_import.sass +0 -11
  64. data/test/sass/plugin_test.rb +0 -552
  65. data/test/sass/results/alt.css +0 -4
  66. data/test/sass/results/basic.css +0 -9
  67. data/test/sass/results/cached_import_option.css +0 -3
  68. data/test/sass/results/compact.css +0 -5
  69. data/test/sass/results/complex.css +0 -86
  70. data/test/sass/results/compressed.css +0 -1
  71. data/test/sass/results/expanded.css +0 -19
  72. data/test/sass/results/filename_fn.css +0 -3
  73. data/test/sass/results/if.css +0 -3
  74. data/test/sass/results/import.css +0 -31
  75. data/test/sass/results/import_charset.css +0 -5
  76. data/test/sass/results/import_charset_ibm866.css +0 -5
  77. data/test/sass/results/import_content.css +0 -1
  78. data/test/sass/results/line_numbers.css +0 -49
  79. data/test/sass/results/mixins.css +0 -95
  80. data/test/sass/results/multiline.css +0 -24
  81. data/test/sass/results/nested.css +0 -22
  82. data/test/sass/results/options.css +0 -1
  83. data/test/sass/results/parent_ref.css +0 -13
  84. data/test/sass/results/script.css +0 -16
  85. data/test/sass/results/scss_import.css +0 -31
  86. data/test/sass/results/scss_importee.css +0 -2
  87. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  88. data/test/sass/results/subdir/subdir.css +0 -3
  89. data/test/sass/results/units.css +0 -11
  90. data/test/sass/results/warn.css +0 -0
  91. data/test/sass/results/warn_imported.css +0 -0
  92. data/test/sass/script_conversion_test.rb +0 -365
  93. data/test/sass/script_test.rb +0 -1429
  94. data/test/sass/scss/css_test.rb +0 -1266
  95. data/test/sass/scss/rx_test.rb +0 -159
  96. data/test/sass/scss/scss_test.rb +0 -4238
  97. data/test/sass/scss/test_helper.rb +0 -37
  98. data/test/sass/source_map_test.rb +0 -1052
  99. data/test/sass/superselector_test.rb +0 -209
  100. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  101. data/test/sass/templates/_double_import_loop2.sass +0 -1
  102. data/test/sass/templates/_filename_fn_import.scss +0 -11
  103. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  104. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  105. data/test/sass/templates/_imported_content.sass +0 -3
  106. data/test/sass/templates/_partial.sass +0 -2
  107. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  108. data/test/sass/templates/alt.sass +0 -16
  109. data/test/sass/templates/basic.sass +0 -23
  110. data/test/sass/templates/bork1.sass +0 -2
  111. data/test/sass/templates/bork2.sass +0 -2
  112. data/test/sass/templates/bork3.sass +0 -2
  113. data/test/sass/templates/bork4.sass +0 -2
  114. data/test/sass/templates/bork5.sass +0 -3
  115. data/test/sass/templates/cached_import_option.scss +0 -3
  116. data/test/sass/templates/compact.sass +0 -17
  117. data/test/sass/templates/complex.sass +0 -305
  118. data/test/sass/templates/compressed.sass +0 -15
  119. data/test/sass/templates/double_import_loop1.sass +0 -1
  120. data/test/sass/templates/expanded.sass +0 -17
  121. data/test/sass/templates/filename_fn.scss +0 -18
  122. data/test/sass/templates/if.sass +0 -11
  123. data/test/sass/templates/import.sass +0 -12
  124. data/test/sass/templates/import_charset.sass +0 -9
  125. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  126. data/test/sass/templates/import_content.sass +0 -4
  127. data/test/sass/templates/importee.less +0 -2
  128. data/test/sass/templates/importee.sass +0 -19
  129. data/test/sass/templates/line_numbers.sass +0 -13
  130. data/test/sass/templates/mixin_bork.sass +0 -5
  131. data/test/sass/templates/mixins.sass +0 -76
  132. data/test/sass/templates/multiline.sass +0 -20
  133. data/test/sass/templates/nested.sass +0 -25
  134. data/test/sass/templates/nested_bork1.sass +0 -2
  135. data/test/sass/templates/nested_bork2.sass +0 -2
  136. data/test/sass/templates/nested_bork3.sass +0 -2
  137. data/test/sass/templates/nested_bork4.sass +0 -2
  138. data/test/sass/templates/nested_import.sass +0 -2
  139. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  140. data/test/sass/templates/options.sass +0 -2
  141. data/test/sass/templates/parent_ref.sass +0 -25
  142. data/test/sass/templates/same_name_different_ext.sass +0 -2
  143. data/test/sass/templates/same_name_different_ext.scss +0 -1
  144. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/script.sass +0 -101
  146. data/test/sass/templates/scss_import.scss +0 -12
  147. data/test/sass/templates/scss_importee.scss +0 -1
  148. data/test/sass/templates/single_import_loop.sass +0 -1
  149. data/test/sass/templates/subdir/import_up1.scss +0 -1
  150. data/test/sass/templates/subdir/import_up2.scss +0 -1
  151. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  152. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  153. data/test/sass/templates/subdir/subdir.sass +0 -6
  154. data/test/sass/templates/units.sass +0 -11
  155. data/test/sass/templates/warn.sass +0 -3
  156. data/test/sass/templates/warn_imported.sass +0 -4
  157. data/test/sass/test_helper.rb +0 -8
  158. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  159. data/test/sass/util/normalized_map_test.rb +0 -50
  160. data/test/sass/util/subset_map_test.rb +0 -90
  161. data/test/sass/util_test.rb +0 -403
  162. data/test/sass/value_helpers_test.rb +0 -178
  163. 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,1678 +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
- See https://github.com/sass/sass/issues/1599 for details.
542
- WARNING
543
- end
544
-
545
- def test_long_extendee_requires_all_selectors
546
- silence_warnings do
547
- assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
548
- render_extends '.foo', '.baz {@extend .foo.bar}'
549
- end
550
- end
551
- end
552
-
553
- def test_long_extendee_matches_supersets
554
- silence_warnings {assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'}
555
- end
556
-
557
- def test_long_extendee_runs_unification
558
- silence_warnings {assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'}
559
- end
560
-
561
- ## Long Extenders
562
-
563
- def test_long_extender
564
- assert_extends '.foo.bar', '.baz.bang {@extend .foo}', '.foo.bar, .bar.baz.bang'
565
- end
566
-
567
- def test_long_extender_runs_unification
568
- assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
569
- end
570
-
571
- def test_long_extender_doesnt_unify
572
- assert_extends 'a.foo#bar', 'h1.baz {@extend .foo}', 'a.foo#bar'
573
- assert_extends 'a.foo#bar', '.bang#baz {@extend .foo}', 'a.foo#bar'
574
- end
575
-
576
- ## Nested Extenders
577
-
578
- def test_nested_extender
579
- assert_extends '.foo', 'foo bar {@extend .foo}', '.foo, foo bar'
580
- end
581
-
582
- def test_nested_extender_runs_unification
583
- assert_extends '.foo.bar', 'foo bar {@extend .foo}', '.foo.bar, foo bar.bar'
584
- end
585
-
586
- def test_nested_extender_doesnt_unify
587
- assert_extends 'baz.foo', 'foo bar {@extend .foo}', 'baz.foo'
588
- end
589
-
590
- def test_nested_extender_alternates_parents
591
- assert_extends('.baz .bip .foo', 'foo .grank bar {@extend .foo}',
592
- '.baz .bip .foo, .baz .bip foo .grank bar, foo .grank .baz .bip bar')
593
- end
594
-
595
- def test_nested_extender_unifies_identical_parents
596
- assert_extends('.baz .bip .foo', '.baz .bip bar {@extend .foo}',
597
- '.baz .bip .foo, .baz .bip bar')
598
- end
599
-
600
- def test_nested_extender_unifies_common_substring
601
- assert_extends('.baz .bip .bap .bink .foo', '.brat .bip .bap bar {@extend .foo}',
602
- '.baz .bip .bap .bink .foo, .baz .brat .bip .bap .bink bar, .brat .baz .bip .bap .bink bar')
603
- end
604
-
605
- def test_nested_extender_unifies_common_subseq
606
- assert_extends('.a .x .b .y .foo', '.a .n .b .m bar {@extend .foo}',
607
- '.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')
608
- end
609
-
610
- def test_nested_extender_chooses_first_subseq
611
- assert_extends('.a .b .c .d .foo', '.c .d .a .b .bar {@extend .foo}',
612
- '.a .b .c .d .foo, .a .b .c .d .a .b .bar')
613
- end
614
-
615
- def test_nested_extender_counts_extended_subselectors
616
- assert_extends('.a .bip.bop .foo', '.b .bip .bar {@extend .foo}',
617
- '.a .bip.bop .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
618
- end
619
-
620
- def test_nested_extender_counts_extended_superselectors
621
- assert_extends('.a .bip .foo', '.b .bip.bop .bar {@extend .foo}',
622
- '.a .bip .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
623
- end
624
-
625
- def test_nested_extender_with_child_selector
626
- assert_extends '.baz .foo', 'foo > bar {@extend .foo}', '.baz .foo, .baz foo > bar'
627
- end
628
-
629
- def test_nested_extender_finds_common_selectors_around_child_selector
630
- assert_extends 'a > b c .c1', 'a c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
631
- assert_extends 'a > b c .c1', 'b c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
632
- end
633
-
634
- def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector
635
- 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'
636
- assert_extends 'a + b c .c1', 'a b .c2 {@extend .c1}', 'a + b c .c1, a a + b c .c2'
637
- assert_extends 'a + b c .c1', 'b c .c2 {@extend .c1}', 'a + b c .c1, a + b c .c2'
638
- end
639
-
640
- def test_nested_extender_doesnt_find_common_selectors_around_sibling_selector
641
- 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'
642
- assert_extends 'a ~ b c .c1', 'a b .c2 {@extend .c1}', 'a ~ b c .c1, a a ~ b c .c2'
643
- assert_extends 'a ~ b c .c1', 'b c .c2 {@extend .c1}', 'a ~ b c .c1, a ~ b c .c2'
644
- end
645
-
646
- def test_nested_extender_doesnt_find_common_selectors_around_reference_selector
647
- 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'}
648
- 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'}
649
- silence_warnings {assert_extends 'a /for/ b c .c1', 'b c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'}
650
- end
651
-
652
- def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
653
- assert_extends('.bip > .bap .foo', '.grip > .bap .bar {@extend .foo}',
654
- '.bip > .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar')
655
- assert_extends('.bap > .bip .foo', '.bap > .grip .bar {@extend .foo}',
656
- '.bap > .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar')
657
- end
658
-
659
- def test_nested_extender_with_child_selector_unifies
660
- assert_extends '.baz.foo', 'foo > bar {@extend .foo}', '.baz.foo, foo > bar.baz'
661
-
662
- assert_equal <<CSS, render(<<SCSS)
663
- .baz > .foo, .baz > .bar {
664
- a: b; }
665
- CSS
666
- .baz > {
667
- .foo {a: b}
668
- .bar {@extend .foo}
669
- }
670
- SCSS
671
-
672
- assert_equal <<CSS, render(<<SCSS)
673
- .foo .bar, .foo > .baz {
674
- a: b; }
675
- CSS
676
- .foo {
677
- .bar {a: b}
678
- > .baz {@extend .bar}
679
- }
680
- SCSS
681
- end
682
-
683
- def test_nested_extender_with_early_child_selector
684
- assert_equal <<CSS, render(<<SCSS)
685
- .foo .bar, .foo .bip > .baz {
686
- a: b; }
687
- CSS
688
- .foo {
689
- .bar {a: b}
690
- .bip > .baz {@extend .bar}
691
- }
692
- SCSS
693
-
694
- assert_equal <<CSS, render(<<SCSS)
695
- .foo .bip .bar, .foo .bip .foo > .baz {
696
- a: b; }
697
- CSS
698
- .foo {
699
- .bip .bar {a: b}
700
- > .baz {@extend .bar}
701
- }
702
- SCSS
703
-
704
- assert_extends '.foo > .bar', '.bip + .baz {@extend .bar}', '.foo > .bar, .foo > .bip + .baz'
705
- assert_extends '.foo + .bar', '.bip > .baz {@extend .bar}', '.foo + .bar, .bip > .foo + .baz'
706
- assert_extends '.foo > .bar', '.bip > .baz {@extend .bar}', '.foo > .bar, .bip.foo > .baz'
707
- end
708
-
709
- def test_nested_extender_with_trailing_child_selector
710
- assert_raises(Sass::SyntaxError, "bar > can't extend: invalid selector") do
711
- render("bar > {@extend .baz}")
712
- end
713
- end
714
-
715
- def test_nested_extender_with_sibling_selector
716
- assert_extends '.baz .foo', 'foo + bar {@extend .foo}', '.baz .foo, .baz foo + bar'
717
- end
718
-
719
- def test_nested_extender_with_hacky_selector
720
- assert_extends('.baz .foo', 'foo + > > + bar {@extend .foo}',
721
- '.baz .foo, .baz foo + > > + bar, foo .baz + > > + bar')
722
- assert_extends '.baz .foo', '> > bar {@extend .foo}', '.baz .foo, > > .baz bar'
723
- end
724
-
725
- def test_nested_extender_merges_with_same_selector
726
- assert_equal <<CSS, render(<<SCSS)
727
- .foo .bar, .foo .baz {
728
- a: b; }
729
- CSS
730
- .foo {
731
- .bar {a: b}
732
- .baz {@extend .bar} }
733
- SCSS
734
- end
735
-
736
- def test_nested_extender_with_child_selector_merges_with_same_selector
737
- assert_extends('.foo > .bar .baz', '.foo > .bar .bang {@extend .baz}',
738
- '.foo > .bar .baz, .foo > .bar .bang')
739
- end
740
-
741
- # Combinator Unification
742
-
743
- def test_combinator_unification_for_hacky_combinators
744
- assert_extends '.a > + x', '.b y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
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'
749
- assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
750
- assert_extends '.a ~ > + .b > x', '.c > + .d > y {@extend x}', '.a ~ > + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y'
751
- end
752
-
753
- def test_combinator_unification_double_tilde
754
- assert_extends '.a.b ~ x', '.a ~ y {@extend x}', '.a.b ~ x, .a.b ~ y'
755
- assert_extends '.a ~ x', '.a.b ~ y {@extend x}', '.a ~ x, .a.b ~ y'
756
- assert_extends '.a ~ x', '.b ~ y {@extend x}', '.a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y'
757
- assert_extends 'a.a ~ x', 'b.b ~ y {@extend x}', 'a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y'
758
- end
759
-
760
- def test_combinator_unification_tilde_plus
761
- assert_extends '.a.b + x', '.a ~ y {@extend x}', '.a.b + x, .a.b + y'
762
- assert_extends '.a + x', '.a.b ~ y {@extend x}', '.a + x, .a.b ~ .a + y, .a.b + y'
763
- assert_extends '.a + x', '.b ~ y {@extend x}', '.a + x, .b ~ .a + y, .b.a + y'
764
- assert_extends 'a.a + x', 'b.b ~ y {@extend x}', 'a.a + x, b.b ~ a.a + y'
765
- assert_extends '.a.b ~ x', '.a + y {@extend x}', '.a.b ~ x, .a.b ~ .a + y, .a.b + y'
766
- assert_extends '.a ~ x', '.a.b + y {@extend x}', '.a ~ x, .a.b + y'
767
- assert_extends '.a ~ x', '.b + y {@extend x}', '.a ~ x, .a ~ .b + y, .a.b + y'
768
- assert_extends 'a.a ~ x', 'b.b + y {@extend x}', 'a.a ~ x, a.a ~ b.b + y'
769
- end
770
-
771
- def test_combinator_unification_angle_sibling
772
- assert_extends '.a > x', '.b ~ y {@extend x}', '.a > x, .a > .b ~ y'
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, .b > .a ~ y'
775
- assert_extends '.a + x', '.b > y {@extend x}', '.a + x, .b > .a + y'
776
- end
777
-
778
- def test_combinator_unification_double_angle
779
- assert_extends '.a.b > x', '.b > y {@extend x}', '.a.b > x, .b.a > y'
780
- assert_extends '.a > x', '.a.b > y {@extend x}', '.a > x, .a.b > y'
781
- assert_extends '.a > x', '.b > y {@extend x}', '.a > x, .b.a > y'
782
- assert_extends 'a.a > x', 'b.b > y {@extend x}', 'a.a > x'
783
- end
784
-
785
- def test_combinator_unification_double_plus
786
- assert_extends '.a.b + x', '.b + y {@extend x}', '.a.b + x, .b.a + y'
787
- assert_extends '.a + x', '.a.b + y {@extend x}', '.a + x, .a.b + y'
788
- assert_extends '.a + x', '.b + y {@extend x}', '.a + x, .b.a + y'
789
- assert_extends 'a.a + x', 'b.b + y {@extend x}', 'a.a + x'
790
- end
791
-
792
- def test_combinator_unification_angle_space
793
- assert_extends '.a.b > x', '.a y {@extend x}', '.a.b > x, .a.b > y'
794
- assert_extends '.a > x', '.a.b y {@extend x}', '.a > x, .a.b .a > y'
795
- assert_extends '.a > x', '.b y {@extend x}', '.a > x, .b .a > y'
796
- assert_extends '.a.b x', '.a > y {@extend x}', '.a.b x, .a.b .a > y'
797
- assert_extends '.a x', '.a.b > y {@extend x}', '.a x, .a.b > y'
798
- assert_extends '.a x', '.b > y {@extend x}', '.a x, .a .b > y'
799
- end
800
-
801
- def test_combinator_unification_plus_space
802
- assert_extends '.a.b + x', '.a y {@extend x}', '.a.b + x, .a .a.b + y'
803
- assert_extends '.a + x', '.a.b y {@extend x}', '.a + x, .a.b .a + y'
804
- assert_extends '.a + x', '.b y {@extend x}', '.a + x, .b .a + y'
805
- assert_extends '.a.b x', '.a + y {@extend x}', '.a.b x, .a.b .a + y'
806
- assert_extends '.a x', '.a.b + y {@extend x}', '.a x, .a .a.b + y'
807
- assert_extends '.a x', '.b + y {@extend x}', '.a x, .a .b + y'
808
- end
809
-
810
- def test_combinator_unification_nested
811
- assert_extends '.a > .b + x', '.c > .d + y {@extend x}', '.a > .b + x, .c.a > .d.b + y'
812
- assert_extends '.a > .b + x', '.c > y {@extend x}', '.a > .b + x, .c.a > .b + y'
813
- end
814
-
815
- def test_combinator_unification_with_newlines
816
- assert_equal <<CSS, render(<<SCSS)
817
- .a >
818
- .b
819
- + x, .c.a > .d.b + y {
820
- a: b; }
821
- CSS
822
- .a >
823
- .b
824
- + x {a: b}
825
- .c
826
- > .d +
827
- y {@extend x}
828
- SCSS
829
- end
830
-
831
- # Loops
832
-
833
- def test_extend_self_loop
834
- assert_equal <<CSS, render(<<SCSS)
835
- .foo {
836
- a: b; }
837
- CSS
838
- .foo {a: b; @extend .foo}
839
- SCSS
840
- end
841
-
842
- def test_basic_extend_loop
843
- assert_equal <<CSS, render(<<SCSS)
844
- .foo, .bar {
845
- a: b; }
846
-
847
- .bar, .foo {
848
- c: d; }
849
- CSS
850
- .foo {a: b; @extend .bar}
851
- .bar {c: d; @extend .foo}
852
- SCSS
853
- end
854
-
855
- def test_three_level_extend_loop
856
- assert_equal <<CSS, render(<<SCSS)
857
- .foo, .baz, .bar {
858
- a: b; }
859
-
860
- .bar, .foo, .baz {
861
- c: d; }
862
-
863
- .baz, .bar, .foo {
864
- e: f; }
865
- CSS
866
- .foo {a: b; @extend .bar}
867
- .bar {c: d; @extend .baz}
868
- .baz {e: f; @extend .foo}
869
- SCSS
870
- end
871
-
872
- def test_nested_extend_loop
873
- assert_equal <<CSS, render(<<SCSS)
874
- .bar, .bar .foo {
875
- a: b; }
876
- .bar .foo {
877
- c: d; }
878
- CSS
879
- .bar {
880
- a: b;
881
- .foo {c: d; @extend .bar}
882
- }
883
- SCSS
884
- end
885
-
886
- def test_cross_loop
887
- # The first law of extend means the selector should stick around.
888
- assert_equal <<CSS, render(<<SCSS)
889
- .foo.bar, .foo, .bar {
890
- a: b; }
891
- CSS
892
- .foo.bar {a: b}
893
- .foo {@extend .bar}
894
- .bar {@extend .foo}
895
- SCSS
896
- end
897
-
898
- def test_multiple_extender_merges_with_superset_selector
899
- assert_equal <<CSS, render(<<SCSS)
900
- a.bar.baz, a.foo {
901
- a: b; }
902
- CSS
903
- .foo {@extend .bar; @extend .baz}
904
- a.bar.baz {a: b}
905
- SCSS
906
- end
907
-
908
- def test_control_flow_if
909
- assert_equal <<CSS, render(<<SCSS)
910
- .true, .also-true {
911
- color: green; }
912
-
913
- .false, .also-false {
914
- color: red; }
915
- CSS
916
- .true { color: green; }
917
- .false { color: red; }
918
- .also-true {
919
- @if true { @extend .true; }
920
- @else { @extend .false; }
921
- }
922
- .also-false {
923
- @if false { @extend .true; }
924
- @else { @extend .false; }
925
- }
926
- SCSS
927
- end
928
-
929
- def test_control_flow_for
930
- assert_equal <<CSS, render(<<SCSS)
931
- .base-0, .added {
932
- color: green; }
933
-
934
- .base-1, .added {
935
- display: block; }
936
-
937
- .base-2, .added {
938
- border: 1px solid blue; }
939
- CSS
940
- .base-0 { color: green; }
941
- .base-1 { display: block; }
942
- .base-2 { border: 1px solid blue; }
943
- .added {
944
- @for $i from 0 to 3 {
945
- @extend .base-\#{$i};
946
- }
947
- }
948
- SCSS
949
- end
950
-
951
- def test_control_flow_while
952
- assert_equal <<CSS, render(<<SCSS)
953
- .base-0, .added {
954
- color: green; }
955
-
956
- .base-1, .added {
957
- display: block; }
958
-
959
- .base-2, .added {
960
- border: 1px solid blue; }
961
- CSS
962
- .base-0 { color: green; }
963
- .base-1 { display: block; }
964
- .base-2 { border: 1px solid blue; }
965
- .added {
966
- $i : 0;
967
- @while $i < 3 {
968
- @extend .base-\#{$i};
969
- $i : $i + 1;
970
- }
971
- }
972
- SCSS
973
- end
974
-
975
- def test_basic_placeholder_selector
976
- assert_extends '%foo', '.bar {@extend %foo}', '.bar'
977
- end
978
-
979
- def test_unused_placeholder_selector
980
- assert_equal <<CSS, render(<<SCSS)
981
- .baz {
982
- color: blue; }
983
- CSS
984
- %foo {color: blue}
985
- %bar {color: red}
986
- .baz {@extend %foo}
987
- SCSS
988
- end
989
-
990
- def test_placeholder_descendant_selector
991
- assert_extends '#context %foo a', '.bar {@extend %foo}', '#context .bar a'
992
- end
993
-
994
- def test_semi_placeholder_selector
995
- assert_equal <<CSS, render(<<SCSS)
996
- .bar .baz {
997
- color: blue; }
998
- CSS
999
- #context %foo, .bar .baz {color: blue}
1000
- SCSS
1001
- end
1002
-
1003
- def test_placeholder_selector_with_multiple_extenders
1004
- assert_equal <<CSS, render(<<SCSS)
1005
- .bar, .baz {
1006
- color: blue; }
1007
- CSS
1008
- %foo {color: blue}
1009
- .bar {@extend %foo}
1010
- .baz {@extend %foo}
1011
- SCSS
1012
- end
1013
-
1014
- def test_placeholder_selector_as_modifier
1015
- assert_equal <<CSS, render(<<SCSS)
1016
- a.baz.bar {
1017
- color: blue; }
1018
- CSS
1019
- a%foo.baz {color: blue}
1020
- .bar {@extend %foo}
1021
- div {@extend %foo}
1022
- SCSS
1023
- end
1024
-
1025
- def test_placeholder_interpolation
1026
- assert_equal <<CSS, render(<<SCSS)
1027
- .bar {
1028
- color: blue; }
1029
- CSS
1030
- $foo: foo;
1031
-
1032
- %\#{$foo} {color: blue}
1033
- .bar {@extend %foo}
1034
- SCSS
1035
- end
1036
-
1037
- def test_placeholder_in_selector_pseudoclass
1038
- assert_equal <<CSS, render(<<SCSS)
1039
- :matches(.bar, .baz) {
1040
- color: blue; }
1041
- CSS
1042
- :matches(%foo) {color: blue}
1043
- .bar {@extend %foo}
1044
- .baz {@extend %foo}
1045
- SCSS
1046
- end
1047
-
1048
- def test_media_in_placeholder_selector
1049
- assert_equal <<CSS, render(<<SCSS)
1050
- .baz {
1051
- c: d; }
1052
- CSS
1053
- %foo {bar {@media screen {a: b}}}
1054
- .baz {c: d}
1055
- SCSS
1056
- end
1057
-
1058
- def test_extend_out_of_media
1059
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1060
- You may not @extend an outer selector from within @media.
1061
- You may only @extend selectors within the same directive.
1062
- From "@extend .foo" on line 3 of test_extend_out_of_media_inline.scss.
1063
- ERR
1064
- .foo {a: b}
1065
- @media screen {
1066
- .bar {@extend .foo}
1067
- }
1068
- SCSS
1069
- end
1070
-
1071
- def test_extend_out_of_unknown_directive
1072
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1073
- You may not @extend an outer selector from within @flooblehoof.
1074
- You may only @extend selectors within the same directive.
1075
- From "@extend .foo" on line 3 of test_extend_out_of_unknown_directive_inline.scss.
1076
- ERR
1077
- .foo {a: b}
1078
- @flooblehoof {
1079
- .bar {@extend .foo}
1080
- }
1081
- SCSS
1082
- end
1083
-
1084
- def test_extend_out_of_nested_directives
1085
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1086
- You may not @extend an outer selector from within @flooblehoof.
1087
- You may only @extend selectors within the same directive.
1088
- From "@extend .foo" on line 4 of test_extend_out_of_nested_directives_inline.scss.
1089
- ERR
1090
- @media screen {
1091
- .foo {a: b}
1092
- @flooblehoof {
1093
- .bar {@extend .foo}
1094
- }
1095
- }
1096
- SCSS
1097
- end
1098
-
1099
- def test_extend_within_media
1100
- assert_equal(<<CSS, render(<<SCSS))
1101
- @media screen {
1102
- .foo, .bar {
1103
- a: b; } }
1104
- CSS
1105
- @media screen {
1106
- .foo {a: b}
1107
- .bar {@extend .foo}
1108
- }
1109
- SCSS
1110
- end
1111
-
1112
- def test_extend_within_unknown_directive
1113
- assert_equal(<<CSS, render(<<SCSS))
1114
- @flooblehoof {
1115
- .foo, .bar {
1116
- a: b; } }
1117
- CSS
1118
- @flooblehoof {
1119
- .foo {a: b}
1120
- .bar {@extend .foo}
1121
- }
1122
- SCSS
1123
- end
1124
-
1125
- def test_extend_within_nested_directives
1126
- assert_equal(<<CSS, render(<<SCSS))
1127
- @media screen {
1128
- @flooblehoof {
1129
- .foo, .bar {
1130
- a: b; } } }
1131
- CSS
1132
- @media screen {
1133
- @flooblehoof {
1134
- .foo {a: b}
1135
- .bar {@extend .foo}
1136
- }
1137
- }
1138
- SCSS
1139
- end
1140
-
1141
- def test_extend_within_disparate_media
1142
- assert_equal(<<CSS, render(<<SCSS))
1143
- @media screen {
1144
- .foo, .bar {
1145
- a: b; } }
1146
- CSS
1147
- @media screen {.foo {a: b}}
1148
- @media screen {.bar {@extend .foo}}
1149
- SCSS
1150
- end
1151
-
1152
- def test_extend_within_disparate_unknown_directive
1153
- assert_equal(<<CSS, render(<<SCSS))
1154
- @flooblehoof {
1155
- .foo, .bar {
1156
- a: b; } }
1157
- @flooblehoof {}
1158
- CSS
1159
- @flooblehoof {.foo {a: b}}
1160
- @flooblehoof {.bar {@extend .foo}}
1161
- SCSS
1162
- end
1163
-
1164
- def test_extend_within_disparate_nested_directives
1165
- assert_equal(<<CSS, render(<<SCSS))
1166
- @media screen {
1167
- @flooblehoof {
1168
- .foo, .bar {
1169
- a: b; } } }
1170
- @media screen {
1171
- @flooblehoof {} }
1172
- CSS
1173
- @media screen {@flooblehoof {.foo {a: b}}}
1174
- @media screen {@flooblehoof {.bar {@extend .foo}}}
1175
- SCSS
1176
- end
1177
-
1178
- def test_extend_within_and_without_media
1179
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1180
- You may not @extend an outer selector from within @media.
1181
- You may only @extend selectors within the same directive.
1182
- From "@extend .foo" on line 4 of test_extend_within_and_without_media_inline.scss.
1183
- ERR
1184
- .foo {a: b}
1185
- @media screen {
1186
- .foo {c: d}
1187
- .bar {@extend .foo}
1188
- }
1189
- SCSS
1190
- end
1191
-
1192
- def test_extend_within_and_without_unknown_directive
1193
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1194
- You may not @extend an outer selector from within @flooblehoof.
1195
- You may only @extend selectors within the same directive.
1196
- From "@extend .foo" on line 4 of test_extend_within_and_without_unknown_directive_inline.scss.
1197
- ERR
1198
- .foo {a: b}
1199
- @flooblehoof {
1200
- .foo {c: d}
1201
- .bar {@extend .foo}
1202
- }
1203
- SCSS
1204
- end
1205
-
1206
- def test_extend_within_and_without_nested_directives
1207
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1208
- You may not @extend an outer selector from within @flooblehoof.
1209
- You may only @extend selectors within the same directive.
1210
- From "@extend .foo" on line 5 of test_extend_within_and_without_nested_directives_inline.scss.
1211
- ERR
1212
- @media screen {
1213
- .foo {a: b}
1214
- @flooblehoof {
1215
- .foo {c: d}
1216
- .bar {@extend .foo}
1217
- }
1218
- }
1219
- SCSS
1220
- end
1221
-
1222
- def test_extend_with_subject_transfers_subject_to_extender
1223
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1224
- foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
1225
- a: b; }
1226
- CSS
1227
- foo bar! baz {a: b}
1228
- .bip .bap {@extend bar}
1229
- SCSS
1230
-
1231
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1232
- foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
1233
- a: b; }
1234
- CSS
1235
- foo.x bar.y! baz.z {a: b}
1236
- .bip .bap {@extend .y}
1237
- SCSS
1238
- end
1239
-
1240
- def test_extend_with_subject_retains_subject_on_target
1241
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1242
- .foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
1243
- a: b; }
1244
- CSS
1245
- .foo! .bar {a: b}
1246
- .bip .bap {@extend .bar}
1247
- SCSS
1248
- end
1249
-
1250
- def test_extend_with_subject_transfers_subject_to_target
1251
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1252
- a.foo .bar, .bip a.bap! .bar {
1253
- a: b; }
1254
- CSS
1255
- a.foo .bar {a: b}
1256
- .bip .bap! {@extend .foo}
1257
- SCSS
1258
- end
1259
-
1260
- def test_extend_with_subject_retains_subject_on_extender
1261
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1262
- .foo .bar, .foo .bip! .bap, .bip! .foo .bap {
1263
- a: b; }
1264
- CSS
1265
- .foo .bar {a: b}
1266
- .bip! .bap {@extend .bar}
1267
- SCSS
1268
- end
1269
-
1270
- def test_extend_with_subject_fails_with_conflicting_subject
1271
- silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1272
- x! .bar {
1273
- a: b; }
1274
- CSS
1275
- x! .bar {a: b}
1276
- y! .bap {@extend .bar}
1277
- SCSS
1278
- end
1279
-
1280
- def test_extend_warns_when_extendee_doesnt_exist
1281
- assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
1282
- ".foo" failed to @extend ".bar".
1283
- The selector ".bar" was not found.
1284
- Use "@extend .bar !optional" if the extend should be able to fail.
1285
- ERR
1286
- .foo {@extend .bar}
1287
- SCSS
1288
- end
1289
-
1290
- def test_extend_succeeds_when_one_extension_fails_but_others_dont
1291
- assert_equal(<<CSS, render(<<SCSS))
1292
- a.bar {
1293
- a: b; }
1294
-
1295
- .bar, b.foo {
1296
- c: d; }
1297
- CSS
1298
- a.bar {a: b}
1299
- .bar {c: d}
1300
- b.foo {@extend .bar}
1301
- SCSS
1302
- end
1303
-
1304
- def test_optional_extend_succeeds_when_extendee_doesnt_exist
1305
- assert_equal("", render(<<SCSS))
1306
- .foo {@extend .bar !optional}
1307
- SCSS
1308
- end
1309
-
1310
- def test_optional_extend_succeeds_when_extension_fails
1311
- assert_equal(<<CSS, render(<<SCSS))
1312
- a.bar {
1313
- a: b; }
1314
- CSS
1315
- a.bar {a: b}
1316
- b.foo {@extend .bar !optional}
1317
- SCSS
1318
- end
1319
-
1320
- # Regression Tests
1321
-
1322
- def test_extend_with_middle_pseudo
1323
- assert_equal(<<CSS, render(<<SCSS))
1324
- .btn:active.focus, :active.focus:before {
1325
- a: b; }
1326
- CSS
1327
- .btn:active.focus {a: b}
1328
- :before {@extend .btn}
1329
- SCSS
1330
- end
1331
-
1332
- def test_extend_parent_selector_suffix
1333
- assert_equal <<CSS, render(<<SCSS)
1334
- .a-b, .c {
1335
- x: y; }
1336
- CSS
1337
- .a {&-b {x: y}}
1338
- .c {@extend .a-b}
1339
- SCSS
1340
- end
1341
-
1342
- def test_pseudo_element_superselector
1343
- # Pseudo-elements shouldn't be removed in superselector calculations.
1344
- assert_equal <<CSS, render(<<SCSS)
1345
- a#bar, a#bar::fblthp {
1346
- a: b; }
1347
- CSS
1348
- %x#bar {a: b} // Add an id to make the results have high specificity
1349
- %y, %y::fblthp {@extend %x}
1350
- a {@extend %y}
1351
- SCSS
1352
-
1353
- # Pseudo-classes can be removed when the second law allows.
1354
- assert_equal <<CSS, render(<<SCSS)
1355
- a#bar {
1356
- a: b; }
1357
- CSS
1358
- %x#bar {a: b}
1359
- %y, %y:fblthp {@extend %x}
1360
- a {@extend %y}
1361
- SCSS
1362
-
1363
- # A few pseudo-elements can be written as pseudo-elements for historical
1364
- # reasons. See http://www.w3.org/TR/selectors4/#pseudo-elements.
1365
- %w[first-line first-letter before after].each do |pseudo|
1366
- assert_equal <<CSS, render(<<SCSS)
1367
- a#bar, a#bar:#{pseudo} {
1368
- a: b; }
1369
- CSS
1370
- %x#bar {a: b}
1371
- %y, %y:#{pseudo} {@extend %x}
1372
- a {@extend %y}
1373
- SCSS
1374
- end
1375
- end
1376
-
1377
- def test_multiple_source_redundancy_elimination
1378
- assert_equal <<CSS, render(<<SCSS)
1379
- .test-case, .test-case:active {
1380
- color: red; }
1381
-
1382
- .test-case:hover {
1383
- color: green; }
1384
- CSS
1385
- %default-color {color: red}
1386
- %alt-color {color: green}
1387
-
1388
- %default-style {
1389
- @extend %default-color;
1390
- &:hover {@extend %alt-color}
1391
- &:active {@extend %default-color}
1392
- }
1393
-
1394
- .test-case {@extend %default-style}
1395
- SCSS
1396
- end
1397
-
1398
- def test_nested_sibling_extend
1399
- assert_equal <<CSS, render(<<SCSS)
1400
- .parent .bar, .parent .foo {
1401
- width: 2000px; }
1402
- CSS
1403
- .foo {@extend .bar}
1404
-
1405
- .parent {
1406
- .bar {
1407
- width: 2000px;
1408
- }
1409
- .foo {
1410
- @extend .bar
1411
- }
1412
- }
1413
- SCSS
1414
- end
1415
-
1416
- def test_parent_and_sibling_extend
1417
- assert_equal <<CSS, render(<<SCSS)
1418
- .parent1 .parent2 .child1.child2, .parent2 .parent1 .child1.child2 {
1419
- c: d; }
1420
- CSS
1421
- %foo %bar%baz {c: d}
1422
-
1423
- .parent1 {
1424
- @extend %foo;
1425
- .child1 {@extend %bar}
1426
- }
1427
-
1428
- .parent2 {
1429
- @extend %foo;
1430
- .child2 {@extend %baz}
1431
- }
1432
- SCSS
1433
- end
1434
-
1435
- def test_nested_extend_specificity
1436
- assert_equal <<CSS, render(<<SCSS)
1437
- a :b, a :b:c {
1438
- a: b; }
1439
- CSS
1440
- %foo {a: b}
1441
-
1442
- a {
1443
- :b {@extend %foo}
1444
- :b:c {@extend %foo}
1445
- }
1446
- SCSS
1447
- end
1448
-
1449
- def test_nested_double_extend_optimization
1450
- assert_equal <<CSS, render(<<SCSS)
1451
- .parent1 .child {
1452
- a: b; }
1453
- CSS
1454
- %foo %bar {
1455
- a: b;
1456
- }
1457
-
1458
- .parent1 {
1459
- @extend %foo;
1460
-
1461
- .child {
1462
- @extend %bar;
1463
- }
1464
- }
1465
-
1466
- .parent2 {
1467
- @extend %foo;
1468
- }
1469
- SCSS
1470
- end
1471
-
1472
- def test_extend_in_double_nested_media_query
1473
- assert_equal <<CSS, render(<<SCSS)
1474
- @media all and (orientation: landscape) {
1475
- .bar {
1476
- color: blue; } }
1477
- CSS
1478
- @media all {
1479
- @media (orientation: landscape) {
1480
- %foo {color: blue}
1481
- .bar {@extend %foo}
1482
- }
1483
- }
1484
- SCSS
1485
- end
1486
-
1487
- def test_partially_failed_extend
1488
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1489
- .rc, test {
1490
- color: white; }
1491
-
1492
- .prices span.pill span.rc {
1493
- color: red; }
1494
- CSS
1495
- test { @extend .rc; }
1496
- .rc {color: white;}
1497
- .prices span.pill span.rc {color: red;}
1498
- SCSS
1499
- end
1500
-
1501
- def test_newline_near_combinator
1502
- assert_equal <<CSS, render(<<SCSS)
1503
- .a +
1504
- .b x, .a +
1505
- .b .c y, .c .a +
1506
- .b y {
1507
- a: b; }
1508
- CSS
1509
- .a +
1510
- .b x {a: b}
1511
- .c y {@extend x}
1512
- SCSS
1513
- end
1514
-
1515
- def test_duplicated_selector_with_newlines
1516
- assert_equal(<<CSS, render(<<SCSS))
1517
- .example-1-1,
1518
- .example-1-2,
1519
- .my-page-1 .my-module-1-1,
1520
- .example-1-3 {
1521
- a: b; }
1522
- CSS
1523
- .example-1-1,
1524
- .example-1-2,
1525
- .example-1-3 {
1526
- a: b;
1527
- }
1528
-
1529
- .my-page-1 .my-module-1-1 {@extend .example-1-2}
1530
- SCSS
1531
- end
1532
-
1533
- def test_nested_selector_with_child_selector_hack_extendee
1534
- assert_extends '> .foo', 'foo bar {@extend .foo}', '> .foo, > foo bar'
1535
- end
1536
-
1537
- def test_nested_selector_with_child_selector_hack_extender
1538
- assert_extends '.foo .bar', '> foo bar {@extend .bar}', '.foo .bar, > .foo foo bar, > foo .foo bar'
1539
- end
1540
-
1541
- def test_nested_selector_with_child_selector_hack_extender_and_extendee
1542
- assert_extends '> .foo', '> foo bar {@extend .foo}', '> .foo, > foo bar'
1543
- end
1544
-
1545
- def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee
1546
- assert_extends '~ .foo', '> foo bar {@extend .foo}', '~ .foo'
1547
- end
1548
-
1549
- def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline
1550
- assert_equal <<CSS, render(<<SCSS)
1551
- > .foo, > flip,
1552
- > foo bar {
1553
- a: b; }
1554
- CSS
1555
- > .foo {a: b}
1556
- flip,
1557
- > foo bar {@extend .foo}
1558
- SCSS
1559
- end
1560
-
1561
- def test_extended_parent_and_child_redundancy_elimination
1562
- assert_equal <<CSS, render(<<SCSS)
1563
- a b, d b, a c, d c {
1564
- a: b; }
1565
- CSS
1566
- a {
1567
- b {a: b}
1568
- c {@extend b}
1569
- }
1570
- d {@extend a}
1571
- SCSS
1572
- end
1573
-
1574
- def test_extend_redundancy_elimination_when_it_would_reduce_specificity
1575
- assert_extends 'a', 'a.foo {@extend a}', 'a, a.foo'
1576
- end
1577
-
1578
- def test_extend_redundancy_elimination_when_it_would_preserve_specificity
1579
- assert_extends '.bar a', 'a.foo {@extend a}', '.bar a'
1580
- end
1581
-
1582
- def test_extend_redundancy_elimination_never_eliminates_base_selector
1583
- assert_extends 'a.foo', '.foo {@extend a}', 'a.foo, .foo'
1584
- end
1585
-
1586
- def test_extend_cross_branch_redundancy_elimination
1587
- assert_equal <<CSS, render(<<SCSS)
1588
- .a .c .d, .b .c .a .d {
1589
- a: b; }
1590
- CSS
1591
- %x .c %y {a: b}
1592
- .a, .b {@extend %x}
1593
- .a .d {@extend %y}
1594
- SCSS
1595
-
1596
- assert_equal <<CSS, render(<<SCSS)
1597
- .e .a .c .d, .a .c .e .d, .e .b .c .a .d, .b .c .a .e .d {
1598
- a: b; }
1599
- CSS
1600
- .e %z {a: b}
1601
- %x .c %y {@extend %z}
1602
- .a, .b {@extend %x}
1603
- .a .d {@extend %y}
1604
- SCSS
1605
- end
1606
-
1607
- private
1608
-
1609
- def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
1610
- message = "\"#{extender}\" failed to @extend \"#{target}\"."
1611
- reason =
1612
- if reason == :not_found
1613
- "The selector \"#{target}\" was not found."
1614
- else
1615
- "No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
1616
- end
1617
-
1618
- assert_raise_message(Sass::SyntaxError, <<ERR) {yield}
1619
- #{message}
1620
- #{reason}
1621
- Use "@extend #{target} !optional" if the extend should be able to fail.
1622
- ERR
1623
- end
1624
-
1625
- def assert_unification(selector, extension, unified, nested = true)
1626
- # Do some trickery so the first law of extend doesn't get in our way.
1627
- assert_extends(
1628
- "%-a #{selector}",
1629
- extension + " -a {@extend %-a}",
1630
- unified.split(', ').map {|s| "-a #{s}"}.join(', '))
1631
- end
1632
-
1633
- def assert_specificity_equals(sel1, sel2)
1634
- assert_specificity_gte(sel1, sel2)
1635
- assert_specificity_gte(sel2, sel1)
1636
- end
1637
-
1638
- def assert_specificity_gte(sel1, sel2)
1639
- assert_equal <<CSS, render(<<SCSS)
1640
- #{sel1} .a {
1641
- a: b; }
1642
- CSS
1643
- #{sel1} %-a {a: b}
1644
- .a {@extend %-a}
1645
- #{sel2}.a {@extend %-a}
1646
- SCSS
1647
- end
1648
-
1649
- def render_unification(selector, extension)
1650
- render_extends(
1651
- "%-a #{selector}",
1652
- extension + " -a {@extend %-a}")
1653
- end
1654
-
1655
- def assert_extends(selector, extension, result)
1656
- assert_equal <<CSS, render_extends(selector, extension)
1657
- #{result} {
1658
- a: b; }
1659
- CSS
1660
- end
1661
-
1662
- def assert_extends_to_nothing(selector, extension)
1663
- assert_equal '', render_extends(selector, extension)
1664
- end
1665
-
1666
- def render_extends(selector, extension)
1667
- render(<<SCSS)
1668
- #{selector} {a: b}
1669
- #{extension}
1670
- SCSS
1671
- end
1672
-
1673
- def render(sass, options = {})
1674
- options = {:syntax => :scss}.merge(options)
1675
- munge_filename options
1676
- Sass::Engine.new(sass, options).render
1677
- end
1678
- end