oreorenasass 3.4.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 +221 -0
- data/Rakefile +370 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -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 +34 -0
- data/lib/sass/cache_stores/filesystem.rb +60 -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 +67 -0
- data/lib/sass/css.rb +407 -0
- data/lib/sass/engine.rb +1181 -0
- data/lib/sass/environment.rb +191 -0
- data/lib/sass/error.rb +198 -0
- data/lib/sass/exec/base.rb +187 -0
- data/lib/sass/exec/sass_convert.rb +264 -0
- data/lib/sass/exec/sass_scss.rb +424 -0
- data/lib/sass/exec.rb +9 -0
- data/lib/sass/features.rb +47 -0
- data/lib/sass/importers/base.rb +182 -0
- data/lib/sass/importers/filesystem.rb +211 -0
- data/lib/sass/importers.rb +22 -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 +210 -0
- data/lib/sass/plugin/compiler.rb +565 -0
- data/lib/sass/plugin/configuration.rb +118 -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/css_lexer.rb +33 -0
- data/lib/sass/script/css_parser.rb +34 -0
- data/lib/sass/script/functions.rb +2626 -0
- data/lib/sass/script/lexer.rb +449 -0
- data/lib/sass/script/parser.rb +637 -0
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/tree/interpolation.rb +118 -0
- 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/tree/node.rb +109 -0
- data/lib/sass/script/tree/operation.rb +103 -0
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +104 -0
- data/lib/sass/script/tree/unary_operation.rb +69 -0
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +16 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +240 -0
- data/lib/sass/script/value/bool.rb +35 -0
- data/lib/sass/script/value/color.rb +680 -0
- data/lib/sass/script/value/helpers.rb +262 -0
- data/lib/sass/script/value/list.rb +113 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +44 -0
- data/lib/sass/script/value/number.rb +530 -0
- data/lib/sass/script/value/string.rb +97 -0
- data/lib/sass/script/value.rb +11 -0
- data/lib/sass/script.rb +66 -0
- data/lib/sass/scss/css_parser.rb +42 -0
- data/lib/sass/scss/parser.rb +1209 -0
- data/lib/sass/scss/rx.rb +141 -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 +368 -0
- data/lib/sass/scss.rb +16 -0
- data/lib/sass/selector/abstract_sequence.rb +109 -0
- data/lib/sass/selector/comma_sequence.rb +175 -0
- data/lib/sass/selector/pseudo.rb +256 -0
- data/lib/sass/selector/sequence.rb +600 -0
- data/lib/sass/selector/simple.rb +117 -0
- data/lib/sass/selector/simple_sequence.rb +325 -0
- data/lib/sass/selector.rb +326 -0
- data/lib/sass/shared.rb +76 -0
- data/lib/sass/source/map.rb +210 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +120 -0
- data/lib/sass/supports.rb +227 -0
- data/lib/sass/tree/at_root_node.rb +83 -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 +59 -0
- data/lib/sass/tree/each_node.rb +24 -0
- data/lib/sass/tree/error_node.rb +18 -0
- data/lib/sass/tree/extend_node.rb +43 -0
- data/lib/sass/tree/for_node.rb +36 -0
- data/lib/sass/tree/function_node.rb +39 -0
- data/lib/sass/tree/if_node.rb +52 -0
- data/lib/sass/tree/import_node.rb +74 -0
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/media_node.rb +48 -0
- data/lib/sass/tree/mixin_def_node.rb +38 -0
- data/lib/sass/tree/mixin_node.rb +52 -0
- data/lib/sass/tree/node.rb +238 -0
- data/lib/sass/tree/prop_node.rb +171 -0
- data/lib/sass/tree/return_node.rb +19 -0
- data/lib/sass/tree/root_node.rb +44 -0
- data/lib/sass/tree/rule_node.rb +145 -0
- 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 +36 -0
- data/lib/sass/tree/visitors/base.rb +72 -0
- data/lib/sass/tree/visitors/check_nesting.rb +177 -0
- data/lib/sass/tree/visitors/convert.rb +334 -0
- data/lib/sass/tree/visitors/cssize.rb +369 -0
- data/lib/sass/tree/visitors/deep_copy.rb +107 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +539 -0
- data/lib/sass/tree/visitors/set_options.rb +139 -0
- data/lib/sass/tree/visitors/to_css.rb +381 -0
- data/lib/sass/tree/warn_node.rb +18 -0
- data/lib/sass/tree/while_node.rb +18 -0
- 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 +110 -0
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +1318 -0
- data/lib/sass/version.rb +124 -0
- data/lib/sass.rb +102 -0
- data/rails/init.rb +1 -0
- data/test/sass/cache_test.rb +131 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/compiler_test.rb +232 -0
- data/test/sass/conversion_test.rb +2054 -0
- data/test/sass/css2sass_test.rb +477 -0
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +3301 -0
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +1661 -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 +1926 -0
- data/test/sass/importer_test.rb +412 -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 +554 -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 +328 -0
- data/test/sass/script_test.rb +1054 -0
- data/test/sass/scss/css_test.rb +1215 -0
- data/test/sass/scss/rx_test.rb +156 -0
- data/test/sass/scss/scss_test.rb +3900 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/source_map_test.rb +977 -0
- data/test/sass/superselector_test.rb +191 -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 +12 -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/normalized_map_test.rb +51 -0
- data/test/sass/util/subset_map_test.rb +91 -0
- data/test/sass/util_test.rb +467 -0
- data/test/sass/value_helpers_test.rb +179 -0
- data/test/test_helper.rb +109 -0
- metadata +386 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
4
|
+
require 'sass/engine'
|
5
|
+
|
6
|
+
class ScssRxTest < MiniTest::Test
|
7
|
+
include Sass::SCSS::RX
|
8
|
+
|
9
|
+
def test_identifiers
|
10
|
+
assert_match IDENT, "foo"
|
11
|
+
assert_match IDENT, "\xC3\xBFoo" # Initial char can be nonascii
|
12
|
+
assert_match IDENT, "\\123abcoo" # Initial char can be unicode escape
|
13
|
+
assert_match IDENT, "\\f oo" # Unicode escapes can be followed by whitespace
|
14
|
+
assert_match IDENT, "\\fa\too"
|
15
|
+
assert_match IDENT, "\\ff2\roo"
|
16
|
+
assert_match IDENT, "\\f13a\foo"
|
17
|
+
assert_match IDENT, "\\f13abcoo"
|
18
|
+
assert_match IDENT, "\\ oo" # Initial char can be a plain escape as well
|
19
|
+
assert_match IDENT, "\\~oo"
|
20
|
+
assert_match IDENT, "\\\\oo"
|
21
|
+
assert_match IDENT, "\\{oo"
|
22
|
+
assert_match IDENT, "\\\xC3\xBFoo"
|
23
|
+
assert_match IDENT, "-foo" # Can put a - before anything
|
24
|
+
assert_match IDENT, "-\xC3\xBFoo"
|
25
|
+
assert_match IDENT, "-\\f oo"
|
26
|
+
assert_match IDENT, "_foo" # Can put a _ before anything
|
27
|
+
assert_match IDENT, "_\xC3\xBFoo"
|
28
|
+
assert_match IDENT, "_\\f oo"
|
29
|
+
assert_match IDENT, "--foo" # "Custom" identifier
|
30
|
+
|
31
|
+
assert_match IDENT, "foo-bar"
|
32
|
+
assert_match IDENT, "f012-23"
|
33
|
+
assert_match IDENT, "foo_-_bar"
|
34
|
+
assert_match IDENT, "f012_23"
|
35
|
+
|
36
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-003.xht
|
37
|
+
assert_match IDENT, "c\\lass"
|
38
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-004.xht
|
39
|
+
assert_match IDENT, "c\\00006Cas\\000073"
|
40
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-001.xht
|
41
|
+
assert_match IDENT, "IdE6n-3t0_6"
|
42
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-006.xht
|
43
|
+
assert_match IDENT, "\\6000ident"
|
44
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-007.xht
|
45
|
+
assert_match IDENT, "iden\\6000t\\6000"
|
46
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-013.xht
|
47
|
+
assert_match IDENT, "\\-ident"
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_underscores_in_identifiers
|
51
|
+
assert_match IDENT, "foo_bar"
|
52
|
+
assert_match IDENT, "_\xC3\xBFfoo"
|
53
|
+
assert_match IDENT, "__foo"
|
54
|
+
assert_match IDENT, "_1foo"
|
55
|
+
assert_match IDENT, "-_foo"
|
56
|
+
assert_match IDENT, "_-foo"
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_invalid_identifiers
|
60
|
+
assert_no_match IDENT, ""
|
61
|
+
assert_no_match IDENT, "1foo"
|
62
|
+
assert_no_match IDENT, "-1foo"
|
63
|
+
assert_no_match IDENT, "foo bar"
|
64
|
+
assert_no_match IDENT, "foo~bar"
|
65
|
+
|
66
|
+
# http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-008.xht
|
67
|
+
assert_no_match IDENT, "c\\06C ass"
|
68
|
+
assert_no_match IDENT, "back\\67\n round"
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_double_quote_strings
|
72
|
+
assert_match STRING, '"foo bar"'
|
73
|
+
assert_match STRING, '"foo\\\nbar"'
|
74
|
+
assert_match STRING, "\"\\\"\""
|
75
|
+
assert_match STRING, '"\t !#$%&(-~()*+,-./0123456789~"'
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_single_quote_strings
|
79
|
+
assert_match STRING, "'foo bar'"
|
80
|
+
assert_match STRING, "'foo\\\nbar'"
|
81
|
+
assert_match STRING, "'\\''"
|
82
|
+
assert_match STRING, "'\t !#\$%&(-~()*+,-./0123456789~'"
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_invalid_strings
|
86
|
+
assert_no_match STRING, "\"foo\nbar\""
|
87
|
+
assert_no_match STRING, "\"foo\"bar\""
|
88
|
+
assert_no_match STRING, "'foo\nbar'"
|
89
|
+
assert_no_match STRING, "'foo'bar'"
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_uri
|
93
|
+
assert_match URI, 'url("foo bar)")'
|
94
|
+
assert_match URI, "url('foo bar)')"
|
95
|
+
assert_match URI, 'url( "foo bar)" )'
|
96
|
+
assert_match URI, "url(#\\%&**+,-./0123456789~)"
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_invalid_uri
|
100
|
+
assert_no_match URI, 'url(foo)bar)'
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_unicode_range
|
104
|
+
assert_match UNICODERANGE, 'U+00-Ff'
|
105
|
+
assert_match UNICODERANGE, 'u+980-9FF'
|
106
|
+
assert_match UNICODERANGE, 'U+9aF??'
|
107
|
+
assert_match UNICODERANGE, 'U+??'
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_escape_empty_ident
|
111
|
+
assert_equal "", Sass::SCSS::RX.escape_ident("")
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_escape_just_prefix_ident
|
115
|
+
assert_equal "\\-", Sass::SCSS::RX.escape_ident("-")
|
116
|
+
assert_equal "\\_", Sass::SCSS::RX.escape_ident("_")
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_escape_plain_ident
|
120
|
+
assert_equal "foo", Sass::SCSS::RX.escape_ident("foo")
|
121
|
+
assert_equal "foo-1bar", Sass::SCSS::RX.escape_ident("foo-1bar")
|
122
|
+
assert_equal "-foo-bar", Sass::SCSS::RX.escape_ident("-foo-bar")
|
123
|
+
assert_equal "f2oo_bar", Sass::SCSS::RX.escape_ident("f2oo_bar")
|
124
|
+
assert_equal "_foo_bar", Sass::SCSS::RX.escape_ident("_foo_bar")
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_escape_initial_funky_ident
|
128
|
+
assert_equal "\\000035foo", Sass::SCSS::RX.escape_ident("5foo")
|
129
|
+
assert_equal "-\\000035foo", Sass::SCSS::RX.escape_ident("-5foo")
|
130
|
+
assert_equal "_\\000035foo", Sass::SCSS::RX.escape_ident("_5foo")
|
131
|
+
|
132
|
+
assert_equal "\\&foo", Sass::SCSS::RX.escape_ident("&foo")
|
133
|
+
assert_equal "-\\&foo", Sass::SCSS::RX.escape_ident("-&foo")
|
134
|
+
|
135
|
+
assert_equal "-\\ foo", Sass::SCSS::RX.escape_ident("- foo")
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_escape_mid_funky_ident
|
139
|
+
assert_equal "foo\\&bar", Sass::SCSS::RX.escape_ident("foo&bar")
|
140
|
+
assert_equal "foo\\ \\ bar", Sass::SCSS::RX.escape_ident("foo bar")
|
141
|
+
assert_equal "foo\\00007fbar", Sass::SCSS::RX.escape_ident("foo\177bar")
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def assert_match(rx, str)
|
147
|
+
refute_nil(match = rx.match(str))
|
148
|
+
assert_equal str.size, match[0].size
|
149
|
+
end
|
150
|
+
|
151
|
+
def assert_no_match(rx, str)
|
152
|
+
match = rx.match(str)
|
153
|
+
refute_equal str.size, match && match[0].size
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
@@ -0,0 +1,3900 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require File.dirname(__FILE__) + '/test_helper'
|
4
|
+
|
5
|
+
class ScssTest < MiniTest::Test
|
6
|
+
include ScssTestHelper
|
7
|
+
|
8
|
+
## One-Line Comments
|
9
|
+
|
10
|
+
def test_one_line_comments
|
11
|
+
assert_equal <<CSS, render(<<SCSS)
|
12
|
+
.foo {
|
13
|
+
baz: bang; }
|
14
|
+
CSS
|
15
|
+
.foo {// bar: baz;}
|
16
|
+
baz: bang; //}
|
17
|
+
}
|
18
|
+
SCSS
|
19
|
+
assert_equal <<CSS, render(<<SCSS)
|
20
|
+
.foo bar[val="//"] {
|
21
|
+
baz: bang; }
|
22
|
+
CSS
|
23
|
+
.foo bar[val="//"] {
|
24
|
+
baz: bang; //}
|
25
|
+
}
|
26
|
+
SCSS
|
27
|
+
end
|
28
|
+
|
29
|
+
## Script
|
30
|
+
|
31
|
+
def test_variables
|
32
|
+
assert_equal <<CSS, render(<<SCSS)
|
33
|
+
blat {
|
34
|
+
a: foo; }
|
35
|
+
CSS
|
36
|
+
$var: foo;
|
37
|
+
|
38
|
+
blat {a: $var}
|
39
|
+
SCSS
|
40
|
+
|
41
|
+
assert_equal <<CSS, render(<<SCSS)
|
42
|
+
foo {
|
43
|
+
a: 2;
|
44
|
+
b: 6; }
|
45
|
+
CSS
|
46
|
+
foo {
|
47
|
+
$var: 2;
|
48
|
+
$another-var: 4;
|
49
|
+
a: $var;
|
50
|
+
b: $var + $another-var;}
|
51
|
+
SCSS
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_unicode_variables
|
55
|
+
assert_equal <<CSS, render(<<SCSS)
|
56
|
+
blat {
|
57
|
+
a: foo; }
|
58
|
+
CSS
|
59
|
+
$vär: foo;
|
60
|
+
|
61
|
+
blat {a: $vär}
|
62
|
+
SCSS
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_guard_assign
|
66
|
+
assert_equal <<CSS, render(<<SCSS)
|
67
|
+
foo {
|
68
|
+
a: 1; }
|
69
|
+
CSS
|
70
|
+
$var: 1;
|
71
|
+
$var: 2 !default;
|
72
|
+
|
73
|
+
foo {a: $var}
|
74
|
+
SCSS
|
75
|
+
|
76
|
+
assert_equal <<CSS, render(<<SCSS)
|
77
|
+
foo {
|
78
|
+
a: 2; }
|
79
|
+
CSS
|
80
|
+
$var: 2 !default;
|
81
|
+
|
82
|
+
foo {a: $var}
|
83
|
+
SCSS
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_sass_script
|
87
|
+
assert_equal <<CSS, render(<<SCSS)
|
88
|
+
foo {
|
89
|
+
a: 3;
|
90
|
+
b: -1;
|
91
|
+
c: foobar;
|
92
|
+
d: 12px; }
|
93
|
+
CSS
|
94
|
+
foo {
|
95
|
+
a: 1 + 2;
|
96
|
+
b: 1 - 2;
|
97
|
+
c: foo + bar;
|
98
|
+
d: floor(12.3px); }
|
99
|
+
SCSS
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_debug_directive
|
103
|
+
assert_warning "test_debug_directive_inline.scss:2 DEBUG: hello world!" do
|
104
|
+
assert_equal <<CSS, render(<<SCSS)
|
105
|
+
foo {
|
106
|
+
a: b; }
|
107
|
+
|
108
|
+
bar {
|
109
|
+
c: d; }
|
110
|
+
CSS
|
111
|
+
foo {a: b}
|
112
|
+
@debug "hello world!";
|
113
|
+
bar {c: d}
|
114
|
+
SCSS
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_error_directive
|
119
|
+
assert_raise_message(Sass::SyntaxError, "hello world!") {render(<<SCSS)}
|
120
|
+
foo {a: b}
|
121
|
+
@error "hello world!";
|
122
|
+
bar {c: d}
|
123
|
+
SCSS
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_warn_directive
|
127
|
+
expected_warning = <<EXPECTATION
|
128
|
+
WARNING: this is a warning
|
129
|
+
on line 2 of test_warn_directive_inline.scss
|
130
|
+
|
131
|
+
WARNING: this is a mixin
|
132
|
+
on line 1 of test_warn_directive_inline.scss, in `foo'
|
133
|
+
from line 3 of test_warn_directive_inline.scss
|
134
|
+
EXPECTATION
|
135
|
+
assert_warning expected_warning do
|
136
|
+
assert_equal <<CSS, render(<<SCSS)
|
137
|
+
bar {
|
138
|
+
c: d; }
|
139
|
+
CSS
|
140
|
+
@mixin foo { @warn "this is a mixin";}
|
141
|
+
@warn "this is a warning";
|
142
|
+
bar {c: d; @include foo;}
|
143
|
+
SCSS
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_for_directive
|
148
|
+
assert_equal <<CSS, render(<<SCSS)
|
149
|
+
.foo {
|
150
|
+
a: 1;
|
151
|
+
a: 2;
|
152
|
+
a: 3;
|
153
|
+
a: 4; }
|
154
|
+
CSS
|
155
|
+
.foo {
|
156
|
+
@for $var from 1 to 5 {a: $var;}
|
157
|
+
}
|
158
|
+
SCSS
|
159
|
+
|
160
|
+
assert_equal <<CSS, render(<<SCSS)
|
161
|
+
.foo {
|
162
|
+
a: 1;
|
163
|
+
a: 2;
|
164
|
+
a: 3;
|
165
|
+
a: 4;
|
166
|
+
a: 5; }
|
167
|
+
CSS
|
168
|
+
.foo {
|
169
|
+
@for $var from 1 through 5 {a: $var;}
|
170
|
+
}
|
171
|
+
SCSS
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_for_directive_with_same_start_and_end
|
175
|
+
assert_equal <<CSS, render(<<SCSS)
|
176
|
+
CSS
|
177
|
+
.foo {
|
178
|
+
@for $var from 1 to 1 {a: $var;}
|
179
|
+
}
|
180
|
+
SCSS
|
181
|
+
|
182
|
+
assert_equal <<CSS, render(<<SCSS)
|
183
|
+
.foo {
|
184
|
+
a: 1; }
|
185
|
+
CSS
|
186
|
+
.foo {
|
187
|
+
@for $var from 1 through 1 {a: $var;}
|
188
|
+
}
|
189
|
+
SCSS
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_decrementing_estfor_directive
|
193
|
+
assert_equal <<CSS, render(<<SCSS)
|
194
|
+
.foo {
|
195
|
+
a: 5;
|
196
|
+
a: 4;
|
197
|
+
a: 3;
|
198
|
+
a: 2;
|
199
|
+
a: 1; }
|
200
|
+
CSS
|
201
|
+
.foo {
|
202
|
+
@for $var from 5 through 1 {a: $var;}
|
203
|
+
}
|
204
|
+
SCSS
|
205
|
+
|
206
|
+
assert_equal <<CSS, render(<<SCSS)
|
207
|
+
.foo {
|
208
|
+
a: 5;
|
209
|
+
a: 4;
|
210
|
+
a: 3;
|
211
|
+
a: 2; }
|
212
|
+
CSS
|
213
|
+
.foo {
|
214
|
+
@for $var from 5 to 1 {a: $var;}
|
215
|
+
}
|
216
|
+
SCSS
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_if_directive
|
220
|
+
assert_equal <<CSS, render(<<SCSS)
|
221
|
+
foo {
|
222
|
+
a: b; }
|
223
|
+
CSS
|
224
|
+
@if "foo" == "foo" {foo {a: b}}
|
225
|
+
@if "foo" != "foo" {bar {a: b}}
|
226
|
+
SCSS
|
227
|
+
|
228
|
+
assert_equal <<CSS, render(<<SCSS)
|
229
|
+
bar {
|
230
|
+
a: b; }
|
231
|
+
CSS
|
232
|
+
@if "foo" != "foo" {foo {a: b}}
|
233
|
+
@else if "foo" == "foo" {bar {a: b}}
|
234
|
+
@else if true {baz {a: b}}
|
235
|
+
SCSS
|
236
|
+
|
237
|
+
assert_equal <<CSS, render(<<SCSS)
|
238
|
+
bar {
|
239
|
+
a: b; }
|
240
|
+
CSS
|
241
|
+
@if "foo" != "foo" {foo {a: b}}
|
242
|
+
@else {bar {a: b}}
|
243
|
+
SCSS
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_comment_after_if_directive
|
247
|
+
assert_equal <<CSS, render(<<SCSS)
|
248
|
+
foo {
|
249
|
+
a: b;
|
250
|
+
/* This is a comment */
|
251
|
+
c: d; }
|
252
|
+
CSS
|
253
|
+
foo {
|
254
|
+
@if true {a: b}
|
255
|
+
/* This is a comment */
|
256
|
+
c: d }
|
257
|
+
SCSS
|
258
|
+
assert_equal <<CSS, render(<<SCSS)
|
259
|
+
foo {
|
260
|
+
a: b;
|
261
|
+
/* This is a comment */
|
262
|
+
c: d; }
|
263
|
+
CSS
|
264
|
+
foo {
|
265
|
+
@if true {a: b}
|
266
|
+
@else {x: y}
|
267
|
+
/* This is a comment */
|
268
|
+
c: d }
|
269
|
+
SCSS
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_while_directive
|
273
|
+
assert_equal <<CSS, render(<<SCSS)
|
274
|
+
.foo {
|
275
|
+
a: 1;
|
276
|
+
a: 2;
|
277
|
+
a: 3;
|
278
|
+
a: 4; }
|
279
|
+
CSS
|
280
|
+
$i: 1;
|
281
|
+
|
282
|
+
.foo {
|
283
|
+
@while $i != 5 {
|
284
|
+
a: $i;
|
285
|
+
$i: $i + 1 !global;
|
286
|
+
}
|
287
|
+
}
|
288
|
+
SCSS
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_each_directive
|
292
|
+
assert_equal <<CSS, render(<<SCSS)
|
293
|
+
a {
|
294
|
+
b: 1px;
|
295
|
+
b: 2px;
|
296
|
+
b: 3px;
|
297
|
+
b: 4px; }
|
298
|
+
|
299
|
+
c {
|
300
|
+
d: foo;
|
301
|
+
d: bar;
|
302
|
+
d: baz;
|
303
|
+
d: bang; }
|
304
|
+
CSS
|
305
|
+
a {
|
306
|
+
@each $number in 1px 2px 3px 4px {
|
307
|
+
b: $number;
|
308
|
+
}
|
309
|
+
}
|
310
|
+
c {
|
311
|
+
@each $str in foo, bar, baz, bang {
|
312
|
+
d: $str;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
SCSS
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_destructuring_each_directive
|
319
|
+
assert_equal <<CSS, render(<<SCSS)
|
320
|
+
a {
|
321
|
+
foo: 1px;
|
322
|
+
bar: 2px;
|
323
|
+
baz: 3px; }
|
324
|
+
|
325
|
+
c {
|
326
|
+
foo: "Value is bar";
|
327
|
+
bar: "Value is baz";
|
328
|
+
bang: "Value is "; }
|
329
|
+
CSS
|
330
|
+
a {
|
331
|
+
@each $name, $number in (foo: 1px, bar: 2px, baz: 3px) {
|
332
|
+
\#{$name}: $number;
|
333
|
+
}
|
334
|
+
}
|
335
|
+
c {
|
336
|
+
@each $key, $value in (foo bar) (bar, baz) bang {
|
337
|
+
\#{$key}: "Value is \#{$value}";
|
338
|
+
}
|
339
|
+
}
|
340
|
+
SCSS
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_css_import_directive
|
344
|
+
assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
|
345
|
+
assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
|
346
|
+
assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
|
347
|
+
assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
|
348
|
+
assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_css_string_import_directive_with_media
|
352
|
+
assert_parses '@import "foo.css" screen;'
|
353
|
+
assert_parses '@import "foo.css" screen, print;'
|
354
|
+
assert_parses '@import "foo.css" screen, print and (foo: 0);'
|
355
|
+
assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_css_url_import_directive_with_media
|
359
|
+
assert_parses '@import url("foo.css") screen;'
|
360
|
+
assert_parses '@import url("foo.css") screen, print;'
|
361
|
+
assert_parses '@import url("foo.css") screen, print and (foo: 0);'
|
362
|
+
assert_parses '@import url("foo.css") screen, only print, screen and (foo: 0);'
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_media_import
|
366
|
+
assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_dynamic_media_import
|
370
|
+
assert_equal(<<CSS, render(<<SCSS))
|
371
|
+
@import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
|
372
|
+
CSS
|
373
|
+
$media: print;
|
374
|
+
$key: -webkit-min-device-pixel-ratio;
|
375
|
+
$value: 20;
|
376
|
+
@import "foo" \#{$media} and ($key + "-foo": $value + 5);
|
377
|
+
SCSS
|
378
|
+
end
|
379
|
+
|
380
|
+
def test_http_import
|
381
|
+
assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n",
|
382
|
+
render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";"))
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_protocol_relative_import
|
386
|
+
assert_equal("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";\n",
|
387
|
+
render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";"))
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_import_with_interpolation
|
391
|
+
assert_equal <<CSS, render(<<SCSS)
|
392
|
+
@import url("http://fonts.googleapis.com/css?family=Droid+Sans");
|
393
|
+
CSS
|
394
|
+
$family: unquote("Droid+Sans");
|
395
|
+
@import url("http://fonts.googleapis.com/css?family=\#{$family}");
|
396
|
+
SCSS
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_url_import
|
400
|
+
assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_css_import_doesnt_move_through_comments
|
404
|
+
assert_equal <<CSS, render(<<SCSS)
|
405
|
+
/* Comment 1 */
|
406
|
+
@import url("foo.css");
|
407
|
+
/* Comment 2 */
|
408
|
+
@import url("bar.css");
|
409
|
+
CSS
|
410
|
+
/* Comment 1 */
|
411
|
+
@import url("foo.css");
|
412
|
+
|
413
|
+
/* Comment 2 */
|
414
|
+
@import url("bar.css");
|
415
|
+
SCSS
|
416
|
+
end
|
417
|
+
|
418
|
+
def test_css_import_movement_stops_at_comments
|
419
|
+
assert_equal <<CSS, render(<<SCSS)
|
420
|
+
/* Comment 1 */
|
421
|
+
@import url("foo.css");
|
422
|
+
/* Comment 2 */
|
423
|
+
@import url("bar.css");
|
424
|
+
.foo {
|
425
|
+
a: b; }
|
426
|
+
|
427
|
+
/* Comment 3 */
|
428
|
+
CSS
|
429
|
+
/* Comment 1 */
|
430
|
+
@import url("foo.css");
|
431
|
+
|
432
|
+
/* Comment 2 */
|
433
|
+
|
434
|
+
.foo {a: b}
|
435
|
+
|
436
|
+
/* Comment 3 */
|
437
|
+
@import url("bar.css");
|
438
|
+
SCSS
|
439
|
+
end
|
440
|
+
|
441
|
+
def test_block_comment_in_script
|
442
|
+
assert_equal <<CSS, render(<<SCSS)
|
443
|
+
foo {
|
444
|
+
a: 1bar; }
|
445
|
+
CSS
|
446
|
+
foo {a: 1 + /* flang */ bar}
|
447
|
+
SCSS
|
448
|
+
end
|
449
|
+
|
450
|
+
def test_line_comment_in_script
|
451
|
+
assert_equal <<CSS, render(<<SCSS)
|
452
|
+
foo {
|
453
|
+
a: 1blang; }
|
454
|
+
CSS
|
455
|
+
foo {a: 1 + // flang }
|
456
|
+
blang }
|
457
|
+
SCSS
|
458
|
+
end
|
459
|
+
|
460
|
+
## Nested Rules
|
461
|
+
|
462
|
+
def test_nested_rules
|
463
|
+
assert_equal <<CSS, render(<<SCSS)
|
464
|
+
foo bar {
|
465
|
+
a: b; }
|
466
|
+
CSS
|
467
|
+
foo {bar {a: b}}
|
468
|
+
SCSS
|
469
|
+
assert_equal <<CSS, render(<<SCSS)
|
470
|
+
foo bar {
|
471
|
+
a: b; }
|
472
|
+
foo baz {
|
473
|
+
b: c; }
|
474
|
+
CSS
|
475
|
+
foo {
|
476
|
+
bar {a: b}
|
477
|
+
baz {b: c}}
|
478
|
+
SCSS
|
479
|
+
assert_equal <<CSS, render(<<SCSS)
|
480
|
+
foo bar baz {
|
481
|
+
a: b; }
|
482
|
+
foo bang bip {
|
483
|
+
a: b; }
|
484
|
+
CSS
|
485
|
+
foo {
|
486
|
+
bar {baz {a: b}}
|
487
|
+
bang {bip {a: b}}}
|
488
|
+
SCSS
|
489
|
+
end
|
490
|
+
|
491
|
+
def test_nested_rules_with_declarations
|
492
|
+
assert_equal <<CSS, render(<<SCSS)
|
493
|
+
foo {
|
494
|
+
a: b; }
|
495
|
+
foo bar {
|
496
|
+
c: d; }
|
497
|
+
CSS
|
498
|
+
foo {
|
499
|
+
a: b;
|
500
|
+
bar {c: d}}
|
501
|
+
SCSS
|
502
|
+
assert_equal <<CSS, render(<<SCSS)
|
503
|
+
foo {
|
504
|
+
a: b; }
|
505
|
+
foo bar {
|
506
|
+
c: d; }
|
507
|
+
CSS
|
508
|
+
foo {
|
509
|
+
bar {c: d}
|
510
|
+
a: b}
|
511
|
+
SCSS
|
512
|
+
assert_equal <<CSS, render(<<SCSS)
|
513
|
+
foo {
|
514
|
+
ump: nump;
|
515
|
+
grump: clump; }
|
516
|
+
foo bar {
|
517
|
+
blat: bang;
|
518
|
+
habit: rabbit; }
|
519
|
+
foo bar baz {
|
520
|
+
a: b; }
|
521
|
+
foo bar bip {
|
522
|
+
c: d; }
|
523
|
+
foo bibble bap {
|
524
|
+
e: f; }
|
525
|
+
CSS
|
526
|
+
foo {
|
527
|
+
ump: nump;
|
528
|
+
grump: clump;
|
529
|
+
bar {
|
530
|
+
blat: bang;
|
531
|
+
habit: rabbit;
|
532
|
+
baz {a: b}
|
533
|
+
bip {c: d}}
|
534
|
+
bibble {
|
535
|
+
bap {e: f}}}
|
536
|
+
SCSS
|
537
|
+
end
|
538
|
+
|
539
|
+
def test_nested_rules_with_fancy_selectors
|
540
|
+
assert_equal <<CSS, render(<<SCSS)
|
541
|
+
foo .bar {
|
542
|
+
a: b; }
|
543
|
+
foo :baz {
|
544
|
+
c: d; }
|
545
|
+
foo bang:bop {
|
546
|
+
e: f; }
|
547
|
+
foo ::qux {
|
548
|
+
g: h; }
|
549
|
+
foo zap::fblthp {
|
550
|
+
i: j; }
|
551
|
+
CSS
|
552
|
+
foo {
|
553
|
+
.bar {a: b}
|
554
|
+
:baz {c: d}
|
555
|
+
bang:bop {e: f}
|
556
|
+
::qux {g: h}
|
557
|
+
zap::fblthp {i: j}}
|
558
|
+
SCSS
|
559
|
+
end
|
560
|
+
|
561
|
+
def test_almost_ambiguous_nested_rules_and_declarations
|
562
|
+
assert_equal <<CSS, render(<<SCSS)
|
563
|
+
foo {
|
564
|
+
bar: baz bang bop biddle woo look at all these elems; }
|
565
|
+
foo bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {
|
566
|
+
a: b; }
|
567
|
+
foo bar:baz bang bop biddle woo look at all these elems {
|
568
|
+
a: b; }
|
569
|
+
CSS
|
570
|
+
foo {
|
571
|
+
bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {a: b};
|
572
|
+
bar:baz bang bop biddle woo look at all these elems {a: b};
|
573
|
+
bar:baz bang bop biddle woo look at all these elems; }
|
574
|
+
SCSS
|
575
|
+
end
|
576
|
+
|
577
|
+
def test_newlines_in_selectors
|
578
|
+
assert_equal <<CSS, render(<<SCSS)
|
579
|
+
foo
|
580
|
+
bar {
|
581
|
+
a: b; }
|
582
|
+
CSS
|
583
|
+
foo
|
584
|
+
bar {a: b}
|
585
|
+
SCSS
|
586
|
+
|
587
|
+
assert_equal <<CSS, render(<<SCSS)
|
588
|
+
foo baz,
|
589
|
+
foo bang,
|
590
|
+
bar baz,
|
591
|
+
bar bang {
|
592
|
+
a: b; }
|
593
|
+
CSS
|
594
|
+
foo,
|
595
|
+
bar {
|
596
|
+
baz,
|
597
|
+
bang {a: b}}
|
598
|
+
SCSS
|
599
|
+
|
600
|
+
assert_equal <<CSS, render(<<SCSS)
|
601
|
+
foo
|
602
|
+
bar baz
|
603
|
+
bang {
|
604
|
+
a: b; }
|
605
|
+
foo
|
606
|
+
bar bip bop {
|
607
|
+
c: d; }
|
608
|
+
CSS
|
609
|
+
foo
|
610
|
+
bar {
|
611
|
+
baz
|
612
|
+
bang {a: b}
|
613
|
+
|
614
|
+
bip bop {c: d}}
|
615
|
+
SCSS
|
616
|
+
|
617
|
+
assert_equal <<CSS, render(<<SCSS)
|
618
|
+
foo bang, foo bip
|
619
|
+
bop, bar
|
620
|
+
baz bang, bar
|
621
|
+
baz bip
|
622
|
+
bop {
|
623
|
+
a: b; }
|
624
|
+
CSS
|
625
|
+
foo, bar
|
626
|
+
baz {
|
627
|
+
bang, bip
|
628
|
+
bop {a: b}}
|
629
|
+
SCSS
|
630
|
+
end
|
631
|
+
|
632
|
+
def test_trailing_comma_in_selector
|
633
|
+
assert_equal <<CSS, render(<<SCSS)
|
634
|
+
#foo #bar,
|
635
|
+
#baz #boom {
|
636
|
+
a: b; }
|
637
|
+
|
638
|
+
#bip #bop {
|
639
|
+
c: d; }
|
640
|
+
CSS
|
641
|
+
#foo #bar,,
|
642
|
+
,#baz #boom, {a: b}
|
643
|
+
|
644
|
+
#bip #bop, ,, {c: d}
|
645
|
+
SCSS
|
646
|
+
end
|
647
|
+
|
648
|
+
def test_parent_selectors
|
649
|
+
assert_equal <<CSS, render(<<SCSS)
|
650
|
+
foo:hover {
|
651
|
+
a: b; }
|
652
|
+
bar foo.baz {
|
653
|
+
c: d; }
|
654
|
+
CSS
|
655
|
+
foo {
|
656
|
+
&:hover {a: b}
|
657
|
+
bar &.baz {c: d}}
|
658
|
+
SCSS
|
659
|
+
end
|
660
|
+
|
661
|
+
def test_parent_selector_with_subject
|
662
|
+
silence_warnings {assert_equal <<CSS, render(<<SCSS)}
|
663
|
+
bar foo.baz! .bip {
|
664
|
+
a: b; }
|
665
|
+
|
666
|
+
bar foo bar.baz! .bip {
|
667
|
+
c: d; }
|
668
|
+
CSS
|
669
|
+
foo {
|
670
|
+
bar &.baz! .bip {a: b}}
|
671
|
+
|
672
|
+
foo bar {
|
673
|
+
bar &.baz! .bip {c: d}}
|
674
|
+
SCSS
|
675
|
+
end
|
676
|
+
|
677
|
+
def test_parent_selector_with_suffix
|
678
|
+
assert_equal <<CSS, render(<<SCSS)
|
679
|
+
.foo-bar {
|
680
|
+
a: b; }
|
681
|
+
.foo_bar {
|
682
|
+
c: d; }
|
683
|
+
.foobar {
|
684
|
+
e: f; }
|
685
|
+
.foo123 {
|
686
|
+
e: f; }
|
687
|
+
|
688
|
+
:hover-suffix {
|
689
|
+
g: h; }
|
690
|
+
CSS
|
691
|
+
.foo {
|
692
|
+
&-bar {a: b}
|
693
|
+
&_bar {c: d}
|
694
|
+
&bar {e: f}
|
695
|
+
&123 {e: f}
|
696
|
+
}
|
697
|
+
|
698
|
+
:hover {
|
699
|
+
&-suffix {g: h}
|
700
|
+
}
|
701
|
+
SCSS
|
702
|
+
end
|
703
|
+
|
704
|
+
def test_unknown_directive_bubbling
|
705
|
+
assert_equal(<<CSS, render(<<SCSS, :style => :nested))
|
706
|
+
@fblthp {
|
707
|
+
.foo .bar {
|
708
|
+
a: b; } }
|
709
|
+
CSS
|
710
|
+
.foo {
|
711
|
+
@fblthp {
|
712
|
+
.bar {a: b}
|
713
|
+
}
|
714
|
+
}
|
715
|
+
SCSS
|
716
|
+
end
|
717
|
+
|
718
|
+
## Namespace Properties
|
719
|
+
|
720
|
+
def test_namespace_properties
|
721
|
+
assert_equal <<CSS, render(<<SCSS)
|
722
|
+
foo {
|
723
|
+
bar: baz;
|
724
|
+
bang-bip: 1px;
|
725
|
+
bang-bop: bar; }
|
726
|
+
CSS
|
727
|
+
foo {
|
728
|
+
bar: baz;
|
729
|
+
bang: {
|
730
|
+
bip: 1px;
|
731
|
+
bop: bar;}}
|
732
|
+
SCSS
|
733
|
+
end
|
734
|
+
|
735
|
+
def test_several_namespace_properties
|
736
|
+
assert_equal <<CSS, render(<<SCSS)
|
737
|
+
foo {
|
738
|
+
bar: baz;
|
739
|
+
bang-bip: 1px;
|
740
|
+
bang-bop: bar;
|
741
|
+
buzz-fram: "foo";
|
742
|
+
buzz-frum: moo; }
|
743
|
+
CSS
|
744
|
+
foo {
|
745
|
+
bar: baz;
|
746
|
+
bang: {
|
747
|
+
bip: 1px;
|
748
|
+
bop: bar;}
|
749
|
+
buzz: {
|
750
|
+
fram: "foo";
|
751
|
+
frum: moo;
|
752
|
+
}
|
753
|
+
}
|
754
|
+
SCSS
|
755
|
+
end
|
756
|
+
|
757
|
+
def test_nested_namespace_properties
|
758
|
+
assert_equal <<CSS, render(<<SCSS)
|
759
|
+
foo {
|
760
|
+
bar: baz;
|
761
|
+
bang-bip: 1px;
|
762
|
+
bang-bop: bar;
|
763
|
+
bang-blat-baf: bort; }
|
764
|
+
CSS
|
765
|
+
foo {
|
766
|
+
bar: baz;
|
767
|
+
bang: {
|
768
|
+
bip: 1px;
|
769
|
+
bop: bar;
|
770
|
+
blat:{baf:bort}}}
|
771
|
+
SCSS
|
772
|
+
end
|
773
|
+
|
774
|
+
def test_namespace_properties_with_value
|
775
|
+
assert_equal <<CSS, render(<<SCSS)
|
776
|
+
foo {
|
777
|
+
bar: baz;
|
778
|
+
bar-bip: bop;
|
779
|
+
bar-bing: bop; }
|
780
|
+
CSS
|
781
|
+
foo {
|
782
|
+
bar: baz {
|
783
|
+
bip: bop;
|
784
|
+
bing: bop; }}
|
785
|
+
SCSS
|
786
|
+
end
|
787
|
+
|
788
|
+
def test_namespace_properties_with_script_value
|
789
|
+
assert_equal <<CSS, render(<<SCSS)
|
790
|
+
foo {
|
791
|
+
bar: bazbang;
|
792
|
+
bar-bip: bop;
|
793
|
+
bar-bing: bop; }
|
794
|
+
CSS
|
795
|
+
foo {
|
796
|
+
bar: baz + bang {
|
797
|
+
bip: bop;
|
798
|
+
bing: bop; }}
|
799
|
+
SCSS
|
800
|
+
end
|
801
|
+
|
802
|
+
def test_no_namespace_properties_without_space
|
803
|
+
assert_equal <<CSS, render(<<SCSS)
|
804
|
+
foo bar:baz {
|
805
|
+
bip: bop; }
|
806
|
+
CSS
|
807
|
+
foo {
|
808
|
+
bar:baz {
|
809
|
+
bip: bop }}
|
810
|
+
SCSS
|
811
|
+
end
|
812
|
+
|
813
|
+
def test_no_namespace_properties_without_space_even_when_its_unambiguous
|
814
|
+
render(<<SCSS)
|
815
|
+
foo {
|
816
|
+
bar:baz calc(1 + 2) {
|
817
|
+
bip: bop }}
|
818
|
+
SCSS
|
819
|
+
assert(false, "Expected syntax error")
|
820
|
+
rescue Sass::SyntaxError => e
|
821
|
+
assert_equal 'Invalid CSS after "bar:baz calc": expected selector, was "(1 + 2)"', e.message
|
822
|
+
assert_equal 2, e.sass_line
|
823
|
+
end
|
824
|
+
|
825
|
+
def test_namespace_properties_without_space_allowed_for_non_identifier
|
826
|
+
assert_equal <<CSS, render(<<SCSS)
|
827
|
+
foo {
|
828
|
+
bar: 1px;
|
829
|
+
bar-bip: bop; }
|
830
|
+
CSS
|
831
|
+
foo {
|
832
|
+
bar:1px {
|
833
|
+
bip: bop }}
|
834
|
+
SCSS
|
835
|
+
end
|
836
|
+
|
837
|
+
## Mixins
|
838
|
+
|
839
|
+
def test_basic_mixins
|
840
|
+
assert_equal <<CSS, render(<<SCSS)
|
841
|
+
.foo {
|
842
|
+
a: b; }
|
843
|
+
CSS
|
844
|
+
@mixin foo {
|
845
|
+
.foo {a: b}}
|
846
|
+
|
847
|
+
@include foo;
|
848
|
+
SCSS
|
849
|
+
|
850
|
+
assert_equal <<CSS, render(<<SCSS)
|
851
|
+
bar {
|
852
|
+
c: d; }
|
853
|
+
bar .foo {
|
854
|
+
a: b; }
|
855
|
+
CSS
|
856
|
+
@mixin foo {
|
857
|
+
.foo {a: b}}
|
858
|
+
|
859
|
+
bar {
|
860
|
+
@include foo;
|
861
|
+
c: d; }
|
862
|
+
SCSS
|
863
|
+
|
864
|
+
assert_equal <<CSS, render(<<SCSS)
|
865
|
+
bar {
|
866
|
+
a: b;
|
867
|
+
c: d; }
|
868
|
+
CSS
|
869
|
+
@mixin foo {a: b}
|
870
|
+
|
871
|
+
bar {
|
872
|
+
@include foo;
|
873
|
+
c: d; }
|
874
|
+
SCSS
|
875
|
+
end
|
876
|
+
|
877
|
+
def test_mixins_with_empty_args
|
878
|
+
assert_equal <<CSS, render(<<SCSS)
|
879
|
+
.foo {
|
880
|
+
a: b; }
|
881
|
+
CSS
|
882
|
+
@mixin foo() {a: b}
|
883
|
+
|
884
|
+
.foo {@include foo();}
|
885
|
+
SCSS
|
886
|
+
|
887
|
+
assert_equal <<CSS, render(<<SCSS)
|
888
|
+
.foo {
|
889
|
+
a: b; }
|
890
|
+
CSS
|
891
|
+
@mixin foo() {a: b}
|
892
|
+
|
893
|
+
.foo {@include foo;}
|
894
|
+
SCSS
|
895
|
+
|
896
|
+
assert_equal <<CSS, render(<<SCSS)
|
897
|
+
.foo {
|
898
|
+
a: b; }
|
899
|
+
CSS
|
900
|
+
@mixin foo {a: b}
|
901
|
+
|
902
|
+
.foo {@include foo();}
|
903
|
+
SCSS
|
904
|
+
end
|
905
|
+
|
906
|
+
def test_mixins_with_args
|
907
|
+
assert_equal <<CSS, render(<<SCSS)
|
908
|
+
.foo {
|
909
|
+
a: bar; }
|
910
|
+
CSS
|
911
|
+
@mixin foo($a) {a: $a}
|
912
|
+
|
913
|
+
.foo {@include foo(bar)}
|
914
|
+
SCSS
|
915
|
+
|
916
|
+
assert_equal <<CSS, render(<<SCSS)
|
917
|
+
.foo {
|
918
|
+
a: bar;
|
919
|
+
b: 12px; }
|
920
|
+
CSS
|
921
|
+
@mixin foo($a, $b) {
|
922
|
+
a: $a;
|
923
|
+
b: $b; }
|
924
|
+
|
925
|
+
.foo {@include foo(bar, 12px)}
|
926
|
+
SCSS
|
927
|
+
end
|
928
|
+
|
929
|
+
def test_keyframes_rules_in_content
|
930
|
+
assert_equal <<CSS, render(<<SCSS)
|
931
|
+
@keyframes identifier {
|
932
|
+
0% {
|
933
|
+
top: 0;
|
934
|
+
left: 0; }
|
935
|
+
30% {
|
936
|
+
top: 50px; }
|
937
|
+
68%, 72% {
|
938
|
+
left: 50px; }
|
939
|
+
100% {
|
940
|
+
top: 100px;
|
941
|
+
left: 100%; } }
|
942
|
+
CSS
|
943
|
+
@mixin keyframes {
|
944
|
+
@keyframes identifier { @content }
|
945
|
+
}
|
946
|
+
|
947
|
+
@include keyframes {
|
948
|
+
0% {top: 0; left: 0}
|
949
|
+
\#{"30%"} {top: 50px}
|
950
|
+
68%, 72% {left: 50px}
|
951
|
+
100% {top: 100px; left: 100%}
|
952
|
+
}
|
953
|
+
SCSS
|
954
|
+
end
|
955
|
+
|
956
|
+
## Functions
|
957
|
+
|
958
|
+
def test_basic_function
|
959
|
+
assert_equal(<<CSS, render(<<SASS))
|
960
|
+
bar {
|
961
|
+
a: 3; }
|
962
|
+
CSS
|
963
|
+
@function foo() {
|
964
|
+
@return 1 + 2;
|
965
|
+
}
|
966
|
+
|
967
|
+
bar {
|
968
|
+
a: foo();
|
969
|
+
}
|
970
|
+
SASS
|
971
|
+
end
|
972
|
+
|
973
|
+
def test_function_args
|
974
|
+
assert_equal(<<CSS, render(<<SASS))
|
975
|
+
bar {
|
976
|
+
a: 3; }
|
977
|
+
CSS
|
978
|
+
@function plus($var1, $var2) {
|
979
|
+
@return $var1 + $var2;
|
980
|
+
}
|
981
|
+
|
982
|
+
bar {
|
983
|
+
a: plus(1, 2);
|
984
|
+
}
|
985
|
+
SASS
|
986
|
+
end
|
987
|
+
|
988
|
+
## Var Args
|
989
|
+
|
990
|
+
def test_mixin_var_args
|
991
|
+
assert_equal <<CSS, render(<<SCSS)
|
992
|
+
.foo {
|
993
|
+
a: 1;
|
994
|
+
b: 2, 3, 4; }
|
995
|
+
CSS
|
996
|
+
@mixin foo($a, $b...) {
|
997
|
+
a: $a;
|
998
|
+
b: $b;
|
999
|
+
}
|
1000
|
+
|
1001
|
+
.foo {@include foo(1, 2, 3, 4)}
|
1002
|
+
SCSS
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
def test_mixin_empty_var_args
|
1006
|
+
assert_equal <<CSS, render(<<SCSS)
|
1007
|
+
.foo {
|
1008
|
+
a: 1;
|
1009
|
+
b: 0; }
|
1010
|
+
CSS
|
1011
|
+
@mixin foo($a, $b...) {
|
1012
|
+
a: $a;
|
1013
|
+
b: length($b);
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
.foo {@include foo(1)}
|
1017
|
+
SCSS
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
def test_mixin_var_args_act_like_list
|
1021
|
+
assert_equal <<CSS, render(<<SCSS)
|
1022
|
+
.foo {
|
1023
|
+
a: 3;
|
1024
|
+
b: 3; }
|
1025
|
+
CSS
|
1026
|
+
@mixin foo($a, $b...) {
|
1027
|
+
a: length($b);
|
1028
|
+
b: nth($b, 2);
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
.foo {@include foo(1, 2, 3, 4)}
|
1032
|
+
SCSS
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
def test_mixin_splat_args
|
1036
|
+
assert_equal <<CSS, render(<<SCSS)
|
1037
|
+
.foo {
|
1038
|
+
a: 1;
|
1039
|
+
b: 2;
|
1040
|
+
c: 3;
|
1041
|
+
d: 4; }
|
1042
|
+
CSS
|
1043
|
+
@mixin foo($a, $b, $c, $d) {
|
1044
|
+
a: $a;
|
1045
|
+
b: $b;
|
1046
|
+
c: $c;
|
1047
|
+
d: $d;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
$list: 2, 3, 4;
|
1051
|
+
.foo {@include foo(1, $list...)}
|
1052
|
+
SCSS
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
def test_mixin_splat_expression
|
1056
|
+
assert_equal <<CSS, render(<<SCSS)
|
1057
|
+
.foo {
|
1058
|
+
a: 1;
|
1059
|
+
b: 2;
|
1060
|
+
c: 3;
|
1061
|
+
d: 4; }
|
1062
|
+
CSS
|
1063
|
+
@mixin foo($a, $b, $c, $d) {
|
1064
|
+
a: $a;
|
1065
|
+
b: $b;
|
1066
|
+
c: $c;
|
1067
|
+
d: $d;
|
1068
|
+
}
|
1069
|
+
|
1070
|
+
.foo {@include foo(1, (2, 3, 4)...)}
|
1071
|
+
SCSS
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
def test_mixin_splat_args_with_var_args
|
1075
|
+
assert_equal <<CSS, render(<<SCSS)
|
1076
|
+
.foo {
|
1077
|
+
a: 1;
|
1078
|
+
b: 2, 3, 4; }
|
1079
|
+
CSS
|
1080
|
+
@mixin foo($a, $b...) {
|
1081
|
+
a: $a;
|
1082
|
+
b: $b;
|
1083
|
+
}
|
1084
|
+
|
1085
|
+
$list: 2, 3, 4;
|
1086
|
+
.foo {@include foo(1, $list...)}
|
1087
|
+
SCSS
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
def test_mixin_splat_args_with_var_args_and_normal_args
|
1091
|
+
assert_equal <<CSS, render(<<SCSS)
|
1092
|
+
.foo {
|
1093
|
+
a: 1;
|
1094
|
+
b: 2;
|
1095
|
+
c: 3, 4; }
|
1096
|
+
CSS
|
1097
|
+
@mixin foo($a, $b, $c...) {
|
1098
|
+
a: $a;
|
1099
|
+
b: $b;
|
1100
|
+
c: $c;
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
$list: 2, 3, 4;
|
1104
|
+
.foo {@include foo(1, $list...)}
|
1105
|
+
SCSS
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
def test_mixin_splat_args_with_var_args_preserves_separator
|
1109
|
+
assert_equal <<CSS, render(<<SCSS)
|
1110
|
+
.foo {
|
1111
|
+
a: 1;
|
1112
|
+
b: 2 3 4 5; }
|
1113
|
+
CSS
|
1114
|
+
@mixin foo($a, $b...) {
|
1115
|
+
a: $a;
|
1116
|
+
b: $b;
|
1117
|
+
}
|
1118
|
+
|
1119
|
+
$list: 3 4 5;
|
1120
|
+
.foo {@include foo(1, 2, $list...)}
|
1121
|
+
SCSS
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
def test_mixin_var_and_splat_args_pass_through_keywords
|
1125
|
+
assert_equal <<CSS, render(<<SCSS)
|
1126
|
+
.foo {
|
1127
|
+
a: 3;
|
1128
|
+
b: 1;
|
1129
|
+
c: 2; }
|
1130
|
+
CSS
|
1131
|
+
@mixin foo($a...) {
|
1132
|
+
@include bar($a...);
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
@mixin bar($b, $c, $a) {
|
1136
|
+
a: $a;
|
1137
|
+
b: $b;
|
1138
|
+
c: $c;
|
1139
|
+
}
|
1140
|
+
|
1141
|
+
.foo {@include foo(1, $c: 2, $a: 3)}
|
1142
|
+
SCSS
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
def test_mixin_var_keyword_args
|
1146
|
+
assert_equal <<CSS, render(<<SCSS)
|
1147
|
+
.foo {
|
1148
|
+
a: 1;
|
1149
|
+
b: 2;
|
1150
|
+
c: 3; }
|
1151
|
+
CSS
|
1152
|
+
@mixin foo($args...) {
|
1153
|
+
a: map-get(keywords($args), a);
|
1154
|
+
b: map-get(keywords($args), b);
|
1155
|
+
c: map-get(keywords($args), c);
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
.foo {@include foo($a: 1, $b: 2, $c: 3)}
|
1159
|
+
SCSS
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
def test_mixin_empty_var_keyword_args
|
1163
|
+
assert_equal <<CSS, render(<<SCSS)
|
1164
|
+
.foo {
|
1165
|
+
length: 0; }
|
1166
|
+
CSS
|
1167
|
+
@mixin foo($args...) {
|
1168
|
+
length: length(keywords($args));
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
.foo {@include foo}
|
1172
|
+
SCSS
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
def test_mixin_map_splat
|
1176
|
+
assert_equal <<CSS, render(<<SCSS)
|
1177
|
+
.foo {
|
1178
|
+
a: 1;
|
1179
|
+
b: 2;
|
1180
|
+
c: 3; }
|
1181
|
+
CSS
|
1182
|
+
@mixin foo($a, $b, $c) {
|
1183
|
+
a: $a;
|
1184
|
+
b: $b;
|
1185
|
+
c: $c;
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
.foo {
|
1189
|
+
$map: (a: 1, b: 2, c: 3);
|
1190
|
+
@include foo($map...);
|
1191
|
+
}
|
1192
|
+
SCSS
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
def test_mixin_map_and_list_splat
|
1196
|
+
assert_equal <<CSS, render(<<SCSS)
|
1197
|
+
.foo {
|
1198
|
+
a: x;
|
1199
|
+
b: y;
|
1200
|
+
c: z;
|
1201
|
+
d: 1;
|
1202
|
+
e: 2;
|
1203
|
+
f: 3; }
|
1204
|
+
CSS
|
1205
|
+
@mixin foo($a, $b, $c, $d, $e, $f) {
|
1206
|
+
a: $a;
|
1207
|
+
b: $b;
|
1208
|
+
c: $c;
|
1209
|
+
d: $d;
|
1210
|
+
e: $e;
|
1211
|
+
f: $f;
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
.foo {
|
1215
|
+
$list: x y z;
|
1216
|
+
$map: (d: 1, e: 2, f: 3);
|
1217
|
+
@include foo($list..., $map...);
|
1218
|
+
}
|
1219
|
+
SCSS
|
1220
|
+
end
|
1221
|
+
|
1222
|
+
def test_mixin_map_splat_takes_precedence_over_pass_through
|
1223
|
+
assert_equal <<CSS, render(<<SCSS)
|
1224
|
+
.foo {
|
1225
|
+
a: 1;
|
1226
|
+
b: 2;
|
1227
|
+
c: z; }
|
1228
|
+
CSS
|
1229
|
+
@mixin foo($args...) {
|
1230
|
+
$map: (c: z);
|
1231
|
+
@include bar($args..., $map...);
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
@mixin bar($a, $b, $c) {
|
1235
|
+
a: $a;
|
1236
|
+
b: $b;
|
1237
|
+
c: $c;
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
.foo {
|
1241
|
+
@include foo(1, $b: 2, $c: 3);
|
1242
|
+
}
|
1243
|
+
SCSS
|
1244
|
+
end
|
1245
|
+
|
1246
|
+
def test_mixin_list_of_pairs_splat_treated_as_list
|
1247
|
+
assert_equal <<CSS, render(<<SCSS)
|
1248
|
+
.foo {
|
1249
|
+
a: a 1;
|
1250
|
+
b: b 2;
|
1251
|
+
c: c 3; }
|
1252
|
+
CSS
|
1253
|
+
@mixin foo($a, $b, $c) {
|
1254
|
+
a: $a;
|
1255
|
+
b: $b;
|
1256
|
+
c: $c;
|
1257
|
+
}
|
1258
|
+
|
1259
|
+
.foo {
|
1260
|
+
@include foo((a 1, b 2, c 3)...);
|
1261
|
+
}
|
1262
|
+
SCSS
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
def test_mixin_splat_after_keyword_args
|
1266
|
+
assert_equal <<CSS, render(<<SCSS)
|
1267
|
+
.foo {
|
1268
|
+
a: 1;
|
1269
|
+
b: 2;
|
1270
|
+
c: 3; }
|
1271
|
+
CSS
|
1272
|
+
@mixin foo($a, $b, $c) {
|
1273
|
+
a: 1;
|
1274
|
+
b: 2;
|
1275
|
+
c: 3;
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
.foo {
|
1279
|
+
@include foo(1, $c: 3, 2...);
|
1280
|
+
}
|
1281
|
+
SCSS
|
1282
|
+
end
|
1283
|
+
|
1284
|
+
def test_mixin_keyword_args_after_splat
|
1285
|
+
assert_equal <<CSS, render(<<SCSS)
|
1286
|
+
.foo {
|
1287
|
+
a: 1;
|
1288
|
+
b: 2;
|
1289
|
+
c: 3; }
|
1290
|
+
CSS
|
1291
|
+
@mixin foo($a, $b, $c) {
|
1292
|
+
a: 1;
|
1293
|
+
b: 2;
|
1294
|
+
c: 3;
|
1295
|
+
}
|
1296
|
+
|
1297
|
+
.foo {
|
1298
|
+
@include foo(1, 2..., $c: 3);
|
1299
|
+
}
|
1300
|
+
SCSS
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
def test_mixin_keyword_splat_after_keyword_args
|
1304
|
+
assert_equal <<CSS, render(<<SCSS)
|
1305
|
+
.foo {
|
1306
|
+
a: 1;
|
1307
|
+
b: 2;
|
1308
|
+
c: 3; }
|
1309
|
+
CSS
|
1310
|
+
@mixin foo($a, $b, $c) {
|
1311
|
+
a: 1;
|
1312
|
+
b: 2;
|
1313
|
+
c: 3;
|
1314
|
+
}
|
1315
|
+
|
1316
|
+
.foo {
|
1317
|
+
@include foo(1, $b: 2, (c: 3)...);
|
1318
|
+
}
|
1319
|
+
SCSS
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
def test_mixin_triple_keyword_splat_merge
|
1323
|
+
assert_equal <<CSS, render(<<SCSS)
|
1324
|
+
.foo {
|
1325
|
+
foo: 1;
|
1326
|
+
bar: 2;
|
1327
|
+
kwarg: 3;
|
1328
|
+
a: 3;
|
1329
|
+
b: 2;
|
1330
|
+
c: 3; }
|
1331
|
+
CSS
|
1332
|
+
@mixin foo($foo, $bar, $kwarg, $a, $b, $c) {
|
1333
|
+
foo: $foo;
|
1334
|
+
bar: $bar;
|
1335
|
+
kwarg: $kwarg;
|
1336
|
+
a: $a;
|
1337
|
+
b: $b;
|
1338
|
+
c: $c;
|
1339
|
+
}
|
1340
|
+
|
1341
|
+
@mixin bar($args...) {
|
1342
|
+
@include foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
.foo {
|
1346
|
+
@include bar($foo: 1, $a: 1, $b: 1, $c: 1);
|
1347
|
+
}
|
1348
|
+
SCSS
|
1349
|
+
end
|
1350
|
+
|
1351
|
+
def test_mixin_map_splat_converts_hyphens_and_underscores_for_real_args
|
1352
|
+
assert_equal <<CSS, render(<<SCSS)
|
1353
|
+
.foo {
|
1354
|
+
a: 1;
|
1355
|
+
b: 2;
|
1356
|
+
c: 3;
|
1357
|
+
d: 4; }
|
1358
|
+
CSS
|
1359
|
+
@mixin foo($a-1, $b-2, $c_3, $d_4) {
|
1360
|
+
a: $a-1;
|
1361
|
+
b: $b-2;
|
1362
|
+
c: $c_3;
|
1363
|
+
d: $d_4;
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
.foo {
|
1367
|
+
$map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
|
1368
|
+
@include foo($map...);
|
1369
|
+
}
|
1370
|
+
SCSS
|
1371
|
+
end
|
1372
|
+
|
1373
|
+
def test_mixin_map_splat_doesnt_convert_hyphens_and_underscores_for_var_args
|
1374
|
+
assert_equal <<CSS, render(<<SCSS)
|
1375
|
+
.foo {
|
1376
|
+
a-1: 1;
|
1377
|
+
b_2: 2;
|
1378
|
+
c-3: 3;
|
1379
|
+
d_4: 4; }
|
1380
|
+
CSS
|
1381
|
+
@mixin foo($args...) {
|
1382
|
+
@each $key, $value in keywords($args) {
|
1383
|
+
\#{$key}: $value;
|
1384
|
+
}
|
1385
|
+
}
|
1386
|
+
|
1387
|
+
.foo {
|
1388
|
+
$map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
|
1389
|
+
@include foo($map...);
|
1390
|
+
}
|
1391
|
+
SCSS
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
def test_mixin_conflicting_splat_after_keyword_args
|
1395
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1396
|
+
Mixin foo was passed argument $b both by position and by name.
|
1397
|
+
MESSAGE
|
1398
|
+
@mixin foo($a, $b, $c) {
|
1399
|
+
a: 1;
|
1400
|
+
b: 2;
|
1401
|
+
c: 3;
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
.foo {
|
1405
|
+
@include foo(1, $b: 2, 3...);
|
1406
|
+
}
|
1407
|
+
SCSS
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def test_mixin_keyword_splat_must_have_string_keys
|
1411
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
1412
|
+
Variable keyword argument map must have string keys.
|
1413
|
+
12 is not a string in (12: 1).
|
1414
|
+
MESSAGE
|
1415
|
+
@mixin foo($a) {
|
1416
|
+
a: $a;
|
1417
|
+
}
|
1418
|
+
|
1419
|
+
.foo {@include foo((12: 1)...)}
|
1420
|
+
SCSS
|
1421
|
+
end
|
1422
|
+
|
1423
|
+
def test_mixin_positional_arg_after_splat
|
1424
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1425
|
+
Only keyword arguments may follow variable arguments (...).
|
1426
|
+
MESSAGE
|
1427
|
+
@mixin foo($a, $b, $c) {
|
1428
|
+
a: 1;
|
1429
|
+
b: 2;
|
1430
|
+
c: 3;
|
1431
|
+
}
|
1432
|
+
|
1433
|
+
.foo {
|
1434
|
+
@include foo(1, 2..., 3);
|
1435
|
+
}
|
1436
|
+
SCSS
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
def test_mixin_var_args_with_keyword
|
1440
|
+
assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
|
1441
|
+
@mixin foo($a, $b...) {
|
1442
|
+
a: $a;
|
1443
|
+
b: $b;
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
.foo {@include foo($a: 1, 2, 3, 4)}
|
1447
|
+
SCSS
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
def test_mixin_keyword_for_var_arg
|
1451
|
+
assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") {render <<SCSS}
|
1452
|
+
@mixin foo($a, $b...) {
|
1453
|
+
a: $a;
|
1454
|
+
b: $b;
|
1455
|
+
}
|
1456
|
+
|
1457
|
+
.foo {@include foo(1, $b: 2 3 4)}
|
1458
|
+
SCSS
|
1459
|
+
end
|
1460
|
+
|
1461
|
+
def test_mixin_keyword_for_unknown_arg_with_var_args
|
1462
|
+
assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
|
1463
|
+
@mixin foo($a, $b...) {
|
1464
|
+
a: $a;
|
1465
|
+
b: $b;
|
1466
|
+
}
|
1467
|
+
|
1468
|
+
.foo {@include foo(1, $c: 2 3 4)}
|
1469
|
+
SCSS
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
def test_mixin_map_splat_before_list_splat
|
1473
|
+
assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was (2 3)).") {render <<SCSS}
|
1474
|
+
@mixin foo($a, $b, $c) {
|
1475
|
+
a: $a;
|
1476
|
+
b: $b;
|
1477
|
+
c: $c;
|
1478
|
+
}
|
1479
|
+
|
1480
|
+
.foo {
|
1481
|
+
@include foo((a: 1)..., (2 3)...);
|
1482
|
+
}
|
1483
|
+
SCSS
|
1484
|
+
end
|
1485
|
+
|
1486
|
+
def test_mixin_map_splat_with_unknown_keyword
|
1487
|
+
assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
|
1488
|
+
@mixin foo($a, $b) {
|
1489
|
+
a: $a;
|
1490
|
+
b: $b;
|
1491
|
+
}
|
1492
|
+
|
1493
|
+
.foo {
|
1494
|
+
@include foo(1, 2, (c: 1)...);
|
1495
|
+
}
|
1496
|
+
SCSS
|
1497
|
+
end
|
1498
|
+
|
1499
|
+
def test_mixin_map_splat_with_wrong_type
|
1500
|
+
assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was 12).") {render <<SCSS}
|
1501
|
+
@mixin foo($a, $b) {
|
1502
|
+
a: $a;
|
1503
|
+
b: $b;
|
1504
|
+
}
|
1505
|
+
|
1506
|
+
.foo {
|
1507
|
+
@include foo((1, 2)..., 12...);
|
1508
|
+
}
|
1509
|
+
SCSS
|
1510
|
+
end
|
1511
|
+
|
1512
|
+
def test_function_var_args
|
1513
|
+
assert_equal <<CSS, render(<<SCSS)
|
1514
|
+
.foo {
|
1515
|
+
val: "a: 1, b: 2, 3, 4"; }
|
1516
|
+
CSS
|
1517
|
+
@function foo($a, $b...) {
|
1518
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1519
|
+
}
|
1520
|
+
|
1521
|
+
.foo {val: foo(1, 2, 3, 4)}
|
1522
|
+
SCSS
|
1523
|
+
end
|
1524
|
+
|
1525
|
+
def test_function_empty_var_args
|
1526
|
+
assert_equal <<CSS, render(<<SCSS)
|
1527
|
+
.foo {
|
1528
|
+
val: "a: 1, b: 0"; }
|
1529
|
+
CSS
|
1530
|
+
@function foo($a, $b...) {
|
1531
|
+
@return "a: \#{$a}, b: \#{length($b)}";
|
1532
|
+
}
|
1533
|
+
|
1534
|
+
.foo {val: foo(1)}
|
1535
|
+
SCSS
|
1536
|
+
end
|
1537
|
+
|
1538
|
+
def test_function_var_args_act_like_list
|
1539
|
+
assert_equal <<CSS, render(<<SCSS)
|
1540
|
+
.foo {
|
1541
|
+
val: "a: 3, b: 3"; }
|
1542
|
+
CSS
|
1543
|
+
@function foo($a, $b...) {
|
1544
|
+
@return "a: \#{length($b)}, b: \#{nth($b, 2)}";
|
1545
|
+
}
|
1546
|
+
|
1547
|
+
.foo {val: foo(1, 2, 3, 4)}
|
1548
|
+
SCSS
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
def test_function_splat_args
|
1552
|
+
assert_equal <<CSS, render(<<SCSS)
|
1553
|
+
.foo {
|
1554
|
+
val: "a: 1, b: 2, c: 3, d: 4"; }
|
1555
|
+
CSS
|
1556
|
+
@function foo($a, $b, $c, $d) {
|
1557
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
|
1558
|
+
}
|
1559
|
+
|
1560
|
+
$list: 2, 3, 4;
|
1561
|
+
.foo {val: foo(1, $list...)}
|
1562
|
+
SCSS
|
1563
|
+
end
|
1564
|
+
|
1565
|
+
def test_function_splat_expression
|
1566
|
+
assert_equal <<CSS, render(<<SCSS)
|
1567
|
+
.foo {
|
1568
|
+
val: "a: 1, b: 2, c: 3, d: 4"; }
|
1569
|
+
CSS
|
1570
|
+
@function foo($a, $b, $c, $d) {
|
1571
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
.foo {val: foo(1, (2, 3, 4)...)}
|
1575
|
+
SCSS
|
1576
|
+
end
|
1577
|
+
|
1578
|
+
def test_function_splat_args_with_var_args
|
1579
|
+
assert_equal <<CSS, render(<<SCSS)
|
1580
|
+
.foo {
|
1581
|
+
val: "a: 1, b: 2, 3, 4"; }
|
1582
|
+
CSS
|
1583
|
+
@function foo($a, $b...) {
|
1584
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1585
|
+
}
|
1586
|
+
|
1587
|
+
$list: 2, 3, 4;
|
1588
|
+
.foo {val: foo(1, $list...)}
|
1589
|
+
SCSS
|
1590
|
+
end
|
1591
|
+
|
1592
|
+
def test_function_splat_args_with_var_args_and_normal_args
|
1593
|
+
assert_equal <<CSS, render(<<SCSS)
|
1594
|
+
.foo {
|
1595
|
+
val: "a: 1, b: 2, c: 3, 4"; }
|
1596
|
+
CSS
|
1597
|
+
@function foo($a, $b, $c...) {
|
1598
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1599
|
+
}
|
1600
|
+
|
1601
|
+
$list: 2, 3, 4;
|
1602
|
+
.foo {val: foo(1, $list...)}
|
1603
|
+
SCSS
|
1604
|
+
end
|
1605
|
+
|
1606
|
+
def test_function_splat_args_with_var_args_preserves_separator
|
1607
|
+
assert_equal <<CSS, render(<<SCSS)
|
1608
|
+
.foo {
|
1609
|
+
val: "a: 1, b: 2 3 4 5"; }
|
1610
|
+
CSS
|
1611
|
+
@function foo($a, $b...) {
|
1612
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1613
|
+
}
|
1614
|
+
|
1615
|
+
$list: 3 4 5;
|
1616
|
+
.foo {val: foo(1, 2, $list...)}
|
1617
|
+
SCSS
|
1618
|
+
end
|
1619
|
+
|
1620
|
+
def test_function_var_and_splat_args_pass_through_keywords
|
1621
|
+
assert_equal <<CSS, render(<<SCSS)
|
1622
|
+
.foo {
|
1623
|
+
val: "a: 3, b: 1, c: 2"; }
|
1624
|
+
CSS
|
1625
|
+
@function foo($a...) {
|
1626
|
+
@return bar($a...);
|
1627
|
+
}
|
1628
|
+
|
1629
|
+
@function bar($b, $c, $a) {
|
1630
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1631
|
+
}
|
1632
|
+
|
1633
|
+
.foo {val: foo(1, $c: 2, $a: 3)}
|
1634
|
+
SCSS
|
1635
|
+
end
|
1636
|
+
|
1637
|
+
def test_function_var_keyword_args
|
1638
|
+
assert_equal <<CSS, render(<<SCSS)
|
1639
|
+
.foo {
|
1640
|
+
val: "a: 1, b: 2, c: 3"; }
|
1641
|
+
CSS
|
1642
|
+
@function foo($args...) {
|
1643
|
+
@return "a: \#{map-get(keywords($args), a)}, " +
|
1644
|
+
"b: \#{map-get(keywords($args), b)}, " +
|
1645
|
+
"c: \#{map-get(keywords($args), c)}";
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
.foo {val: foo($a: 1, $b: 2, $c: 3)}
|
1649
|
+
SCSS
|
1650
|
+
end
|
1651
|
+
|
1652
|
+
def test_function_empty_var_keyword_args
|
1653
|
+
assert_equal <<CSS, render(<<SCSS)
|
1654
|
+
.foo {
|
1655
|
+
length: 0; }
|
1656
|
+
CSS
|
1657
|
+
@function foo($args...) {
|
1658
|
+
@return length(keywords($args));
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
.foo {length: foo()}
|
1662
|
+
SCSS
|
1663
|
+
end
|
1664
|
+
|
1665
|
+
def test_function_map_splat
|
1666
|
+
assert_equal <<CSS, render(<<SCSS)
|
1667
|
+
.foo {
|
1668
|
+
val: "a: 1, b: 2, c: 3"; }
|
1669
|
+
CSS
|
1670
|
+
@function foo($a, $b, $c) {
|
1671
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1672
|
+
}
|
1673
|
+
|
1674
|
+
.foo {
|
1675
|
+
$map: (a: 1, b: 2, c: 3);
|
1676
|
+
val: foo($map...);
|
1677
|
+
}
|
1678
|
+
SCSS
|
1679
|
+
end
|
1680
|
+
|
1681
|
+
def test_function_map_and_list_splat
|
1682
|
+
assert_equal <<CSS, render(<<SCSS)
|
1683
|
+
.foo {
|
1684
|
+
val: "a: x, b: y, c: z, d: 1, e: 2, f: 3"; }
|
1685
|
+
CSS
|
1686
|
+
@function foo($a, $b, $c, $d, $e, $f) {
|
1687
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}, e: \#{$e}, f: \#{$f}";
|
1688
|
+
}
|
1689
|
+
|
1690
|
+
.foo {
|
1691
|
+
$list: x y z;
|
1692
|
+
$map: (d: 1, e: 2, f: 3);
|
1693
|
+
val: foo($list..., $map...);
|
1694
|
+
}
|
1695
|
+
SCSS
|
1696
|
+
end
|
1697
|
+
|
1698
|
+
def test_function_map_splat_takes_precedence_over_pass_through
|
1699
|
+
assert_equal <<CSS, render(<<SCSS)
|
1700
|
+
.foo {
|
1701
|
+
val: "a: 1, b: 2, c: z"; }
|
1702
|
+
CSS
|
1703
|
+
@function foo($args...) {
|
1704
|
+
$map: (c: z);
|
1705
|
+
@return bar($args..., $map...);
|
1706
|
+
}
|
1707
|
+
|
1708
|
+
@function bar($a, $b, $c) {
|
1709
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1710
|
+
}
|
1711
|
+
|
1712
|
+
.foo {
|
1713
|
+
val: foo(1, $b: 2, $c: 3);
|
1714
|
+
}
|
1715
|
+
SCSS
|
1716
|
+
end
|
1717
|
+
|
1718
|
+
def test_ruby_function_map_splat_takes_precedence_over_pass_through
|
1719
|
+
assert_equal <<CSS, render(<<SCSS)
|
1720
|
+
.foo {
|
1721
|
+
val: 1 2 3 z; }
|
1722
|
+
CSS
|
1723
|
+
@function foo($args...) {
|
1724
|
+
$map: (val: z);
|
1725
|
+
@return append($args..., $map...);
|
1726
|
+
}
|
1727
|
+
|
1728
|
+
.foo {
|
1729
|
+
val: foo(1 2 3, $val: 4)
|
1730
|
+
}
|
1731
|
+
SCSS
|
1732
|
+
end
|
1733
|
+
|
1734
|
+
def test_function_list_of_pairs_splat_treated_as_list
|
1735
|
+
assert_equal <<CSS, render(<<SCSS)
|
1736
|
+
.foo {
|
1737
|
+
val: "a: a 1, b: b 2, c: c 3"; }
|
1738
|
+
CSS
|
1739
|
+
@function foo($a, $b, $c) {
|
1740
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1741
|
+
}
|
1742
|
+
|
1743
|
+
.foo {
|
1744
|
+
val: foo((a 1, b 2, c 3)...);
|
1745
|
+
}
|
1746
|
+
SCSS
|
1747
|
+
end
|
1748
|
+
|
1749
|
+
def test_function_splat_after_keyword_args
|
1750
|
+
assert_equal <<CSS, render(<<SCSS)
|
1751
|
+
.foo {
|
1752
|
+
val: "a: 1, b: 2, c: 3"; }
|
1753
|
+
CSS
|
1754
|
+
@function foo($a, $b, $c) {
|
1755
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
.foo {
|
1759
|
+
val: foo(1, $c: 3, 2...);
|
1760
|
+
}
|
1761
|
+
SCSS
|
1762
|
+
end
|
1763
|
+
|
1764
|
+
def test_function_keyword_args_after_splat
|
1765
|
+
assert_equal <<CSS, render(<<SCSS)
|
1766
|
+
.foo {
|
1767
|
+
val: "a: 1, b: 2, c: 3"; }
|
1768
|
+
CSS
|
1769
|
+
@function foo($a, $b, $c) {
|
1770
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1771
|
+
}
|
1772
|
+
|
1773
|
+
.foo {
|
1774
|
+
val: foo(1, 2..., $c: 3);
|
1775
|
+
}
|
1776
|
+
SCSS
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
def test_function_keyword_splat_after_keyword_args
|
1780
|
+
assert_equal <<CSS, render(<<SCSS)
|
1781
|
+
.foo {
|
1782
|
+
val: "a: 1, b: 2, c: 3"; }
|
1783
|
+
CSS
|
1784
|
+
@function foo($a, $b, $c) {
|
1785
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1786
|
+
}
|
1787
|
+
|
1788
|
+
.foo {
|
1789
|
+
val: foo(1, $b: 2, (c: 3)...);
|
1790
|
+
}
|
1791
|
+
SCSS
|
1792
|
+
end
|
1793
|
+
|
1794
|
+
def test_function_triple_keyword_splat_merge
|
1795
|
+
assert_equal <<CSS, render(<<SCSS)
|
1796
|
+
.foo {
|
1797
|
+
val: "foo: 1, bar: 2, kwarg: 3, a: 3, b: 2, c: 3"; }
|
1798
|
+
CSS
|
1799
|
+
@function foo($foo, $bar, $kwarg, $a, $b, $c) {
|
1800
|
+
@return "foo: \#{$foo}, bar: \#{$bar}, kwarg: \#{$kwarg}, a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1801
|
+
}
|
1802
|
+
|
1803
|
+
@function bar($args...) {
|
1804
|
+
@return foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
|
1805
|
+
}
|
1806
|
+
|
1807
|
+
.foo {
|
1808
|
+
val: bar($foo: 1, $a: 1, $b: 1, $c: 1);
|
1809
|
+
}
|
1810
|
+
SCSS
|
1811
|
+
end
|
1812
|
+
|
1813
|
+
def test_function_conflicting_splat_after_keyword_args
|
1814
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1815
|
+
Function foo was passed argument $b both by position and by name.
|
1816
|
+
MESSAGE
|
1817
|
+
@function foo($a, $b, $c) {
|
1818
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1819
|
+
}
|
1820
|
+
|
1821
|
+
.foo {
|
1822
|
+
val: foo(1, $b: 2, 3...);
|
1823
|
+
}
|
1824
|
+
SCSS
|
1825
|
+
end
|
1826
|
+
|
1827
|
+
def test_function_positional_arg_after_splat
|
1828
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1829
|
+
Only keyword arguments may follow variable arguments (...).
|
1830
|
+
MESSAGE
|
1831
|
+
@function foo($a, $b, $c) {
|
1832
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1833
|
+
}
|
1834
|
+
|
1835
|
+
.foo {
|
1836
|
+
val: foo(1, 2..., 3);
|
1837
|
+
}
|
1838
|
+
SCSS
|
1839
|
+
end
|
1840
|
+
|
1841
|
+
def test_function_var_args_with_keyword
|
1842
|
+
assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
|
1843
|
+
@function foo($a, $b...) {
|
1844
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1845
|
+
}
|
1846
|
+
|
1847
|
+
.foo {val: foo($a: 1, 2, 3, 4)}
|
1848
|
+
SCSS
|
1849
|
+
end
|
1850
|
+
|
1851
|
+
def test_function_keyword_for_var_arg
|
1852
|
+
assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named argument.") {render <<SCSS}
|
1853
|
+
@function foo($a, $b...) {
|
1854
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1855
|
+
}
|
1856
|
+
|
1857
|
+
.foo {val: foo(1, $b: 2 3 4)}
|
1858
|
+
SCSS
|
1859
|
+
end
|
1860
|
+
|
1861
|
+
def test_function_keyword_for_unknown_arg_with_var_args
|
1862
|
+
assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
|
1863
|
+
@function foo($a, $b...) {
|
1864
|
+
@return "a: \#{$a}, b: \#{length($b)}";
|
1865
|
+
}
|
1866
|
+
|
1867
|
+
.foo {val: foo(1, $c: 2 3 4)}
|
1868
|
+
SCSS
|
1869
|
+
end
|
1870
|
+
|
1871
|
+
def test_function_var_args_passed_to_native
|
1872
|
+
assert_equal <<CSS, render(<<SCSS)
|
1873
|
+
.foo {
|
1874
|
+
val: #102035; }
|
1875
|
+
CSS
|
1876
|
+
@function foo($args...) {
|
1877
|
+
@return adjust-color($args...);
|
1878
|
+
}
|
1879
|
+
|
1880
|
+
.foo {val: foo(#102030, $blue: 5)}
|
1881
|
+
SCSS
|
1882
|
+
end
|
1883
|
+
|
1884
|
+
def test_function_map_splat_before_list_splat
|
1885
|
+
assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was (2 3)).") {render <<SCSS}
|
1886
|
+
@function foo($a, $b, $c) {
|
1887
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1888
|
+
}
|
1889
|
+
|
1890
|
+
.foo {
|
1891
|
+
val: foo((a: 1)..., (2 3)...);
|
1892
|
+
}
|
1893
|
+
SCSS
|
1894
|
+
end
|
1895
|
+
|
1896
|
+
def test_function_map_splat_with_unknown_keyword
|
1897
|
+
assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
|
1898
|
+
@function foo($a, $b) {
|
1899
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1900
|
+
}
|
1901
|
+
|
1902
|
+
.foo {
|
1903
|
+
val: foo(1, 2, (c: 1)...);
|
1904
|
+
}
|
1905
|
+
SCSS
|
1906
|
+
end
|
1907
|
+
|
1908
|
+
def test_function_map_splat_with_wrong_type
|
1909
|
+
assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was 12).") {render <<SCSS}
|
1910
|
+
@function foo($a, $b) {
|
1911
|
+
@return "a: \#{$a}, b: \#{$b}";
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
.foo {
|
1915
|
+
val: foo((1, 2)..., 12...);
|
1916
|
+
}
|
1917
|
+
SCSS
|
1918
|
+
end
|
1919
|
+
|
1920
|
+
def test_function_keyword_splat_must_have_string_keys
|
1921
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
1922
|
+
Variable keyword argument map must have string keys.
|
1923
|
+
12 is not a string in (12: 1).
|
1924
|
+
MESSAGE
|
1925
|
+
@function foo($a) {
|
1926
|
+
@return $a;
|
1927
|
+
}
|
1928
|
+
|
1929
|
+
.foo {val: foo((12: 1)...)}
|
1930
|
+
SCSS
|
1931
|
+
end
|
1932
|
+
|
1933
|
+
## Interpolation
|
1934
|
+
|
1935
|
+
def test_basic_selector_interpolation
|
1936
|
+
assert_equal <<CSS, render(<<SCSS)
|
1937
|
+
foo ab baz {
|
1938
|
+
a: b; }
|
1939
|
+
CSS
|
1940
|
+
foo \#{'a' + 'b'} baz {a: b}
|
1941
|
+
SCSS
|
1942
|
+
assert_equal <<CSS, render(<<SCSS)
|
1943
|
+
foo.bar baz {
|
1944
|
+
a: b; }
|
1945
|
+
CSS
|
1946
|
+
foo\#{".bar"} baz {a: b}
|
1947
|
+
SCSS
|
1948
|
+
assert_equal <<CSS, render(<<SCSS)
|
1949
|
+
foo.bar baz {
|
1950
|
+
a: b; }
|
1951
|
+
CSS
|
1952
|
+
\#{"foo"}.bar baz {a: b}
|
1953
|
+
SCSS
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
def test_selector_only_interpolation
|
1957
|
+
assert_equal <<CSS, render(<<SCSS)
|
1958
|
+
foo bar {
|
1959
|
+
a: b; }
|
1960
|
+
CSS
|
1961
|
+
\#{"foo" + " bar"} {a: b}
|
1962
|
+
SCSS
|
1963
|
+
end
|
1964
|
+
|
1965
|
+
def test_selector_interpolation_before_element_name
|
1966
|
+
assert_equal <<CSS, render(<<SCSS)
|
1967
|
+
foo barbaz {
|
1968
|
+
a: b; }
|
1969
|
+
CSS
|
1970
|
+
\#{"foo" + " bar"}baz {a: b}
|
1971
|
+
SCSS
|
1972
|
+
end
|
1973
|
+
|
1974
|
+
def test_selector_interpolation_in_string
|
1975
|
+
assert_equal <<CSS, render(<<SCSS)
|
1976
|
+
foo[val="bar foo bar baz"] {
|
1977
|
+
a: b; }
|
1978
|
+
CSS
|
1979
|
+
foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
|
1980
|
+
SCSS
|
1981
|
+
end
|
1982
|
+
|
1983
|
+
def test_selector_interpolation_in_pseudoclass
|
1984
|
+
assert_equal <<CSS, render(<<SCSS)
|
1985
|
+
foo:nth-child(5n) {
|
1986
|
+
a: b; }
|
1987
|
+
CSS
|
1988
|
+
foo:nth-child(\#{5 + "n"}) {a: b}
|
1989
|
+
SCSS
|
1990
|
+
end
|
1991
|
+
|
1992
|
+
def test_selector_interpolation_at_class_begininng
|
1993
|
+
assert_equal <<CSS, render(<<SCSS)
|
1994
|
+
.zzz {
|
1995
|
+
a: b; }
|
1996
|
+
CSS
|
1997
|
+
$zzz: zzz;
|
1998
|
+
.\#{$zzz} { a: b; }
|
1999
|
+
SCSS
|
2000
|
+
end
|
2001
|
+
|
2002
|
+
def test_selector_interpolation_at_id_begininng
|
2003
|
+
assert_equal <<CSS, render(<<SCSS)
|
2004
|
+
#zzz {
|
2005
|
+
a: b; }
|
2006
|
+
CSS
|
2007
|
+
$zzz: zzz;
|
2008
|
+
#\#{$zzz} { a: b; }
|
2009
|
+
SCSS
|
2010
|
+
end
|
2011
|
+
|
2012
|
+
def test_selector_interpolation_at_pseudo_begininng
|
2013
|
+
assert_equal <<CSS, render(<<SCSS)
|
2014
|
+
:zzz::zzz {
|
2015
|
+
a: b; }
|
2016
|
+
CSS
|
2017
|
+
$zzz: zzz;
|
2018
|
+
:\#{$zzz}::\#{$zzz} { a: b; }
|
2019
|
+
SCSS
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
def test_selector_interpolation_at_attr_beginning
|
2023
|
+
assert_equal <<CSS, render(<<SCSS)
|
2024
|
+
[zzz=foo] {
|
2025
|
+
a: b; }
|
2026
|
+
CSS
|
2027
|
+
$zzz: zzz;
|
2028
|
+
[\#{$zzz}=foo] { a: b; }
|
2029
|
+
SCSS
|
2030
|
+
end
|
2031
|
+
|
2032
|
+
def test_selector_interpolation_at_attr_end
|
2033
|
+
assert_equal <<CSS, render(<<SCSS)
|
2034
|
+
[foo=zzz] {
|
2035
|
+
a: b; }
|
2036
|
+
CSS
|
2037
|
+
$zzz: zzz;
|
2038
|
+
[foo=\#{$zzz}] { a: b; }
|
2039
|
+
SCSS
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
def test_selector_interpolation_at_dashes
|
2043
|
+
assert_equal <<CSS, render(<<SCSS)
|
2044
|
+
div {
|
2045
|
+
-foo-a-b-foo: foo; }
|
2046
|
+
CSS
|
2047
|
+
$a : a;
|
2048
|
+
$b : b;
|
2049
|
+
div { -foo-\#{$a}-\#{$b}-foo: foo }
|
2050
|
+
SCSS
|
2051
|
+
end
|
2052
|
+
|
2053
|
+
def test_selector_interpolation_in_reference_combinator
|
2054
|
+
assert_equal <<CSS, render(<<SCSS)
|
2055
|
+
.foo /a/ .bar /b|c/ .baz {
|
2056
|
+
a: b; }
|
2057
|
+
CSS
|
2058
|
+
$a: a;
|
2059
|
+
$b: b;
|
2060
|
+
$c: c;
|
2061
|
+
.foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
|
2062
|
+
SCSS
|
2063
|
+
end
|
2064
|
+
|
2065
|
+
def test_parent_selector_with_parent_and_subject
|
2066
|
+
silence_warnings {assert_equal <<CSS, render(<<SCSS)}
|
2067
|
+
bar foo.baz! .bip {
|
2068
|
+
c: d; }
|
2069
|
+
CSS
|
2070
|
+
$subject: "!";
|
2071
|
+
foo {
|
2072
|
+
bar &.baz\#{$subject} .bip {c: d}}
|
2073
|
+
SCSS
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
def test_basic_prop_name_interpolation
|
2077
|
+
assert_equal <<CSS, render(<<SCSS)
|
2078
|
+
foo {
|
2079
|
+
barbazbang: blip; }
|
2080
|
+
CSS
|
2081
|
+
foo {bar\#{"baz" + "bang"}: blip}
|
2082
|
+
SCSS
|
2083
|
+
assert_equal <<CSS, render(<<SCSS)
|
2084
|
+
foo {
|
2085
|
+
bar3: blip; }
|
2086
|
+
CSS
|
2087
|
+
foo {bar\#{1 + 2}: blip}
|
2088
|
+
SCSS
|
2089
|
+
end
|
2090
|
+
|
2091
|
+
def test_prop_name_only_interpolation
|
2092
|
+
assert_equal <<CSS, render(<<SCSS)
|
2093
|
+
foo {
|
2094
|
+
bazbang: blip; }
|
2095
|
+
CSS
|
2096
|
+
foo {\#{"baz" + "bang"}: blip}
|
2097
|
+
SCSS
|
2098
|
+
end
|
2099
|
+
|
2100
|
+
def test_directive_interpolation
|
2101
|
+
assert_equal <<CSS, render(<<SCSS)
|
2102
|
+
@foo bar12 qux {
|
2103
|
+
a: b; }
|
2104
|
+
CSS
|
2105
|
+
$baz: 12;
|
2106
|
+
@foo bar\#{$baz} qux {a: b}
|
2107
|
+
SCSS
|
2108
|
+
end
|
2109
|
+
|
2110
|
+
def test_media_interpolation
|
2111
|
+
assert_equal <<CSS, render(<<SCSS)
|
2112
|
+
@media bar12 {
|
2113
|
+
a: b; }
|
2114
|
+
CSS
|
2115
|
+
$baz: 12;
|
2116
|
+
@media bar\#{$baz} {a: b}
|
2117
|
+
SCSS
|
2118
|
+
end
|
2119
|
+
|
2120
|
+
def test_script_in_media
|
2121
|
+
assert_equal <<CSS, render(<<SCSS)
|
2122
|
+
@media screen and (-webkit-min-device-pixel-ratio: 20), only print {
|
2123
|
+
a: b; }
|
2124
|
+
CSS
|
2125
|
+
$media1: screen;
|
2126
|
+
$media2: print;
|
2127
|
+
$var: -webkit-min-device-pixel-ratio;
|
2128
|
+
$val: 20;
|
2129
|
+
@media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
|
2130
|
+
SCSS
|
2131
|
+
|
2132
|
+
assert_equal <<CSS, render(<<SCSS)
|
2133
|
+
@media screen and (-webkit-min-device-pixel-ratio: 13) {
|
2134
|
+
a: b; }
|
2135
|
+
CSS
|
2136
|
+
$vals: 1 2 3;
|
2137
|
+
@media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
|
2138
|
+
SCSS
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
def test_media_interpolation_with_reparse
|
2142
|
+
assert_equal <<CSS, render(<<SCSS)
|
2143
|
+
@media screen and (max-width: 300px) {
|
2144
|
+
a: b; }
|
2145
|
+
@media screen and (max-width: 300px) {
|
2146
|
+
a: b; }
|
2147
|
+
@media screen and (max-width: 300px) {
|
2148
|
+
a: b; }
|
2149
|
+
@media screen and (max-width: 300px), print and (max-width: 300px) {
|
2150
|
+
a: b; }
|
2151
|
+
CSS
|
2152
|
+
$constraint: "(max-width: 300px)";
|
2153
|
+
$fragment: "nd \#{$constraint}";
|
2154
|
+
$comma: "een, pri";
|
2155
|
+
@media screen and \#{$constraint} {a: b}
|
2156
|
+
@media screen {
|
2157
|
+
@media \#{$constraint} {a: b}
|
2158
|
+
}
|
2159
|
+
@media screen a\#{$fragment} {a: b}
|
2160
|
+
@media scr\#{$comma}nt {
|
2161
|
+
@media \#{$constraint} {a: b}
|
2162
|
+
}
|
2163
|
+
SCSS
|
2164
|
+
end
|
2165
|
+
|
2166
|
+
def test_moz_document_interpolation
|
2167
|
+
assert_equal <<CSS, render(<<SCSS)
|
2168
|
+
@-moz-document url(http://sass-lang.com/),
|
2169
|
+
url-prefix(http://sass-lang.com/docs),
|
2170
|
+
domain(sass-lang.com),
|
2171
|
+
domain("sass-lang.com") {
|
2172
|
+
.foo {
|
2173
|
+
a: b; } }
|
2174
|
+
CSS
|
2175
|
+
$domain: "sass-lang.com";
|
2176
|
+
@-moz-document url(http://\#{$domain}/),
|
2177
|
+
url-prefix(http://\#{$domain}/docs),
|
2178
|
+
domain(\#{$domain}),
|
2179
|
+
\#{domain($domain)} {
|
2180
|
+
.foo {a: b}
|
2181
|
+
}
|
2182
|
+
SCSS
|
2183
|
+
end
|
2184
|
+
|
2185
|
+
def test_supports_with_expressions
|
2186
|
+
assert_equal <<CSS, render(<<SCSS)
|
2187
|
+
@supports (feature1: val) and (feature2: val) or (not (feature23: val4)) {
|
2188
|
+
foo {
|
2189
|
+
a: b; } }
|
2190
|
+
CSS
|
2191
|
+
$query: "(feature1: val)";
|
2192
|
+
$feature: feature2;
|
2193
|
+
$val: val;
|
2194
|
+
@supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
|
2195
|
+
foo {a: b}
|
2196
|
+
}
|
2197
|
+
SCSS
|
2198
|
+
end
|
2199
|
+
|
2200
|
+
def test_supports_bubbling
|
2201
|
+
assert_equal <<CSS, render(<<SCSS)
|
2202
|
+
@supports (foo: bar) {
|
2203
|
+
a {
|
2204
|
+
b: c; }
|
2205
|
+
@supports (baz: bang) {
|
2206
|
+
a {
|
2207
|
+
d: e; } } }
|
2208
|
+
CSS
|
2209
|
+
a {
|
2210
|
+
@supports (foo: bar) {
|
2211
|
+
b: c;
|
2212
|
+
@supports (baz: bang) {
|
2213
|
+
d: e;
|
2214
|
+
}
|
2215
|
+
}
|
2216
|
+
}
|
2217
|
+
SCSS
|
2218
|
+
end
|
2219
|
+
|
2220
|
+
def test_random_directive_interpolation
|
2221
|
+
assert_equal <<CSS, render(<<SCSS)
|
2222
|
+
@foo url(http://sass-lang.com/),
|
2223
|
+
domain("sass-lang.com"),
|
2224
|
+
"foobarbaz",
|
2225
|
+
foobarbaz {
|
2226
|
+
.foo {
|
2227
|
+
a: b; } }
|
2228
|
+
CSS
|
2229
|
+
$domain: "sass-lang.com";
|
2230
|
+
@foo url(http://\#{$domain}/),
|
2231
|
+
\#{domain($domain)},
|
2232
|
+
"foo\#{'ba' + 'r'}baz",
|
2233
|
+
foo\#{'ba' + 'r'}baz {
|
2234
|
+
.foo {a: b}
|
2235
|
+
}
|
2236
|
+
SCSS
|
2237
|
+
end
|
2238
|
+
|
2239
|
+
def test_color_interpolation_warning_in_selector
|
2240
|
+
assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
|
2241
|
+
WARNING on line 1, column 4 of #{filename_for_test(:scss)}:
|
2242
|
+
You probably don't mean to use the color value `blue' in interpolation here.
|
2243
|
+
It may end up represented as #0000ff, which will likely produce invalid CSS.
|
2244
|
+
Always quote color names when using them as strings (for example, "blue").
|
2245
|
+
If you really want to use the color value here, use `"" + blue'.
|
2246
|
+
WARNING
|
2247
|
+
fooblue {
|
2248
|
+
a: b; }
|
2249
|
+
CSS
|
2250
|
+
foo\#{blue} {a: b}
|
2251
|
+
SCSS
|
2252
|
+
end
|
2253
|
+
|
2254
|
+
def test_color_interpolation_warning_in_directive
|
2255
|
+
assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
|
2256
|
+
WARNING on line 1, column 12 of #{filename_for_test(:scss)}:
|
2257
|
+
You probably don't mean to use the color value `blue' in interpolation here.
|
2258
|
+
It may end up represented as #0000ff, which will likely produce invalid CSS.
|
2259
|
+
Always quote color names when using them as strings (for example, "blue").
|
2260
|
+
If you really want to use the color value here, use `"" + blue'.
|
2261
|
+
WARNING
|
2262
|
+
@fblthp fooblue {
|
2263
|
+
a: b; }
|
2264
|
+
CSS
|
2265
|
+
@fblthp foo\#{blue} {a: b}
|
2266
|
+
SCSS
|
2267
|
+
end
|
2268
|
+
|
2269
|
+
def test_color_interpolation_warning_in_property_name
|
2270
|
+
assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
|
2271
|
+
WARNING on line 1, column 8 of #{filename_for_test(:scss)}:
|
2272
|
+
You probably don't mean to use the color value `blue' in interpolation here.
|
2273
|
+
It may end up represented as #0000ff, which will likely produce invalid CSS.
|
2274
|
+
Always quote color names when using them as strings (for example, "blue").
|
2275
|
+
If you really want to use the color value here, use `"" + blue'.
|
2276
|
+
WARNING
|
2277
|
+
foo {
|
2278
|
+
a-blue: b; }
|
2279
|
+
CSS
|
2280
|
+
foo {a-\#{blue}: b}
|
2281
|
+
SCSS
|
2282
|
+
end
|
2283
|
+
|
2284
|
+
def test_no_color_interpolation_warning_in_property_value
|
2285
|
+
assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
|
2286
|
+
foo {
|
2287
|
+
a: b-blue; }
|
2288
|
+
CSS
|
2289
|
+
foo {a: b-\#{blue}}
|
2290
|
+
SCSS
|
2291
|
+
end
|
2292
|
+
|
2293
|
+
def test_no_color_interpolation_warning_for_nameless_color
|
2294
|
+
assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
|
2295
|
+
foo-#abcdef {
|
2296
|
+
a: b; }
|
2297
|
+
CSS
|
2298
|
+
foo-\#{#abcdef} {a: b}
|
2299
|
+
SCSS
|
2300
|
+
end
|
2301
|
+
|
2302
|
+
def test_nested_mixin_def
|
2303
|
+
assert_equal <<CSS, render(<<SCSS)
|
2304
|
+
foo {
|
2305
|
+
a: b; }
|
2306
|
+
CSS
|
2307
|
+
foo {
|
2308
|
+
@mixin bar {a: b}
|
2309
|
+
@include bar; }
|
2310
|
+
SCSS
|
2311
|
+
end
|
2312
|
+
|
2313
|
+
def test_nested_mixin_shadow
|
2314
|
+
assert_equal <<CSS, render(<<SCSS)
|
2315
|
+
foo {
|
2316
|
+
c: d; }
|
2317
|
+
|
2318
|
+
baz {
|
2319
|
+
a: b; }
|
2320
|
+
CSS
|
2321
|
+
@mixin bar {a: b}
|
2322
|
+
|
2323
|
+
foo {
|
2324
|
+
@mixin bar {c: d}
|
2325
|
+
@include bar;
|
2326
|
+
}
|
2327
|
+
|
2328
|
+
baz {@include bar}
|
2329
|
+
SCSS
|
2330
|
+
end
|
2331
|
+
|
2332
|
+
def test_nested_function_def
|
2333
|
+
assert_equal <<CSS, render(<<SCSS)
|
2334
|
+
foo {
|
2335
|
+
a: 1; }
|
2336
|
+
|
2337
|
+
bar {
|
2338
|
+
b: foo(); }
|
2339
|
+
CSS
|
2340
|
+
foo {
|
2341
|
+
@function foo() {@return 1}
|
2342
|
+
a: foo(); }
|
2343
|
+
|
2344
|
+
bar {b: foo()}
|
2345
|
+
SCSS
|
2346
|
+
end
|
2347
|
+
|
2348
|
+
def test_nested_function_shadow
|
2349
|
+
assert_equal <<CSS, render(<<SCSS)
|
2350
|
+
foo {
|
2351
|
+
a: 2; }
|
2352
|
+
|
2353
|
+
baz {
|
2354
|
+
b: 1; }
|
2355
|
+
CSS
|
2356
|
+
@function foo() {@return 1}
|
2357
|
+
|
2358
|
+
foo {
|
2359
|
+
@function foo() {@return 2}
|
2360
|
+
a: foo();
|
2361
|
+
}
|
2362
|
+
|
2363
|
+
baz {b: foo()}
|
2364
|
+
SCSS
|
2365
|
+
end
|
2366
|
+
|
2367
|
+
## @at-root
|
2368
|
+
|
2369
|
+
def test_simple_at_root
|
2370
|
+
assert_equal <<CSS, render(<<SCSS)
|
2371
|
+
.bar {
|
2372
|
+
a: b; }
|
2373
|
+
CSS
|
2374
|
+
.foo {
|
2375
|
+
@at-root {
|
2376
|
+
.bar {a: b}
|
2377
|
+
}
|
2378
|
+
}
|
2379
|
+
SCSS
|
2380
|
+
end
|
2381
|
+
|
2382
|
+
def test_at_root_with_selector
|
2383
|
+
assert_equal <<CSS, render(<<SCSS)
|
2384
|
+
.bar {
|
2385
|
+
a: b; }
|
2386
|
+
CSS
|
2387
|
+
.foo {
|
2388
|
+
@at-root .bar {a: b}
|
2389
|
+
}
|
2390
|
+
SCSS
|
2391
|
+
end
|
2392
|
+
|
2393
|
+
def test_at_root_in_mixin
|
2394
|
+
assert_equal <<CSS, render(<<SCSS)
|
2395
|
+
.bar {
|
2396
|
+
a: b; }
|
2397
|
+
CSS
|
2398
|
+
@mixin bar {
|
2399
|
+
@at-root .bar {a: b}
|
2400
|
+
}
|
2401
|
+
|
2402
|
+
.foo {
|
2403
|
+
@include bar;
|
2404
|
+
}
|
2405
|
+
SCSS
|
2406
|
+
end
|
2407
|
+
|
2408
|
+
def test_at_root_in_media
|
2409
|
+
assert_equal <<CSS, render(<<SCSS)
|
2410
|
+
@media screen {
|
2411
|
+
.bar {
|
2412
|
+
a: b; } }
|
2413
|
+
CSS
|
2414
|
+
@media screen {
|
2415
|
+
.foo {
|
2416
|
+
@at-root .bar {a: b}
|
2417
|
+
}
|
2418
|
+
}
|
2419
|
+
SCSS
|
2420
|
+
end
|
2421
|
+
|
2422
|
+
def test_at_root_in_bubbled_media
|
2423
|
+
assert_equal <<CSS, render(<<SCSS)
|
2424
|
+
@media screen {
|
2425
|
+
.bar {
|
2426
|
+
a: b; } }
|
2427
|
+
CSS
|
2428
|
+
.foo {
|
2429
|
+
@media screen {
|
2430
|
+
@at-root .bar {a: b}
|
2431
|
+
}
|
2432
|
+
}
|
2433
|
+
SCSS
|
2434
|
+
end
|
2435
|
+
|
2436
|
+
def test_at_root_in_unknown_directive
|
2437
|
+
assert_equal <<CSS, render(<<SCSS)
|
2438
|
+
@fblthp {
|
2439
|
+
.bar {
|
2440
|
+
a: b; } }
|
2441
|
+
CSS
|
2442
|
+
@fblthp {
|
2443
|
+
.foo {
|
2444
|
+
@at-root .bar {a: b}
|
2445
|
+
}
|
2446
|
+
}
|
2447
|
+
SCSS
|
2448
|
+
end
|
2449
|
+
|
2450
|
+
def test_comments_in_at_root
|
2451
|
+
assert_equal <<CSS, render(<<SCSS)
|
2452
|
+
/* foo */
|
2453
|
+
.bar {
|
2454
|
+
a: b; }
|
2455
|
+
|
2456
|
+
/* baz */
|
2457
|
+
CSS
|
2458
|
+
.foo {
|
2459
|
+
@at-root {
|
2460
|
+
/* foo */
|
2461
|
+
.bar {a: b}
|
2462
|
+
/* baz */
|
2463
|
+
}
|
2464
|
+
}
|
2465
|
+
SCSS
|
2466
|
+
end
|
2467
|
+
|
2468
|
+
def test_comments_in_at_root_in_media
|
2469
|
+
assert_equal <<CSS, render(<<SCSS)
|
2470
|
+
@media screen {
|
2471
|
+
/* foo */
|
2472
|
+
.bar {
|
2473
|
+
a: b; }
|
2474
|
+
|
2475
|
+
/* baz */ }
|
2476
|
+
CSS
|
2477
|
+
@media screen {
|
2478
|
+
.foo {
|
2479
|
+
@at-root {
|
2480
|
+
/* foo */
|
2481
|
+
.bar {a: b}
|
2482
|
+
/* baz */
|
2483
|
+
}
|
2484
|
+
}
|
2485
|
+
}
|
2486
|
+
SCSS
|
2487
|
+
end
|
2488
|
+
|
2489
|
+
def test_comments_in_at_root_in_unknown_directive
|
2490
|
+
assert_equal <<CSS, render(<<SCSS)
|
2491
|
+
@fblthp {
|
2492
|
+
/* foo */
|
2493
|
+
.bar {
|
2494
|
+
a: b; }
|
2495
|
+
|
2496
|
+
/* baz */ }
|
2497
|
+
CSS
|
2498
|
+
@fblthp {
|
2499
|
+
.foo {
|
2500
|
+
@at-root {
|
2501
|
+
/* foo */
|
2502
|
+
.bar {a: b}
|
2503
|
+
/* baz */
|
2504
|
+
}
|
2505
|
+
}
|
2506
|
+
}
|
2507
|
+
SCSS
|
2508
|
+
end
|
2509
|
+
|
2510
|
+
def test_media_directive_in_at_root
|
2511
|
+
assert_equal <<CSS, render(<<SCSS)
|
2512
|
+
@media screen {
|
2513
|
+
.bar {
|
2514
|
+
a: b; } }
|
2515
|
+
CSS
|
2516
|
+
.foo {
|
2517
|
+
@at-root {
|
2518
|
+
@media screen {.bar {a: b}}
|
2519
|
+
}
|
2520
|
+
}
|
2521
|
+
SCSS
|
2522
|
+
end
|
2523
|
+
|
2524
|
+
def test_bubbled_media_directive_in_at_root
|
2525
|
+
assert_equal <<CSS, render(<<SCSS)
|
2526
|
+
@media screen {
|
2527
|
+
.bar .baz {
|
2528
|
+
a: b; } }
|
2529
|
+
CSS
|
2530
|
+
.foo {
|
2531
|
+
@at-root {
|
2532
|
+
.bar {
|
2533
|
+
@media screen {.baz {a: b}}
|
2534
|
+
}
|
2535
|
+
}
|
2536
|
+
}
|
2537
|
+
SCSS
|
2538
|
+
end
|
2539
|
+
|
2540
|
+
def test_unknown_directive_in_at_root
|
2541
|
+
assert_equal <<CSS, render(<<SCSS)
|
2542
|
+
@fblthp {
|
2543
|
+
.bar {
|
2544
|
+
a: b; } }
|
2545
|
+
CSS
|
2546
|
+
.foo {
|
2547
|
+
@at-root {
|
2548
|
+
@fblthp {.bar {a: b}}
|
2549
|
+
}
|
2550
|
+
}
|
2551
|
+
SCSS
|
2552
|
+
end
|
2553
|
+
|
2554
|
+
def test_at_root_in_at_root
|
2555
|
+
assert_equal <<CSS, render(<<SCSS)
|
2556
|
+
.bar {
|
2557
|
+
a: b; }
|
2558
|
+
CSS
|
2559
|
+
.foo {
|
2560
|
+
@at-root {
|
2561
|
+
@at-root .bar {a: b}
|
2562
|
+
}
|
2563
|
+
}
|
2564
|
+
SCSS
|
2565
|
+
end
|
2566
|
+
|
2567
|
+
def test_at_root_with_parent_ref
|
2568
|
+
assert_equal <<CSS, render(<<SCSS)
|
2569
|
+
.foo {
|
2570
|
+
a: b; }
|
2571
|
+
CSS
|
2572
|
+
.foo {
|
2573
|
+
@at-root & {
|
2574
|
+
a: b;
|
2575
|
+
}
|
2576
|
+
}
|
2577
|
+
SCSS
|
2578
|
+
end
|
2579
|
+
|
2580
|
+
def test_multi_level_at_root_with_parent_ref
|
2581
|
+
assert_equal <<CSS, render(<<SCSS)
|
2582
|
+
.foo .bar {
|
2583
|
+
a: b; }
|
2584
|
+
CSS
|
2585
|
+
.foo {
|
2586
|
+
@at-root & {
|
2587
|
+
.bar {
|
2588
|
+
@at-root & {
|
2589
|
+
a: b;
|
2590
|
+
}
|
2591
|
+
}
|
2592
|
+
}
|
2593
|
+
}
|
2594
|
+
SCSS
|
2595
|
+
end
|
2596
|
+
|
2597
|
+
def test_multi_level_at_root_with_inner_parent_ref
|
2598
|
+
assert_equal <<CSS, render(<<SCSS)
|
2599
|
+
.bar {
|
2600
|
+
a: b; }
|
2601
|
+
CSS
|
2602
|
+
.foo {
|
2603
|
+
@at-root .bar {
|
2604
|
+
@at-root & {
|
2605
|
+
a: b;
|
2606
|
+
}
|
2607
|
+
}
|
2608
|
+
}
|
2609
|
+
SCSS
|
2610
|
+
end
|
2611
|
+
|
2612
|
+
def test_at_root_beneath_comma_selector
|
2613
|
+
assert_equal(<<CSS, render(<<SCSS))
|
2614
|
+
.baz {
|
2615
|
+
a: b; }
|
2616
|
+
CSS
|
2617
|
+
.foo, .bar {
|
2618
|
+
@at-root .baz {
|
2619
|
+
a: b;
|
2620
|
+
}
|
2621
|
+
}
|
2622
|
+
SCSS
|
2623
|
+
end
|
2624
|
+
|
2625
|
+
def test_at_root_with_parent_ref_and_class
|
2626
|
+
assert_equal(<<CSS, render(<<SCSS))
|
2627
|
+
.foo.bar {
|
2628
|
+
a: b; }
|
2629
|
+
CSS
|
2630
|
+
.foo {
|
2631
|
+
@at-root &.bar {
|
2632
|
+
a: b;
|
2633
|
+
}
|
2634
|
+
}
|
2635
|
+
SCSS
|
2636
|
+
end
|
2637
|
+
|
2638
|
+
def test_at_root_beneath_comma_selector_with_parent_ref
|
2639
|
+
assert_equal(<<CSS, render(<<SCSS))
|
2640
|
+
.foo.baz, .bar.baz {
|
2641
|
+
a: b; }
|
2642
|
+
CSS
|
2643
|
+
.foo, .bar {
|
2644
|
+
@at-root &.baz {
|
2645
|
+
a: b;
|
2646
|
+
}
|
2647
|
+
}
|
2648
|
+
SCSS
|
2649
|
+
end
|
2650
|
+
|
2651
|
+
## @at-root (...)
|
2652
|
+
|
2653
|
+
def test_at_root_without_media
|
2654
|
+
assert_equal <<CSS, render(<<SCSS)
|
2655
|
+
.foo .bar {
|
2656
|
+
a: b; }
|
2657
|
+
CSS
|
2658
|
+
.foo {
|
2659
|
+
@media screen {
|
2660
|
+
@at-root (without: media) {
|
2661
|
+
.bar {
|
2662
|
+
a: b;
|
2663
|
+
}
|
2664
|
+
}
|
2665
|
+
}
|
2666
|
+
}
|
2667
|
+
SCSS
|
2668
|
+
end
|
2669
|
+
|
2670
|
+
def test_at_root_without_supports
|
2671
|
+
assert_equal <<CSS, render(<<SCSS)
|
2672
|
+
.foo .bar {
|
2673
|
+
a: b; }
|
2674
|
+
CSS
|
2675
|
+
.foo {
|
2676
|
+
@supports (foo: bar) {
|
2677
|
+
@at-root (without: supports) {
|
2678
|
+
.bar {
|
2679
|
+
a: b;
|
2680
|
+
}
|
2681
|
+
}
|
2682
|
+
}
|
2683
|
+
}
|
2684
|
+
SCSS
|
2685
|
+
end
|
2686
|
+
|
2687
|
+
def test_at_root_without_rule
|
2688
|
+
assert_equal <<CSS, render(<<SCSS)
|
2689
|
+
@media screen {
|
2690
|
+
.bar {
|
2691
|
+
a: b; } }
|
2692
|
+
CSS
|
2693
|
+
.foo {
|
2694
|
+
@media screen {
|
2695
|
+
@at-root (without: rule) {
|
2696
|
+
.bar {
|
2697
|
+
a: b;
|
2698
|
+
}
|
2699
|
+
}
|
2700
|
+
}
|
2701
|
+
}
|
2702
|
+
SCSS
|
2703
|
+
end
|
2704
|
+
|
2705
|
+
def test_at_root_without_unknown_directive
|
2706
|
+
assert_equal <<CSS, render(<<SCSS)
|
2707
|
+
@fblthp {}
|
2708
|
+
.foo .bar {
|
2709
|
+
a: b; }
|
2710
|
+
CSS
|
2711
|
+
.foo {
|
2712
|
+
@fblthp {
|
2713
|
+
@at-root (without: fblthp) {
|
2714
|
+
.bar {
|
2715
|
+
a: b;
|
2716
|
+
}
|
2717
|
+
}
|
2718
|
+
}
|
2719
|
+
}
|
2720
|
+
SCSS
|
2721
|
+
end
|
2722
|
+
|
2723
|
+
def test_at_root_without_multiple
|
2724
|
+
assert_equal <<CSS, render(<<SCSS)
|
2725
|
+
@supports (foo: bar) {
|
2726
|
+
.bar {
|
2727
|
+
a: b; } }
|
2728
|
+
CSS
|
2729
|
+
.foo {
|
2730
|
+
@media screen {
|
2731
|
+
@supports (foo: bar) {
|
2732
|
+
@at-root (without: media rule) {
|
2733
|
+
.bar {
|
2734
|
+
a: b;
|
2735
|
+
}
|
2736
|
+
}
|
2737
|
+
}
|
2738
|
+
}
|
2739
|
+
}
|
2740
|
+
SCSS
|
2741
|
+
end
|
2742
|
+
|
2743
|
+
def test_at_root_without_all
|
2744
|
+
assert_equal <<CSS, render(<<SCSS)
|
2745
|
+
@supports (foo: bar) {
|
2746
|
+
@fblthp {} }
|
2747
|
+
.bar {
|
2748
|
+
a: b; }
|
2749
|
+
CSS
|
2750
|
+
.foo {
|
2751
|
+
@supports (foo: bar) {
|
2752
|
+
@fblthp {
|
2753
|
+
@at-root (without: all) {
|
2754
|
+
.bar {
|
2755
|
+
a: b;
|
2756
|
+
}
|
2757
|
+
}
|
2758
|
+
}
|
2759
|
+
}
|
2760
|
+
}
|
2761
|
+
SCSS
|
2762
|
+
end
|
2763
|
+
|
2764
|
+
def test_at_root_with_media
|
2765
|
+
assert_equal <<CSS, render(<<SCSS)
|
2766
|
+
@media screen {
|
2767
|
+
@fblthp {}
|
2768
|
+
.bar {
|
2769
|
+
a: b; } }
|
2770
|
+
CSS
|
2771
|
+
.foo {
|
2772
|
+
@media screen {
|
2773
|
+
@fblthp {
|
2774
|
+
@supports (foo: bar) {
|
2775
|
+
@at-root (with: media) {
|
2776
|
+
.bar {
|
2777
|
+
a: b;
|
2778
|
+
}
|
2779
|
+
}
|
2780
|
+
}
|
2781
|
+
}
|
2782
|
+
}
|
2783
|
+
}
|
2784
|
+
SCSS
|
2785
|
+
end
|
2786
|
+
|
2787
|
+
def test_at_root_with_rule
|
2788
|
+
assert_equal <<CSS, render(<<SCSS)
|
2789
|
+
@media screen {
|
2790
|
+
@fblthp {} }
|
2791
|
+
.foo .bar {
|
2792
|
+
a: b; }
|
2793
|
+
CSS
|
2794
|
+
.foo {
|
2795
|
+
@media screen {
|
2796
|
+
@fblthp {
|
2797
|
+
@supports (foo: bar) {
|
2798
|
+
@at-root (with: rule) {
|
2799
|
+
.bar {
|
2800
|
+
a: b;
|
2801
|
+
}
|
2802
|
+
}
|
2803
|
+
}
|
2804
|
+
}
|
2805
|
+
}
|
2806
|
+
}
|
2807
|
+
SCSS
|
2808
|
+
end
|
2809
|
+
|
2810
|
+
def test_at_root_with_supports
|
2811
|
+
assert_equal <<CSS, render(<<SCSS)
|
2812
|
+
@media screen {
|
2813
|
+
@fblthp {} }
|
2814
|
+
@supports (foo: bar) {
|
2815
|
+
.bar {
|
2816
|
+
a: b; } }
|
2817
|
+
CSS
|
2818
|
+
.foo {
|
2819
|
+
@media screen {
|
2820
|
+
@fblthp {
|
2821
|
+
@supports (foo: bar) {
|
2822
|
+
@at-root (with: supports) {
|
2823
|
+
.bar {
|
2824
|
+
a: b;
|
2825
|
+
}
|
2826
|
+
}
|
2827
|
+
}
|
2828
|
+
}
|
2829
|
+
}
|
2830
|
+
}
|
2831
|
+
SCSS
|
2832
|
+
end
|
2833
|
+
|
2834
|
+
def test_at_root_with_unknown_directive
|
2835
|
+
assert_equal <<CSS, render(<<SCSS)
|
2836
|
+
@media screen {
|
2837
|
+
@fblthp {} }
|
2838
|
+
@fblthp {
|
2839
|
+
.bar {
|
2840
|
+
a: b; } }
|
2841
|
+
CSS
|
2842
|
+
.foo {
|
2843
|
+
@media screen {
|
2844
|
+
@fblthp {
|
2845
|
+
@supports (foo: bar) {
|
2846
|
+
@at-root (with: fblthp) {
|
2847
|
+
.bar {
|
2848
|
+
a: b;
|
2849
|
+
}
|
2850
|
+
}
|
2851
|
+
}
|
2852
|
+
}
|
2853
|
+
}
|
2854
|
+
}
|
2855
|
+
SCSS
|
2856
|
+
end
|
2857
|
+
|
2858
|
+
def test_at_root_with_multiple
|
2859
|
+
assert_equal <<CSS, render(<<SCSS)
|
2860
|
+
@media screen {
|
2861
|
+
@fblthp {}
|
2862
|
+
.foo .bar {
|
2863
|
+
a: b; } }
|
2864
|
+
CSS
|
2865
|
+
.foo {
|
2866
|
+
@media screen {
|
2867
|
+
@fblthp {
|
2868
|
+
@supports (foo: bar) {
|
2869
|
+
@at-root (with: media rule) {
|
2870
|
+
.bar {
|
2871
|
+
a: b;
|
2872
|
+
}
|
2873
|
+
}
|
2874
|
+
}
|
2875
|
+
}
|
2876
|
+
}
|
2877
|
+
}
|
2878
|
+
SCSS
|
2879
|
+
end
|
2880
|
+
|
2881
|
+
def test_at_root_with_all
|
2882
|
+
assert_equal <<CSS, render(<<SCSS)
|
2883
|
+
@media screen {
|
2884
|
+
@fblthp {
|
2885
|
+
@supports (foo: bar) {
|
2886
|
+
.foo .bar {
|
2887
|
+
a: b; } } } }
|
2888
|
+
CSS
|
2889
|
+
.foo {
|
2890
|
+
@media screen {
|
2891
|
+
@fblthp {
|
2892
|
+
@supports (foo: bar) {
|
2893
|
+
@at-root (with: all) {
|
2894
|
+
.bar {
|
2895
|
+
a: b;
|
2896
|
+
}
|
2897
|
+
}
|
2898
|
+
}
|
2899
|
+
}
|
2900
|
+
}
|
2901
|
+
}
|
2902
|
+
SCSS
|
2903
|
+
end
|
2904
|
+
|
2905
|
+
def test_at_root_dynamic_values
|
2906
|
+
assert_equal <<CSS, render(<<SCSS)
|
2907
|
+
@media screen {
|
2908
|
+
.bar {
|
2909
|
+
a: b; } }
|
2910
|
+
CSS
|
2911
|
+
$key: with;
|
2912
|
+
$value: media;
|
2913
|
+
.foo {
|
2914
|
+
@media screen {
|
2915
|
+
@at-root ($key: $value) {
|
2916
|
+
.bar {
|
2917
|
+
a: b;
|
2918
|
+
}
|
2919
|
+
}
|
2920
|
+
}
|
2921
|
+
}
|
2922
|
+
SCSS
|
2923
|
+
end
|
2924
|
+
|
2925
|
+
def test_at_root_interpolated_query
|
2926
|
+
assert_equal <<CSS, render(<<SCSS)
|
2927
|
+
@media screen {
|
2928
|
+
.bar {
|
2929
|
+
a: b; } }
|
2930
|
+
CSS
|
2931
|
+
.foo {
|
2932
|
+
@media screen {
|
2933
|
+
@at-root (\#{"with: media"}) {
|
2934
|
+
.bar {
|
2935
|
+
a: b;
|
2936
|
+
}
|
2937
|
+
}
|
2938
|
+
}
|
2939
|
+
}
|
2940
|
+
SCSS
|
2941
|
+
end
|
2942
|
+
|
2943
|
+
def test_at_root_plus_extend
|
2944
|
+
assert_equal <<CSS, render(<<SCSS)
|
2945
|
+
.foo .bar {
|
2946
|
+
a: b; }
|
2947
|
+
CSS
|
2948
|
+
%base {
|
2949
|
+
a: b;
|
2950
|
+
}
|
2951
|
+
|
2952
|
+
.foo {
|
2953
|
+
@media screen {
|
2954
|
+
@at-root (without: media) {
|
2955
|
+
.bar {
|
2956
|
+
@extend %base;
|
2957
|
+
}
|
2958
|
+
}
|
2959
|
+
}
|
2960
|
+
}
|
2961
|
+
SCSS
|
2962
|
+
end
|
2963
|
+
|
2964
|
+
def test_at_root_without_keyframes_in_keyframe_rule
|
2965
|
+
assert_equal <<CSS, render(<<SCSS)
|
2966
|
+
.foo {
|
2967
|
+
a: b; }
|
2968
|
+
CSS
|
2969
|
+
@keyframes identifier {
|
2970
|
+
0% {
|
2971
|
+
@at-root (without: keyframes) {
|
2972
|
+
.foo {a: b}
|
2973
|
+
}
|
2974
|
+
}
|
2975
|
+
}
|
2976
|
+
SCSS
|
2977
|
+
end
|
2978
|
+
|
2979
|
+
def test_at_root_without_rule_in_keyframe_rule
|
2980
|
+
assert_equal <<CSS, render(<<SCSS)
|
2981
|
+
@keyframes identifier {
|
2982
|
+
0% {
|
2983
|
+
a: b; } }
|
2984
|
+
CSS
|
2985
|
+
@keyframes identifier {
|
2986
|
+
0% {
|
2987
|
+
@at-root (without: rule) {a: b}
|
2988
|
+
}
|
2989
|
+
}
|
2990
|
+
SCSS
|
2991
|
+
end
|
2992
|
+
|
2993
|
+
## Selector Script
|
2994
|
+
|
2995
|
+
def test_selector_script
|
2996
|
+
assert_equal(<<CSS, render(<<SCSS))
|
2997
|
+
.foo .bar {
|
2998
|
+
content: ".foo .bar"; }
|
2999
|
+
CSS
|
3000
|
+
.foo .bar {
|
3001
|
+
content: "\#{&}";
|
3002
|
+
}
|
3003
|
+
SCSS
|
3004
|
+
end
|
3005
|
+
|
3006
|
+
def test_nested_selector_script
|
3007
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3008
|
+
.foo .bar {
|
3009
|
+
content: ".foo .bar"; }
|
3010
|
+
CSS
|
3011
|
+
.foo {
|
3012
|
+
.bar {
|
3013
|
+
content: "\#{&}";
|
3014
|
+
}
|
3015
|
+
}
|
3016
|
+
SCSS
|
3017
|
+
end
|
3018
|
+
|
3019
|
+
def test_nested_selector_script_with_outer_comma_selector
|
3020
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3021
|
+
.foo .baz, .bar .baz {
|
3022
|
+
content: ".foo .baz, .bar .baz"; }
|
3023
|
+
CSS
|
3024
|
+
.foo, .bar {
|
3025
|
+
.baz {
|
3026
|
+
content: "\#{&}";
|
3027
|
+
}
|
3028
|
+
}
|
3029
|
+
SCSS
|
3030
|
+
end
|
3031
|
+
|
3032
|
+
def test_nested_selector_script_with_inner_comma_selector
|
3033
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3034
|
+
.foo .bar, .foo .baz {
|
3035
|
+
content: ".foo .bar, .foo .baz"; }
|
3036
|
+
CSS
|
3037
|
+
.foo {
|
3038
|
+
.bar, .baz {
|
3039
|
+
content: "\#{&}";
|
3040
|
+
}
|
3041
|
+
}
|
3042
|
+
SCSS
|
3043
|
+
end
|
3044
|
+
|
3045
|
+
def test_selector_script_through_mixin
|
3046
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3047
|
+
.foo {
|
3048
|
+
content: ".foo"; }
|
3049
|
+
CSS
|
3050
|
+
@mixin mixin {
|
3051
|
+
content: "\#{&}";
|
3052
|
+
}
|
3053
|
+
|
3054
|
+
.foo {
|
3055
|
+
@include mixin;
|
3056
|
+
}
|
3057
|
+
SCSS
|
3058
|
+
end
|
3059
|
+
|
3060
|
+
def test_selector_script_through_content
|
3061
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3062
|
+
.foo {
|
3063
|
+
content: ".foo"; }
|
3064
|
+
CSS
|
3065
|
+
@mixin mixin {
|
3066
|
+
@content;
|
3067
|
+
}
|
3068
|
+
|
3069
|
+
.foo {
|
3070
|
+
@include mixin {
|
3071
|
+
content: "\#{&}";
|
3072
|
+
}
|
3073
|
+
}
|
3074
|
+
SCSS
|
3075
|
+
end
|
3076
|
+
|
3077
|
+
def test_selector_script_through_function
|
3078
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3079
|
+
.foo {
|
3080
|
+
content: ".foo"; }
|
3081
|
+
CSS
|
3082
|
+
@function fn() {
|
3083
|
+
@return "\#{&}";
|
3084
|
+
}
|
3085
|
+
|
3086
|
+
.foo {
|
3087
|
+
content: fn();
|
3088
|
+
}
|
3089
|
+
SCSS
|
3090
|
+
end
|
3091
|
+
|
3092
|
+
def test_selector_script_through_media
|
3093
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3094
|
+
.foo {
|
3095
|
+
content: "outer"; }
|
3096
|
+
@media screen {
|
3097
|
+
.foo .bar {
|
3098
|
+
content: ".foo .bar"; } }
|
3099
|
+
CSS
|
3100
|
+
.foo {
|
3101
|
+
content: "outer";
|
3102
|
+
@media screen {
|
3103
|
+
.bar {
|
3104
|
+
content: "\#{&}";
|
3105
|
+
}
|
3106
|
+
}
|
3107
|
+
}
|
3108
|
+
SCSS
|
3109
|
+
end
|
3110
|
+
|
3111
|
+
def test_selector_script_save_and_reuse
|
3112
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3113
|
+
.bar {
|
3114
|
+
content: ".foo"; }
|
3115
|
+
CSS
|
3116
|
+
$var: null;
|
3117
|
+
.foo {
|
3118
|
+
$var: & !global;
|
3119
|
+
}
|
3120
|
+
|
3121
|
+
.bar {
|
3122
|
+
content: "\#{$var}";
|
3123
|
+
}
|
3124
|
+
SCSS
|
3125
|
+
end
|
3126
|
+
|
3127
|
+
def test_selector_script_with_at_root
|
3128
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3129
|
+
.foo-bar {
|
3130
|
+
a: b; }
|
3131
|
+
CSS
|
3132
|
+
.foo {
|
3133
|
+
@at-root \#{&}-bar {
|
3134
|
+
a: b;
|
3135
|
+
}
|
3136
|
+
}
|
3137
|
+
SCSS
|
3138
|
+
end
|
3139
|
+
|
3140
|
+
def test_multi_level_at_root_with_inner_selector_script
|
3141
|
+
assert_equal <<CSS, render(<<SCSS)
|
3142
|
+
.bar {
|
3143
|
+
a: b; }
|
3144
|
+
CSS
|
3145
|
+
.foo {
|
3146
|
+
@at-root .bar {
|
3147
|
+
@at-root \#{&} {
|
3148
|
+
a: b;
|
3149
|
+
}
|
3150
|
+
}
|
3151
|
+
}
|
3152
|
+
SCSS
|
3153
|
+
end
|
3154
|
+
|
3155
|
+
def test_at_root_with_at_root_through_mixin
|
3156
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3157
|
+
.bar-baz {
|
3158
|
+
a: b; }
|
3159
|
+
CSS
|
3160
|
+
@mixin foo {
|
3161
|
+
.bar {
|
3162
|
+
@at-root \#{&}-baz {
|
3163
|
+
a: b;
|
3164
|
+
}
|
3165
|
+
}
|
3166
|
+
}
|
3167
|
+
|
3168
|
+
@include foo;
|
3169
|
+
SCSS
|
3170
|
+
end
|
3171
|
+
|
3172
|
+
# See https://github.com/sass/sass/issues/1294
|
3173
|
+
def test_extend_top_leveled_by_at_root
|
3174
|
+
render(<<SCSS)
|
3175
|
+
.span-10 {
|
3176
|
+
@at-root (without: all) {
|
3177
|
+
@extend %column;
|
3178
|
+
}
|
3179
|
+
}
|
3180
|
+
SCSS
|
3181
|
+
|
3182
|
+
assert(false, "Expected syntax error")
|
3183
|
+
rescue Sass::SyntaxError => e
|
3184
|
+
assert_equal "Extend directives may only be used within rules.", e.message
|
3185
|
+
assert_equal 3, e.sass_line
|
3186
|
+
end
|
3187
|
+
|
3188
|
+
def test_at_root_doesnt_always_break_blocks
|
3189
|
+
assert_equal <<CSS, render(<<SCSS)
|
3190
|
+
.foo {
|
3191
|
+
a: b; }
|
3192
|
+
|
3193
|
+
@media screen {
|
3194
|
+
.foo {
|
3195
|
+
c: d; }
|
3196
|
+
.bar {
|
3197
|
+
e: f; } }
|
3198
|
+
CSS
|
3199
|
+
%base {
|
3200
|
+
a: b;
|
3201
|
+
}
|
3202
|
+
|
3203
|
+
@media screen {
|
3204
|
+
.foo {
|
3205
|
+
c: d;
|
3206
|
+
@at-root (without: media) {
|
3207
|
+
@extend %base;
|
3208
|
+
}
|
3209
|
+
}
|
3210
|
+
|
3211
|
+
.bar {e: f}
|
3212
|
+
}
|
3213
|
+
SCSS
|
3214
|
+
end
|
3215
|
+
|
3216
|
+
## Errors
|
3217
|
+
|
3218
|
+
def test_keyframes_rule_outside_of_keyframes
|
3219
|
+
render <<SCSS
|
3220
|
+
0% {
|
3221
|
+
top: 0; }
|
3222
|
+
SCSS
|
3223
|
+
assert(false, "Expected syntax error")
|
3224
|
+
rescue Sass::SyntaxError => e
|
3225
|
+
assert_equal 'Invalid CSS after "": expected selector, was "0%"', e.message
|
3226
|
+
assert_equal 1, e.sass_line
|
3227
|
+
end
|
3228
|
+
|
3229
|
+
def test_selector_rule_in_keyframes
|
3230
|
+
render <<SCSS
|
3231
|
+
@keyframes identifier {
|
3232
|
+
.foo {
|
3233
|
+
top: 0; } }
|
3234
|
+
SCSS
|
3235
|
+
assert(false, "Expected syntax error")
|
3236
|
+
rescue Sass::SyntaxError => e
|
3237
|
+
assert_equal 'Invalid CSS after "": expected keyframes selector (e.g. 10%), was ".foo"', e.message
|
3238
|
+
assert_equal 2, e.sass_line
|
3239
|
+
end
|
3240
|
+
|
3241
|
+
def test_nested_mixin_def_is_scoped
|
3242
|
+
render <<SCSS
|
3243
|
+
foo {
|
3244
|
+
@mixin bar {a: b}}
|
3245
|
+
bar {@include bar}
|
3246
|
+
SCSS
|
3247
|
+
assert(false, "Expected syntax error")
|
3248
|
+
rescue Sass::SyntaxError => e
|
3249
|
+
assert_equal "Undefined mixin 'bar'.", e.message
|
3250
|
+
assert_equal 3, e.sass_line
|
3251
|
+
end
|
3252
|
+
|
3253
|
+
def test_rules_beneath_properties
|
3254
|
+
render <<SCSS
|
3255
|
+
foo {
|
3256
|
+
bar: {
|
3257
|
+
baz {
|
3258
|
+
bang: bop }}}
|
3259
|
+
SCSS
|
3260
|
+
assert(false, "Expected syntax error")
|
3261
|
+
rescue Sass::SyntaxError => e
|
3262
|
+
assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message
|
3263
|
+
assert_equal 3, e.sass_line
|
3264
|
+
end
|
3265
|
+
|
3266
|
+
def test_uses_property_exception_with_star_hack
|
3267
|
+
render <<SCSS
|
3268
|
+
foo {
|
3269
|
+
*bar:baz [fail]; }
|
3270
|
+
SCSS
|
3271
|
+
assert(false, "Expected syntax error")
|
3272
|
+
rescue Sass::SyntaxError => e
|
3273
|
+
assert_equal 'Invalid CSS after " *bar:baz ": expected ";", was "[fail]; }"', e.message
|
3274
|
+
assert_equal 2, e.sass_line
|
3275
|
+
end
|
3276
|
+
|
3277
|
+
def test_uses_property_exception_with_colon_hack
|
3278
|
+
render <<SCSS
|
3279
|
+
foo {
|
3280
|
+
:bar:baz [fail]; }
|
3281
|
+
SCSS
|
3282
|
+
assert(false, "Expected syntax error")
|
3283
|
+
rescue Sass::SyntaxError => e
|
3284
|
+
assert_equal 'Invalid CSS after " :bar:baz ": expected ";", was "[fail]; }"', e.message
|
3285
|
+
assert_equal 2, e.sass_line
|
3286
|
+
end
|
3287
|
+
|
3288
|
+
def test_uses_rule_exception_with_dot_hack
|
3289
|
+
render <<SCSS
|
3290
|
+
foo {
|
3291
|
+
.bar:baz <fail>; }
|
3292
|
+
SCSS
|
3293
|
+
assert(false, "Expected syntax error")
|
3294
|
+
rescue Sass::SyntaxError => e
|
3295
|
+
assert_equal 'Invalid CSS after " .bar:baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
|
3296
|
+
assert_equal 2, e.sass_line
|
3297
|
+
end
|
3298
|
+
|
3299
|
+
def test_uses_property_exception_with_space_after_name
|
3300
|
+
render <<SCSS
|
3301
|
+
foo {
|
3302
|
+
bar: baz [fail]; }
|
3303
|
+
SCSS
|
3304
|
+
assert(false, "Expected syntax error")
|
3305
|
+
rescue Sass::SyntaxError => e
|
3306
|
+
assert_equal 'Invalid CSS after " bar: baz ": expected ";", was "[fail]; }"', e.message
|
3307
|
+
assert_equal 2, e.sass_line
|
3308
|
+
end
|
3309
|
+
|
3310
|
+
def test_uses_property_exception_with_non_identifier_after_name
|
3311
|
+
render <<SCSS
|
3312
|
+
foo {
|
3313
|
+
bar:1px [fail]; }
|
3314
|
+
SCSS
|
3315
|
+
assert(false, "Expected syntax error")
|
3316
|
+
rescue Sass::SyntaxError => e
|
3317
|
+
assert_equal 'Invalid CSS after " bar:1px ": expected ";", was "[fail]; }"', e.message
|
3318
|
+
assert_equal 2, e.sass_line
|
3319
|
+
end
|
3320
|
+
|
3321
|
+
def test_uses_property_exception_when_followed_by_open_bracket
|
3322
|
+
render <<SCSS
|
3323
|
+
foo {
|
3324
|
+
bar:{baz: .fail} }
|
3325
|
+
SCSS
|
3326
|
+
assert(false, "Expected syntax error")
|
3327
|
+
rescue Sass::SyntaxError => e
|
3328
|
+
assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message
|
3329
|
+
assert_equal 2, e.sass_line
|
3330
|
+
end
|
3331
|
+
|
3332
|
+
def test_script_error
|
3333
|
+
render <<SCSS
|
3334
|
+
foo {
|
3335
|
+
bar: "baz" * * }
|
3336
|
+
SCSS
|
3337
|
+
assert(false, "Expected syntax error")
|
3338
|
+
rescue Sass::SyntaxError => e
|
3339
|
+
assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
|
3340
|
+
assert_equal 2, e.sass_line
|
3341
|
+
end
|
3342
|
+
|
3343
|
+
def test_multiline_script_syntax_error
|
3344
|
+
render <<SCSS
|
3345
|
+
foo {
|
3346
|
+
bar:
|
3347
|
+
"baz" * * }
|
3348
|
+
SCSS
|
3349
|
+
assert(false, "Expected syntax error")
|
3350
|
+
rescue Sass::SyntaxError => e
|
3351
|
+
assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
|
3352
|
+
assert_equal 3, e.sass_line
|
3353
|
+
end
|
3354
|
+
|
3355
|
+
def test_multiline_script_runtime_error
|
3356
|
+
render <<SCSS
|
3357
|
+
foo {
|
3358
|
+
bar: "baz" +
|
3359
|
+
"bar" +
|
3360
|
+
$bang }
|
3361
|
+
SCSS
|
3362
|
+
assert(false, "Expected syntax error")
|
3363
|
+
rescue Sass::SyntaxError => e
|
3364
|
+
assert_equal "Undefined variable: \"$bang\".", e.message
|
3365
|
+
assert_equal 4, e.sass_line
|
3366
|
+
end
|
3367
|
+
|
3368
|
+
def test_post_multiline_script_runtime_error
|
3369
|
+
render <<SCSS
|
3370
|
+
foo {
|
3371
|
+
bar: "baz" +
|
3372
|
+
"bar" +
|
3373
|
+
"baz";
|
3374
|
+
bip: $bop; }
|
3375
|
+
SCSS
|
3376
|
+
assert(false, "Expected syntax error")
|
3377
|
+
rescue Sass::SyntaxError => e
|
3378
|
+
assert_equal "Undefined variable: \"$bop\".", e.message
|
3379
|
+
assert_equal 5, e.sass_line
|
3380
|
+
end
|
3381
|
+
|
3382
|
+
def test_multiline_property_runtime_error
|
3383
|
+
render <<SCSS
|
3384
|
+
foo {
|
3385
|
+
bar: baz
|
3386
|
+
bar
|
3387
|
+
\#{$bang} }
|
3388
|
+
SCSS
|
3389
|
+
assert(false, "Expected syntax error")
|
3390
|
+
rescue Sass::SyntaxError => e
|
3391
|
+
assert_equal "Undefined variable: \"$bang\".", e.message
|
3392
|
+
assert_equal 4, e.sass_line
|
3393
|
+
end
|
3394
|
+
|
3395
|
+
def test_post_resolution_selector_error
|
3396
|
+
render "\n\nfoo \#{\") bar\"} {a: b}"
|
3397
|
+
assert(false, "Expected syntax error")
|
3398
|
+
rescue Sass::SyntaxError => e
|
3399
|
+
assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message
|
3400
|
+
assert_equal 3, e.sass_line
|
3401
|
+
end
|
3402
|
+
|
3403
|
+
def test_parent_in_mid_selector_error
|
3404
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
3405
|
+
Invalid CSS after ".foo": expected "{", was "&.bar"
|
3406
|
+
|
3407
|
+
"&.bar" may only be used at the beginning of a compound selector.
|
3408
|
+
MESSAGE
|
3409
|
+
flim {
|
3410
|
+
.foo&.bar {a: b}
|
3411
|
+
}
|
3412
|
+
SCSS
|
3413
|
+
end
|
3414
|
+
|
3415
|
+
def test_parent_after_selector_error
|
3416
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
3417
|
+
Invalid CSS after ".foo.bar": expected "{", was "&"
|
3418
|
+
|
3419
|
+
"&" may only be used at the beginning of a compound selector.
|
3420
|
+
MESSAGE
|
3421
|
+
flim {
|
3422
|
+
.foo.bar& {a: b}
|
3423
|
+
}
|
3424
|
+
SCSS
|
3425
|
+
end
|
3426
|
+
|
3427
|
+
def test_double_parent_selector_error
|
3428
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
3429
|
+
Invalid CSS after "&": expected "{", was "&"
|
3430
|
+
|
3431
|
+
"&" may only be used at the beginning of a compound selector.
|
3432
|
+
MESSAGE
|
3433
|
+
flim {
|
3434
|
+
&& {a: b}
|
3435
|
+
}
|
3436
|
+
SCSS
|
3437
|
+
end
|
3438
|
+
|
3439
|
+
def test_no_lonely_else
|
3440
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
3441
|
+
Invalid CSS: @else must come after @if
|
3442
|
+
MESSAGE
|
3443
|
+
@else {foo: bar}
|
3444
|
+
SCSS
|
3445
|
+
end
|
3446
|
+
|
3447
|
+
def test_failed_parent_selector_with_suffix
|
3448
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
3449
|
+
Invalid parent selector for "&-bar": "*"
|
3450
|
+
MESSAGE
|
3451
|
+
* {
|
3452
|
+
&-bar {a: b}
|
3453
|
+
}
|
3454
|
+
SCSS
|
3455
|
+
|
3456
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
3457
|
+
Invalid parent selector for "&-bar": "[foo=bar]"
|
3458
|
+
MESSAGE
|
3459
|
+
[foo=bar] {
|
3460
|
+
&-bar {a: b}
|
3461
|
+
}
|
3462
|
+
SCSS
|
3463
|
+
|
3464
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
3465
|
+
Invalid parent selector for "&-bar": "::nth-child(2n+1)"
|
3466
|
+
MESSAGE
|
3467
|
+
::nth-child(2n+1) {
|
3468
|
+
&-bar {a: b}
|
3469
|
+
}
|
3470
|
+
SCSS
|
3471
|
+
|
3472
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
3473
|
+
Invalid parent selector for "&-bar": ":not(.foo)"
|
3474
|
+
MESSAGE
|
3475
|
+
:not(.foo) {
|
3476
|
+
&-bar {a: b}
|
3477
|
+
}
|
3478
|
+
SCSS
|
3479
|
+
|
3480
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
3481
|
+
Invalid parent selector for "&-bar": ".foo +"
|
3482
|
+
MESSAGE
|
3483
|
+
.foo + {
|
3484
|
+
&-bar {a: b}
|
3485
|
+
}
|
3486
|
+
SCSS
|
3487
|
+
end
|
3488
|
+
|
3489
|
+
def test_empty_media_query_error
|
3490
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
3491
|
+
Invalid CSS after "": expected media query list, was ""
|
3492
|
+
MESSAGE
|
3493
|
+
@media \#{""} {
|
3494
|
+
foo {a: b}
|
3495
|
+
}
|
3496
|
+
SCSS
|
3497
|
+
end
|
3498
|
+
|
3499
|
+
def test_newline_in_property_value
|
3500
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3501
|
+
.foo {
|
3502
|
+
bar: "bazbang"; }
|
3503
|
+
CSS
|
3504
|
+
.foo {
|
3505
|
+
$var: "baz\\
|
3506
|
+
bang";
|
3507
|
+
bar: $var;
|
3508
|
+
}
|
3509
|
+
SCSS
|
3510
|
+
end
|
3511
|
+
|
3512
|
+
def test_raw_newline_warning
|
3513
|
+
assert_warning(<<MESSAGE.rstrip) {assert_equal(<<CSS, render(<<SCSS))}
|
3514
|
+
DEPRECATION WARNING on line 2, column 9 of #{filename_for_test :scss}:
|
3515
|
+
Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
|
3516
|
+
To include a newline in a string, use "\\a" or "\\a " as in CSS.
|
3517
|
+
MESSAGE
|
3518
|
+
.foo {
|
3519
|
+
bar: "baz\\a bang"; }
|
3520
|
+
CSS
|
3521
|
+
.foo {
|
3522
|
+
$var: "baz
|
3523
|
+
bang";
|
3524
|
+
bar: $var;
|
3525
|
+
}
|
3526
|
+
SCSS
|
3527
|
+
end
|
3528
|
+
|
3529
|
+
# Regression
|
3530
|
+
|
3531
|
+
def test_top_level_unknown_directive_in_at_root
|
3532
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3533
|
+
@fblthp {
|
3534
|
+
a: b; }
|
3535
|
+
CSS
|
3536
|
+
@at-root {
|
3537
|
+
@fblthp {a: b}
|
3538
|
+
}
|
3539
|
+
SCSS
|
3540
|
+
end
|
3541
|
+
|
3542
|
+
def test_parent_ref_with_newline
|
3543
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3544
|
+
a.c
|
3545
|
+
, b.c {
|
3546
|
+
x: y; }
|
3547
|
+
CSS
|
3548
|
+
a
|
3549
|
+
, b {&.c {x: y}}
|
3550
|
+
SCSS
|
3551
|
+
end
|
3552
|
+
|
3553
|
+
def test_parent_ref_in_nested_at_root
|
3554
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3555
|
+
#test {
|
3556
|
+
border: 0; }
|
3557
|
+
#test:hover {
|
3558
|
+
display: none; }
|
3559
|
+
CSS
|
3560
|
+
a {
|
3561
|
+
@at-root #test {
|
3562
|
+
border: 0;
|
3563
|
+
&:hover{
|
3564
|
+
display: none;
|
3565
|
+
}
|
3566
|
+
}
|
3567
|
+
}
|
3568
|
+
SCSS
|
3569
|
+
end
|
3570
|
+
|
3571
|
+
def test_loud_comment_in_compressed_mode
|
3572
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3573
|
+
/*! foo */
|
3574
|
+
CSS
|
3575
|
+
/*! foo */
|
3576
|
+
SCSS
|
3577
|
+
end
|
3578
|
+
|
3579
|
+
def test_parsing_decimals_followed_by_comments_doesnt_take_forever
|
3580
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3581
|
+
.foo {
|
3582
|
+
padding: 4.21053% 4.21053% 5.63158%; }
|
3583
|
+
CSS
|
3584
|
+
.foo {
|
3585
|
+
padding: 4.21052631578947% 4.21052631578947% 5.631578947368421% /**/
|
3586
|
+
}
|
3587
|
+
SCSS
|
3588
|
+
end
|
3589
|
+
|
3590
|
+
def test_parsing_many_numbers_doesnt_take_forever
|
3591
|
+
values = ["80% 90%"] * 1000
|
3592
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3593
|
+
.foo {
|
3594
|
+
padding: #{values.join(', ')}; }
|
3595
|
+
CSS
|
3596
|
+
.foo {
|
3597
|
+
padding: #{values.join(', ')};
|
3598
|
+
}
|
3599
|
+
SCSS
|
3600
|
+
end
|
3601
|
+
|
3602
|
+
def test_import_comments_in_imports
|
3603
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3604
|
+
@import url(foo.css);
|
3605
|
+
@import url(bar.css);
|
3606
|
+
@import url(baz.css);
|
3607
|
+
CSS
|
3608
|
+
@import "foo.css", // this is a comment
|
3609
|
+
"bar.css", /* this is another comment */
|
3610
|
+
"baz.css"; // this is a third comment
|
3611
|
+
SCSS
|
3612
|
+
end
|
3613
|
+
|
3614
|
+
def test_reference_combinator_with_parent_ref
|
3615
|
+
assert_equal <<CSS, render(<<SCSS)
|
3616
|
+
a /foo/ b {
|
3617
|
+
c: d; }
|
3618
|
+
CSS
|
3619
|
+
a {& /foo/ b {c: d}}
|
3620
|
+
SCSS
|
3621
|
+
end
|
3622
|
+
|
3623
|
+
def test_newline_selector_rendered_multiple_times
|
3624
|
+
assert_equal <<CSS, render(<<SCSS)
|
3625
|
+
form input,
|
3626
|
+
form select {
|
3627
|
+
color: white; }
|
3628
|
+
|
3629
|
+
form input,
|
3630
|
+
form select {
|
3631
|
+
color: white; }
|
3632
|
+
CSS
|
3633
|
+
@for $i from 1 through 2 {
|
3634
|
+
form {
|
3635
|
+
input,
|
3636
|
+
select {
|
3637
|
+
color: white;
|
3638
|
+
}
|
3639
|
+
}
|
3640
|
+
}
|
3641
|
+
SCSS
|
3642
|
+
end
|
3643
|
+
|
3644
|
+
def test_prop_name_interpolation_after_hyphen
|
3645
|
+
assert_equal <<CSS, render(<<SCSS)
|
3646
|
+
a {
|
3647
|
+
-foo-bar: b; }
|
3648
|
+
CSS
|
3649
|
+
a { -\#{"foo"}-bar: b; }
|
3650
|
+
SCSS
|
3651
|
+
end
|
3652
|
+
|
3653
|
+
def test_star_plus_and_parent
|
3654
|
+
assert_equal <<CSS, render(<<SCSS)
|
3655
|
+
* + html foo {
|
3656
|
+
a: b; }
|
3657
|
+
CSS
|
3658
|
+
foo {*+html & {a: b}}
|
3659
|
+
SCSS
|
3660
|
+
end
|
3661
|
+
|
3662
|
+
def test_weird_added_space
|
3663
|
+
assert_equal <<CSS, render(<<SCSS)
|
3664
|
+
foo {
|
3665
|
+
bar: -moz-bip; }
|
3666
|
+
CSS
|
3667
|
+
$value : bip;
|
3668
|
+
|
3669
|
+
foo {
|
3670
|
+
bar: -moz-\#{$value};
|
3671
|
+
}
|
3672
|
+
SCSS
|
3673
|
+
end
|
3674
|
+
|
3675
|
+
def test_interpolation_with_bracket_on_next_line
|
3676
|
+
assert_equal <<CSS, render(<<SCSS)
|
3677
|
+
a.foo b {
|
3678
|
+
color: red; }
|
3679
|
+
CSS
|
3680
|
+
a.\#{"foo"} b
|
3681
|
+
{color: red}
|
3682
|
+
SCSS
|
3683
|
+
end
|
3684
|
+
|
3685
|
+
def test_extra_comma_in_mixin_arglist_error
|
3686
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
3687
|
+
Invalid CSS after "...clude foo(bar, ": expected mixin argument, was ");"
|
3688
|
+
MESSAGE
|
3689
|
+
@mixin foo($a1, $a2) {
|
3690
|
+
baz: $a1 $a2;
|
3691
|
+
}
|
3692
|
+
|
3693
|
+
.bar {
|
3694
|
+
@include foo(bar, );
|
3695
|
+
}
|
3696
|
+
SCSS
|
3697
|
+
end
|
3698
|
+
|
3699
|
+
def test_interpolation
|
3700
|
+
assert_equal <<CSS, render(<<SCSS)
|
3701
|
+
ul li#foo a span.label {
|
3702
|
+
foo: bar; }
|
3703
|
+
CSS
|
3704
|
+
$bar : "#foo";
|
3705
|
+
ul li\#{$bar} a span.label { foo: bar; }
|
3706
|
+
SCSS
|
3707
|
+
end
|
3708
|
+
|
3709
|
+
def test_mixin_with_keyword_args
|
3710
|
+
assert_equal <<CSS, render(<<SCSS)
|
3711
|
+
.mixed {
|
3712
|
+
required: foo;
|
3713
|
+
arg1: default-val1;
|
3714
|
+
arg2: non-default-val2; }
|
3715
|
+
CSS
|
3716
|
+
@mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
|
3717
|
+
required: $required;
|
3718
|
+
arg1: $arg1;
|
3719
|
+
arg2: $arg2;
|
3720
|
+
}
|
3721
|
+
.mixed { @include a-mixin(foo, $arg2: non-default-val2); }
|
3722
|
+
SCSS
|
3723
|
+
end
|
3724
|
+
|
3725
|
+
def test_passing_required_args_as_a_keyword_arg
|
3726
|
+
assert_equal <<CSS, render(<<SCSS)
|
3727
|
+
.mixed {
|
3728
|
+
required: foo;
|
3729
|
+
arg1: default-val1;
|
3730
|
+
arg2: default-val2; }
|
3731
|
+
CSS
|
3732
|
+
@mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
|
3733
|
+
required: $required;
|
3734
|
+
arg1: $arg1;
|
3735
|
+
arg2: $arg2; }
|
3736
|
+
.mixed { @include a-mixin($required: foo); }
|
3737
|
+
SCSS
|
3738
|
+
end
|
3739
|
+
|
3740
|
+
def test_passing_all_as_keyword_args_in_opposite_order
|
3741
|
+
assert_equal <<CSS, render(<<SCSS)
|
3742
|
+
.mixed {
|
3743
|
+
required: foo;
|
3744
|
+
arg1: non-default-val1;
|
3745
|
+
arg2: non-default-val2; }
|
3746
|
+
CSS
|
3747
|
+
@mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
|
3748
|
+
required: $required;
|
3749
|
+
arg1: $arg1;
|
3750
|
+
arg2: $arg2; }
|
3751
|
+
.mixed { @include a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo); }
|
3752
|
+
SCSS
|
3753
|
+
end
|
3754
|
+
|
3755
|
+
def test_keyword_args_in_functions
|
3756
|
+
assert_equal <<CSS, render(<<SCSS)
|
3757
|
+
.keyed {
|
3758
|
+
color: rgba(170, 119, 204, 0.4); }
|
3759
|
+
CSS
|
3760
|
+
.keyed { color: rgba($color: #a7c, $alpha: 0.4) }
|
3761
|
+
SCSS
|
3762
|
+
end
|
3763
|
+
|
3764
|
+
def test_unknown_keyword_arg_raises_error
|
3765
|
+
assert_raise_message(Sass::SyntaxError, "Mixin a doesn't have an argument named $c.") {render <<SCSS}
|
3766
|
+
@mixin a($b: 1) { a: $b; }
|
3767
|
+
div { @include a(1, $c: 3); }
|
3768
|
+
SCSS
|
3769
|
+
end
|
3770
|
+
|
3771
|
+
|
3772
|
+
def test_newlines_removed_from_selectors_when_compressed
|
3773
|
+
assert_equal <<CSS, render(<<SCSS, :style => :compressed)
|
3774
|
+
z a,z b{display:block}
|
3775
|
+
CSS
|
3776
|
+
a
|
3777
|
+
, b {
|
3778
|
+
z & {
|
3779
|
+
display: block;
|
3780
|
+
}
|
3781
|
+
}
|
3782
|
+
SCSS
|
3783
|
+
end
|
3784
|
+
|
3785
|
+
def test_if_error_line
|
3786
|
+
assert_raise_line(2) {render(<<SCSS)}
|
3787
|
+
@if true {foo: bar}
|
3788
|
+
}
|
3789
|
+
SCSS
|
3790
|
+
end
|
3791
|
+
|
3792
|
+
def test_multiline_var
|
3793
|
+
assert_equal <<CSS, render(<<SCSS)
|
3794
|
+
foo {
|
3795
|
+
a: 3;
|
3796
|
+
b: false;
|
3797
|
+
c: a b c; }
|
3798
|
+
CSS
|
3799
|
+
foo {
|
3800
|
+
$var1: 1 +
|
3801
|
+
2;
|
3802
|
+
$var2: true and
|
3803
|
+
false;
|
3804
|
+
$var3: a b
|
3805
|
+
c;
|
3806
|
+
a: $var1;
|
3807
|
+
b: $var2;
|
3808
|
+
c: $var3; }
|
3809
|
+
SCSS
|
3810
|
+
end
|
3811
|
+
|
3812
|
+
def test_mixin_content
|
3813
|
+
assert_equal <<CSS, render(<<SASS)
|
3814
|
+
.parent {
|
3815
|
+
background-color: red;
|
3816
|
+
border-color: red; }
|
3817
|
+
.parent .child {
|
3818
|
+
background-color: yellow;
|
3819
|
+
color: blue;
|
3820
|
+
border-color: yellow; }
|
3821
|
+
CSS
|
3822
|
+
$color: blue;
|
3823
|
+
@mixin context($class, $color: red) {
|
3824
|
+
.\#{$class} {
|
3825
|
+
background-color: $color;
|
3826
|
+
@content;
|
3827
|
+
border-color: $color;
|
3828
|
+
}
|
3829
|
+
}
|
3830
|
+
@include context(parent) {
|
3831
|
+
@include context(child, $color: yellow) {
|
3832
|
+
color: $color;
|
3833
|
+
}
|
3834
|
+
}
|
3835
|
+
SASS
|
3836
|
+
end
|
3837
|
+
|
3838
|
+
def test_empty_content
|
3839
|
+
assert_equal <<CSS, render(<<SCSS)
|
3840
|
+
a {
|
3841
|
+
b: c; }
|
3842
|
+
CSS
|
3843
|
+
@mixin foo { @content }
|
3844
|
+
a { b: c; @include foo {} }
|
3845
|
+
SCSS
|
3846
|
+
end
|
3847
|
+
|
3848
|
+
def test_options_passed_to_script
|
3849
|
+
assert_equal <<CSS, render(<<SCSS, :style => :compressed)
|
3850
|
+
foo{color:#000}
|
3851
|
+
CSS
|
3852
|
+
foo {color: darken(black, 10%)}
|
3853
|
+
SCSS
|
3854
|
+
end
|
3855
|
+
|
3856
|
+
# ref: https://github.com/nex3/sass/issues/104
|
3857
|
+
def test_no_buffer_overflow
|
3858
|
+
template = render <<SCSS
|
3859
|
+
.aaa {
|
3860
|
+
background-color: white;
|
3861
|
+
}
|
3862
|
+
.aaa .aaa .aaa {
|
3863
|
+
background-color: black;
|
3864
|
+
}
|
3865
|
+
.bbb {
|
3866
|
+
@extend .aaa;
|
3867
|
+
}
|
3868
|
+
.xxx {
|
3869
|
+
@extend .bbb;
|
3870
|
+
}
|
3871
|
+
.yyy {
|
3872
|
+
@extend .bbb;
|
3873
|
+
}
|
3874
|
+
.zzz {
|
3875
|
+
@extend .bbb;
|
3876
|
+
}
|
3877
|
+
SCSS
|
3878
|
+
Sass::SCSS::Parser.new(template, "test.scss", nil).parse
|
3879
|
+
end
|
3880
|
+
|
3881
|
+
def test_extend_in_media_in_rule
|
3882
|
+
assert_equal(<<CSS, render(<<SCSS))
|
3883
|
+
@media screen {
|
3884
|
+
.foo {
|
3885
|
+
a: b; } }
|
3886
|
+
CSS
|
3887
|
+
.foo {
|
3888
|
+
@media screen {
|
3889
|
+
@extend %bar;
|
3890
|
+
}
|
3891
|
+
}
|
3892
|
+
|
3893
|
+
@media screen {
|
3894
|
+
%bar {
|
3895
|
+
a: b;
|
3896
|
+
}
|
3897
|
+
}
|
3898
|
+
SCSS
|
3899
|
+
end
|
3900
|
+
end
|