sass 3.5.2 → 3.7.4

Sign up to get free protection for your applications and to get access to all the features.
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