sass 3.4.24 → 3.7.4

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