xass 0.1.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/.yardopts +11 -0
- data/CONTRIBUTING +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +201 -0
- data/Rakefile +349 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/push +13 -0
- data/bin/sass +13 -0
- data/bin/sass-convert +12 -0
- data/bin/scss +13 -0
- data/extra/update_watch.rb +13 -0
- data/init.rb +18 -0
- data/lib/sass/cache_stores/base.rb +88 -0
- data/lib/sass/cache_stores/chain.rb +33 -0
- data/lib/sass/cache_stores/filesystem.rb +64 -0
- data/lib/sass/cache_stores/memory.rb +47 -0
- data/lib/sass/cache_stores/null.rb +25 -0
- data/lib/sass/cache_stores.rb +15 -0
- data/lib/sass/callbacks.rb +66 -0
- data/lib/sass/css.rb +409 -0
- data/lib/sass/engine.rb +930 -0
- data/lib/sass/environment.rb +101 -0
- data/lib/sass/error.rb +201 -0
- data/lib/sass/exec.rb +707 -0
- data/lib/sass/importers/base.rb +139 -0
- data/lib/sass/importers/filesystem.rb +186 -0
- data/lib/sass/importers.rb +22 -0
- data/lib/sass/logger/base.rb +32 -0
- data/lib/sass/logger/log_level.rb +49 -0
- data/lib/sass/logger.rb +15 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +406 -0
- data/lib/sass/plugin/configuration.rb +123 -0
- data/lib/sass/plugin/generic.rb +15 -0
- data/lib/sass/plugin/merb.rb +48 -0
- data/lib/sass/plugin/rack.rb +60 -0
- data/lib/sass/plugin/rails.rb +47 -0
- data/lib/sass/plugin/staleness_checker.rb +199 -0
- data/lib/sass/plugin.rb +133 -0
- data/lib/sass/railtie.rb +10 -0
- data/lib/sass/repl.rb +57 -0
- data/lib/sass/root.rb +7 -0
- data/lib/sass/script/arg_list.rb +52 -0
- data/lib/sass/script/bool.rb +18 -0
- data/lib/sass/script/color.rb +606 -0
- data/lib/sass/script/css_lexer.rb +29 -0
- data/lib/sass/script/css_parser.rb +31 -0
- data/lib/sass/script/funcall.rb +245 -0
- data/lib/sass/script/functions.rb +1543 -0
- data/lib/sass/script/interpolation.rb +79 -0
- data/lib/sass/script/lexer.rb +345 -0
- data/lib/sass/script/list.rb +85 -0
- data/lib/sass/script/literal.rb +221 -0
- data/lib/sass/script/node.rb +99 -0
- data/lib/sass/script/null.rb +37 -0
- data/lib/sass/script/number.rb +453 -0
- data/lib/sass/script/operation.rb +110 -0
- data/lib/sass/script/parser.rb +502 -0
- data/lib/sass/script/string.rb +51 -0
- data/lib/sass/script/string_interpolation.rb +103 -0
- data/lib/sass/script/unary_operation.rb +69 -0
- data/lib/sass/script/variable.rb +58 -0
- data/lib/sass/script.rb +39 -0
- data/lib/sass/scss/css_parser.rb +36 -0
- data/lib/sass/scss/parser.rb +1180 -0
- data/lib/sass/scss/rx.rb +133 -0
- data/lib/sass/scss/script_lexer.rb +15 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/scss/static_parser.rb +54 -0
- data/lib/sass/scss.rb +16 -0
- data/lib/sass/selector/abstract_sequence.rb +94 -0
- data/lib/sass/selector/comma_sequence.rb +92 -0
- data/lib/sass/selector/sequence.rb +507 -0
- data/lib/sass/selector/simple.rb +119 -0
- data/lib/sass/selector/simple_sequence.rb +215 -0
- data/lib/sass/selector.rb +452 -0
- data/lib/sass/shared.rb +76 -0
- data/lib/sass/supports.rb +229 -0
- data/lib/sass/tree/charset_node.rb +22 -0
- data/lib/sass/tree/comment_node.rb +82 -0
- 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 +18 -0
- data/lib/sass/tree/directive_node.rb +42 -0
- data/lib/sass/tree/each_node.rb +24 -0
- data/lib/sass/tree/extend_node.rb +36 -0
- data/lib/sass/tree/for_node.rb +36 -0
- data/lib/sass/tree/function_node.rb +34 -0
- data/lib/sass/tree/if_node.rb +52 -0
- data/lib/sass/tree/import_node.rb +75 -0
- data/lib/sass/tree/media_node.rb +58 -0
- data/lib/sass/tree/mixin_def_node.rb +38 -0
- data/lib/sass/tree/mixin_node.rb +39 -0
- data/lib/sass/tree/node.rb +196 -0
- data/lib/sass/tree/prop_node.rb +152 -0
- data/lib/sass/tree/return_node.rb +18 -0
- data/lib/sass/tree/root_node.rb +78 -0
- data/lib/sass/tree/rule_node.rb +132 -0
- data/lib/sass/tree/supports_node.rb +51 -0
- data/lib/sass/tree/trace_node.rb +32 -0
- data/lib/sass/tree/variable_node.rb +30 -0
- data/lib/sass/tree/visitors/base.rb +75 -0
- data/lib/sass/tree/visitors/check_nesting.rb +147 -0
- data/lib/sass/tree/visitors/convert.rb +316 -0
- data/lib/sass/tree/visitors/cssize.rb +241 -0
- 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 +446 -0
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +228 -0
- data/lib/sass/tree/warn_node.rb +18 -0
- data/lib/sass/tree/while_node.rb +18 -0
- data/lib/sass/util/multibyte_string_scanner.rb +155 -0
- data/lib/sass/util/subset_map.rb +109 -0
- data/lib/sass/util/test.rb +10 -0
- data/lib/sass/util.rb +948 -0
- data/lib/sass/version.rb +126 -0
- data/lib/sass.rb +95 -0
- data/rails/init.rb +1 -0
- data/test/Gemfile +3 -0
- data/test/Gemfile.lock +10 -0
- data/test/sass/cache_test.rb +89 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/conversion_test.rb +1760 -0
- data/test/sass/css2sass_test.rb +458 -0
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/engine_test.rb +3244 -0
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +1482 -0
- 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 +1139 -0
- data/test/sass/importer_test.rb +192 -0
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/mock_importer.rb +49 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +564 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +86 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/if.css +3 -0
- data/test/sass/results/import.css +31 -0
- data/test/sass/results/import_charset.css +5 -0
- data/test/sass/results/import_charset_1_8.css +5 -0
- data/test/sass/results/import_charset_ibm866.css +5 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/options.css +1 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/scss_import.css +31 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +299 -0
- data/test/sass/script_test.rb +622 -0
- data/test/sass/scss/css_test.rb +1100 -0
- data/test/sass/scss/rx_test.rb +156 -0
- data/test/sass/scss/scss_test.rb +2106 -0
- data/test/sass/scss/test_helper.rb +37 -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_charset_ibm866.sass +4 -0
- data/test/sass/templates/_imported_charset_utf8.sass +4 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork1.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/bork4.sass +2 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +305 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/if.sass +11 -0
- data/test/sass/templates/import.sass +12 -0
- data/test/sass/templates/import_charset.sass +9 -0
- data/test/sass/templates/import_charset_1_8.sass +6 -0
- data/test/sass/templates/import_charset_ibm866.sass +11 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/importee.less +2 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixin_bork.sass +5 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -0
- data/test/sass/templates/nested_bork4.sass +2 -0
- data/test/sass/templates/nested_import.sass +2 -0
- data/test/sass/templates/nested_mixin_bork.sass +6 -0
- data/test/sass/templates/options.sass +2 -0
- data/test/sass/templates/parent_ref.sass +25 -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/script.sass +101 -0
- data/test/sass/templates/scss_import.scss +11 -0
- data/test/sass/templates/scss_importee.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/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/sass/templates/warn.sass +3 -0
- data/test/sass/templates/warn_imported.sass +4 -0
- data/test/sass/test_helper.rb +8 -0
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/subset_map_test.rb +91 -0
- data/test/sass/util_test.rb +382 -0
- data/test/test_helper.rb +80 -0
- metadata +354 -0
|
@@ -0,0 +1,1482 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
3
|
+
|
|
4
|
+
class ExtendTest < Test::Unit::TestCase
|
|
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
|
+
assert_unification '.foo#baz', '#bar {@extend .foo}', '.foo#baz'
|
|
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_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
|
|
177
|
+
|
|
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|*'
|
|
181
|
+
|
|
182
|
+
assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
|
|
183
|
+
assert_unification 'ns1|*.foo', 'ns2|* {@extend .foo}', 'ns1|*.foo'
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
assert_unification 'ns|*.foo', 'ns|* {@extend .foo}', 'ns|*'
|
|
187
|
+
end
|
|
188
|
+
|
|
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
|
|
197
|
+
|
|
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'
|
|
201
|
+
|
|
202
|
+
assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
|
|
203
|
+
assert_unification 'ns1|a.foo', 'ns2|* {@extend .foo}', 'ns1|a.foo'
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
assert_unification 'ns|a.foo', 'ns|* {@extend .foo}', 'ns|a'
|
|
207
|
+
end
|
|
208
|
+
|
|
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
|
|
215
|
+
|
|
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'
|
|
223
|
+
end
|
|
224
|
+
|
|
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'
|
|
228
|
+
|
|
229
|
+
assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
|
|
230
|
+
assert_unification 'ns1|*.foo', 'ns2|a {@extend .foo}', 'ns1|*.foo'
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
assert_unification 'ns|*.foo', 'ns|a {@extend .foo}', 'ns|*.foo, ns|a'
|
|
234
|
+
end
|
|
235
|
+
|
|
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
|
+
assert_unification 'a.foo', 'h1 {@extend .foo}', 'a.foo'
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
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'
|
|
252
|
+
|
|
253
|
+
assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
|
|
254
|
+
assert_unification 'ns1|a.foo', 'ns2|a {@extend .foo}', 'ns1|a.foo'
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
assert_unification 'ns|a.foo', 'ns|a {@extend .foo}', 'ns|a'
|
|
258
|
+
end
|
|
259
|
+
|
|
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
|
|
267
|
+
|
|
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'
|
|
271
|
+
|
|
272
|
+
assert_extend_doesnt_match('::bar', '.baz', :failed_to_unify, 2) do
|
|
273
|
+
assert_unification '::foo.baz', '::bar {@extend .baz}', '::foo.baz'
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
assert_extend_doesnt_match('::foo(2n+1)', '.baz', :failed_to_unify, 2) do
|
|
277
|
+
assert_unification '::foo.baz', '::foo(2n+1) {@extend .baz}', '::foo.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'
|
|
286
|
+
end
|
|
287
|
+
|
|
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
|
|
292
|
+
|
|
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
|
|
297
|
+
|
|
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
|
|
301
|
+
|
|
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'
|
|
305
|
+
end
|
|
306
|
+
|
|
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
|
|
319
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
320
|
+
.foo, .baz {
|
|
321
|
+
a: b; }
|
|
322
|
+
|
|
323
|
+
.bar, .baz {
|
|
324
|
+
c: d; }
|
|
325
|
+
CSS
|
|
326
|
+
.foo {a: b}
|
|
327
|
+
.bar {c: d}
|
|
328
|
+
.baz {@extend .foo, .bar}
|
|
329
|
+
SCSS
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def test_redundant_selector_elimination
|
|
333
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
334
|
+
.foo.bar, .x, .y {
|
|
335
|
+
a: b; }
|
|
336
|
+
CSS
|
|
337
|
+
.foo.bar {a: b}
|
|
338
|
+
.x {@extend .foo, .bar}
|
|
339
|
+
.y {@extend .foo, .bar}
|
|
340
|
+
SCSS
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
## Long Extendees
|
|
344
|
+
|
|
345
|
+
def test_long_extendee
|
|
346
|
+
assert_extends '.foo.bar', '.baz {@extend .foo.bar}', '.foo.bar, .baz'
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def test_long_extendee_requires_all_selectors
|
|
350
|
+
assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
|
|
351
|
+
assert_extends '.foo', '.baz {@extend .foo.bar}', '.foo'
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def test_long_extendee_matches_supersets
|
|
356
|
+
assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'
|
|
357
|
+
end
|
|
358
|
+
|
|
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
|
|
362
|
+
|
|
363
|
+
## Long Extenders
|
|
364
|
+
|
|
365
|
+
def test_long_extender
|
|
366
|
+
assert_extends '.foo.bar', '.baz.bang {@extend .foo}', '.foo.bar, .bar.baz.bang'
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def test_long_extender_runs_unification
|
|
370
|
+
assert_extends 'ns|*.foo.bar', 'a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def test_long_extender_aborts_unification
|
|
374
|
+
assert_extend_doesnt_match('h1.baz', '.foo', :failed_to_unify, 2) do
|
|
375
|
+
assert_extends 'a.foo#bar', 'h1.baz {@extend .foo}', 'a.foo#bar'
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
assert_extend_doesnt_match('.bang#baz', '.foo', :failed_to_unify, 2) do
|
|
379
|
+
assert_extends 'a.foo#bar', '.bang#baz {@extend .foo}', 'a.foo#bar'
|
|
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
|
+
assert_extends 'baz.foo', 'foo bar {@extend .foo}', 'baz.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'
|
|
470
|
+
|
|
471
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
472
|
+
.baz > .foo, .baz > .bar {
|
|
473
|
+
a: b; }
|
|
474
|
+
CSS
|
|
475
|
+
.baz > {
|
|
476
|
+
.foo {a: b}
|
|
477
|
+
.bar {@extend .foo}
|
|
478
|
+
}
|
|
479
|
+
SCSS
|
|
480
|
+
|
|
481
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
482
|
+
.foo .bar, .foo > .baz {
|
|
483
|
+
a: b; }
|
|
484
|
+
CSS
|
|
485
|
+
.foo {
|
|
486
|
+
.bar {a: b}
|
|
487
|
+
> .baz {@extend .bar}
|
|
488
|
+
}
|
|
489
|
+
SCSS
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def test_another_nested_extender_with_early_child_selectors_doesnt_subseq_them
|
|
493
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
494
|
+
.foo .bar, .foo .bip > .baz {
|
|
495
|
+
a: b; }
|
|
496
|
+
CSS
|
|
497
|
+
.foo {
|
|
498
|
+
.bar {a: b}
|
|
499
|
+
.bip > .baz {@extend .bar}
|
|
500
|
+
}
|
|
501
|
+
SCSS
|
|
502
|
+
|
|
503
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
504
|
+
.foo .bip .bar, .foo .bip .foo > .baz {
|
|
505
|
+
a: b; }
|
|
506
|
+
CSS
|
|
507
|
+
.foo {
|
|
508
|
+
.bip .bar {a: b}
|
|
509
|
+
> .baz {@extend .bar}
|
|
510
|
+
}
|
|
511
|
+
SCSS
|
|
512
|
+
|
|
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
|
|
517
|
+
|
|
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
|
|
523
|
+
|
|
524
|
+
def test_nested_extender_with_sibling_selector
|
|
525
|
+
assert_extends '.baz .foo', 'foo + bar {@extend .foo}', '.baz .foo, .baz foo + bar'
|
|
526
|
+
end
|
|
527
|
+
|
|
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
|
|
533
|
+
|
|
534
|
+
def test_nested_extender_merges_with_same_selector
|
|
535
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
536
|
+
.foo .bar, .foo .baz {
|
|
537
|
+
a: b; }
|
|
538
|
+
CSS
|
|
539
|
+
.foo {
|
|
540
|
+
.bar {a: b}
|
|
541
|
+
.baz {@extend .bar} }
|
|
542
|
+
SCSS
|
|
543
|
+
end
|
|
544
|
+
|
|
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
|
|
549
|
+
|
|
550
|
+
# Combinator Unification
|
|
551
|
+
|
|
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
|
|
561
|
+
|
|
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'
|
|
567
|
+
end
|
|
568
|
+
|
|
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
|
|
579
|
+
|
|
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
|
|
586
|
+
|
|
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
|
|
593
|
+
|
|
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
|
|
600
|
+
|
|
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'
|
|
608
|
+
end
|
|
609
|
+
|
|
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
|
|
618
|
+
|
|
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
|
|
623
|
+
|
|
624
|
+
def test_combinator_unification_with_newlines
|
|
625
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
626
|
+
.a >
|
|
627
|
+
.b
|
|
628
|
+
+ x, .c.a > .d.b + y {
|
|
629
|
+
a: b; }
|
|
630
|
+
CSS
|
|
631
|
+
.a >
|
|
632
|
+
.b
|
|
633
|
+
+ x {a: b}
|
|
634
|
+
.c
|
|
635
|
+
> .d +
|
|
636
|
+
y {@extend x}
|
|
637
|
+
SCSS
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
# Loops
|
|
641
|
+
|
|
642
|
+
def test_extend_self_loop
|
|
643
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
644
|
+
.foo {
|
|
645
|
+
a: b; }
|
|
646
|
+
CSS
|
|
647
|
+
.foo {a: b; @extend .foo}
|
|
648
|
+
SCSS
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def test_basic_extend_loop
|
|
652
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
653
|
+
.bar, .foo {
|
|
654
|
+
a: b; }
|
|
655
|
+
|
|
656
|
+
.foo, .bar {
|
|
657
|
+
c: d; }
|
|
658
|
+
CSS
|
|
659
|
+
.foo {a: b; @extend .bar}
|
|
660
|
+
.bar {c: d; @extend .foo}
|
|
661
|
+
SCSS
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
def test_three_level_extend_loop
|
|
665
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
666
|
+
.baz, .bar, .foo {
|
|
667
|
+
a: b; }
|
|
668
|
+
|
|
669
|
+
.foo, .baz, .bar {
|
|
670
|
+
c: d; }
|
|
671
|
+
|
|
672
|
+
.bar, .foo, .baz {
|
|
673
|
+
e: f; }
|
|
674
|
+
CSS
|
|
675
|
+
.foo {a: b; @extend .bar}
|
|
676
|
+
.bar {c: d; @extend .baz}
|
|
677
|
+
.baz {e: f; @extend .foo}
|
|
678
|
+
SCSS
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def test_nested_extend_loop
|
|
682
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
683
|
+
.bar, .bar .foo {
|
|
684
|
+
a: b; }
|
|
685
|
+
.bar .foo {
|
|
686
|
+
c: d; }
|
|
687
|
+
CSS
|
|
688
|
+
.bar {
|
|
689
|
+
a: b;
|
|
690
|
+
.foo {c: d; @extend .bar}
|
|
691
|
+
}
|
|
692
|
+
SCSS
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
def test_multiple_extender_merges_with_superset_selector
|
|
696
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
697
|
+
a.bar.baz, a.foo {
|
|
698
|
+
a: b; }
|
|
699
|
+
CSS
|
|
700
|
+
.foo {@extend .bar; @extend .baz}
|
|
701
|
+
a.bar.baz {a: b}
|
|
702
|
+
SCSS
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def test_control_flow_if
|
|
706
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
707
|
+
.true, .also-true {
|
|
708
|
+
color: green; }
|
|
709
|
+
|
|
710
|
+
.false, .also-false {
|
|
711
|
+
color: red; }
|
|
712
|
+
CSS
|
|
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
|
+
}
|
|
723
|
+
SCSS
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
def test_control_flow_for
|
|
727
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
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; }
|
|
736
|
+
CSS
|
|
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
|
+
}
|
|
745
|
+
SCSS
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
def test_control_flow_while
|
|
749
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
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; }
|
|
758
|
+
CSS
|
|
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
|
+
}
|
|
769
|
+
SCSS
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
def test_basic_placeholder_selector
|
|
773
|
+
assert_extends '%foo', '.bar {@extend %foo}', '.bar'
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
def test_unused_placeholder_selector
|
|
777
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
778
|
+
.baz {
|
|
779
|
+
color: blue; }
|
|
780
|
+
CSS
|
|
781
|
+
%foo {color: blue}
|
|
782
|
+
%bar {color: red}
|
|
783
|
+
.baz {@extend %foo}
|
|
784
|
+
SCSS
|
|
785
|
+
end
|
|
786
|
+
|
|
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
|
|
792
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
793
|
+
.bar .baz {
|
|
794
|
+
color: blue; }
|
|
795
|
+
CSS
|
|
796
|
+
#context %foo, .bar .baz {color: blue}
|
|
797
|
+
SCSS
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
def test_placeholder_selector_with_multiple_extenders
|
|
801
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
802
|
+
.bar, .baz {
|
|
803
|
+
color: blue; }
|
|
804
|
+
CSS
|
|
805
|
+
%foo {color: blue}
|
|
806
|
+
.bar {@extend %foo}
|
|
807
|
+
.baz {@extend %foo}
|
|
808
|
+
SCSS
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
def test_placeholder_selector_as_modifier
|
|
812
|
+
assert_extend_doesnt_match('div', '%foo', :failed_to_unify, 3) do
|
|
813
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
814
|
+
a.baz.bar {
|
|
815
|
+
color: blue; }
|
|
816
|
+
CSS
|
|
817
|
+
a%foo.baz {color: blue}
|
|
818
|
+
.bar {@extend %foo}
|
|
819
|
+
div {@extend %foo}
|
|
820
|
+
SCSS
|
|
821
|
+
end
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
def test_placeholder_interpolation
|
|
825
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
826
|
+
.bar {
|
|
827
|
+
color: blue; }
|
|
828
|
+
CSS
|
|
829
|
+
$foo: foo;
|
|
830
|
+
|
|
831
|
+
%\#{$foo} {color: blue}
|
|
832
|
+
.bar {@extend %foo}
|
|
833
|
+
SCSS
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
def test_media_in_placeholder_selector
|
|
837
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
838
|
+
.baz {
|
|
839
|
+
c: d; }
|
|
840
|
+
CSS
|
|
841
|
+
%foo {bar {@media screen {a: b}}}
|
|
842
|
+
.baz {c: d}
|
|
843
|
+
SCSS
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
def test_extend_out_of_media
|
|
847
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
848
|
+
DEPRECATION WARNING on line 3 of test_extend_out_of_media_inline.scss:
|
|
849
|
+
@extending an outer selector from within @media is deprecated.
|
|
850
|
+
You may only @extend selectors within the same directive.
|
|
851
|
+
This will be an error in Sass 3.3.
|
|
852
|
+
It can only work once @extend is supported natively in the browser.
|
|
853
|
+
WARN
|
|
854
|
+
.foo {
|
|
855
|
+
a: b; }
|
|
856
|
+
CSS
|
|
857
|
+
.foo {a: b}
|
|
858
|
+
@media screen {
|
|
859
|
+
.bar {@extend .foo}
|
|
860
|
+
}
|
|
861
|
+
SCSS
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
def test_extend_out_of_unknown_directive
|
|
865
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
866
|
+
DEPRECATION WARNING on line 3 of test_extend_out_of_unknown_directive_inline.scss:
|
|
867
|
+
@extending an outer selector from within @flooblehoof is deprecated.
|
|
868
|
+
You may only @extend selectors within the same directive.
|
|
869
|
+
This will be an error in Sass 3.3.
|
|
870
|
+
It can only work once @extend is supported natively in the browser.
|
|
871
|
+
WARN
|
|
872
|
+
.foo {
|
|
873
|
+
a: b; }
|
|
874
|
+
|
|
875
|
+
@flooblehoof {}
|
|
876
|
+
CSS
|
|
877
|
+
.foo {a: b}
|
|
878
|
+
@flooblehoof {
|
|
879
|
+
.bar {@extend .foo}
|
|
880
|
+
}
|
|
881
|
+
SCSS
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
def test_extend_out_of_nested_directives
|
|
885
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
886
|
+
DEPRECATION WARNING on line 4 of test_extend_out_of_nested_directives_inline.scss:
|
|
887
|
+
@extending an outer selector from within @flooblehoof is deprecated.
|
|
888
|
+
You may only @extend selectors within the same directive.
|
|
889
|
+
This will be an error in Sass 3.3.
|
|
890
|
+
It can only work once @extend is supported natively in the browser.
|
|
891
|
+
WARN
|
|
892
|
+
@media screen {
|
|
893
|
+
.foo {
|
|
894
|
+
a: b; }
|
|
895
|
+
|
|
896
|
+
@flooblehoof {} }
|
|
897
|
+
CSS
|
|
898
|
+
@media screen {
|
|
899
|
+
.foo {a: b}
|
|
900
|
+
@flooblehoof {
|
|
901
|
+
.bar {@extend .foo}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
SCSS
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
def test_extend_within_media
|
|
908
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
909
|
+
@media screen {
|
|
910
|
+
.foo, .bar {
|
|
911
|
+
a: b; } }
|
|
912
|
+
CSS
|
|
913
|
+
@media screen {
|
|
914
|
+
.foo {a: b}
|
|
915
|
+
.bar {@extend .foo}
|
|
916
|
+
}
|
|
917
|
+
SCSS
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
def test_extend_within_unknown_directive
|
|
921
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
922
|
+
@flooblehoof {
|
|
923
|
+
.foo, .bar {
|
|
924
|
+
a: b; } }
|
|
925
|
+
CSS
|
|
926
|
+
@flooblehoof {
|
|
927
|
+
.foo {a: b}
|
|
928
|
+
.bar {@extend .foo}
|
|
929
|
+
}
|
|
930
|
+
SCSS
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
def test_extend_within_nested_directives
|
|
934
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
935
|
+
@media screen {
|
|
936
|
+
@flooblehoof {
|
|
937
|
+
.foo, .bar {
|
|
938
|
+
a: b; } } }
|
|
939
|
+
CSS
|
|
940
|
+
@media screen {
|
|
941
|
+
@flooblehoof {
|
|
942
|
+
.foo {a: b}
|
|
943
|
+
.bar {@extend .foo}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
SCSS
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
def test_extend_within_disparate_media
|
|
950
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
951
|
+
@media screen {
|
|
952
|
+
.foo, .bar {
|
|
953
|
+
a: b; } }
|
|
954
|
+
CSS
|
|
955
|
+
@media screen {.foo {a: b}}
|
|
956
|
+
@media screen {.bar {@extend .foo}}
|
|
957
|
+
SCSS
|
|
958
|
+
end
|
|
959
|
+
|
|
960
|
+
def test_extend_within_disparate_unknown_directive
|
|
961
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
962
|
+
@flooblehoof {
|
|
963
|
+
.foo, .bar {
|
|
964
|
+
a: b; } }
|
|
965
|
+
|
|
966
|
+
@flooblehoof {}
|
|
967
|
+
CSS
|
|
968
|
+
@flooblehoof {.foo {a: b}}
|
|
969
|
+
@flooblehoof {.bar {@extend .foo}}
|
|
970
|
+
SCSS
|
|
971
|
+
end
|
|
972
|
+
|
|
973
|
+
def test_extend_within_disparate_nested_directives
|
|
974
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
975
|
+
@media screen {
|
|
976
|
+
@flooblehoof {
|
|
977
|
+
.foo, .bar {
|
|
978
|
+
a: b; } } }
|
|
979
|
+
@media screen {
|
|
980
|
+
@flooblehoof {} }
|
|
981
|
+
CSS
|
|
982
|
+
@media screen {@flooblehoof {.foo {a: b}}}
|
|
983
|
+
@media screen {@flooblehoof {.bar {@extend .foo}}}
|
|
984
|
+
SCSS
|
|
985
|
+
end
|
|
986
|
+
|
|
987
|
+
def test_extend_within_and_without_media
|
|
988
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
989
|
+
DEPRECATION WARNING on line 4 of test_extend_within_and_without_media_inline.scss:
|
|
990
|
+
@extending an outer selector from within @media is deprecated.
|
|
991
|
+
You may only @extend selectors within the same directive.
|
|
992
|
+
This will be an error in Sass 3.3.
|
|
993
|
+
It can only work once @extend is supported natively in the browser.
|
|
994
|
+
WARN
|
|
995
|
+
.foo {
|
|
996
|
+
a: b; }
|
|
997
|
+
|
|
998
|
+
@media screen {
|
|
999
|
+
.foo, .bar {
|
|
1000
|
+
c: d; } }
|
|
1001
|
+
CSS
|
|
1002
|
+
.foo {a: b}
|
|
1003
|
+
@media screen {
|
|
1004
|
+
.foo {c: d}
|
|
1005
|
+
.bar {@extend .foo}
|
|
1006
|
+
}
|
|
1007
|
+
SCSS
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
def test_extend_within_and_without_unknown_directive
|
|
1011
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
1012
|
+
DEPRECATION WARNING on line 4 of test_extend_within_and_without_unknown_directive_inline.scss:
|
|
1013
|
+
@extending an outer selector from within @flooblehoof is deprecated.
|
|
1014
|
+
You may only @extend selectors within the same directive.
|
|
1015
|
+
This will be an error in Sass 3.3.
|
|
1016
|
+
It can only work once @extend is supported natively in the browser.
|
|
1017
|
+
WARN
|
|
1018
|
+
.foo {
|
|
1019
|
+
a: b; }
|
|
1020
|
+
|
|
1021
|
+
@flooblehoof {
|
|
1022
|
+
.foo, .bar {
|
|
1023
|
+
c: d; } }
|
|
1024
|
+
CSS
|
|
1025
|
+
.foo {a: b}
|
|
1026
|
+
@flooblehoof {
|
|
1027
|
+
.foo {c: d}
|
|
1028
|
+
.bar {@extend .foo}
|
|
1029
|
+
}
|
|
1030
|
+
SCSS
|
|
1031
|
+
end
|
|
1032
|
+
|
|
1033
|
+
def test_extend_within_and_without_nested_directives
|
|
1034
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
1035
|
+
DEPRECATION WARNING on line 5 of test_extend_within_and_without_nested_directives_inline.scss:
|
|
1036
|
+
@extending an outer selector from within @flooblehoof is deprecated.
|
|
1037
|
+
You may only @extend selectors within the same directive.
|
|
1038
|
+
This will be an error in Sass 3.3.
|
|
1039
|
+
It can only work once @extend is supported natively in the browser.
|
|
1040
|
+
WARN
|
|
1041
|
+
@media screen {
|
|
1042
|
+
.foo {
|
|
1043
|
+
a: b; }
|
|
1044
|
+
|
|
1045
|
+
@flooblehoof {
|
|
1046
|
+
.foo, .bar {
|
|
1047
|
+
c: d; } } }
|
|
1048
|
+
CSS
|
|
1049
|
+
@media screen {
|
|
1050
|
+
.foo {a: b}
|
|
1051
|
+
@flooblehoof {
|
|
1052
|
+
.foo {c: d}
|
|
1053
|
+
.bar {@extend .foo}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
SCSS
|
|
1057
|
+
end
|
|
1058
|
+
|
|
1059
|
+
def test_extend_with_subject_transfers_subject_to_extender
|
|
1060
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1061
|
+
foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
|
|
1062
|
+
a: b; }
|
|
1063
|
+
CSS
|
|
1064
|
+
foo bar! baz {a: b}
|
|
1065
|
+
.bip .bap {@extend bar}
|
|
1066
|
+
SCSS
|
|
1067
|
+
|
|
1068
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1069
|
+
foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
|
|
1070
|
+
a: b; }
|
|
1071
|
+
CSS
|
|
1072
|
+
foo.x bar.y! baz.z {a: b}
|
|
1073
|
+
.bip .bap {@extend .y}
|
|
1074
|
+
SCSS
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
def test_extend_with_subject_retains_subject_on_target
|
|
1078
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1079
|
+
.foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
|
|
1080
|
+
a: b; }
|
|
1081
|
+
CSS
|
|
1082
|
+
.foo! .bar {a: b}
|
|
1083
|
+
.bip .bap {@extend .bar}
|
|
1084
|
+
SCSS
|
|
1085
|
+
end
|
|
1086
|
+
|
|
1087
|
+
def test_extend_with_subject_transfers_subject_to_target
|
|
1088
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1089
|
+
a.foo .bar, .bip a.bap! .bar {
|
|
1090
|
+
a: b; }
|
|
1091
|
+
CSS
|
|
1092
|
+
a.foo .bar {a: b}
|
|
1093
|
+
.bip .bap! {@extend .foo}
|
|
1094
|
+
SCSS
|
|
1095
|
+
end
|
|
1096
|
+
|
|
1097
|
+
def test_extend_with_subject_retains_subject_on_extender
|
|
1098
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1099
|
+
.foo .bar, .foo .bip! .bap, .bip! .foo .bap {
|
|
1100
|
+
a: b; }
|
|
1101
|
+
CSS
|
|
1102
|
+
.foo .bar {a: b}
|
|
1103
|
+
.bip! .bap {@extend .bar}
|
|
1104
|
+
SCSS
|
|
1105
|
+
end
|
|
1106
|
+
|
|
1107
|
+
def test_extend_with_subject_fails_with_conflicting_subject
|
|
1108
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1109
|
+
x! .bar {
|
|
1110
|
+
a: b; }
|
|
1111
|
+
CSS
|
|
1112
|
+
x! .bar {a: b}
|
|
1113
|
+
y! .bap {@extend .bar}
|
|
1114
|
+
SCSS
|
|
1115
|
+
end
|
|
1116
|
+
|
|
1117
|
+
def test_extend_warns_when_extendee_doesnt_exist
|
|
1118
|
+
assert_warning(<<WARN) {assert_equal("", render(<<SCSS))}
|
|
1119
|
+
WARNING on line 1 of test_extend_warns_when_extendee_doesnt_exist_inline.scss: ".foo" failed to @extend ".bar".
|
|
1120
|
+
The selector ".bar" was not found.
|
|
1121
|
+
This will be an error in future releases of Sass.
|
|
1122
|
+
Use "@extend .bar !optional" if the extend should be able to fail.
|
|
1123
|
+
WARN
|
|
1124
|
+
.foo {@extend .bar}
|
|
1125
|
+
SCSS
|
|
1126
|
+
end
|
|
1127
|
+
|
|
1128
|
+
def test_extend_warns_when_extension_fails
|
|
1129
|
+
assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
|
|
1130
|
+
WARNING on line 2 of test_extend_warns_when_extension_fails_inline.scss: "b.foo" failed to @extend ".bar".
|
|
1131
|
+
No selectors matching ".bar" could be unified with "b.foo".
|
|
1132
|
+
This will be an error in future releases of Sass.
|
|
1133
|
+
Use "@extend .bar !optional" if the extend should be able to fail.
|
|
1134
|
+
WARN
|
|
1135
|
+
a.bar {
|
|
1136
|
+
a: b; }
|
|
1137
|
+
CSS
|
|
1138
|
+
a.bar {a: b}
|
|
1139
|
+
b.foo {@extend .bar}
|
|
1140
|
+
SCSS
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
def test_extend_does_not_warn_when_one_extension_fails_but_others_dont
|
|
1144
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
|
1145
|
+
a.bar {
|
|
1146
|
+
a: b; }
|
|
1147
|
+
|
|
1148
|
+
.bar, b.foo {
|
|
1149
|
+
c: d; }
|
|
1150
|
+
CSS
|
|
1151
|
+
a.bar {a: b}
|
|
1152
|
+
.bar {c: d}
|
|
1153
|
+
b.foo {@extend .bar}
|
|
1154
|
+
SCSS
|
|
1155
|
+
end
|
|
1156
|
+
|
|
1157
|
+
def test_optional_extend_does_not_warn_when_extendee_doesnt_exist
|
|
1158
|
+
assert_no_warning {assert_equal("", render(<<SCSS))}
|
|
1159
|
+
.foo {@extend .bar !optional}
|
|
1160
|
+
SCSS
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
def test_optional_extend_does_not_warn_when_extension_fails
|
|
1164
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
|
1165
|
+
a.bar {
|
|
1166
|
+
a: b; }
|
|
1167
|
+
CSS
|
|
1168
|
+
a.bar {a: b}
|
|
1169
|
+
b.foo {@extend .bar !optional}
|
|
1170
|
+
SCSS
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1173
|
+
# Regression Tests
|
|
1174
|
+
|
|
1175
|
+
def test_pseudo_element_superselector
|
|
1176
|
+
# Pseudo-elements shouldn't be removed in superselector calculations.
|
|
1177
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1178
|
+
a#bar, a#bar::fblthp {
|
|
1179
|
+
a: b; }
|
|
1180
|
+
CSS
|
|
1181
|
+
%x#bar {a: b} // Add an id to make the results have high specificity
|
|
1182
|
+
%y, %y::fblthp {@extend %x}
|
|
1183
|
+
a {@extend %y}
|
|
1184
|
+
SCSS
|
|
1185
|
+
|
|
1186
|
+
# Pseudo-classes can be removed when the second law allows.
|
|
1187
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1188
|
+
a#bar {
|
|
1189
|
+
a: b; }
|
|
1190
|
+
CSS
|
|
1191
|
+
%x#bar {a: b}
|
|
1192
|
+
%y, %y:fblthp {@extend %x}
|
|
1193
|
+
a {@extend %y}
|
|
1194
|
+
SCSS
|
|
1195
|
+
|
|
1196
|
+
# A few pseudo-elements can be written as pseudo-elements for historical
|
|
1197
|
+
# reasons. See http://www.w3.org/TR/selectors4/#pseudo-elements.
|
|
1198
|
+
%w[first-line first-letter before after].each do |pseudo|
|
|
1199
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1200
|
+
a#bar, a#bar:#{pseudo} {
|
|
1201
|
+
a: b; }
|
|
1202
|
+
CSS
|
|
1203
|
+
%x#bar {a: b}
|
|
1204
|
+
%y, %y:#{pseudo} {@extend %x}
|
|
1205
|
+
a {@extend %y}
|
|
1206
|
+
SCSS
|
|
1207
|
+
end
|
|
1208
|
+
end
|
|
1209
|
+
|
|
1210
|
+
def test_multiple_source_redundancy_elimination
|
|
1211
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1212
|
+
.test-case, .test-case:active {
|
|
1213
|
+
color: red; }
|
|
1214
|
+
|
|
1215
|
+
.test-case:hover {
|
|
1216
|
+
color: green; }
|
|
1217
|
+
CSS
|
|
1218
|
+
%default-color {color: red}
|
|
1219
|
+
%alt-color {color: green}
|
|
1220
|
+
|
|
1221
|
+
%default-style {
|
|
1222
|
+
@extend %default-color;
|
|
1223
|
+
&:hover {@extend %alt-color}
|
|
1224
|
+
&:active {@extend %default-color}
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
.test-case {@extend %default-style}
|
|
1228
|
+
SCSS
|
|
1229
|
+
end
|
|
1230
|
+
|
|
1231
|
+
def test_nested_sibling_extend
|
|
1232
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1233
|
+
.parent .bar, .parent .foo {
|
|
1234
|
+
width: 2000px; }
|
|
1235
|
+
CSS
|
|
1236
|
+
.foo {@extend .bar}
|
|
1237
|
+
|
|
1238
|
+
.parent {
|
|
1239
|
+
.bar {
|
|
1240
|
+
width: 2000px;
|
|
1241
|
+
}
|
|
1242
|
+
.foo {
|
|
1243
|
+
@extend .bar
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
SCSS
|
|
1247
|
+
end
|
|
1248
|
+
|
|
1249
|
+
def test_parent_and_sibling_extend
|
|
1250
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1251
|
+
.parent1 .parent2 .child1.child2, .parent2 .parent1 .child1.child2 {
|
|
1252
|
+
c: d; }
|
|
1253
|
+
CSS
|
|
1254
|
+
%foo %bar%baz {c: d}
|
|
1255
|
+
|
|
1256
|
+
.parent1 {
|
|
1257
|
+
@extend %foo;
|
|
1258
|
+
.child1 {@extend %bar}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
.parent2 {
|
|
1262
|
+
@extend %foo;
|
|
1263
|
+
.child2 {@extend %baz}
|
|
1264
|
+
}
|
|
1265
|
+
SCSS
|
|
1266
|
+
end
|
|
1267
|
+
|
|
1268
|
+
def test_nested_extend_specificity
|
|
1269
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1270
|
+
a :b, a :b:c {
|
|
1271
|
+
a: b; }
|
|
1272
|
+
CSS
|
|
1273
|
+
%foo {a: b}
|
|
1274
|
+
|
|
1275
|
+
a {
|
|
1276
|
+
:b {@extend %foo}
|
|
1277
|
+
:b:c {@extend %foo}
|
|
1278
|
+
}
|
|
1279
|
+
SCSS
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1282
|
+
def test_nested_double_extend_optimization
|
|
1283
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1284
|
+
.parent1 .child {
|
|
1285
|
+
a: b; }
|
|
1286
|
+
CSS
|
|
1287
|
+
%foo %bar {
|
|
1288
|
+
a: b;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
.parent1 {
|
|
1292
|
+
@extend %foo;
|
|
1293
|
+
|
|
1294
|
+
.child {
|
|
1295
|
+
@extend %bar;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
.parent2 {
|
|
1300
|
+
@extend %foo;
|
|
1301
|
+
}
|
|
1302
|
+
SCSS
|
|
1303
|
+
end
|
|
1304
|
+
|
|
1305
|
+
def test_extend_in_double_nested_media_query
|
|
1306
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1307
|
+
@media all and (orientation: landscape) {
|
|
1308
|
+
.bar {
|
|
1309
|
+
color: blue; } }
|
|
1310
|
+
CSS
|
|
1311
|
+
@media all {
|
|
1312
|
+
@media (orientation: landscape) {
|
|
1313
|
+
%foo {color: blue}
|
|
1314
|
+
.bar {@extend %foo}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
SCSS
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
def test_partially_failed_extend
|
|
1321
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
|
|
1322
|
+
.rc, test {
|
|
1323
|
+
color: white; }
|
|
1324
|
+
|
|
1325
|
+
.prices span.pill span.rc {
|
|
1326
|
+
color: red; }
|
|
1327
|
+
CSS
|
|
1328
|
+
test { @extend .rc; }
|
|
1329
|
+
.rc {color: white;}
|
|
1330
|
+
.prices span.pill span.rc {color: red;}
|
|
1331
|
+
SCSS
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
def test_newline_near_combinator
|
|
1335
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1336
|
+
.a +
|
|
1337
|
+
.b x, .a +
|
|
1338
|
+
.b .c y, .c .a +
|
|
1339
|
+
.b y {
|
|
1340
|
+
a: b; }
|
|
1341
|
+
CSS
|
|
1342
|
+
.a +
|
|
1343
|
+
.b x {a: b}
|
|
1344
|
+
.c y {@extend x}
|
|
1345
|
+
SCSS
|
|
1346
|
+
end
|
|
1347
|
+
|
|
1348
|
+
def test_duplicated_selector_with_newlines
|
|
1349
|
+
assert_equal(<<CSS, render(<<SCSS))
|
|
1350
|
+
.example-1-1,
|
|
1351
|
+
.example-1-2,
|
|
1352
|
+
.my-page-1 .my-module-1-1,
|
|
1353
|
+
.example-1-3 {
|
|
1354
|
+
a: b; }
|
|
1355
|
+
CSS
|
|
1356
|
+
.example-1-1,
|
|
1357
|
+
.example-1-2,
|
|
1358
|
+
.example-1-3 {
|
|
1359
|
+
a: b;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
.my-page-1 .my-module-1-1 {@extend .example-1-2}
|
|
1363
|
+
SCSS
|
|
1364
|
+
end
|
|
1365
|
+
|
|
1366
|
+
def test_nested_selector_with_child_selector_hack_extendee
|
|
1367
|
+
assert_extends '> .foo', 'foo bar {@extend .foo}', '> .foo, > foo bar'
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1370
|
+
def test_nested_selector_with_child_selector_hack_extender
|
|
1371
|
+
assert_extends '.foo .bar', '> foo bar {@extend .bar}', '.foo .bar, > .foo foo bar, > foo .foo bar'
|
|
1372
|
+
end
|
|
1373
|
+
|
|
1374
|
+
def test_nested_selector_with_child_selector_hack_extender_and_extendee
|
|
1375
|
+
assert_extends '> .foo', '> foo bar {@extend .foo}', '> .foo, > foo bar'
|
|
1376
|
+
end
|
|
1377
|
+
|
|
1378
|
+
def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee
|
|
1379
|
+
assert_extends '~ .foo', '> foo bar {@extend .foo}', '~ .foo'
|
|
1380
|
+
end
|
|
1381
|
+
|
|
1382
|
+
def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline
|
|
1383
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1384
|
+
> .foo, > flip,
|
|
1385
|
+
> foo bar {
|
|
1386
|
+
a: b; }
|
|
1387
|
+
CSS
|
|
1388
|
+
> .foo {a: b}
|
|
1389
|
+
flip,
|
|
1390
|
+
> foo bar {@extend .foo}
|
|
1391
|
+
SCSS
|
|
1392
|
+
end
|
|
1393
|
+
|
|
1394
|
+
def test_extended_parent_and_child_redundancy_elimination
|
|
1395
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1396
|
+
a b, d b, a c, d c {
|
|
1397
|
+
a: b; }
|
|
1398
|
+
CSS
|
|
1399
|
+
a {
|
|
1400
|
+
b {a: b}
|
|
1401
|
+
c {@extend b}
|
|
1402
|
+
}
|
|
1403
|
+
d {@extend a}
|
|
1404
|
+
SCSS
|
|
1405
|
+
end
|
|
1406
|
+
|
|
1407
|
+
def test_extend_redundancy_elimination_when_it_would_reduce_specificity
|
|
1408
|
+
assert_extends 'a', 'a.foo {@extend a}', 'a, a.foo'
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
def test_extend_redundancy_elimination_when_it_would_preserve_specificity
|
|
1412
|
+
assert_extends '.bar a', 'a.foo {@extend a}', '.bar a'
|
|
1413
|
+
end
|
|
1414
|
+
|
|
1415
|
+
def test_extend_redundancy_elimination_never_eliminates_base_selector
|
|
1416
|
+
assert_extends 'a.foo', '.foo {@extend a}', 'a.foo, .foo'
|
|
1417
|
+
end
|
|
1418
|
+
|
|
1419
|
+
def test_extend_cross_branch_redundancy_elimination
|
|
1420
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1421
|
+
.a .c .d, .b .c .a .d {
|
|
1422
|
+
a: b; }
|
|
1423
|
+
CSS
|
|
1424
|
+
%x .c %y {a: b}
|
|
1425
|
+
.a, .b {@extend %x}
|
|
1426
|
+
.a .d {@extend %y}
|
|
1427
|
+
SCSS
|
|
1428
|
+
|
|
1429
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1430
|
+
.e .a .c .d, .a .c .e .d, .e .b .c .a .d, .b .c .a .e .d {
|
|
1431
|
+
a: b; }
|
|
1432
|
+
CSS
|
|
1433
|
+
.e %z {a: b}
|
|
1434
|
+
%x .c %y {@extend %z}
|
|
1435
|
+
.a, .b {@extend %x}
|
|
1436
|
+
.a .d {@extend %y}
|
|
1437
|
+
SCSS
|
|
1438
|
+
end
|
|
1439
|
+
|
|
1440
|
+
private
|
|
1441
|
+
|
|
1442
|
+
def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
|
|
1443
|
+
warn = "\"#{extender}\" failed to @extend \"#{target}\"."
|
|
1444
|
+
reason =
|
|
1445
|
+
if reason == :not_found
|
|
1446
|
+
"The selector \"#{target}\" was not found."
|
|
1447
|
+
else
|
|
1448
|
+
"No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
|
|
1449
|
+
end
|
|
1450
|
+
|
|
1451
|
+
assert_warning(<<WARNING) {yield}
|
|
1452
|
+
WARNING on line #{line} of #{filename_for_test syntax}: #{warn}
|
|
1453
|
+
#{reason}
|
|
1454
|
+
This will be an error in future releases of Sass.
|
|
1455
|
+
Use "@extend #{target} !optional" if the extend should be able to fail.
|
|
1456
|
+
WARNING
|
|
1457
|
+
end
|
|
1458
|
+
|
|
1459
|
+
def assert_unification(selector, extension, unified)
|
|
1460
|
+
# Do some trickery so the first law of extend doesn't get in our way.
|
|
1461
|
+
assert_extends(
|
|
1462
|
+
"%-a #{selector}",
|
|
1463
|
+
extension + " -a {@extend %-a}",
|
|
1464
|
+
unified.split(', ').map {|s| "-a #{s}"}.join(', '))
|
|
1465
|
+
end
|
|
1466
|
+
|
|
1467
|
+
def assert_extends(selector, extension, result)
|
|
1468
|
+
assert_equal <<CSS, render(<<SCSS)
|
|
1469
|
+
#{result} {
|
|
1470
|
+
a: b; }
|
|
1471
|
+
CSS
|
|
1472
|
+
#{selector} {a: b}
|
|
1473
|
+
#{extension}
|
|
1474
|
+
SCSS
|
|
1475
|
+
end
|
|
1476
|
+
|
|
1477
|
+
def render(sass, options = {})
|
|
1478
|
+
options = {:syntax => :scss}.merge(options)
|
|
1479
|
+
munge_filename options
|
|
1480
|
+
Sass::Engine.new(sass, options).render
|
|
1481
|
+
end
|
|
1482
|
+
end
|