sass 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +0 -14
data/test/sass/extend_test.rb
CHANGED
@@ -93,21 +93,9 @@ SCSS
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def test_multiple_extends_with_single_extender_and_single_target
|
96
|
-
|
97
|
-
.foo .bar, .baz .bar, .foo .baz, .baz .baz
|
98
|
-
|
99
|
-
CSS
|
100
|
-
.foo .bar {a: b}
|
101
|
-
.baz {@extend .foo; @extend .bar}
|
102
|
-
SCSS
|
103
|
-
|
104
|
-
assert_equal <<CSS, render(<<SCSS)
|
105
|
-
.foo.bar, .baz {
|
106
|
-
a: b; }
|
107
|
-
CSS
|
108
|
-
.foo.bar {a: b}
|
109
|
-
.baz {@extend .foo; @extend .bar}
|
110
|
-
SCSS
|
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'
|
111
99
|
end
|
112
100
|
|
113
101
|
def test_multiple_extends_with_multiple_extenders_and_single_target
|
@@ -143,1206 +131,1314 @@ SCSS
|
|
143
131
|
end
|
144
132
|
|
145
133
|
def test_dynamic_extendee
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
CSS
|
150
|
-
.foo {a: b}
|
151
|
-
.bar {@extend \#{".foo"}}
|
152
|
-
SCSS
|
153
|
-
|
154
|
-
assert_equal <<CSS, render(<<SCSS)
|
155
|
-
[baz^="blip12px"], .bar {
|
156
|
-
a: b; }
|
157
|
-
CSS
|
158
|
-
[baz^="blip12px"] {a: b}
|
159
|
-
.bar {@extend [baz^="blip\#{12px}"]}
|
160
|
-
SCSS
|
134
|
+
assert_extends '.foo', '.bar {@extend #{".foo"}}', '.foo, .bar'
|
135
|
+
assert_extends('[baz^="blip12px"]', '.bar {@extend [baz^="blip#{12px}"]}',
|
136
|
+
'[baz^="blip12px"], .bar')
|
161
137
|
end
|
162
138
|
|
163
139
|
def test_nested_target
|
164
|
-
|
165
|
-
.foo .bar, .foo .baz {
|
166
|
-
a: b; }
|
167
|
-
CSS
|
168
|
-
.foo .bar {a: b}
|
169
|
-
.baz {@extend .bar}
|
170
|
-
SCSS
|
140
|
+
assert_extends '.foo .bar', '.baz {@extend .bar}', '.foo .bar, .foo .baz'
|
171
141
|
end
|
172
142
|
|
173
143
|
def test_target_with_child
|
174
|
-
|
175
|
-
.foo .bar, .baz .bar {
|
176
|
-
a: b; }
|
177
|
-
CSS
|
178
|
-
.foo .bar {a: b}
|
179
|
-
.baz {@extend .foo}
|
180
|
-
SCSS
|
144
|
+
assert_extends '.foo .bar', '.baz {@extend .foo}', '.foo .bar, .baz .bar'
|
181
145
|
end
|
182
146
|
|
183
147
|
def test_class_unification
|
184
|
-
|
185
|
-
.foo.
|
186
|
-
a: b; }
|
187
|
-
CSS
|
188
|
-
.foo.bar {a: b}
|
189
|
-
.baz {@extend .foo}
|
190
|
-
SCSS
|
191
|
-
|
192
|
-
assert_equal <<CSS, render(<<SCSS)
|
193
|
-
.baz {
|
194
|
-
a: b; }
|
195
|
-
CSS
|
196
|
-
.foo.baz {a: b}
|
197
|
-
.baz {@extend .foo}
|
198
|
-
SCSS
|
148
|
+
assert_unification '.foo.bar', '.baz {@extend .foo}', '.foo.bar, .bar.baz'
|
149
|
+
assert_unification '.foo.baz', '.baz {@extend .foo}', '.baz'
|
199
150
|
end
|
200
151
|
|
201
152
|
def test_id_unification
|
202
|
-
|
203
|
-
.foo
|
204
|
-
a: b; }
|
205
|
-
CSS
|
206
|
-
.foo.bar {a: b}
|
207
|
-
#baz {@extend .foo}
|
208
|
-
SCSS
|
209
|
-
|
210
|
-
assert_equal <<CSS, render(<<SCSS)
|
211
|
-
#baz {
|
212
|
-
a: b; }
|
213
|
-
CSS
|
214
|
-
.foo#baz {a: b}
|
215
|
-
#baz {@extend .foo}
|
216
|
-
SCSS
|
153
|
+
assert_unification '.foo.bar', '#baz {@extend .foo}', '.foo.bar, .bar#baz'
|
154
|
+
assert_unification '.foo#baz', '#baz {@extend .foo}', '#baz'
|
217
155
|
|
218
|
-
|
219
|
-
.foo#baz {
|
220
|
-
|
221
|
-
CSS
|
222
|
-
.foo#baz {a: b}
|
223
|
-
#bar {@extend .foo}
|
224
|
-
SCSS
|
156
|
+
assert_extend_doesnt_match('#bar', '.foo', :failed_to_unify, 2) do
|
157
|
+
render_unification '.foo#baz', '#bar {@extend .foo}'
|
158
|
+
end
|
225
159
|
end
|
226
160
|
|
227
161
|
def test_universal_unification_with_simple_target
|
228
|
-
|
229
|
-
.foo,
|
230
|
-
|
231
|
-
|
232
|
-
.foo {
|
233
|
-
|
234
|
-
SCSS
|
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
|
235
168
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
169
|
+
def test_universal_unification_with_namespaceless_universal_target
|
170
|
+
assert_unification '*.foo', '* {@extend .foo}', '*'
|
171
|
+
assert_unification '*.foo', '*|* {@extend .foo}', '*'
|
172
|
+
assert_unification '*|*.foo', '* {@extend .foo}', '*|*.foo, *'
|
173
|
+
assert_unification '*|*.foo', '*|* {@extend .foo}', '*|*'
|
174
|
+
assert_unification '*.foo', 'ns|* {@extend .foo}', '*.foo, ns|*'
|
175
|
+
assert_unification '*|*.foo', 'ns|* {@extend .foo}', '*|*.foo, ns|*'
|
176
|
+
end
|
243
177
|
|
244
|
-
|
245
|
-
.
|
246
|
-
|
247
|
-
CSS
|
248
|
-
.foo.bar {a: b}
|
249
|
-
* {@extend .foo}
|
250
|
-
SCSS
|
178
|
+
def test_universal_unification_with_namespaced_universal_target
|
179
|
+
assert_unification 'ns|*.foo', '* {@extend .foo}', 'ns|*'
|
180
|
+
assert_unification 'ns|*.foo', '*|* {@extend .foo}', 'ns|*'
|
251
181
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
CSS
|
256
|
-
.foo.bar {a: b}
|
257
|
-
*|* {@extend .foo}
|
258
|
-
SCSS
|
182
|
+
assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
|
183
|
+
render_unification 'ns1|*.foo', 'ns2|* {@extend .foo}'
|
184
|
+
end
|
259
185
|
|
260
|
-
|
261
|
-
.foo.bar, ns|*.bar {
|
262
|
-
a: b; }
|
263
|
-
CSS
|
264
|
-
.foo.bar {a: b}
|
265
|
-
ns|* {@extend .foo}
|
266
|
-
SCSS
|
186
|
+
assert_unification 'ns|*.foo', 'ns|* {@extend .foo}', 'ns|*'
|
267
187
|
end
|
268
188
|
|
269
|
-
def
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
189
|
+
def test_universal_unification_with_namespaceless_element_target
|
190
|
+
assert_unification 'a.foo', '* {@extend .foo}', 'a'
|
191
|
+
assert_unification 'a.foo', '*|* {@extend .foo}', 'a'
|
192
|
+
assert_unification '*|a.foo', '* {@extend .foo}', '*|a.foo, a'
|
193
|
+
assert_unification '*|a.foo', '*|* {@extend .foo}', '*|a'
|
194
|
+
assert_unification 'a.foo', 'ns|* {@extend .foo}', 'a.foo, ns|a'
|
195
|
+
assert_unification '*|a.foo', 'ns|* {@extend .foo}', '*|a.foo, ns|a'
|
196
|
+
end
|
277
197
|
|
278
|
-
|
279
|
-
* {
|
280
|
-
|
281
|
-
CSS
|
282
|
-
*.foo {a: b}
|
283
|
-
*|* {@extend .foo}
|
284
|
-
SCSS
|
198
|
+
def test_universal_unification_with_namespaced_element_target
|
199
|
+
assert_unification 'ns|a.foo', '* {@extend .foo}', 'ns|a'
|
200
|
+
assert_unification 'ns|a.foo', '*|* {@extend .foo}', 'ns|a'
|
285
201
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
CSS
|
290
|
-
*|*.foo {a: b}
|
291
|
-
* {@extend .foo}
|
292
|
-
SCSS
|
202
|
+
assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
|
203
|
+
render_unification 'ns1|a.foo', 'ns2|* {@extend .foo}'
|
204
|
+
end
|
293
205
|
|
294
|
-
|
295
|
-
|
296
|
-
a: b; }
|
297
|
-
CSS
|
298
|
-
*|*.foo {a: b}
|
299
|
-
*|* {@extend .foo}
|
300
|
-
SCSS
|
206
|
+
assert_unification 'ns|a.foo', 'ns|* {@extend .foo}', 'ns|a'
|
207
|
+
end
|
301
208
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
SCSS
|
209
|
+
def test_element_unification_with_simple_target
|
210
|
+
assert_unification '.foo', 'a {@extend .foo}', '.foo, a'
|
211
|
+
assert_unification '.foo.bar', 'a {@extend .foo}', '.foo.bar, a.bar'
|
212
|
+
assert_unification '.foo.bar', '*|a {@extend .foo}', '.foo.bar, *|a.bar'
|
213
|
+
assert_unification '.foo.bar', 'ns|a {@extend .foo}', '.foo.bar, ns|a.bar'
|
214
|
+
end
|
309
215
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
*|*.foo
|
315
|
-
ns
|
316
|
-
|
216
|
+
def test_element_unification_with_namespaceless_universal_target
|
217
|
+
assert_unification '*.foo', 'a {@extend .foo}', '*.foo, a'
|
218
|
+
assert_unification '*.foo', '*|a {@extend .foo}', '*.foo, a'
|
219
|
+
assert_unification '*|*.foo', 'a {@extend .foo}', '*|*.foo, a'
|
220
|
+
assert_unification '*|*.foo', '*|a {@extend .foo}', '*|*.foo, *|a'
|
221
|
+
assert_unification '*.foo', 'ns|a {@extend .foo}', '*.foo, ns|a'
|
222
|
+
assert_unification '*|*.foo', 'ns|a {@extend .foo}', '*|*.foo, ns|a'
|
317
223
|
end
|
318
224
|
|
319
|
-
def
|
320
|
-
|
321
|
-
ns
|
322
|
-
a: b; }
|
323
|
-
CSS
|
324
|
-
ns|*.foo {a: b}
|
325
|
-
* {@extend .foo}
|
326
|
-
SCSS
|
225
|
+
def test_element_unification_with_namespaced_universal_target
|
226
|
+
assert_unification 'ns|*.foo', 'a {@extend .foo}', 'ns|*.foo, ns|a'
|
227
|
+
assert_unification 'ns|*.foo', '*|a {@extend .foo}', 'ns|*.foo, ns|a'
|
327
228
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
CSS
|
332
|
-
ns|*.foo {a: b}
|
333
|
-
*|* {@extend .foo}
|
334
|
-
SCSS
|
229
|
+
assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
|
230
|
+
render_unification 'ns1|*.foo', 'ns2|a {@extend .foo}'
|
231
|
+
end
|
335
232
|
|
336
|
-
|
337
|
-
|
338
|
-
a: b; }
|
339
|
-
CSS
|
340
|
-
ns1|*.foo {a: b}
|
341
|
-
ns2|* {@extend .foo}
|
342
|
-
SCSS
|
233
|
+
assert_unification 'ns|*.foo', 'ns|a {@extend .foo}', 'ns|*.foo, ns|a'
|
234
|
+
end
|
343
235
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
ns
|
350
|
-
|
236
|
+
def test_element_unification_with_namespaceless_element_target
|
237
|
+
assert_unification 'a.foo', 'a {@extend .foo}', 'a'
|
238
|
+
assert_unification 'a.foo', '*|a {@extend .foo}', 'a'
|
239
|
+
assert_unification '*|a.foo', 'a {@extend .foo}', '*|a.foo, a'
|
240
|
+
assert_unification '*|a.foo', '*|a {@extend .foo}', '*|a'
|
241
|
+
assert_unification 'a.foo', 'ns|a {@extend .foo}', 'a.foo, ns|a'
|
242
|
+
assert_unification '*|a.foo', 'ns|a {@extend .foo}', '*|a.foo, ns|a'
|
243
|
+
|
244
|
+
assert_extend_doesnt_match('h1', '.foo', :failed_to_unify, 2) do
|
245
|
+
render_unification 'a.foo', 'h1 {@extend .foo}'
|
246
|
+
end
|
351
247
|
end
|
352
248
|
|
353
|
-
def
|
354
|
-
|
355
|
-
a {
|
356
|
-
a: b; }
|
357
|
-
CSS
|
358
|
-
a.foo {a: b}
|
359
|
-
* {@extend .foo}
|
360
|
-
SCSS
|
249
|
+
def test_element_unification_with_namespaced_element_target
|
250
|
+
assert_unification 'ns|a.foo', 'a {@extend .foo}', 'ns|a'
|
251
|
+
assert_unification 'ns|a.foo', '*|a {@extend .foo}', 'ns|a'
|
361
252
|
|
362
|
-
|
363
|
-
a {
|
364
|
-
|
365
|
-
CSS
|
366
|
-
a.foo {a: b}
|
367
|
-
*|* {@extend .foo}
|
368
|
-
SCSS
|
253
|
+
assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
|
254
|
+
render_unification 'ns1|a.foo', 'ns2|a {@extend .foo}'
|
255
|
+
end
|
369
256
|
|
370
|
-
|
371
|
-
|
372
|
-
a: b; }
|
373
|
-
CSS
|
374
|
-
*|a.foo {a: b}
|
375
|
-
* {@extend .foo}
|
376
|
-
SCSS
|
257
|
+
assert_unification 'ns|a.foo', 'ns|a {@extend .foo}', 'ns|a'
|
258
|
+
end
|
377
259
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
260
|
+
def test_attribute_unification
|
261
|
+
assert_unification '[foo=bar].baz', '[foo=baz] {@extend .baz}', '[foo=bar].baz, [foo=bar][foo=baz]'
|
262
|
+
assert_unification '[foo=bar].baz', '[foo^=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][foo^=bar]'
|
263
|
+
assert_unification '[foo=bar].baz', '[foot=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][foot=bar]'
|
264
|
+
assert_unification '[foo=bar].baz', '[ns|foo=bar] {@extend .baz}', '[foo=bar].baz, [foo=bar][ns|foo=bar]'
|
265
|
+
assert_unification '%-a [foo=bar].bar', '[foo=bar] {@extend .bar}', '-a [foo=bar]'
|
266
|
+
end
|
385
267
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
CSS
|
390
|
-
a.foo {a: b}
|
391
|
-
ns|* {@extend .foo}
|
392
|
-
SCSS
|
268
|
+
def test_pseudo_unification
|
269
|
+
assert_unification ':foo.baz', ':foo(2n+1) {@extend .baz}', ':foo.baz, :foo:foo(2n+1)'
|
270
|
+
assert_unification ':foo.baz', '::foo {@extend .baz}', ':foo.baz, :foo::foo'
|
393
271
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
272
|
+
assert_extend_doesnt_match('::bar', '.baz', :failed_to_unify, 2) do
|
273
|
+
render_unification '::foo.baz', '::bar {@extend .baz}'
|
274
|
+
end
|
275
|
+
|
276
|
+
assert_extend_doesnt_match('::foo(2n+1)', '.baz', :failed_to_unify, 2) do
|
277
|
+
render_unification '::foo.baz', '::foo(2n+1) {@extend .baz}'
|
278
|
+
end
|
279
|
+
|
280
|
+
assert_unification '::foo.baz', '::foo {@extend .baz}', '::foo'
|
281
|
+
assert_unification '::foo(2n+1).baz', '::foo(2n+1) {@extend .baz}', '::foo(2n+1)'
|
282
|
+
assert_unification ':foo.baz', ':bar {@extend .baz}', ':foo.baz, :foo:bar'
|
283
|
+
assert_unification '.baz:foo', ':after {@extend .baz}', '.baz:foo, :foo:after'
|
284
|
+
assert_unification '.baz:after', ':foo {@extend .baz}', '.baz:after, :foo:after'
|
285
|
+
assert_unification ':foo.baz', ':foo {@extend .baz}', ':foo'
|
401
286
|
end
|
402
287
|
|
403
|
-
def
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
CSS
|
408
|
-
ns|a.foo {a: b}
|
409
|
-
* {@extend .foo}
|
410
|
-
SCSS
|
288
|
+
def test_pseudoelement_remains_at_end_of_selector
|
289
|
+
assert_extends '.foo::bar', '.baz {@extend .foo}', '.foo::bar, .baz::bar'
|
290
|
+
assert_extends 'a.foo::bar', '.baz {@extend .foo}', 'a.foo::bar, a.baz::bar'
|
291
|
+
end
|
411
292
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
ns|a.foo {a: b}
|
417
|
-
*|* {@extend .foo}
|
418
|
-
SCSS
|
293
|
+
def test_pseudoclass_remains_at_end_of_selector
|
294
|
+
assert_extends '.foo:bar', '.baz {@extend .foo}', '.foo:bar, .baz:bar'
|
295
|
+
assert_extends 'a.foo:bar', '.baz {@extend .foo}', 'a.foo:bar, a.baz:bar'
|
296
|
+
end
|
419
297
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
CSS
|
424
|
-
ns1|a.foo {a: b}
|
425
|
-
ns2|* {@extend .foo}
|
426
|
-
SCSS
|
298
|
+
def test_not_remains_at_end_of_selector
|
299
|
+
assert_extends '.foo:not(.bar)', '.baz {@extend .foo}', '.foo:not(.bar), .baz:not(.bar)'
|
300
|
+
end
|
427
301
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
CSS
|
432
|
-
ns|a.foo {a: b}
|
433
|
-
ns|* {@extend .foo}
|
434
|
-
SCSS
|
302
|
+
def test_pseudoelement_goes_lefter_than_pseudoclass
|
303
|
+
assert_extends '.foo::bar', '.baz:bang {@extend .foo}', '.foo::bar, .baz:bang::bar'
|
304
|
+
assert_extends '.foo:bar', '.baz::bang {@extend .foo}', '.foo:bar, .baz:bar::bang'
|
435
305
|
end
|
436
306
|
|
437
|
-
def
|
307
|
+
def test_pseudoelement_goes_lefter_than_not
|
308
|
+
assert_extends '.foo::bar', '.baz:not(.bang) {@extend .foo}', '.foo::bar, .baz:not(.bang)::bar'
|
309
|
+
assert_extends '.foo:not(.bang)', '.baz::bar {@extend .foo}', '.foo:not(.bang), .baz:not(.bang)::bar'
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_negation_unification
|
313
|
+
assert_unification ':not(.foo).baz', ':not(.bar) {@extend .baz}', ':not(.foo).baz, :not(.foo):not(.bar)'
|
314
|
+
assert_unification ':not(.foo).baz', ':not(.foo) {@extend .baz}', ':not(.foo)'
|
315
|
+
assert_unification ':not([a=b]).baz', ':not([a = b]) {@extend .baz}', ':not([a=b])'
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_comma_extendee
|
438
319
|
assert_equal <<CSS, render(<<SCSS)
|
439
|
-
.foo,
|
320
|
+
.foo, .baz {
|
440
321
|
a: b; }
|
322
|
+
|
323
|
+
.bar, .baz {
|
324
|
+
c: d; }
|
441
325
|
CSS
|
442
326
|
.foo {a: b}
|
443
|
-
|
327
|
+
.bar {c: d}
|
328
|
+
.baz {@extend .foo, .bar}
|
444
329
|
SCSS
|
330
|
+
end
|
445
331
|
|
332
|
+
def test_redundant_selector_elimination
|
446
333
|
assert_equal <<CSS, render(<<SCSS)
|
447
|
-
.foo.bar,
|
334
|
+
.foo.bar, .x, .y {
|
448
335
|
a: b; }
|
449
336
|
CSS
|
450
337
|
.foo.bar {a: b}
|
451
|
-
|
338
|
+
.x {@extend .foo, .bar}
|
339
|
+
.y {@extend .foo, .bar}
|
452
340
|
SCSS
|
341
|
+
end
|
453
342
|
|
454
|
-
|
455
|
-
.foo.bar, *|a.bar {
|
456
|
-
a: b; }
|
457
|
-
CSS
|
458
|
-
.foo.bar {a: b}
|
459
|
-
*|a {@extend .foo}
|
460
|
-
SCSS
|
343
|
+
## Long Extendees
|
461
344
|
|
462
|
-
|
463
|
-
.foo.bar,
|
464
|
-
a: b; }
|
465
|
-
CSS
|
466
|
-
.foo.bar {a: b}
|
467
|
-
ns|a {@extend .foo}
|
468
|
-
SCSS
|
345
|
+
def test_long_extendee
|
346
|
+
assert_extends '.foo.bar', '.baz {@extend .foo.bar}', '.foo.bar, .baz'
|
469
347
|
end
|
470
348
|
|
471
|
-
def
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
*.foo {a: b}
|
477
|
-
a {@extend .foo}
|
478
|
-
SCSS
|
349
|
+
def test_long_extendee_requires_all_selectors
|
350
|
+
assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
|
351
|
+
render_extends '.foo', '.baz {@extend .foo.bar}'
|
352
|
+
end
|
353
|
+
end
|
479
354
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
CSS
|
484
|
-
*.foo {a: b}
|
485
|
-
*|a {@extend .foo}
|
486
|
-
SCSS
|
355
|
+
def test_long_extendee_matches_supersets
|
356
|
+
assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'
|
357
|
+
end
|
487
358
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
CSS
|
492
|
-
*|*.foo {a: b}
|
493
|
-
a {@extend .foo}
|
494
|
-
SCSS
|
359
|
+
def test_long_extendee_runs_unification
|
360
|
+
assert_extends 'ns|*.foo.bar', 'a.baz {@extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'
|
361
|
+
end
|
495
362
|
|
496
|
-
|
497
|
-
*|*.foo, *|a {
|
498
|
-
a: b; }
|
499
|
-
CSS
|
500
|
-
*|*.foo {a: b}
|
501
|
-
*|a {@extend .foo}
|
502
|
-
SCSS
|
363
|
+
## Long Extenders
|
503
364
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
CSS
|
508
|
-
*.foo {a: b}
|
509
|
-
ns|a {@extend .foo}
|
510
|
-
SCSS
|
365
|
+
def test_long_extender
|
366
|
+
assert_extends '.foo.bar', '.baz.bang {@extend .foo}', '.foo.bar, .bar.baz.bang'
|
367
|
+
end
|
511
368
|
|
512
|
-
|
513
|
-
|
514
|
-
a: b; }
|
515
|
-
CSS
|
516
|
-
*|*.foo {a: b}
|
517
|
-
ns|a {@extend .foo}
|
518
|
-
SCSS
|
369
|
+
def test_long_extender_runs_unification
|
370
|
+
assert_extends 'ns|*.foo.bar', 'a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
|
519
371
|
end
|
520
372
|
|
521
|
-
def
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
CSS
|
526
|
-
ns|*.foo {a: b}
|
527
|
-
a {@extend .foo}
|
528
|
-
SCSS
|
373
|
+
def test_long_extender_aborts_unification
|
374
|
+
assert_extend_doesnt_match('h1.baz', '.foo', :failed_to_unify, 2) do
|
375
|
+
render_extends 'a.foo#bar', 'h1.baz {@extend .foo}'
|
376
|
+
end
|
529
377
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
378
|
+
assert_extend_doesnt_match('.bang#baz', '.foo', :failed_to_unify, 2) do
|
379
|
+
render_extends 'a.foo#bar', '.bang#baz {@extend .foo}'
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
## Nested Extenders
|
384
|
+
|
385
|
+
def test_nested_extender
|
386
|
+
assert_extends '.foo', 'foo bar {@extend .foo}', '.foo, foo bar'
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_nested_extender_runs_unification
|
390
|
+
assert_extends '.foo.bar', 'foo bar {@extend .foo}', '.foo.bar, foo bar.bar'
|
391
|
+
end
|
392
|
+
|
393
|
+
def test_nested_extender_aborts_unification
|
394
|
+
assert_extend_doesnt_match('foo bar', '.foo', :failed_to_unify, 2) do
|
395
|
+
render_extends 'baz.foo', 'foo bar {@extend .foo}'
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_nested_extender_alternates_parents
|
400
|
+
assert_extends('.baz .bip .foo', 'foo .grank bar {@extend .foo}',
|
401
|
+
'.baz .bip .foo, .baz .bip foo .grank bar, foo .grank .baz .bip bar')
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_nested_extender_unifies_identical_parents
|
405
|
+
assert_extends('.baz .bip .foo', '.baz .bip bar {@extend .foo}',
|
406
|
+
'.baz .bip .foo, .baz .bip bar')
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_nested_extender_unifies_common_substring
|
410
|
+
assert_extends('.baz .bip .bap .bink .foo', '.brat .bip .bap bar {@extend .foo}',
|
411
|
+
'.baz .bip .bap .bink .foo, .baz .brat .bip .bap .bink bar, .brat .baz .bip .bap .bink bar')
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_nested_extender_unifies_common_subseq
|
415
|
+
assert_extends('.a .x .b .y .foo', '.a .n .b .m bar {@extend .foo}',
|
416
|
+
'.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')
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_nested_extender_chooses_first_subseq
|
420
|
+
assert_extends('.a .b .c .d .foo', '.c .d .a .b .bar {@extend .foo}',
|
421
|
+
'.a .b .c .d .foo, .a .b .c .d .a .b .bar')
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_nested_extender_counts_extended_subselectors
|
425
|
+
assert_extends('.a .bip.bop .foo', '.b .bip .bar {@extend .foo}',
|
426
|
+
'.a .bip.bop .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
|
427
|
+
end
|
428
|
+
|
429
|
+
def test_nested_extender_counts_extended_superselectors
|
430
|
+
assert_extends('.a .bip .foo', '.b .bip.bop .bar {@extend .foo}',
|
431
|
+
'.a .bip .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
|
432
|
+
end
|
433
|
+
|
434
|
+
def test_nested_extender_with_child_selector
|
435
|
+
assert_extends '.baz .foo', 'foo > bar {@extend .foo}', '.baz .foo, .baz foo > bar'
|
436
|
+
end
|
437
|
+
|
438
|
+
def test_nested_extender_finds_common_selectors_around_child_selector
|
439
|
+
assert_extends 'a > b c .c1', 'a c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
|
440
|
+
assert_extends 'a > b c .c1', 'b c .c2 {@extend .c1}', 'a > b c .c1, a > b c .c2'
|
441
|
+
end
|
442
|
+
|
443
|
+
def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector
|
444
|
+
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'
|
445
|
+
assert_extends 'a + b c .c1', 'a b .c2 {@extend .c1}', 'a + b c .c1, a a + b c .c2'
|
446
|
+
assert_extends 'a + b c .c1', 'b c .c2 {@extend .c1}', 'a + b c .c1, a + b c .c2'
|
447
|
+
end
|
448
|
+
|
449
|
+
def test_nested_extender_doesnt_find_common_selectors_around_sibling_selector
|
450
|
+
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'
|
451
|
+
assert_extends 'a ~ b c .c1', 'a b .c2 {@extend .c1}', 'a ~ b c .c1, a a ~ b c .c2'
|
452
|
+
assert_extends 'a ~ b c .c1', 'b c .c2 {@extend .c1}', 'a ~ b c .c1, a ~ b c .c2'
|
453
|
+
end
|
454
|
+
|
455
|
+
def test_nested_extender_doesnt_find_common_selectors_around_reference_selector
|
456
|
+
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'
|
457
|
+
assert_extends 'a /for/ b c .c1', 'a b .c2 {@extend .c1}', 'a /for/ b c .c1, a a /for/ b c .c2'
|
458
|
+
assert_extends 'a /for/ b c .c1', 'b c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
|
462
|
+
assert_extends('.bip > .bap .foo', '.grip > .bap .bar {@extend .foo}',
|
463
|
+
'.bip > .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar')
|
464
|
+
assert_extends('.bap > .bip .foo', '.bap > .grip .bar {@extend .foo}',
|
465
|
+
'.bap > .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar')
|
466
|
+
end
|
467
|
+
|
468
|
+
def test_nested_extender_with_child_selector_unifies
|
469
|
+
assert_extends '.baz.foo', 'foo > bar {@extend .foo}', '.baz.foo, foo > bar.baz'
|
537
470
|
|
538
471
|
assert_equal <<CSS, render(<<SCSS)
|
539
|
-
|
472
|
+
.baz > .foo, .baz > .bar {
|
540
473
|
a: b; }
|
541
474
|
CSS
|
542
|
-
|
543
|
-
|
475
|
+
.baz > {
|
476
|
+
.foo {a: b}
|
477
|
+
.bar {@extend .foo}
|
478
|
+
}
|
544
479
|
SCSS
|
545
480
|
|
546
481
|
assert_equal <<CSS, render(<<SCSS)
|
547
|
-
|
482
|
+
.foo .bar, .foo > .baz {
|
548
483
|
a: b; }
|
549
484
|
CSS
|
550
|
-
|
551
|
-
|
485
|
+
.foo {
|
486
|
+
.bar {a: b}
|
487
|
+
> .baz {@extend .bar}
|
488
|
+
}
|
552
489
|
SCSS
|
553
490
|
end
|
554
491
|
|
555
|
-
def
|
492
|
+
def test_nested_extender_with_early_child_selector
|
556
493
|
assert_equal <<CSS, render(<<SCSS)
|
557
|
-
|
494
|
+
.foo .bar, .foo .bip > .baz {
|
558
495
|
a: b; }
|
559
496
|
CSS
|
560
|
-
|
561
|
-
|
497
|
+
.foo {
|
498
|
+
.bar {a: b}
|
499
|
+
.bip > .baz {@extend .bar}
|
500
|
+
}
|
562
501
|
SCSS
|
563
502
|
|
564
503
|
assert_equal <<CSS, render(<<SCSS)
|
565
|
-
|
504
|
+
.foo .bip .bar, .foo .bip .foo > .baz {
|
566
505
|
a: b; }
|
567
506
|
CSS
|
568
|
-
|
569
|
-
|
507
|
+
.foo {
|
508
|
+
.bip .bar {a: b}
|
509
|
+
> .baz {@extend .bar}
|
510
|
+
}
|
570
511
|
SCSS
|
571
512
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
*|a.foo {a: b}
|
577
|
-
a {@extend .foo}
|
578
|
-
SCSS
|
513
|
+
assert_extends '.foo > .bar', '.bip + .baz {@extend .bar}', '.foo > .bar, .foo > .bip + .baz'
|
514
|
+
assert_extends '.foo + .bar', '.bip > .baz {@extend .bar}', '.foo + .bar, .bip > .foo + .baz'
|
515
|
+
assert_extends '.foo > .bar', '.bip > .baz {@extend .bar}', '.foo > .bar, .bip.foo > .baz'
|
516
|
+
end
|
579
517
|
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
*|a {@extend .foo}
|
586
|
-
SCSS
|
518
|
+
def test_nested_extender_with_trailing_child_selector
|
519
|
+
assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do
|
520
|
+
render("bar > {@extend .baz}")
|
521
|
+
end
|
522
|
+
end
|
587
523
|
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
CSS
|
592
|
-
a.foo {a: b}
|
593
|
-
ns|a {@extend .foo}
|
594
|
-
SCSS
|
524
|
+
def test_nested_extender_with_sibling_selector
|
525
|
+
assert_extends '.baz .foo', 'foo + bar {@extend .foo}', '.baz .foo, .baz foo + bar'
|
526
|
+
end
|
595
527
|
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
ns|a {@extend .foo}
|
602
|
-
SCSS
|
528
|
+
def test_nested_extender_with_hacky_selector
|
529
|
+
assert_extends('.baz .foo', 'foo + > > + bar {@extend .foo}',
|
530
|
+
'.baz .foo, .baz foo + > > + bar, foo .baz + > > + bar')
|
531
|
+
assert_extends '.baz .foo', '> > bar {@extend .foo}', '.baz .foo, > > .baz bar'
|
532
|
+
end
|
603
533
|
|
534
|
+
def test_nested_extender_merges_with_same_selector
|
604
535
|
assert_equal <<CSS, render(<<SCSS)
|
605
|
-
|
536
|
+
.foo .bar, .foo .baz {
|
606
537
|
a: b; }
|
607
538
|
CSS
|
608
|
-
|
609
|
-
|
539
|
+
.foo {
|
540
|
+
.bar {a: b}
|
541
|
+
.baz {@extend .bar} }
|
610
542
|
SCSS
|
611
543
|
end
|
612
544
|
|
613
|
-
def
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
CSS
|
618
|
-
ns|a.foo {a: b}
|
619
|
-
a {@extend .foo}
|
620
|
-
SCSS
|
545
|
+
def test_nested_extender_with_child_selector_merges_with_same_selector
|
546
|
+
assert_extends('.foo > .bar .baz', '.foo > .bar .bang {@extend .baz}',
|
547
|
+
'.foo > .bar .baz, .foo > .bar .bang')
|
548
|
+
end
|
621
549
|
|
622
|
-
|
623
|
-
ns|a {
|
624
|
-
a: b; }
|
625
|
-
CSS
|
626
|
-
ns|a.foo {a: b}
|
627
|
-
*|a {@extend .foo}
|
628
|
-
SCSS
|
550
|
+
# Combinator Unification
|
629
551
|
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
552
|
+
def test_combinator_unification_for_hacky_combinators
|
553
|
+
assert_extends '.a > + x', '.b y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
|
554
|
+
assert_extends '.a x', '.b > + y {@extend x}', '.a x, .a .b > + y, .b .a > + y'
|
555
|
+
assert_extends '.a > + x', '.b > + y {@extend x}', '.a > + x, .a .b > + y, .b .a > + y'
|
556
|
+
assert_extends '.a ~ > + x', '.b > + y {@extend x}', '.a ~ > + x, .a .b ~ > + y, .b .a ~ > + y'
|
557
|
+
assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
|
558
|
+
assert_extends '.a + > x', '.b > + y {@extend x}', '.a + > x'
|
559
|
+
assert_extends '.a ~ > + .b > x', '.c > + .d > y {@extend x}', '.a ~ > + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y'
|
560
|
+
end
|
637
561
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
ns|a {@extend .foo}
|
644
|
-
SCSS
|
562
|
+
def test_combinator_unification_double_tilde
|
563
|
+
assert_extends '.a.b ~ x', '.a ~ y {@extend x}', '.a.b ~ x, .a.b ~ y'
|
564
|
+
assert_extends '.a ~ x', '.a.b ~ y {@extend x}', '.a ~ x, .a.b ~ y'
|
565
|
+
assert_extends '.a ~ x', '.b ~ y {@extend x}', '.a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y'
|
566
|
+
assert_extends 'a.a ~ x', 'b.b ~ y {@extend x}', 'a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y'
|
645
567
|
end
|
646
568
|
|
647
|
-
def
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
569
|
+
def test_combinator_unification_tilde_plus
|
570
|
+
assert_extends '.a.b + x', '.a ~ y {@extend x}', '.a.b + x, .a.b + y'
|
571
|
+
assert_extends '.a + x', '.a.b ~ y {@extend x}', '.a + x, .a.b ~ .a + y, .a.b + y'
|
572
|
+
assert_extends '.a + x', '.b ~ y {@extend x}', '.a + x, .b ~ .a + y, .b.a + y'
|
573
|
+
assert_extends 'a.a + x', 'b.b ~ y {@extend x}', 'a.a + x, b.b ~ a.a + y'
|
574
|
+
assert_extends '.a.b ~ x', '.a + y {@extend x}', '.a.b ~ x, .a.b ~ .a + y, .a.b + y'
|
575
|
+
assert_extends '.a ~ x', '.a.b + y {@extend x}', '.a ~ x, .a.b + y'
|
576
|
+
assert_extends '.a ~ x', '.b + y {@extend x}', '.a ~ x, .a ~ .b + y, .a.b + y'
|
577
|
+
assert_extends 'a.a ~ x', 'b.b + y {@extend x}', 'a.a ~ x, a.a ~ b.b + y'
|
578
|
+
end
|
655
579
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
SCSS
|
580
|
+
def test_combinator_unification_angle_sibling
|
581
|
+
assert_extends '.a > x', '.b ~ y {@extend x}', '.a > x, .a > .b ~ y'
|
582
|
+
assert_extends '.a > x', '.b + y {@extend x}', '.a > x, .a > .b + y'
|
583
|
+
assert_extends '.a ~ x', '.b > y {@extend x}', '.a ~ x, .b > .a ~ y'
|
584
|
+
assert_extends '.a + x', '.b > y {@extend x}', '.a + x, .b > .a + y'
|
585
|
+
end
|
663
586
|
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
SCSS
|
587
|
+
def test_combinator_unification_double_angle
|
588
|
+
assert_extends '.a.b > x', '.b > y {@extend x}', '.a.b > x, .b.a > y'
|
589
|
+
assert_extends '.a > x', '.a.b > y {@extend x}', '.a > x, .a.b > y'
|
590
|
+
assert_extends '.a > x', '.b > y {@extend x}', '.a > x, .b.a > y'
|
591
|
+
assert_extends 'a.a > x', 'b.b > y {@extend x}', 'a.a > x'
|
592
|
+
end
|
671
593
|
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
SCSS
|
594
|
+
def test_combinator_unification_double_plus
|
595
|
+
assert_extends '.a.b + x', '.b + y {@extend x}', '.a.b + x, .b.a + y'
|
596
|
+
assert_extends '.a + x', '.a.b + y {@extend x}', '.a + x, .a.b + y'
|
597
|
+
assert_extends '.a + x', '.b + y {@extend x}', '.a + x, .b.a + y'
|
598
|
+
assert_extends 'a.a + x', 'b.b + y {@extend x}', 'a.a + x'
|
599
|
+
end
|
679
600
|
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
601
|
+
def test_combinator_unification_angle_space
|
602
|
+
assert_extends '.a.b > x', '.a y {@extend x}', '.a.b > x, .a.b > y'
|
603
|
+
assert_extends '.a > x', '.a.b y {@extend x}', '.a > x, .a.b .a > y'
|
604
|
+
assert_extends '.a > x', '.b y {@extend x}', '.a > x, .b .a > y'
|
605
|
+
assert_extends '.a.b x', '.a > y {@extend x}', '.a.b x, .a.b .a > y'
|
606
|
+
assert_extends '.a x', '.a.b > y {@extend x}', '.a x, .a.b > y'
|
607
|
+
assert_extends '.a x', '.b > y {@extend x}', '.a x, .a .b > y'
|
687
608
|
end
|
688
609
|
|
689
|
-
def
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
610
|
+
def test_combinator_unification_plus_space
|
611
|
+
assert_extends '.a.b + x', '.a y {@extend x}', '.a.b + x, .a .a.b + y'
|
612
|
+
assert_extends '.a + x', '.a.b y {@extend x}', '.a + x, .a.b .a + y'
|
613
|
+
assert_extends '.a + x', '.b y {@extend x}', '.a + x, .b .a + y'
|
614
|
+
assert_extends '.a.b x', '.a + y {@extend x}', '.a.b x, .a.b .a + y'
|
615
|
+
assert_extends '.a x', '.a.b + y {@extend x}', '.a x, .a .a.b + y'
|
616
|
+
assert_extends '.a x', '.b + y {@extend x}', '.a x, .a .b + y'
|
617
|
+
end
|
697
618
|
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
:foo.baz {a: b}
|
703
|
-
::foo {@extend .baz}
|
704
|
-
SCSS
|
619
|
+
def test_combinator_unification_nested
|
620
|
+
assert_extends '.a > .b + x', '.c > .d + y {@extend x}', '.a > .b + x, .c.a > .d.b + y'
|
621
|
+
assert_extends '.a > .b + x', '.c > y {@extend x}', '.a > .b + x, .c.a > .b + y'
|
622
|
+
end
|
705
623
|
|
624
|
+
def test_combinator_unification_with_newlines
|
706
625
|
assert_equal <<CSS, render(<<SCSS)
|
707
|
-
|
626
|
+
.a >
|
627
|
+
.b
|
628
|
+
+ x, .c.a > .d.b + y {
|
708
629
|
a: b; }
|
709
630
|
CSS
|
710
|
-
|
711
|
-
|
631
|
+
.a >
|
632
|
+
.b
|
633
|
+
+ x {a: b}
|
634
|
+
.c
|
635
|
+
> .d +
|
636
|
+
y {@extend x}
|
712
637
|
SCSS
|
638
|
+
end
|
713
639
|
|
714
|
-
|
715
|
-
::foo.baz {
|
716
|
-
a: b; }
|
717
|
-
CSS
|
718
|
-
::foo.baz {a: b}
|
719
|
-
::foo(2n+1) {@extend .baz}
|
720
|
-
SCSS
|
640
|
+
# Loops
|
721
641
|
|
642
|
+
def test_extend_self_loop
|
722
643
|
assert_equal <<CSS, render(<<SCSS)
|
723
|
-
|
644
|
+
.foo {
|
724
645
|
a: b; }
|
725
646
|
CSS
|
726
|
-
|
727
|
-
::foo {@extend .baz}
|
647
|
+
.foo {a: b; @extend .foo}
|
728
648
|
SCSS
|
649
|
+
end
|
729
650
|
|
651
|
+
def test_basic_extend_loop
|
730
652
|
assert_equal <<CSS, render(<<SCSS)
|
731
|
-
|
653
|
+
.bar, .foo {
|
732
654
|
a: b; }
|
733
|
-
CSS
|
734
|
-
::foo(2n+1).baz {a: b}
|
735
|
-
::foo(2n+1) {@extend .baz}
|
736
|
-
SCSS
|
737
655
|
|
738
|
-
|
739
|
-
:
|
740
|
-
a: b; }
|
656
|
+
.foo, .bar {
|
657
|
+
c: d; }
|
741
658
|
CSS
|
742
|
-
|
743
|
-
|
659
|
+
.foo {a: b; @extend .bar}
|
660
|
+
.bar {c: d; @extend .foo}
|
744
661
|
SCSS
|
662
|
+
end
|
745
663
|
|
664
|
+
def test_three_level_extend_loop
|
746
665
|
assert_equal <<CSS, render(<<SCSS)
|
747
|
-
|
666
|
+
.baz, .bar, .foo {
|
748
667
|
a: b; }
|
668
|
+
|
669
|
+
.foo, .baz, .bar {
|
670
|
+
c: d; }
|
671
|
+
|
672
|
+
.bar, .foo, .baz {
|
673
|
+
e: f; }
|
749
674
|
CSS
|
750
|
-
|
751
|
-
:
|
675
|
+
.foo {a: b; @extend .bar}
|
676
|
+
.bar {c: d; @extend .baz}
|
677
|
+
.baz {e: f; @extend .foo}
|
752
678
|
SCSS
|
753
679
|
end
|
754
680
|
|
755
|
-
def
|
681
|
+
def test_nested_extend_loop
|
756
682
|
assert_equal <<CSS, render(<<SCSS)
|
757
|
-
.
|
683
|
+
.bar, .bar .foo {
|
758
684
|
a: b; }
|
685
|
+
.bar .foo {
|
686
|
+
c: d; }
|
759
687
|
CSS
|
760
|
-
.
|
761
|
-
|
688
|
+
.bar {
|
689
|
+
a: b;
|
690
|
+
.foo {c: d; @extend .bar}
|
691
|
+
}
|
762
692
|
SCSS
|
693
|
+
end
|
763
694
|
|
695
|
+
def test_multiple_extender_merges_with_superset_selector
|
764
696
|
assert_equal <<CSS, render(<<SCSS)
|
765
|
-
a.
|
697
|
+
a.bar.baz, a.foo {
|
766
698
|
a: b; }
|
767
699
|
CSS
|
768
|
-
|
769
|
-
.baz {
|
700
|
+
.foo {@extend .bar; @extend .baz}
|
701
|
+
a.bar.baz {a: b}
|
770
702
|
SCSS
|
771
703
|
end
|
772
704
|
|
773
|
-
def
|
705
|
+
def test_control_flow_if
|
774
706
|
assert_equal <<CSS, render(<<SCSS)
|
775
|
-
.
|
776
|
-
|
777
|
-
CSS
|
778
|
-
.foo:bar {a: b}
|
779
|
-
.baz {@extend .foo}
|
780
|
-
SCSS
|
707
|
+
.true, .also-true {
|
708
|
+
color: green; }
|
781
709
|
|
782
|
-
|
783
|
-
|
784
|
-
a: b; }
|
710
|
+
.false, .also-false {
|
711
|
+
color: red; }
|
785
712
|
CSS
|
786
|
-
|
787
|
-
.
|
713
|
+
.true { color: green; }
|
714
|
+
.false { color: red; }
|
715
|
+
.also-true {
|
716
|
+
@if true { @extend .true; }
|
717
|
+
@else { @extend .false; }
|
718
|
+
}
|
719
|
+
.also-false {
|
720
|
+
@if false { @extend .true; }
|
721
|
+
@else { @extend .false; }
|
722
|
+
}
|
788
723
|
SCSS
|
789
724
|
end
|
790
725
|
|
791
|
-
def
|
726
|
+
def test_control_flow_for
|
792
727
|
assert_equal <<CSS, render(<<SCSS)
|
793
|
-
.
|
794
|
-
|
728
|
+
.base-0, .added {
|
729
|
+
color: green; }
|
730
|
+
|
731
|
+
.base-1, .added {
|
732
|
+
display: block; }
|
733
|
+
|
734
|
+
.base-2, .added {
|
735
|
+
border: 1px solid blue; }
|
795
736
|
CSS
|
796
|
-
.
|
797
|
-
.
|
737
|
+
.base-0 { color: green; }
|
738
|
+
.base-1 { display: block; }
|
739
|
+
.base-2 { border: 1px solid blue; }
|
740
|
+
.added {
|
741
|
+
@for $i from 0 to 3 {
|
742
|
+
@extend .base-\#{$i};
|
743
|
+
}
|
744
|
+
}
|
798
745
|
SCSS
|
799
746
|
end
|
800
747
|
|
801
|
-
def
|
748
|
+
def test_control_flow_while
|
802
749
|
assert_equal <<CSS, render(<<SCSS)
|
803
|
-
.
|
804
|
-
|
750
|
+
.base-0, .added {
|
751
|
+
color: green; }
|
752
|
+
|
753
|
+
.base-1, .added {
|
754
|
+
display: block; }
|
755
|
+
|
756
|
+
.base-2, .added {
|
757
|
+
border: 1px solid blue; }
|
805
758
|
CSS
|
806
|
-
.
|
807
|
-
.
|
759
|
+
.base-0 { color: green; }
|
760
|
+
.base-1 { display: block; }
|
761
|
+
.base-2 { border: 1px solid blue; }
|
762
|
+
.added {
|
763
|
+
$i : 0;
|
764
|
+
@while $i < 3 {
|
765
|
+
@extend .base-\#{$i};
|
766
|
+
$i : $i + 1;
|
767
|
+
}
|
768
|
+
}
|
808
769
|
SCSS
|
770
|
+
end
|
771
|
+
|
772
|
+
def test_basic_placeholder_selector
|
773
|
+
assert_extends '%foo', '.bar {@extend %foo}', '.bar'
|
774
|
+
end
|
809
775
|
|
776
|
+
def test_unused_placeholder_selector
|
810
777
|
assert_equal <<CSS, render(<<SCSS)
|
811
|
-
.
|
812
|
-
|
778
|
+
.baz {
|
779
|
+
color: blue; }
|
813
780
|
CSS
|
814
|
-
|
815
|
-
|
781
|
+
%foo {color: blue}
|
782
|
+
%bar {color: red}
|
783
|
+
.baz {@extend %foo}
|
816
784
|
SCSS
|
817
785
|
end
|
818
786
|
|
819
|
-
def
|
787
|
+
def test_placeholder_descendant_selector
|
788
|
+
assert_extends '#context %foo a', '.bar {@extend %foo}', '#context .bar a'
|
789
|
+
end
|
790
|
+
|
791
|
+
def test_semi_placeholder_selector
|
820
792
|
assert_equal <<CSS, render(<<SCSS)
|
821
|
-
.
|
822
|
-
|
793
|
+
.bar .baz {
|
794
|
+
color: blue; }
|
823
795
|
CSS
|
824
|
-
.
|
825
|
-
.baz:not(.bang) {@extend .foo}
|
796
|
+
#context %foo, .bar .baz {color: blue}
|
826
797
|
SCSS
|
798
|
+
end
|
827
799
|
|
800
|
+
def test_placeholder_selector_with_multiple_extenders
|
828
801
|
assert_equal <<CSS, render(<<SCSS)
|
829
|
-
.
|
830
|
-
|
802
|
+
.bar, .baz {
|
803
|
+
color: blue; }
|
831
804
|
CSS
|
832
|
-
|
833
|
-
.
|
805
|
+
%foo {color: blue}
|
806
|
+
.bar {@extend %foo}
|
807
|
+
.baz {@extend %foo}
|
834
808
|
SCSS
|
835
809
|
end
|
836
810
|
|
837
|
-
def
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
:not(.bar) {@extend .baz}
|
811
|
+
def test_placeholder_selector_as_modifier
|
812
|
+
assert_extend_doesnt_match('div', '%foo', :failed_to_unify, 3) do
|
813
|
+
render(<<SCSS)
|
814
|
+
a%foo.baz {color: blue}
|
815
|
+
.bar {@extend %foo}
|
816
|
+
div {@extend %foo}
|
844
817
|
SCSS
|
818
|
+
end
|
819
|
+
end
|
845
820
|
|
821
|
+
def test_placeholder_interpolation
|
846
822
|
assert_equal <<CSS, render(<<SCSS)
|
847
|
-
|
848
|
-
|
823
|
+
.bar {
|
824
|
+
color: blue; }
|
849
825
|
CSS
|
850
|
-
|
851
|
-
|
826
|
+
$foo: foo;
|
827
|
+
|
828
|
+
%\#{$foo} {color: blue}
|
829
|
+
.bar {@extend %foo}
|
852
830
|
SCSS
|
831
|
+
end
|
853
832
|
|
833
|
+
def test_media_in_placeholder_selector
|
854
834
|
assert_equal <<CSS, render(<<SCSS)
|
855
|
-
|
856
|
-
|
835
|
+
.baz {
|
836
|
+
c: d; }
|
857
837
|
CSS
|
858
|
-
|
859
|
-
|
838
|
+
%foo {bar {@media screen {a: b}}}
|
839
|
+
.baz {c: d}
|
860
840
|
SCSS
|
861
841
|
end
|
862
842
|
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
.foo
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
.
|
843
|
+
def test_extend_out_of_media
|
844
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
845
|
+
You may not @extend an outer selector from within @media.
|
846
|
+
You may only @extend selectors within the same directive.
|
847
|
+
From "@extend .foo" on line 3 of test_extend_out_of_media_inline.scss.
|
848
|
+
ERR
|
849
|
+
.foo {a: b}
|
850
|
+
@media screen {
|
851
|
+
.bar {@extend .foo}
|
852
|
+
}
|
872
853
|
SCSS
|
873
854
|
end
|
874
855
|
|
875
|
-
def
|
876
|
-
|
877
|
-
.
|
878
|
-
|
879
|
-
|
856
|
+
def test_extend_out_of_unknown_directive
|
857
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
858
|
+
You may not @extend an outer selector from within @flooblehoof.
|
859
|
+
You may only @extend selectors within the same directive.
|
860
|
+
From "@extend .foo" on line 3 of test_extend_out_of_unknown_directive_inline.scss.
|
861
|
+
ERR
|
880
862
|
.foo {a: b}
|
881
|
-
|
863
|
+
@flooblehoof {
|
864
|
+
.bar {@extend .foo}
|
865
|
+
}
|
866
|
+
SCSS
|
867
|
+
end
|
868
|
+
|
869
|
+
def test_extend_out_of_nested_directives
|
870
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
871
|
+
You may not @extend an outer selector from within @flooblehoof.
|
872
|
+
You may only @extend selectors within the same directive.
|
873
|
+
From "@extend .foo" on line 4 of test_extend_out_of_nested_directives_inline.scss.
|
874
|
+
ERR
|
875
|
+
@media screen {
|
876
|
+
.foo {a: b}
|
877
|
+
@flooblehoof {
|
878
|
+
.bar {@extend .foo}
|
879
|
+
}
|
880
|
+
}
|
882
881
|
SCSS
|
883
882
|
end
|
884
883
|
|
885
|
-
def
|
886
|
-
assert_equal
|
887
|
-
|
888
|
-
|
884
|
+
def test_extend_within_media
|
885
|
+
assert_equal(<<CSS, render(<<SCSS))
|
886
|
+
@media screen {
|
887
|
+
.foo, .bar {
|
888
|
+
a: b; } }
|
889
889
|
CSS
|
890
|
-
|
891
|
-
.
|
890
|
+
@media screen {
|
891
|
+
.foo {a: b}
|
892
|
+
.bar {@extend .foo}
|
893
|
+
}
|
892
894
|
SCSS
|
893
895
|
end
|
894
896
|
|
895
|
-
def
|
896
|
-
assert_equal
|
897
|
-
|
898
|
-
|
897
|
+
def test_extend_within_unknown_directive
|
898
|
+
assert_equal(<<CSS, render(<<SCSS))
|
899
|
+
@flooblehoof {
|
900
|
+
.foo, .bar {
|
901
|
+
a: b; } }
|
899
902
|
CSS
|
900
|
-
|
901
|
-
|
903
|
+
@flooblehoof {
|
904
|
+
.foo {a: b}
|
905
|
+
.bar {@extend .foo}
|
906
|
+
}
|
902
907
|
SCSS
|
903
908
|
end
|
904
909
|
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
.foo
|
910
|
-
|
910
|
+
def test_extend_within_nested_directives
|
911
|
+
assert_equal(<<CSS, render(<<SCSS))
|
912
|
+
@media screen {
|
913
|
+
@flooblehoof {
|
914
|
+
.foo, .bar {
|
915
|
+
a: b; } } }
|
911
916
|
CSS
|
912
|
-
|
913
|
-
|
917
|
+
@media screen {
|
918
|
+
@flooblehoof {
|
919
|
+
.foo {a: b}
|
920
|
+
.bar {@extend .foo}
|
921
|
+
}
|
922
|
+
}
|
914
923
|
SCSS
|
915
924
|
end
|
916
925
|
|
917
|
-
def
|
918
|
-
assert_equal
|
919
|
-
|
920
|
-
|
926
|
+
def test_extend_within_disparate_media
|
927
|
+
assert_equal(<<CSS, render(<<SCSS))
|
928
|
+
@media screen {
|
929
|
+
.foo, .bar {
|
930
|
+
a: b; } }
|
921
931
|
CSS
|
922
|
-
|
923
|
-
|
932
|
+
@media screen {.foo {a: b}}
|
933
|
+
@media screen {.bar {@extend .foo}}
|
924
934
|
SCSS
|
925
935
|
end
|
926
936
|
|
927
|
-
def
|
928
|
-
assert_equal
|
929
|
-
|
930
|
-
|
937
|
+
def test_extend_within_disparate_unknown_directive
|
938
|
+
assert_equal(<<CSS, render(<<SCSS))
|
939
|
+
@flooblehoof {
|
940
|
+
.foo, .bar {
|
941
|
+
a: b; } }
|
942
|
+
@flooblehoof {}
|
931
943
|
CSS
|
932
|
-
|
933
|
-
|
944
|
+
@flooblehoof {.foo {a: b}}
|
945
|
+
@flooblehoof {.bar {@extend .foo}}
|
934
946
|
SCSS
|
947
|
+
end
|
935
948
|
|
936
|
-
|
937
|
-
|
938
|
-
|
949
|
+
def test_extend_within_disparate_nested_directives
|
950
|
+
assert_equal(<<CSS, render(<<SCSS))
|
951
|
+
@media screen {
|
952
|
+
@flooblehoof {
|
953
|
+
.foo, .bar {
|
954
|
+
a: b; } } }
|
955
|
+
@media screen {
|
956
|
+
@flooblehoof {} }
|
939
957
|
CSS
|
940
|
-
|
941
|
-
.
|
958
|
+
@media screen {@flooblehoof {.foo {a: b}}}
|
959
|
+
@media screen {@flooblehoof {.bar {@extend .foo}}}
|
942
960
|
SCSS
|
943
961
|
end
|
944
962
|
|
945
|
-
|
963
|
+
def test_extend_within_and_without_media
|
964
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
965
|
+
You may not @extend an outer selector from within @media.
|
966
|
+
You may only @extend selectors within the same directive.
|
967
|
+
From "@extend .foo" on line 4 of test_extend_within_and_without_media_inline.scss.
|
968
|
+
ERR
|
969
|
+
.foo {a: b}
|
970
|
+
@media screen {
|
971
|
+
.foo {c: d}
|
972
|
+
.bar {@extend .foo}
|
973
|
+
}
|
974
|
+
SCSS
|
975
|
+
end
|
946
976
|
|
947
|
-
def
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
977
|
+
def test_extend_within_and_without_unknown_directive
|
978
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
979
|
+
You may not @extend an outer selector from within @flooblehoof.
|
980
|
+
You may only @extend selectors within the same directive.
|
981
|
+
From "@extend .foo" on line 4 of test_extend_within_and_without_unknown_directive_inline.scss.
|
982
|
+
ERR
|
952
983
|
.foo {a: b}
|
953
|
-
|
984
|
+
@flooblehoof {
|
985
|
+
.foo {c: d}
|
986
|
+
.bar {@extend .foo}
|
987
|
+
}
|
954
988
|
SCSS
|
955
989
|
end
|
956
990
|
|
957
|
-
def
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
991
|
+
def test_extend_within_and_without_nested_directives
|
992
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
993
|
+
You may not @extend an outer selector from within @flooblehoof.
|
994
|
+
You may only @extend selectors within the same directive.
|
995
|
+
From "@extend .foo" on line 5 of test_extend_within_and_without_nested_directives_inline.scss.
|
996
|
+
ERR
|
997
|
+
@media screen {
|
998
|
+
.foo {a: b}
|
999
|
+
@flooblehoof {
|
1000
|
+
.foo {c: d}
|
1001
|
+
.bar {@extend .foo}
|
1002
|
+
}
|
1003
|
+
}
|
964
1004
|
SCSS
|
965
1005
|
end
|
966
1006
|
|
967
|
-
def
|
968
|
-
assert_equal
|
969
|
-
baz.foo {
|
1007
|
+
def test_extend_with_subject_transfers_subject_to_extender
|
1008
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1009
|
+
foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
|
970
1010
|
a: b; }
|
971
1011
|
CSS
|
972
|
-
|
973
|
-
|
1012
|
+
foo bar! baz {a: b}
|
1013
|
+
.bip .bap {@extend bar}
|
974
1014
|
SCSS
|
975
|
-
end
|
976
1015
|
|
977
|
-
|
978
|
-
|
979
|
-
.baz .bip .foo, .baz .bip foo .grank bar, foo .grank .baz .bip bar {
|
1016
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1017
|
+
foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
|
980
1018
|
a: b; }
|
981
1019
|
CSS
|
982
|
-
.
|
983
|
-
|
1020
|
+
foo.x bar.y! baz.z {a: b}
|
1021
|
+
.bip .bap {@extend .y}
|
984
1022
|
SCSS
|
985
1023
|
end
|
986
1024
|
|
987
|
-
def
|
988
|
-
assert_equal
|
989
|
-
.
|
1025
|
+
def test_extend_with_subject_retains_subject_on_target
|
1026
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1027
|
+
.foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
|
990
1028
|
a: b; }
|
991
1029
|
CSS
|
992
|
-
.
|
993
|
-
.
|
1030
|
+
.foo! .bar {a: b}
|
1031
|
+
.bip .bap {@extend .bar}
|
994
1032
|
SCSS
|
995
1033
|
end
|
996
1034
|
|
997
|
-
def
|
998
|
-
assert_equal
|
999
|
-
.
|
1035
|
+
def test_extend_with_subject_transfers_subject_to_target
|
1036
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1037
|
+
a.foo .bar, .bip a.bap! .bar {
|
1000
1038
|
a: b; }
|
1001
1039
|
CSS
|
1002
|
-
.
|
1003
|
-
.
|
1040
|
+
a.foo .bar {a: b}
|
1041
|
+
.bip .bap! {@extend .foo}
|
1004
1042
|
SCSS
|
1005
1043
|
end
|
1006
1044
|
|
1007
|
-
def
|
1008
|
-
assert_equal
|
1009
|
-
.
|
1045
|
+
def test_extend_with_subject_retains_subject_on_extender
|
1046
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1047
|
+
.foo .bar, .foo .bip! .bap, .bip! .foo .bap {
|
1010
1048
|
a: b; }
|
1011
1049
|
CSS
|
1012
|
-
.
|
1013
|
-
.
|
1050
|
+
.foo .bar {a: b}
|
1051
|
+
.bip! .bap {@extend .bar}
|
1014
1052
|
SCSS
|
1015
1053
|
end
|
1016
1054
|
|
1017
|
-
def
|
1018
|
-
assert_equal
|
1019
|
-
|
1055
|
+
def test_extend_with_subject_fails_with_conflicting_subject
|
1056
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1057
|
+
x! .bar {
|
1020
1058
|
a: b; }
|
1021
1059
|
CSS
|
1022
|
-
|
1023
|
-
|
1060
|
+
x! .bar {a: b}
|
1061
|
+
y! .bap {@extend .bar}
|
1024
1062
|
SCSS
|
1025
1063
|
end
|
1026
1064
|
|
1027
|
-
def
|
1028
|
-
|
1029
|
-
.
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
.
|
1065
|
+
def test_extend_warns_when_extendee_doesnt_exist
|
1066
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
1067
|
+
".foo" failed to @extend ".bar".
|
1068
|
+
The selector ".bar" was not found.
|
1069
|
+
Use "@extend .bar !optional" if the extend should be able to fail.
|
1070
|
+
ERR
|
1071
|
+
.foo {@extend .bar}
|
1034
1072
|
SCSS
|
1035
1073
|
end
|
1036
1074
|
|
1037
|
-
def
|
1038
|
-
|
1039
|
-
.
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
.
|
1075
|
+
def test_extend_warns_when_extension_fails
|
1076
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {render(<<SCSS)}
|
1077
|
+
"b.foo" failed to @extend ".bar".
|
1078
|
+
No selectors matching ".bar" could be unified with "b.foo".
|
1079
|
+
Use "@extend .bar !optional" if the extend should be able to fail.
|
1080
|
+
ERR
|
1081
|
+
a.bar {a: b}
|
1082
|
+
b.foo {@extend .bar}
|
1044
1083
|
SCSS
|
1045
1084
|
end
|
1046
1085
|
|
1047
|
-
def
|
1048
|
-
assert_equal
|
1049
|
-
.
|
1086
|
+
def test_extend_succeeds_when_one_extension_fails_but_others_dont
|
1087
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1088
|
+
a.bar {
|
1050
1089
|
a: b; }
|
1090
|
+
|
1091
|
+
.bar, b.foo {
|
1092
|
+
c: d; }
|
1051
1093
|
CSS
|
1052
|
-
.
|
1053
|
-
|
1094
|
+
a.bar {a: b}
|
1095
|
+
.bar {c: d}
|
1096
|
+
b.foo {@extend .bar}
|
1054
1097
|
SCSS
|
1055
1098
|
end
|
1056
1099
|
|
1057
|
-
def
|
1058
|
-
assert_equal
|
1059
|
-
|
1100
|
+
def test_optional_extend_succeeds_when_extendee_doesnt_exist
|
1101
|
+
assert_equal("", render(<<SCSS))
|
1102
|
+
.foo {@extend .bar !optional}
|
1103
|
+
SCSS
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
def test_optional_extend_succeeds_when_extension_fails
|
1107
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1108
|
+
a.bar {
|
1060
1109
|
a: b; }
|
1061
1110
|
CSS
|
1062
|
-
a
|
1063
|
-
|
1111
|
+
a.bar {a: b}
|
1112
|
+
b.foo {@extend .bar !optional}
|
1064
1113
|
SCSS
|
1114
|
+
end
|
1065
1115
|
|
1116
|
+
# Regression Tests
|
1117
|
+
|
1118
|
+
def test_extend_parent_selector_suffix
|
1066
1119
|
assert_equal <<CSS, render(<<SCSS)
|
1067
|
-
a
|
1068
|
-
|
1120
|
+
.a-b, .c {
|
1121
|
+
x: y; }
|
1069
1122
|
CSS
|
1070
|
-
a
|
1071
|
-
|
1123
|
+
.a {&-b {x: y}}
|
1124
|
+
.c {@extend .a-b}
|
1072
1125
|
SCSS
|
1073
1126
|
end
|
1074
1127
|
|
1075
|
-
def
|
1128
|
+
def test_pseudo_element_superselector
|
1129
|
+
# Pseudo-elements shouldn't be removed in superselector calculations.
|
1076
1130
|
assert_equal <<CSS, render(<<SCSS)
|
1077
|
-
a
|
1131
|
+
a#bar, a#bar::fblthp {
|
1078
1132
|
a: b; }
|
1079
1133
|
CSS
|
1080
|
-
a
|
1081
|
-
|
1134
|
+
%x#bar {a: b} // Add an id to make the results have high specificity
|
1135
|
+
%y, %y::fblthp {@extend %x}
|
1136
|
+
a {@extend %y}
|
1082
1137
|
SCSS
|
1083
1138
|
|
1139
|
+
# Pseudo-classes can be removed when the second law allows.
|
1084
1140
|
assert_equal <<CSS, render(<<SCSS)
|
1085
|
-
a
|
1141
|
+
a#bar {
|
1086
1142
|
a: b; }
|
1087
1143
|
CSS
|
1088
|
-
|
1089
|
-
|
1144
|
+
%x#bar {a: b}
|
1145
|
+
%y, %y:fblthp {@extend %x}
|
1146
|
+
a {@extend %y}
|
1090
1147
|
SCSS
|
1091
1148
|
|
1092
|
-
|
1093
|
-
|
1149
|
+
# A few pseudo-elements can be written as pseudo-elements for historical
|
1150
|
+
# reasons. See http://www.w3.org/TR/selectors4/#pseudo-elements.
|
1151
|
+
%w[first-line first-letter before after].each do |pseudo|
|
1152
|
+
assert_equal <<CSS, render(<<SCSS)
|
1153
|
+
a#bar, a#bar:#{pseudo} {
|
1094
1154
|
a: b; }
|
1095
1155
|
CSS
|
1096
|
-
|
1097
|
-
|
1156
|
+
%x#bar {a: b}
|
1157
|
+
%y, %y:#{pseudo} {@extend %x}
|
1158
|
+
a {@extend %y}
|
1098
1159
|
SCSS
|
1160
|
+
end
|
1099
1161
|
end
|
1100
1162
|
|
1101
|
-
def
|
1163
|
+
def test_multiple_source_redundancy_elimination
|
1102
1164
|
assert_equal <<CSS, render(<<SCSS)
|
1103
|
-
|
1104
|
-
|
1165
|
+
.test-case, .test-case:active {
|
1166
|
+
color: red; }
|
1167
|
+
|
1168
|
+
.test-case:hover {
|
1169
|
+
color: green; }
|
1105
1170
|
CSS
|
1106
|
-
|
1107
|
-
|
1171
|
+
%default-color {color: red}
|
1172
|
+
%alt-color {color: green}
|
1173
|
+
|
1174
|
+
%default-style {
|
1175
|
+
@extend %default-color;
|
1176
|
+
&:hover {@extend %alt-color}
|
1177
|
+
&:active {@extend %default-color}
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
.test-case {@extend %default-style}
|
1108
1181
|
SCSS
|
1182
|
+
end
|
1109
1183
|
|
1184
|
+
def test_nested_sibling_extend
|
1110
1185
|
assert_equal <<CSS, render(<<SCSS)
|
1111
|
-
|
1112
|
-
|
1186
|
+
.parent .bar, .parent .foo {
|
1187
|
+
width: 2000px; }
|
1113
1188
|
CSS
|
1114
|
-
|
1115
|
-
|
1189
|
+
.foo {@extend .bar}
|
1190
|
+
|
1191
|
+
.parent {
|
1192
|
+
.bar {
|
1193
|
+
width: 2000px;
|
1194
|
+
}
|
1195
|
+
.foo {
|
1196
|
+
@extend .bar
|
1197
|
+
}
|
1198
|
+
}
|
1116
1199
|
SCSS
|
1200
|
+
end
|
1117
1201
|
|
1202
|
+
def test_parent_and_sibling_extend
|
1118
1203
|
assert_equal <<CSS, render(<<SCSS)
|
1119
|
-
|
1120
|
-
|
1204
|
+
.parent1 .parent2 .child1.child2, .parent2 .parent1 .child1.child2 {
|
1205
|
+
c: d; }
|
1121
1206
|
CSS
|
1122
|
-
|
1123
|
-
|
1207
|
+
%foo %bar%baz {c: d}
|
1208
|
+
|
1209
|
+
.parent1 {
|
1210
|
+
@extend %foo;
|
1211
|
+
.child1 {@extend %bar}
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
.parent2 {
|
1215
|
+
@extend %foo;
|
1216
|
+
.child2 {@extend %baz}
|
1217
|
+
}
|
1124
1218
|
SCSS
|
1125
1219
|
end
|
1126
1220
|
|
1127
|
-
def
|
1221
|
+
def test_nested_extend_specificity
|
1128
1222
|
assert_equal <<CSS, render(<<SCSS)
|
1129
|
-
|
1223
|
+
a :b, a :b:c {
|
1130
1224
|
a: b; }
|
1131
1225
|
CSS
|
1132
|
-
|
1133
|
-
|
1226
|
+
%foo {a: b}
|
1227
|
+
|
1228
|
+
a {
|
1229
|
+
:b {@extend %foo}
|
1230
|
+
:b:c {@extend %foo}
|
1231
|
+
}
|
1134
1232
|
SCSS
|
1233
|
+
end
|
1135
1234
|
|
1235
|
+
def test_nested_double_extend_optimization
|
1136
1236
|
assert_equal <<CSS, render(<<SCSS)
|
1137
|
-
.
|
1237
|
+
.parent1 .child {
|
1138
1238
|
a: b; }
|
1139
1239
|
CSS
|
1140
|
-
|
1141
|
-
|
1240
|
+
%foo %bar {
|
1241
|
+
a: b;
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
.parent1 {
|
1245
|
+
@extend %foo;
|
1246
|
+
|
1247
|
+
.child {
|
1248
|
+
@extend %bar;
|
1249
|
+
}
|
1250
|
+
}
|
1251
|
+
|
1252
|
+
.parent2 {
|
1253
|
+
@extend %foo;
|
1254
|
+
}
|
1142
1255
|
SCSS
|
1143
1256
|
end
|
1144
1257
|
|
1145
|
-
def
|
1258
|
+
def test_extend_in_double_nested_media_query
|
1146
1259
|
assert_equal <<CSS, render(<<SCSS)
|
1147
|
-
|
1148
|
-
|
1260
|
+
@media all and (orientation: landscape) {
|
1261
|
+
.bar {
|
1262
|
+
color: blue; } }
|
1149
1263
|
CSS
|
1150
|
-
|
1151
|
-
|
1264
|
+
@media all {
|
1265
|
+
@media (orientation: landscape) {
|
1266
|
+
%foo {color: blue}
|
1267
|
+
.bar {@extend %foo}
|
1268
|
+
}
|
1269
|
+
}
|
1152
1270
|
SCSS
|
1153
1271
|
end
|
1154
1272
|
|
1155
|
-
def
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
end
|
1273
|
+
def test_partially_failed_extend
|
1274
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
1275
|
+
.rc, test {
|
1276
|
+
color: white; }
|
1160
1277
|
|
1161
|
-
|
1162
|
-
|
1163
|
-
.baz .foo, .baz foo + bar {
|
1164
|
-
a: b; }
|
1278
|
+
.prices span.pill span.rc {
|
1279
|
+
color: red; }
|
1165
1280
|
CSS
|
1166
|
-
|
1167
|
-
|
1281
|
+
test { @extend .rc; }
|
1282
|
+
.rc {color: white;}
|
1283
|
+
.prices span.pill span.rc {color: red;}
|
1168
1284
|
SCSS
|
1169
1285
|
end
|
1170
1286
|
|
1171
|
-
def
|
1287
|
+
def test_newline_near_combinator
|
1172
1288
|
assert_equal <<CSS, render(<<SCSS)
|
1173
|
-
.
|
1289
|
+
.a +
|
1290
|
+
.b x, .a +
|
1291
|
+
.b .c y, .c .a +
|
1292
|
+
.b y {
|
1174
1293
|
a: b; }
|
1175
1294
|
CSS
|
1176
|
-
.
|
1177
|
-
|
1295
|
+
.a +
|
1296
|
+
.b x {a: b}
|
1297
|
+
.c y {@extend x}
|
1178
1298
|
SCSS
|
1299
|
+
end
|
1179
1300
|
|
1180
|
-
|
1181
|
-
|
1301
|
+
def test_duplicated_selector_with_newlines
|
1302
|
+
assert_equal(<<CSS, render(<<SCSS))
|
1303
|
+
.example-1-1,
|
1304
|
+
.example-1-2,
|
1305
|
+
.my-page-1 .my-module-1-1,
|
1306
|
+
.example-1-3 {
|
1182
1307
|
a: b; }
|
1183
1308
|
CSS
|
1184
|
-
.
|
1185
|
-
|
1309
|
+
.example-1-1,
|
1310
|
+
.example-1-2,
|
1311
|
+
.example-1-3 {
|
1312
|
+
a: b;
|
1313
|
+
}
|
1314
|
+
|
1315
|
+
.my-page-1 .my-module-1-1 {@extend .example-1-2}
|
1186
1316
|
SCSS
|
1187
1317
|
end
|
1188
1318
|
|
1189
|
-
def
|
1190
|
-
|
1191
|
-
.foo .bar, .foo .baz {
|
1192
|
-
a: b; }
|
1193
|
-
CSS
|
1194
|
-
.foo {
|
1195
|
-
.bar {a: b}
|
1196
|
-
.baz {@extend .bar} }
|
1197
|
-
SCSS
|
1319
|
+
def test_nested_selector_with_child_selector_hack_extendee
|
1320
|
+
assert_extends '> .foo', 'foo bar {@extend .foo}', '> .foo, > foo bar'
|
1198
1321
|
end
|
1199
1322
|
|
1200
|
-
def
|
1201
|
-
|
1202
|
-
.foo > .bar .baz, .foo > .bar .bang {
|
1203
|
-
a: b; }
|
1204
|
-
CSS
|
1205
|
-
.foo > .bar .baz {a: b}
|
1206
|
-
.foo > .bar .bang {@extend .baz}
|
1207
|
-
SCSS
|
1323
|
+
def test_nested_selector_with_child_selector_hack_extender
|
1324
|
+
assert_extends '.foo .bar', '> foo bar {@extend .bar}', '.foo .bar, > .foo foo bar, > foo .foo bar'
|
1208
1325
|
end
|
1209
1326
|
|
1210
|
-
|
1327
|
+
def test_nested_selector_with_child_selector_hack_extender_and_extendee
|
1328
|
+
assert_extends '> .foo', '> foo bar {@extend .foo}', '> .foo, > foo bar'
|
1329
|
+
end
|
1211
1330
|
|
1212
|
-
def
|
1331
|
+
def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee
|
1332
|
+
assert_extends '~ .foo', '> foo bar {@extend .foo}', '~ .foo'
|
1333
|
+
end
|
1334
|
+
|
1335
|
+
def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline
|
1213
1336
|
assert_equal <<CSS, render(<<SCSS)
|
1214
|
-
.foo
|
1337
|
+
> .foo, > flip,
|
1338
|
+
> foo bar {
|
1215
1339
|
a: b; }
|
1216
1340
|
CSS
|
1217
|
-
.foo {a: b
|
1341
|
+
> .foo {a: b}
|
1342
|
+
flip,
|
1343
|
+
> foo bar {@extend .foo}
|
1218
1344
|
SCSS
|
1219
1345
|
end
|
1220
1346
|
|
1221
|
-
def
|
1347
|
+
def test_extended_parent_and_child_redundancy_elimination
|
1222
1348
|
assert_equal <<CSS, render(<<SCSS)
|
1223
|
-
|
1349
|
+
a b, d b, a c, d c {
|
1224
1350
|
a: b; }
|
1225
|
-
|
1226
|
-
.foo, .bar {
|
1227
|
-
c: d; }
|
1228
1351
|
CSS
|
1229
|
-
|
1230
|
-
|
1352
|
+
a {
|
1353
|
+
b {a: b}
|
1354
|
+
c {@extend b}
|
1355
|
+
}
|
1356
|
+
d {@extend a}
|
1231
1357
|
SCSS
|
1232
1358
|
end
|
1233
1359
|
|
1234
|
-
def
|
1235
|
-
|
1236
|
-
|
1237
|
-
a: b; }
|
1360
|
+
def test_extend_redundancy_elimination_when_it_would_reduce_specificity
|
1361
|
+
assert_extends 'a', 'a.foo {@extend a}', 'a, a.foo'
|
1362
|
+
end
|
1238
1363
|
|
1239
|
-
|
1240
|
-
|
1364
|
+
def test_extend_redundancy_elimination_when_it_would_preserve_specificity
|
1365
|
+
assert_extends '.bar a', 'a.foo {@extend a}', '.bar a'
|
1366
|
+
end
|
1241
1367
|
|
1242
|
-
|
1243
|
-
|
1244
|
-
CSS
|
1245
|
-
.foo {a: b; @extend .bar}
|
1246
|
-
.bar {c: d; @extend .baz}
|
1247
|
-
.baz {e: f; @extend .foo}
|
1248
|
-
SCSS
|
1368
|
+
def test_extend_redundancy_elimination_never_eliminates_base_selector
|
1369
|
+
assert_extends 'a.foo', '.foo {@extend a}', 'a.foo, .foo'
|
1249
1370
|
end
|
1250
1371
|
|
1251
|
-
def
|
1372
|
+
def test_extend_cross_branch_redundancy_elimination
|
1252
1373
|
assert_equal <<CSS, render(<<SCSS)
|
1253
|
-
.
|
1374
|
+
.a .c .d, .b .c .a .d {
|
1254
1375
|
a: b; }
|
1255
|
-
.bar .foo, .bar .foo .foo {
|
1256
|
-
c: d; }
|
1257
1376
|
CSS
|
1258
|
-
.
|
1259
|
-
|
1260
|
-
|
1261
|
-
}
|
1377
|
+
%x .c %y {a: b}
|
1378
|
+
.a, .b {@extend %x}
|
1379
|
+
.a .d {@extend %y}
|
1262
1380
|
SCSS
|
1263
|
-
end
|
1264
1381
|
|
1265
|
-
def test_multiple_extender_merges_with_superset_selector
|
1266
1382
|
assert_equal <<CSS, render(<<SCSS)
|
1267
|
-
a.
|
1383
|
+
.e .a .c .d, .a .c .e .d, .e .b .c .a .d, .b .c .a .e .d {
|
1268
1384
|
a: b; }
|
1269
1385
|
CSS
|
1270
|
-
.
|
1271
|
-
|
1386
|
+
.e %z {a: b}
|
1387
|
+
%x .c %y {@extend %z}
|
1388
|
+
.a, .b {@extend %x}
|
1389
|
+
.a .d {@extend %y}
|
1272
1390
|
SCSS
|
1273
1391
|
end
|
1274
1392
|
|
1275
|
-
|
1276
|
-
assert_equal <<CSS, render(<<SCSS)
|
1277
|
-
.true, .also-true {
|
1278
|
-
color: green; }
|
1393
|
+
private
|
1279
1394
|
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
}
|
1293
|
-
|
1395
|
+
def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
|
1396
|
+
message = "\"#{extender}\" failed to @extend \"#{target}\"."
|
1397
|
+
reason =
|
1398
|
+
if reason == :not_found
|
1399
|
+
"The selector \"#{target}\" was not found."
|
1400
|
+
else
|
1401
|
+
"No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
|
1402
|
+
end
|
1403
|
+
|
1404
|
+
assert_raise_message(Sass::SyntaxError, <<ERR) {yield}
|
1405
|
+
#{message}
|
1406
|
+
#{reason}
|
1407
|
+
Use "@extend #{target} !optional" if the extend should be able to fail.
|
1408
|
+
ERR
|
1294
1409
|
end
|
1295
1410
|
|
1296
|
-
def
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1411
|
+
def assert_unification(selector, extension, unified)
|
1412
|
+
# Do some trickery so the first law of extend doesn't get in our way.
|
1413
|
+
assert_extends(
|
1414
|
+
"%-a #{selector}",
|
1415
|
+
extension + " -a {@extend %-a}",
|
1416
|
+
unified.split(', ').map {|s| "-a #{s}"}.join(', '))
|
1417
|
+
end
|
1300
1418
|
|
1301
|
-
|
1302
|
-
|
1419
|
+
def render_unification(selector, extension)
|
1420
|
+
render_extends(
|
1421
|
+
"%-a #{selector}",
|
1422
|
+
extension + " -a {@extend %-a}")
|
1423
|
+
end
|
1303
1424
|
|
1304
|
-
|
1305
|
-
|
1425
|
+
def assert_extends(selector, extension, result)
|
1426
|
+
assert_equal <<CSS, render_extends(selector, extension)
|
1427
|
+
#{result} {
|
1428
|
+
a: b; }
|
1306
1429
|
CSS
|
1307
|
-
.base-0 { color: green; }
|
1308
|
-
.base-1 { display: block; }
|
1309
|
-
.base-2 { border: 1px solid blue; }
|
1310
|
-
.added {
|
1311
|
-
@for $i from 0 to 3 {
|
1312
|
-
@extend .base-\#{$i};
|
1313
|
-
}
|
1314
|
-
}
|
1315
|
-
SCSS
|
1316
1430
|
end
|
1317
1431
|
|
1318
|
-
def
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
.base-1, .added {
|
1324
|
-
display: block; }
|
1325
|
-
|
1326
|
-
.base-2, .added {
|
1327
|
-
border: 1px solid blue; }
|
1328
|
-
CSS
|
1329
|
-
.base-0 { color: green; }
|
1330
|
-
.base-1 { display: block; }
|
1331
|
-
.base-2 { border: 1px solid blue; }
|
1332
|
-
.added {
|
1333
|
-
$i : 0;
|
1334
|
-
@while $i < 3 {
|
1335
|
-
@extend .base-\#{$i};
|
1336
|
-
$i : $i + 1;
|
1337
|
-
}
|
1338
|
-
}
|
1432
|
+
def render_extends(selector, extension)
|
1433
|
+
render(<<SCSS)
|
1434
|
+
#{selector} {a: b}
|
1435
|
+
#{extension}
|
1339
1436
|
SCSS
|
1340
1437
|
end
|
1341
1438
|
|
1342
|
-
private
|
1343
|
-
|
1344
1439
|
def render(sass, options = {})
|
1440
|
+
options = {:syntax => :scss}.merge(options)
|
1345
1441
|
munge_filename options
|
1346
|
-
Sass::Engine.new(sass,
|
1442
|
+
Sass::Engine.new(sass, options).render
|
1347
1443
|
end
|
1348
1444
|
end
|