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 @@
|
|
1
|
+
#pi { width: 314px; }
|
File without changes
|
File without changes
|
@@ -0,0 +1,328 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
4
|
+
require 'sass/engine'
|
5
|
+
|
6
|
+
class SassScriptConversionTest < MiniTest::Test
|
7
|
+
def test_bool
|
8
|
+
assert_renders "true"
|
9
|
+
assert_renders "false"
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_color
|
13
|
+
assert_renders "#abcdef"
|
14
|
+
assert_renders "blue"
|
15
|
+
assert_renders "rgba(0, 1, 2, 0.2)"
|
16
|
+
assert_renders "#abc"
|
17
|
+
assert_renders "#0000ff"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_number
|
21
|
+
assert_renders "10"
|
22
|
+
assert_renders "10.35"
|
23
|
+
assert_renders "12px"
|
24
|
+
assert_renders "12.45px"
|
25
|
+
|
26
|
+
assert_equal "12.34568", render("12.345678901")
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_string
|
30
|
+
assert_renders '"foo"'
|
31
|
+
assert_renders '"bar baz"'
|
32
|
+
assert_equal '"baz bang"', render("'baz bang'")
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_string_quotes
|
36
|
+
assert_equal "'quote\"quote'", render('"quote\\"quote"')
|
37
|
+
assert_equal '"quote\'quote"', render("'quote\\'quote'")
|
38
|
+
assert_renders '"quote\'quote\\"quote"'
|
39
|
+
assert_equal '"quote\'quote\\"quote"', render("'quote\\'quote\"quote'")
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_string_escapes
|
43
|
+
assert_renders '"foo\\\\bar"'
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_funcall
|
47
|
+
assert_renders "foo(true, blue)"
|
48
|
+
assert_renders "hsla(20deg, 30%, 50%, 0.3)"
|
49
|
+
assert_renders "blam()"
|
50
|
+
|
51
|
+
assert_renders "-\xC3\xBFoo(12px)"
|
52
|
+
assert_renders "-foo(12px)"
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_funcall_with_keyword_args
|
56
|
+
assert_renders "foo(arg1, arg2, $karg1: val, $karg2: val2)"
|
57
|
+
assert_renders "foo($karg1: val, $karg2: val2)"
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_funcall_with_hyphen_conversion_keyword_arg
|
61
|
+
assert_renders "foo($a-b_c: val)"
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_url
|
65
|
+
assert_renders "url(foo.gif)"
|
66
|
+
assert_renders "url($var)"
|
67
|
+
assert_renders "url(\#{$var}/flip.gif)"
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_variable
|
71
|
+
assert_renders "$foo-bar"
|
72
|
+
assert_renders "$flaznicate"
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_null
|
76
|
+
assert_renders "null"
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_empty_list
|
80
|
+
assert_renders "()"
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_list_in_args
|
84
|
+
assert_renders "foo((a, b, c))"
|
85
|
+
assert_renders "foo($arg: (a, b, c))"
|
86
|
+
assert_renders "foo(a, b, (a, b, c)...)"
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_singleton_list
|
90
|
+
assert_renders "(1,)"
|
91
|
+
assert_renders "(1 2 3,)"
|
92
|
+
assert_renders "((1, 2, 3),)"
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_map
|
96
|
+
assert_renders "(foo: bar)"
|
97
|
+
assert_renders "(foo: bar, baz: bip)"
|
98
|
+
assert_renders "(foo: bar, baz: (bip: bap))"
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_map_in_list
|
102
|
+
assert_renders "(foo: bar) baz"
|
103
|
+
assert_renders "(foo: bar), (baz: bip)"
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_list_in_map
|
107
|
+
assert_renders "(foo: bar baz)"
|
108
|
+
assert_renders "(foo: (bar, baz), bip: bop)"
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_selector
|
112
|
+
assert_renders "&"
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.test_precedence(outer, inner)
|
116
|
+
op_outer = Sass::Script::Lexer::OPERATORS_REVERSE[outer]
|
117
|
+
op_inner = Sass::Script::Lexer::OPERATORS_REVERSE[inner]
|
118
|
+
class_eval <<RUBY
|
119
|
+
def test_precedence_#{outer}_#{inner}
|
120
|
+
assert_renders "$foo #{op_outer} $bar #{op_inner} $baz"
|
121
|
+
assert_renders "$foo #{op_inner} $bar #{op_outer} $baz"
|
122
|
+
|
123
|
+
assert_renders "($foo #{op_outer} $bar) #{op_inner} $baz"
|
124
|
+
assert_renders "$foo #{op_inner} ($bar #{op_outer} $baz)"
|
125
|
+
|
126
|
+
assert_equal "$foo #{op_outer} $bar #{op_inner} $baz",
|
127
|
+
render("$foo #{op_outer} ($bar #{op_inner} $baz)")
|
128
|
+
assert_equal "$foo #{op_inner} $bar #{op_outer} $baz",
|
129
|
+
render("($foo #{op_inner} $bar) #{op_outer} $baz")
|
130
|
+
end
|
131
|
+
RUBY
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.assert_associative(op_name, sibling_name)
|
135
|
+
op = separator_for(op_name)
|
136
|
+
sibling = separator_for(sibling_name)
|
137
|
+
class_eval <<RUBY
|
138
|
+
def test_associative_#{op_name}_#{sibling_name}
|
139
|
+
assert_renders "$foo#{op}$bar#{op}$baz"
|
140
|
+
|
141
|
+
assert_equal "$foo#{op}$bar#{op}$baz",
|
142
|
+
render("$foo#{op}($bar#{op}$baz)")
|
143
|
+
assert_equal "$foo#{op}$bar#{op}$baz",
|
144
|
+
render("($foo#{op}$bar)#{op}$baz")
|
145
|
+
|
146
|
+
assert_equal "$foo#{op}$bar#{sibling}$baz",
|
147
|
+
render("$foo#{op}($bar#{sibling}$baz)")
|
148
|
+
assert_equal "$foo#{sibling}$bar#{op}$baz",
|
149
|
+
render("($foo#{sibling}$bar)#{op}$baz")
|
150
|
+
end
|
151
|
+
RUBY
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.separator_for(op_name)
|
155
|
+
case op_name
|
156
|
+
when :comma; ", "
|
157
|
+
when :space; " "
|
158
|
+
else; " #{Sass::Script::Lexer::OPERATORS_REVERSE[op_name]} "
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.assert_non_associative(op_name, sibling_name)
|
163
|
+
op = Sass::Script::Lexer::OPERATORS_REVERSE[op_name]
|
164
|
+
sibling = Sass::Script::Lexer::OPERATORS_REVERSE[sibling_name]
|
165
|
+
class_eval <<RUBY
|
166
|
+
def test_non_associative_#{op_name}_#{sibling_name}
|
167
|
+
assert_renders "$foo #{op} $bar #{op} $baz"
|
168
|
+
|
169
|
+
assert_renders "$foo #{op} ($bar #{op} $baz)"
|
170
|
+
assert_equal "$foo #{op} $bar #{op} $baz",
|
171
|
+
render("($foo #{op} $bar) #{op} $baz")
|
172
|
+
|
173
|
+
assert_renders "$foo #{op} ($bar #{sibling} $baz)"
|
174
|
+
assert_equal "$foo #{sibling} $bar #{op} $baz",
|
175
|
+
render("($foo #{sibling} $bar) #{op} $baz")
|
176
|
+
end
|
177
|
+
RUBY
|
178
|
+
end
|
179
|
+
|
180
|
+
test_precedence :or, :and
|
181
|
+
test_precedence :and, :eq
|
182
|
+
test_precedence :and, :neq
|
183
|
+
test_precedence :eq, :gt
|
184
|
+
test_precedence :eq, :gte
|
185
|
+
test_precedence :eq, :lt
|
186
|
+
test_precedence :eq, :lte
|
187
|
+
test_precedence :gt, :plus
|
188
|
+
test_precedence :gt, :minus
|
189
|
+
test_precedence :plus, :times
|
190
|
+
test_precedence :plus, :div
|
191
|
+
test_precedence :plus, :mod
|
192
|
+
|
193
|
+
assert_associative :plus, :minus
|
194
|
+
assert_associative :times, :div
|
195
|
+
assert_associative :times, :mod
|
196
|
+
|
197
|
+
assert_non_associative :minus, :plus
|
198
|
+
assert_non_associative :div, :times
|
199
|
+
assert_non_associative :mod, :times
|
200
|
+
assert_non_associative :gt, :gte
|
201
|
+
assert_non_associative :gte, :lt
|
202
|
+
assert_non_associative :lt, :lte
|
203
|
+
assert_non_associative :lte, :gt
|
204
|
+
|
205
|
+
def test_comma_precedence
|
206
|
+
assert_renders "$foo, $bar, $baz"
|
207
|
+
|
208
|
+
assert_renders "$foo ($bar, $baz)"
|
209
|
+
assert_renders "($foo, $bar) $baz"
|
210
|
+
|
211
|
+
assert_equal "$foo, $bar $baz", render("$foo, ($bar $baz)")
|
212
|
+
assert_equal "$foo $bar, $baz", render("($foo $bar), $baz")
|
213
|
+
|
214
|
+
assert_equal "$foo, ($bar, $baz)", render("$foo, ($bar, $baz)")
|
215
|
+
assert_equal "($foo, $bar), $baz", render("($foo, $bar), $baz")
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_space_precedence
|
219
|
+
assert_renders "$foo $bar $baz"
|
220
|
+
|
221
|
+
assert_renders "$foo or ($bar $baz)"
|
222
|
+
assert_renders "($foo $bar) or $baz"
|
223
|
+
|
224
|
+
assert_equal "$foo $bar or $baz", render("$foo ($bar or $baz)")
|
225
|
+
assert_equal "$foo or $bar $baz", render("($foo or $bar) $baz")
|
226
|
+
|
227
|
+
assert_equal "$foo ($bar $baz)", render("$foo ($bar $baz)")
|
228
|
+
assert_equal "($foo $bar) $baz", render("($foo $bar) $baz")
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_unary_op
|
232
|
+
assert_renders "-12px"
|
233
|
+
assert_renders '/"foo"'
|
234
|
+
assert_renders 'not true'
|
235
|
+
|
236
|
+
assert_renders "-(foo(12px))"
|
237
|
+
assert_renders "-(-foo(12px))"
|
238
|
+
assert_renders "-(_foo(12px))"
|
239
|
+
assert_renders "-(\xC3\xBFoo(12px))"
|
240
|
+
assert_renders "-(blue)"
|
241
|
+
|
242
|
+
assert_equal 'not true or false', render('(not true) or false')
|
243
|
+
assert_equal 'not (true or false)', render('not (true or false)')
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_interpolation
|
247
|
+
assert_renders "$foo\#{$bar}$baz"
|
248
|
+
assert_renders "$foo\#{$bar} $baz"
|
249
|
+
assert_renders "$foo \#{$bar}$baz"
|
250
|
+
assert_renders "$foo \#{$bar} $baz"
|
251
|
+
assert_renders "$foo \#{$bar}\#{$bang} $baz"
|
252
|
+
assert_renders "$foo \#{$bar} \#{$bang} $baz"
|
253
|
+
assert_renders "\#{$bar}$baz"
|
254
|
+
assert_renders "$foo\#{$bar}"
|
255
|
+
assert_renders "\#{$bar}"
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_interpolation_in_function
|
259
|
+
assert_renders 'flabnabbit(#{1 + "foo"})'
|
260
|
+
assert_renders 'flabnabbit($foo #{1 + "foo"}$baz)'
|
261
|
+
assert_renders 'flabnabbit($foo #{1 + "foo"}#{2 + "bar"} $baz)'
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_interpolation_near_operators
|
265
|
+
assert_renders '#{1 + 2} , #{3 + 4}'
|
266
|
+
assert_renders '#{1 + 2}, #{3 + 4}'
|
267
|
+
assert_renders '#{1 + 2} ,#{3 + 4}'
|
268
|
+
assert_renders '#{1 + 2},#{3 + 4}'
|
269
|
+
assert_renders '#{1 + 2}, #{3 + 4}, #{5 + 6}'
|
270
|
+
assert_renders '3, #{3 + 4}, 11'
|
271
|
+
|
272
|
+
assert_renders '3 / #{3 + 4}'
|
273
|
+
assert_renders '3 /#{3 + 4}'
|
274
|
+
assert_renders '3/ #{3 + 4}'
|
275
|
+
assert_renders '3/#{3 + 4}'
|
276
|
+
|
277
|
+
assert_renders '#{1 + 2} * 7'
|
278
|
+
assert_renders '#{1 + 2}* 7'
|
279
|
+
assert_renders '#{1 + 2} *7'
|
280
|
+
assert_renders '#{1 + 2}*7'
|
281
|
+
|
282
|
+
assert_renders '-#{1 + 2}'
|
283
|
+
assert_renders '- #{1 + 2}'
|
284
|
+
|
285
|
+
assert_renders '5 + #{1 + 2} * #{3 + 4}'
|
286
|
+
assert_renders '5 +#{1 + 2} * #{3 + 4}'
|
287
|
+
assert_renders '5+#{1 + 2} * #{3 + 4}'
|
288
|
+
assert_renders '#{1 + 2} * #{3 + 4} + 5'
|
289
|
+
assert_renders '#{1 + 2} * #{3 + 4}+ 5'
|
290
|
+
assert_renders '#{1 + 2} * #{3 + 4}+5'
|
291
|
+
|
292
|
+
assert_equal '5 / #{1 + 2} + #{3 + 4}', render('5 / (#{1 + 2} + #{3 + 4})')
|
293
|
+
assert_equal '5 / #{1 + 2} + #{3 + 4}', render('5 /(#{1 + 2} + #{3 + 4})')
|
294
|
+
assert_equal '5 / #{1 + 2} + #{3 + 4}', render('5 /( #{1 + 2} + #{3 + 4} )')
|
295
|
+
assert_equal '#{1 + 2} + #{3 + 4} / 5', render('(#{1 + 2} + #{3 + 4}) / 5')
|
296
|
+
assert_equal '#{1 + 2} + #{3 + 4} / 5', render('(#{1 + 2} + #{3 + 4})/ 5')
|
297
|
+
assert_equal '#{1 + 2} + #{3 + 4} / 5', render('( #{1 + 2} + #{3 + 4} )/ 5')
|
298
|
+
|
299
|
+
assert_renders '#{1 + 2} + 2 + 3'
|
300
|
+
assert_renders '#{1 + 2} +2 + 3'
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_string_interpolation
|
304
|
+
assert_renders '"foo#{$bar}baz"'
|
305
|
+
assert_renders '"foo #{$bar}baz"'
|
306
|
+
assert_renders '"foo#{$bar} baz"'
|
307
|
+
assert_renders '"foo #{$bar} baz"'
|
308
|
+
assert_renders '"foo #{$bar}#{$bang} baz"'
|
309
|
+
assert_renders '"foo #{$bar} #{$bang} baz"'
|
310
|
+
assert_renders '"#{$bar}baz"'
|
311
|
+
assert_renders '"foo#{$bar}"'
|
312
|
+
assert_equal '#{$bar}', render('"#{$bar}"')
|
313
|
+
|
314
|
+
assert_equal '"foo#{$bar}baz"', render("'foo\#{$bar}baz'")
|
315
|
+
end
|
316
|
+
|
317
|
+
private
|
318
|
+
|
319
|
+
def assert_renders(script, options = {})
|
320
|
+
assert_equal(script, render(script, options))
|
321
|
+
end
|
322
|
+
|
323
|
+
def render(script, options = {})
|
324
|
+
munge_filename(options)
|
325
|
+
node = Sass::Script.parse(script, 1, 0, options)
|
326
|
+
node.to_sass
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,1054 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
4
|
+
require 'sass/engine'
|
5
|
+
|
6
|
+
module Sass::Script::Functions::UserFunctions
|
7
|
+
def assert_options(val)
|
8
|
+
val.options[:foo]
|
9
|
+
Sass::Script::Value::String.new("Options defined!")
|
10
|
+
end
|
11
|
+
|
12
|
+
def arg_error
|
13
|
+
assert_options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Sass::Script::Functions
|
18
|
+
include Sass::Script::Functions::UserFunctions
|
19
|
+
end
|
20
|
+
|
21
|
+
class SassScriptTest < MiniTest::Test
|
22
|
+
include Sass::Script
|
23
|
+
|
24
|
+
def test_color_clamps_input
|
25
|
+
assert_equal 0, Sass::Script::Value::Color.new([1, 2, -1]).blue
|
26
|
+
assert_equal 255, Sass::Script::Value::Color.new([256, 2, 3]).red
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_color_clamps_rgba_input
|
30
|
+
assert_equal 1, Sass::Script::Value::Color.new([1, 2, 3, 1.1]).alpha
|
31
|
+
assert_equal 0, Sass::Script::Value::Color.new([1, 2, 3, -0.1]).alpha
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_string_escapes
|
35
|
+
assert_equal "'", resolve("\"'\"")
|
36
|
+
assert_equal '"', resolve("\"\\\"\"")
|
37
|
+
assert_equal "\\", resolve("\"\\\\\"")
|
38
|
+
assert_equal "☃", resolve("\"\\2603\"")
|
39
|
+
assert_equal "☃f", resolve("\"\\2603 f\"")
|
40
|
+
assert_equal "☃x", resolve("\"\\2603x\"")
|
41
|
+
assert_equal "\\2603", resolve("\"\\\\2603\"")
|
42
|
+
|
43
|
+
# U+FFFD is the replacement character, "�".
|
44
|
+
assert_equal [0xFFFD].pack("U"), resolve("\"\\0\"")
|
45
|
+
assert_equal [0xFFFD].pack("U"), resolve("\"\\FFFFFF\"")
|
46
|
+
assert_equal [0xFFFD].pack("U"), resolve("\"\\D800\"")
|
47
|
+
assert_equal [0xD7FF].pack("U"), resolve("\"\\D7FF\"")
|
48
|
+
assert_equal [0xFFFD].pack("U"), resolve("\"\\DFFF\"")
|
49
|
+
assert_equal [0xE000].pack("U"), resolve("\"\\E000\"")
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_string_escapes_are_resolved_before_operators
|
53
|
+
assert_equal "true", resolve('"abc" == "\61\62\63"')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_string_quote
|
57
|
+
assert_equal '"foo"', resolve_quoted('"foo"')
|
58
|
+
assert_equal "'f\"oo'", resolve_quoted('"f\"oo"')
|
59
|
+
assert_equal "\"f'oo\"", resolve_quoted("'f\\'oo'")
|
60
|
+
assert_equal "\"f'o\\\"o\"", resolve_quoted("'f\\'o\"o'")
|
61
|
+
assert_equal '"foo bar"', resolve_quoted('"foo\20 bar"')
|
62
|
+
assert_equal '"foo\a bar"', resolve_quoted('"foo\a bar"')
|
63
|
+
assert_equal '"x\ay"', resolve_quoted('"x\a y"')
|
64
|
+
assert_equal '"\a "', resolve_quoted('"\a\20"')
|
65
|
+
assert_equal '"\a abcdef"', resolve_quoted('"\a abcdef"')
|
66
|
+
assert_equal '"☃abcdef"', resolve_quoted('"\2603 abcdef"')
|
67
|
+
assert_equal '"\\\\"', resolve_quoted('"\\\\"')
|
68
|
+
assert_equal '"foobar"', resolve_quoted("\"foo\\\nbar\"")
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_color_names
|
72
|
+
assert_equal "white", resolve("white")
|
73
|
+
assert_equal "#ffffff", resolve("#ffffff")
|
74
|
+
assert_equal "#fffffe", resolve("white - #000001")
|
75
|
+
assert_equal "transparent", resolve("transparent")
|
76
|
+
assert_equal "transparent", resolve("rgba(0, 0, 0, 0)")
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_rgba_color_literals
|
80
|
+
assert_equal Sass::Script::Value::Color.new([1, 2, 3, 0.75]), eval("rgba(1, 2, 3, 0.75)")
|
81
|
+
assert_equal "rgba(1, 2, 3, 0.75)", resolve("rgba(1, 2, 3, 0.75)")
|
82
|
+
|
83
|
+
assert_equal Sass::Script::Value::Color.new([1, 2, 3, 0]), eval("rgba(1, 2, 3, 0)")
|
84
|
+
assert_equal "rgba(1, 2, 3, 0)", resolve("rgba(1, 2, 3, 0)")
|
85
|
+
|
86
|
+
assert_equal Sass::Script::Value::Color.new([1, 2, 3]), eval("rgba(1, 2, 3, 1)")
|
87
|
+
assert_equal Sass::Script::Value::Color.new([1, 2, 3, 1]), eval("rgba(1, 2, 3, 1)")
|
88
|
+
assert_equal "#010203", resolve("rgba(1, 2, 3, 1)")
|
89
|
+
assert_equal "white", resolve("rgba(255, 255, 255, 1)")
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_rgba_color_math
|
93
|
+
assert_equal "rgba(50, 50, 100, 0.35)", resolve("rgba(1, 1, 2, 0.35) * rgba(50, 50, 50, 0.35)")
|
94
|
+
assert_equal "rgba(52, 52, 52, 0.25)", resolve("rgba(2, 2, 2, 0.25) + rgba(50, 50, 50, 0.25)")
|
95
|
+
|
96
|
+
assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)") do
|
97
|
+
resolve("rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)")
|
98
|
+
end
|
99
|
+
assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: #123456 * rgba(50, 50, 50, 0.75)") do
|
100
|
+
resolve("#123456 * rgba(50, 50, 50, 0.75)")
|
101
|
+
end
|
102
|
+
assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(50, 50, 50, 0.75) / #123456") do
|
103
|
+
resolve("rgba(50, 50, 50, 0.75) / #123456")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_rgba_number_math
|
108
|
+
assert_equal "rgba(49, 49, 49, 0.75)", resolve("rgba(50, 50, 50, 0.75) - 1")
|
109
|
+
assert_equal "rgba(100, 100, 100, 0.75)", resolve("rgba(50, 50, 50, 0.75) * 2")
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_rgba_rounding
|
113
|
+
assert_equal "rgba(10, 1, 0, 0.12346)", resolve("rgba(10.0, 1.23456789, 0.0, 0.1234567)")
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_compressed_colors
|
117
|
+
assert_equal "#123456", resolve("#123456", :style => :compressed)
|
118
|
+
assert_equal "rgba(1,2,3,0.5)", resolve("rgba(1, 2, 3, 0.5)", :style => :compressed)
|
119
|
+
assert_equal "#123", resolve("#112233", :style => :compressed)
|
120
|
+
assert_equal "#000", resolve("black", :style => :compressed)
|
121
|
+
assert_equal "red", resolve("#f00", :style => :compressed)
|
122
|
+
assert_equal "blue", resolve("blue", :style => :compressed)
|
123
|
+
assert_equal "navy", resolve("#000080", :style => :compressed)
|
124
|
+
assert_equal "navy #fff", resolve("#000080 white", :style => :compressed)
|
125
|
+
assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed)
|
126
|
+
assert_equal "transparent", resolve("rgba(0, 0, 0, 0)", :style => :compressed)
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_compressed_comma
|
130
|
+
# assert_equal "foo,bar,baz", resolve("foo, bar, baz", :style => :compressed)
|
131
|
+
# assert_equal "foo,#baf,baz", resolve("foo, #baf, baz", :style => :compressed)
|
132
|
+
assert_equal "foo,#baf,red", resolve("foo, #baf, #f00", :style => :compressed)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_implicit_strings
|
136
|
+
assert_equal Sass::Script::Value::String.new("foo"), eval("foo")
|
137
|
+
assert_equal Sass::Script::Value::String.new("foo/bar"), eval("foo/bar")
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_basic_interpolation
|
141
|
+
assert_equal "foo3bar", resolve("foo\#{1 + 2}bar")
|
142
|
+
assert_equal "foo3 bar", resolve("foo\#{1 + 2} bar")
|
143
|
+
assert_equal "foo 3bar", resolve("foo \#{1 + 2}bar")
|
144
|
+
assert_equal "foo 3 bar", resolve("foo \#{1 + 2} bar")
|
145
|
+
assert_equal "foo 35 bar", resolve("foo \#{1 + 2}\#{2 + 3} bar")
|
146
|
+
assert_equal "foo 3 5 bar", resolve("foo \#{1 + 2} \#{2 + 3} bar")
|
147
|
+
assert_equal "3bar", resolve("\#{1 + 2}bar")
|
148
|
+
assert_equal "foo3", resolve("foo\#{1 + 2}")
|
149
|
+
assert_equal "3", resolve("\#{1 + 2}")
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_interpolation_in_function
|
153
|
+
assert_equal 'flabnabbit(1foo)', resolve('flabnabbit(#{1 + "foo"})')
|
154
|
+
assert_equal 'flabnabbit(foo 1foobaz)', resolve('flabnabbit(foo #{1 + "foo"}baz)')
|
155
|
+
assert_equal('flabnabbit(foo 1foo2bar baz)',
|
156
|
+
resolve('flabnabbit(foo #{1 + "foo"}#{2 + "bar"} baz)'))
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_interpolation_near_operators
|
160
|
+
assert_equal '3 , 7', resolve('#{1 + 2} , #{3 + 4}')
|
161
|
+
assert_equal '3, 7', resolve('#{1 + 2}, #{3 + 4}')
|
162
|
+
assert_equal '3 ,7', resolve('#{1 + 2} ,#{3 + 4}')
|
163
|
+
assert_equal '3,7', resolve('#{1 + 2},#{3 + 4}')
|
164
|
+
assert_equal '3, 7, 11', resolve('#{1 + 2}, #{3 + 4}, #{5 + 6}')
|
165
|
+
assert_equal '3, 7, 11', resolve('3, #{3 + 4}, 11')
|
166
|
+
assert_equal '3, 7, 11', resolve('3, 7, #{5 + 6}')
|
167
|
+
|
168
|
+
assert_equal '3 / 7', resolve('3 / #{3 + 4}')
|
169
|
+
assert_equal '3 /7', resolve('3 /#{3 + 4}')
|
170
|
+
assert_equal '3/ 7', resolve('3/ #{3 + 4}')
|
171
|
+
assert_equal '3/7', resolve('3/#{3 + 4}')
|
172
|
+
|
173
|
+
assert_equal '3 * 7', resolve('#{1 + 2} * 7')
|
174
|
+
assert_equal '3* 7', resolve('#{1 + 2}* 7')
|
175
|
+
assert_equal '3 *7', resolve('#{1 + 2} *7')
|
176
|
+
assert_equal '3*7', resolve('#{1 + 2}*7')
|
177
|
+
|
178
|
+
assert_equal '-3', resolve('-#{1 + 2}')
|
179
|
+
assert_equal '- 3', resolve('- #{1 + 2}')
|
180
|
+
|
181
|
+
assert_equal '5 + 3 * 7', resolve('5 + #{1 + 2} * #{3 + 4}')
|
182
|
+
assert_equal '5 +3 * 7', resolve('5 +#{1 + 2} * #{3 + 4}')
|
183
|
+
assert_equal '5+3 * 7', resolve('5+#{1 + 2} * #{3 + 4}')
|
184
|
+
assert_equal '3 * 7 + 5', resolve('#{1 + 2} * #{3 + 4} + 5')
|
185
|
+
assert_equal '3 * 7+ 5', resolve('#{1 + 2} * #{3 + 4}+ 5')
|
186
|
+
assert_equal '3 * 7+5', resolve('#{1 + 2} * #{3 + 4}+5')
|
187
|
+
|
188
|
+
assert_equal '5/3 + 7', resolve('5 / (#{1 + 2} + #{3 + 4})')
|
189
|
+
assert_equal '5/3 + 7', resolve('5 /(#{1 + 2} + #{3 + 4})')
|
190
|
+
assert_equal '5/3 + 7', resolve('5 /( #{1 + 2} + #{3 + 4} )')
|
191
|
+
assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4}) / 5')
|
192
|
+
assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4})/ 5')
|
193
|
+
assert_equal '3 + 7/5', resolve('( #{1 + 2} + #{3 + 4} )/ 5')
|
194
|
+
|
195
|
+
assert_equal '3 + 5', resolve('#{1 + 2} + 2 + 3')
|
196
|
+
assert_equal '3 +5', resolve('#{1 + 2} +2 + 3')
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_string_interpolation
|
200
|
+
assert_equal "foo bar, baz bang", resolve('"foo #{"bar"}, #{"baz"} bang"')
|
201
|
+
assert_equal "foo bar baz bang", resolve('"foo #{"#{"ba" + "r"} baz"} bang"')
|
202
|
+
assert_equal 'foo #{bar baz} bang', resolve('"foo \#{#{"ba" + "r"} baz} bang"')
|
203
|
+
assert_equal 'foo #{baz bang', resolve('"foo #{"\#{" + "baz"} bang"')
|
204
|
+
assert_equal "foo2bar", resolve('\'foo#{1 + 1}bar\'')
|
205
|
+
assert_equal "foo2bar", resolve('"foo#{1 + 1}bar"')
|
206
|
+
assert_equal "foo1bar5baz4bang", resolve('\'foo#{1 + "bar#{2 + 3}baz" + 4}bang\'')
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_interpolation_with_newline
|
210
|
+
assert_equal "\nbang", resolve('"#{"\a "}bang"')
|
211
|
+
assert_equal "\n\nbang", resolve('"#{"\a "}\a bang"')
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_rule_interpolation
|
215
|
+
assert_equal(<<CSS, render(<<SASS))
|
216
|
+
foo bar baz bang {
|
217
|
+
a: b; }
|
218
|
+
CSS
|
219
|
+
foo \#{"\#{"ba" + "r"} baz"} bang
|
220
|
+
a: b
|
221
|
+
SASS
|
222
|
+
assert_equal(<<CSS, render(<<SASS))
|
223
|
+
foo [bar="\#{bar baz}"] bang {
|
224
|
+
a: b; }
|
225
|
+
CSS
|
226
|
+
foo [bar="\\\#{\#{"ba" + "r"} baz}"] bang
|
227
|
+
a: b
|
228
|
+
SASS
|
229
|
+
assert_equal(<<CSS, render(<<SASS))
|
230
|
+
foo [bar="\#{baz"] bang {
|
231
|
+
a: b; }
|
232
|
+
CSS
|
233
|
+
foo [bar="\#{"\\\#{" + "baz"}"] bang
|
234
|
+
a: b
|
235
|
+
SASS
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_inaccessible_functions
|
239
|
+
assert_equal "send(to_s)", resolve("send(to_s)", :line => 2)
|
240
|
+
assert_equal "public_instance_methods()", resolve("public_instance_methods()")
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_adding_functions_directly_to_functions_module
|
244
|
+
assert !Functions.callable?('nonexistant')
|
245
|
+
Functions.class_eval { def nonexistant; end }
|
246
|
+
assert Functions.callable?('nonexistant')
|
247
|
+
Functions.send :remove_method, :nonexistant
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_default_functions
|
251
|
+
assert_equal "url(12)", resolve("url(12)")
|
252
|
+
assert_equal 'blam("foo")', resolve('blam("foo")')
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_function_results_have_options
|
256
|
+
assert_equal "Options defined!", resolve("assert_options(abs(1))")
|
257
|
+
assert_equal "Options defined!", resolve("assert_options(round(1.2))")
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_funcall_requires_no_whitespace_before_lparen
|
261
|
+
assert_equal "no-repeat 15px", resolve("no-repeat (7px + 8px)")
|
262
|
+
assert_equal "no-repeat(15px)", resolve("no-repeat(7px + 8px)")
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_dynamic_url
|
266
|
+
assert_equal "url(foo-bar)", resolve("url($foo)", {}, env('foo' => Sass::Script::Value::String.new("foo-bar")))
|
267
|
+
assert_equal "url(foo-bar baz)", resolve("url($foo $bar)", {}, env('foo' => Sass::Script::Value::String.new("foo-bar"), 'bar' => Sass::Script::Value::String.new("baz")))
|
268
|
+
assert_equal "url(foo baz)", resolve("url(foo $bar)", {}, env('bar' => Sass::Script::Value::String.new("baz")))
|
269
|
+
assert_equal "url(foo bar)", resolve("url(foo bar)")
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_url_with_interpolation
|
273
|
+
assert_equal "url(http://sass-lang.com/images/foo-bar)", resolve("url(http://sass-lang.com/images/\#{foo-bar})")
|
274
|
+
assert_equal 'url("http://sass-lang.com/images/foo-bar")', resolve("url('http://sass-lang.com/images/\#{foo-bar}')")
|
275
|
+
assert_equal 'url("http://sass-lang.com/images/foo-bar")', resolve('url("http://sass-lang.com/images/#{foo-bar}")')
|
276
|
+
assert_unquoted "url(http://sass-lang.com/images/\#{foo-bar})"
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_hyphenated_variables
|
280
|
+
assert_equal("a-b", resolve("$a-b", {}, env("a-b" => Sass::Script::Value::String.new("a-b"))))
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_ruby_equality
|
284
|
+
assert_equal eval('"foo"'), eval('"foo"')
|
285
|
+
assert_equal eval('1'), eval('1.0')
|
286
|
+
assert_equal eval('1 2 3.0'), eval('1 2 3')
|
287
|
+
assert_equal eval('1, 2, 3.0'), eval('1, 2, 3')
|
288
|
+
assert_equal eval('(1 2), (3, 4), (5 6)'), eval('(1 2), (3, 4), (5 6)')
|
289
|
+
refute_equal eval('1, 2, 3'), eval('1 2 3')
|
290
|
+
refute_equal eval('1'), eval('"1"')
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_booleans
|
294
|
+
assert_equal "true", resolve("true")
|
295
|
+
assert_equal "false", resolve("false")
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_null
|
299
|
+
assert_equal "", resolve("null")
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_boolean_ops
|
303
|
+
assert_equal "true", resolve("true and true")
|
304
|
+
assert_equal "true", resolve("false or true")
|
305
|
+
assert_equal "true", resolve("true or false")
|
306
|
+
assert_equal "true", resolve("true or true")
|
307
|
+
assert_equal "false", resolve("false or false")
|
308
|
+
assert_equal "false", resolve("false and true")
|
309
|
+
assert_equal "false", resolve("true and false")
|
310
|
+
assert_equal "false", resolve("false and false")
|
311
|
+
|
312
|
+
assert_equal "true", resolve("not false")
|
313
|
+
assert_equal "false", resolve("not true")
|
314
|
+
assert_equal "true", resolve("not not true")
|
315
|
+
|
316
|
+
assert_equal "1", resolve("false or 1")
|
317
|
+
assert_equal "false", resolve("false and 1")
|
318
|
+
assert_equal "2", resolve("2 or 3")
|
319
|
+
assert_equal "3", resolve("2 and 3")
|
320
|
+
|
321
|
+
assert_equal "true", resolve("null or true")
|
322
|
+
assert_equal "true", resolve("true or null")
|
323
|
+
assert_equal "", resolve("null or null")
|
324
|
+
assert_equal "", resolve("null and true")
|
325
|
+
assert_equal "", resolve("true and null")
|
326
|
+
assert_equal "", resolve("null and null")
|
327
|
+
|
328
|
+
assert_equal "true", resolve("not null")
|
329
|
+
|
330
|
+
assert_equal "1", resolve("null or 1")
|
331
|
+
assert_equal "", resolve("null and 1")
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_arithmetic_ops
|
335
|
+
assert_equal "2", resolve("1 + 1")
|
336
|
+
assert_equal "0", resolve("1 - 1")
|
337
|
+
assert_equal "8", resolve("2 * 4")
|
338
|
+
assert_equal "0.5", resolve("(2 / 4)")
|
339
|
+
assert_equal "2", resolve("(4 / 2)")
|
340
|
+
|
341
|
+
assert_equal "-1", resolve("-1")
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_string_ops
|
345
|
+
assert_equal '"foo" "bar"', resolve('"foo" "bar"')
|
346
|
+
assert_equal "true 1", resolve('true 1')
|
347
|
+
assert_equal '"foo", "bar"', resolve("'foo' , 'bar'")
|
348
|
+
assert_equal "true, 1", resolve('true , 1')
|
349
|
+
assert_equal "foobar", resolve('"foo" + "bar"')
|
350
|
+
assert_equal "\nfoo\nxyz", resolve('"\a foo" + "\axyz"')
|
351
|
+
assert_equal "true1", resolve('true + 1')
|
352
|
+
assert_equal '"foo"-"bar"', resolve("'foo' - 'bar'")
|
353
|
+
assert_equal "true-1", resolve('true - 1')
|
354
|
+
assert_equal '"foo"/"bar"', resolve('"foo" / "bar"')
|
355
|
+
assert_equal "true/1", resolve('true / 1')
|
356
|
+
|
357
|
+
assert_equal '-"bar"', resolve("- 'bar'")
|
358
|
+
assert_equal "-true", resolve('- true')
|
359
|
+
assert_equal '/"bar"', resolve('/ "bar"')
|
360
|
+
assert_equal "/true", resolve('/ true')
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_relational_ops
|
364
|
+
assert_equal "false", resolve("1 > 2")
|
365
|
+
assert_equal "false", resolve("2 > 2")
|
366
|
+
assert_equal "true", resolve("3 > 2")
|
367
|
+
assert_equal "false", resolve("1 >= 2")
|
368
|
+
assert_equal "true", resolve("2 >= 2")
|
369
|
+
assert_equal "true", resolve("3 >= 2")
|
370
|
+
assert_equal "true", resolve("1 < 2")
|
371
|
+
assert_equal "false", resolve("2 < 2")
|
372
|
+
assert_equal "false", resolve("3 < 2")
|
373
|
+
assert_equal "true", resolve("1 <= 2")
|
374
|
+
assert_equal "true", resolve("2 <= 2")
|
375
|
+
assert_equal "false", resolve("3 <= 2")
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_null_ops
|
379
|
+
assert_raise_message(Sass::SyntaxError,
|
380
|
+
'Invalid null operation: "null plus 1".') {eval("null + 1")}
|
381
|
+
assert_raise_message(Sass::SyntaxError,
|
382
|
+
'Invalid null operation: "null minus 1".') {eval("null - 1")}
|
383
|
+
assert_raise_message(Sass::SyntaxError,
|
384
|
+
'Invalid null operation: "null times 1".') {eval("null * 1")}
|
385
|
+
assert_raise_message(Sass::SyntaxError,
|
386
|
+
'Invalid null operation: "null div 1".') {eval("null / 1")}
|
387
|
+
assert_raise_message(Sass::SyntaxError,
|
388
|
+
'Invalid null operation: "null mod 1".') {eval("null % 1")}
|
389
|
+
assert_raise_message(Sass::SyntaxError,
|
390
|
+
'Invalid null operation: "1 plus null".') {eval("1 + null")}
|
391
|
+
assert_raise_message(Sass::SyntaxError,
|
392
|
+
'Invalid null operation: "1 minus null".') {eval("1 - null")}
|
393
|
+
assert_raise_message(Sass::SyntaxError,
|
394
|
+
'Invalid null operation: "1 times null".') {eval("1 * null")}
|
395
|
+
assert_raise_message(Sass::SyntaxError,
|
396
|
+
'Invalid null operation: "1 div null".') {eval("1 / null")}
|
397
|
+
assert_raise_message(Sass::SyntaxError,
|
398
|
+
'Invalid null operation: "1 mod null".') {eval("1 % null")}
|
399
|
+
assert_raise_message(Sass::SyntaxError,
|
400
|
+
'Invalid null operation: "1 gt null".') {eval("1 > null")}
|
401
|
+
assert_raise_message(Sass::SyntaxError,
|
402
|
+
'Invalid null operation: "null lt 1".') {eval("null < 1")}
|
403
|
+
assert_raise_message(Sass::SyntaxError,
|
404
|
+
'Invalid null operation: "null plus null".') {eval("null + null")}
|
405
|
+
assert_raise_message(Sass::SyntaxError,
|
406
|
+
'Invalid null operation: ""foo" plus null".') {eval("foo + null")}
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_equals
|
410
|
+
assert_equal("true", resolve('"foo" == $foo', {},
|
411
|
+
env("foo" => Sass::Script::Value::String.new("foo"))))
|
412
|
+
assert_equal "true", resolve("1 == 1.0")
|
413
|
+
assert_equal "true", resolve("false != true")
|
414
|
+
assert_equal "false", resolve("1em == 1px")
|
415
|
+
assert_equal "false", resolve("12 != 12")
|
416
|
+
assert_equal "true", resolve("(foo bar baz) == (foo bar baz)")
|
417
|
+
assert_equal "true", resolve("(foo, bar, baz) == (foo, bar, baz)")
|
418
|
+
assert_equal "true", resolve('((1 2), (3, 4), (5 6)) == ((1 2), (3, 4), (5 6))')
|
419
|
+
assert_equal "true", resolve('((1 2), (3 4)) == (1 2, 3 4)')
|
420
|
+
assert_equal "false", resolve('((1 2) 3) == (1 2 3)')
|
421
|
+
assert_equal "false", resolve('(1 (2 3)) == (1 2 3)')
|
422
|
+
assert_equal "false", resolve('((1, 2) (3, 4)) == (1, 2 3, 4)')
|
423
|
+
assert_equal "false", resolve('(1 2 3) == (1, 2, 3)')
|
424
|
+
|
425
|
+
assert_equal "true", resolve('null == null')
|
426
|
+
assert_equal "false", resolve('"null" == null')
|
427
|
+
assert_equal "false", resolve('0 == null')
|
428
|
+
assert_equal "false", resolve('() == null')
|
429
|
+
|
430
|
+
assert_equal "false", resolve('null != null')
|
431
|
+
assert_equal "true", resolve('"null" != null')
|
432
|
+
assert_equal "true", resolve('0 != null')
|
433
|
+
assert_equal "true", resolve('() != null')
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_mod
|
437
|
+
assert_equal "5", resolve("29 % 12")
|
438
|
+
assert_equal "5px", resolve("29px % 12")
|
439
|
+
assert_equal "5px", resolve("29px % 12px")
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_operation_precedence
|
443
|
+
assert_equal "false true", resolve("true and false false or true")
|
444
|
+
assert_equal "true", resolve("false and true or true and true")
|
445
|
+
assert_equal "true", resolve("1 == 2 or 3 == 3")
|
446
|
+
assert_equal "true", resolve("1 < 2 == 3 >= 3")
|
447
|
+
assert_equal "true", resolve("1 + 3 > 4 - 2")
|
448
|
+
assert_equal "11", resolve("1 + 2 * 3 + 4")
|
449
|
+
end
|
450
|
+
|
451
|
+
def test_functions
|
452
|
+
assert_equal "#80ff80", resolve("hsl(120, 100%, 75%)")
|
453
|
+
assert_equal "#81ff81", resolve("hsl(120, 100%, 75%) + #010001")
|
454
|
+
end
|
455
|
+
|
456
|
+
def test_operator_unit_conversion
|
457
|
+
assert_equal "1.1cm", resolve("1cm + 1mm")
|
458
|
+
assert_equal "2in", resolve("1in + 96px")
|
459
|
+
assert_equal "true", resolve("2mm < 1cm")
|
460
|
+
assert_equal "true", resolve("10mm == 1cm")
|
461
|
+
assert_equal "true", resolve("1 == 1cm")
|
462
|
+
assert_equal "true", resolve("1.1cm == 11mm")
|
463
|
+
end
|
464
|
+
|
465
|
+
def test_length_units
|
466
|
+
assert_equal "2.54", resolve("(1in/1cm)")
|
467
|
+
assert_equal "2.3622", resolve("(1cm/1pc)")
|
468
|
+
assert_equal "4.23333", resolve("(1pc/1mm)")
|
469
|
+
assert_equal "2.83465", resolve("(1mm/1pt)")
|
470
|
+
assert_equal "1.33333", resolve("(1pt/1px)")
|
471
|
+
assert_equal "0.01042", resolve("(1px/1in)")
|
472
|
+
end
|
473
|
+
|
474
|
+
def test_angle_units
|
475
|
+
assert_equal "1.11111", resolve("(1deg/1grad)")
|
476
|
+
assert_equal "0.01571", resolve("(1grad/1rad)")
|
477
|
+
assert_equal "0.15915", resolve("(1rad/1turn)")
|
478
|
+
assert_equal "360", resolve("(1turn/1deg)")
|
479
|
+
end
|
480
|
+
|
481
|
+
def test_time_units
|
482
|
+
assert_equal "1000", resolve("(1s/1ms)")
|
483
|
+
end
|
484
|
+
|
485
|
+
def test_frequency_units
|
486
|
+
assert_equal "0.001", resolve("(1Hz/1kHz)")
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_resolution_units
|
490
|
+
assert_equal "2.54", resolve("(1dpi/1dpcm)")
|
491
|
+
assert_equal "37.79528", resolve("(1dpcm/1dppx)")
|
492
|
+
assert_equal "0.01042", resolve("(1dppx/1dpi)")
|
493
|
+
end
|
494
|
+
|
495
|
+
def test_operations_have_options
|
496
|
+
assert_equal "Options defined!", resolve("assert_options(1 + 1)")
|
497
|
+
assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')")
|
498
|
+
end
|
499
|
+
|
500
|
+
def test_slash_compiles_literally_when_left_alone
|
501
|
+
assert_equal "1px/2px", resolve("1px/2px")
|
502
|
+
assert_equal "1px/2px/3px/4px", resolve("1px/2px/3px/4px")
|
503
|
+
|
504
|
+
assert_equal "1px/2px redpx bluepx", resolve("1px/2px redpx bluepx")
|
505
|
+
assert_equal "foo 1px/2px/3px bar", resolve("foo 1px/2px/3px bar")
|
506
|
+
end
|
507
|
+
|
508
|
+
def test_slash_divides_with_parens
|
509
|
+
assert_equal "0.5", resolve("(1px/2px)")
|
510
|
+
assert_equal "0.5", resolve("(1px)/2px")
|
511
|
+
assert_equal "0.5", resolve("1px/(2px)")
|
512
|
+
end
|
513
|
+
|
514
|
+
def test_slash_divides_with_other_arithmetic
|
515
|
+
assert_equal "0.5px", resolve("1px*1px/2px")
|
516
|
+
assert_equal "0.5px", resolve("1px/2px*1px")
|
517
|
+
assert_equal "0.5", resolve("0+1px/2px")
|
518
|
+
assert_equal "0.5", resolve("1px/2px+0")
|
519
|
+
end
|
520
|
+
|
521
|
+
def test_slash_divides_with_variable
|
522
|
+
assert_equal "0.5", resolve("$var/2px", {}, env("var" => eval("1px")))
|
523
|
+
assert_equal "0.5", resolve("1px/$var", {}, env("var" => eval("2px")))
|
524
|
+
assert_equal "0.5", resolve("$var", {}, env("var" => eval("1px/2px")))
|
525
|
+
end
|
526
|
+
|
527
|
+
def test_non_ident_colors_with_wrong_number_of_digits
|
528
|
+
assert_raise_message(Sass::SyntaxError,
|
529
|
+
'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1"') {eval("#1")}
|
530
|
+
assert_raise_message(Sass::SyntaxError,
|
531
|
+
'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12"') {eval("#12")}
|
532
|
+
assert_raise_message(Sass::SyntaxError,
|
533
|
+
'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1234"') {eval("#1234")}
|
534
|
+
assert_raise_message(Sass::SyntaxError,
|
535
|
+
'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12345"') {eval("#12345")}
|
536
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "": expected expression (e.g. ' \
|
537
|
+
'1px, bold), was "#1234567"') {eval("#1234567")}
|
538
|
+
end
|
539
|
+
|
540
|
+
def test_case_insensitive_color_names
|
541
|
+
assert_equal "BLUE", resolve("BLUE")
|
542
|
+
assert_equal "rEd", resolve("rEd")
|
543
|
+
assert_equal "#7f4000", resolve("mix(GrEeN, ReD)")
|
544
|
+
end
|
545
|
+
|
546
|
+
def test_empty_list
|
547
|
+
assert_equal "1 2 3", resolve("1 2 () 3")
|
548
|
+
assert_equal "1 2 3", resolve("1 2 3 ()")
|
549
|
+
assert_equal "1 2 3", resolve("() 1 2 3")
|
550
|
+
assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("()")}
|
551
|
+
assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("nth(append((), ()), 1)")}
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_list_with_nulls
|
555
|
+
assert_equal "1, 2, 3", resolve("1, 2, null, 3")
|
556
|
+
assert_equal "1 2 3", resolve("1 2 null 3")
|
557
|
+
assert_equal "1, 2, 3", resolve("1, 2, 3, null")
|
558
|
+
assert_equal "1 2 3", resolve("1 2 3 null")
|
559
|
+
assert_equal "1, 2, 3", resolve("null, 1, 2, 3")
|
560
|
+
assert_equal "1 2 3", resolve("null 1 2 3")
|
561
|
+
end
|
562
|
+
|
563
|
+
def test_map_can_have_trailing_comma
|
564
|
+
assert_equal("(foo: 1, bar: 2)", eval("(foo: 1, bar: 2,)").to_sass)
|
565
|
+
end
|
566
|
+
|
567
|
+
def test_list_can_have_trailing_comma
|
568
|
+
assert_equal("1, 2, 3", resolve("1, 2, 3,"))
|
569
|
+
end
|
570
|
+
|
571
|
+
def test_trailing_comma_defines_singleton_list
|
572
|
+
assert_equal("1 2 3", resolve("nth((1 2 3,), 1)"))
|
573
|
+
end
|
574
|
+
|
575
|
+
def test_map_cannot_have_duplicate_keys
|
576
|
+
assert_raise_message(Sass::SyntaxError, 'Duplicate key "foo" in map (foo: bar, foo: baz).') do
|
577
|
+
eval("(foo: bar, foo: baz)")
|
578
|
+
end
|
579
|
+
assert_raise_message(Sass::SyntaxError, 'Duplicate key "foo" in map (foo: bar, fo + o: baz).') do
|
580
|
+
eval("(foo: bar, fo + o: baz)")
|
581
|
+
end
|
582
|
+
assert_raise_message(Sass::SyntaxError, 'Duplicate key "foo" in map (foo: bar, "foo": baz).') do
|
583
|
+
eval("(foo: bar, 'foo': baz)")
|
584
|
+
end
|
585
|
+
assert_raise_message(Sass::SyntaxError, 'Duplicate key 2px in map (2px: bar, 1px + 1px: baz).') do
|
586
|
+
eval("(2px: bar, 1px + 1px: baz)")
|
587
|
+
end
|
588
|
+
assert_raise_message(Sass::SyntaxError, 'Duplicate key #0000ff in map (blue: bar, #00f: baz).') do
|
589
|
+
eval("(blue: bar, #00f: baz)")
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
def test_non_duplicate_map_keys
|
594
|
+
# These shouldn't throw errors
|
595
|
+
eval("(foo: foo, bar: bar)")
|
596
|
+
eval("(2px: foo, 2: bar)")
|
597
|
+
eval("(2px: foo, 2em: bar)")
|
598
|
+
eval("('2px': foo, 2px: bar)")
|
599
|
+
end
|
600
|
+
|
601
|
+
def test_map_syntax_errors
|
602
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(foo:": expected expression (e.g. 1px, bold), was ")"') do
|
603
|
+
eval("(foo:)")
|
604
|
+
end
|
605
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(": expected ")", was ":bar)"') do
|
606
|
+
eval("(:bar)")
|
607
|
+
end
|
608
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(foo, bar": expected ")", was ": baz)"') do
|
609
|
+
eval("(foo, bar: baz)")
|
610
|
+
end
|
611
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "(foo: bar, baz": expected ":", was ")"') do
|
612
|
+
eval("(foo: bar, baz)")
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
def test_deep_argument_error_not_unwrapped
|
617
|
+
# JRuby (as of 1.6.7.2) offers no way of distinguishing between
|
618
|
+
# argument errors caused by programming errors in a function and
|
619
|
+
# argument errors explicitly thrown within that function.
|
620
|
+
return if RUBY_PLATFORM =~ /java/
|
621
|
+
|
622
|
+
# Don't validate the message; it's different on Rubinius.
|
623
|
+
assert_raises(ArgumentError) {resolve("arg-error()")}
|
624
|
+
end
|
625
|
+
|
626
|
+
def test_shallow_argument_error_unwrapped
|
627
|
+
assert_raise_message(Sass::SyntaxError, "wrong number of arguments (1 for 0) for `arg-error'") {resolve("arg-error(1)")}
|
628
|
+
end
|
629
|
+
|
630
|
+
def test_boolean_ops_short_circuit
|
631
|
+
assert_equal "false", resolve("$ie and $ie <= 7", {}, env('ie' => Sass::Script::Value::Bool.new(false)))
|
632
|
+
assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Value::Bool.new(true)))
|
633
|
+
end
|
634
|
+
|
635
|
+
def test_selector
|
636
|
+
env = Sass::Environment.new
|
637
|
+
assert_equal "true", resolve("& == null", {}, env)
|
638
|
+
|
639
|
+
env.selector = selector('.foo.bar .baz.bang, .bip.bop')
|
640
|
+
assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
|
641
|
+
assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
|
642
|
+
assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
|
643
|
+
assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
|
644
|
+
assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
|
645
|
+
assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
|
646
|
+
assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
|
647
|
+
|
648
|
+
env.selector = selector('.foo > .bar')
|
649
|
+
assert_equal ".foo > .bar", resolve("&", {}, env)
|
650
|
+
assert_equal ".foo > .bar", resolve("nth(&, 1)", {}, env)
|
651
|
+
assert_equal ".foo", resolve("nth(nth(&, 1), 1)", {}, env)
|
652
|
+
assert_equal ">", resolve("nth(nth(&, 1), 2)", {}, env)
|
653
|
+
assert_equal ".bar", resolve("nth(nth(&, 1), 3)", {}, env)
|
654
|
+
end
|
655
|
+
|
656
|
+
def test_selector_with_newlines
|
657
|
+
env = Sass::Environment.new
|
658
|
+
env.selector = selector(".foo.bar\n.baz.bang,\n\n.bip.bop")
|
659
|
+
assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
|
660
|
+
assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
|
661
|
+
assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
|
662
|
+
assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
|
663
|
+
assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
|
664
|
+
assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
|
665
|
+
assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
|
666
|
+
end
|
667
|
+
|
668
|
+
def test_setting_global_variable_globally
|
669
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
|
670
|
+
.foo {
|
671
|
+
a: 1; }
|
672
|
+
|
673
|
+
.bar {
|
674
|
+
b: 2; }
|
675
|
+
CSS
|
676
|
+
$var: 1;
|
677
|
+
|
678
|
+
.foo {
|
679
|
+
a: $var;
|
680
|
+
}
|
681
|
+
|
682
|
+
$var: 2;
|
683
|
+
|
684
|
+
.bar {
|
685
|
+
b: $var;
|
686
|
+
}
|
687
|
+
SCSS
|
688
|
+
end
|
689
|
+
|
690
|
+
def test_setting_global_variable_locally
|
691
|
+
assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
|
692
|
+
.bar {
|
693
|
+
a: x;
|
694
|
+
b: y;
|
695
|
+
c: z; }
|
696
|
+
CSS
|
697
|
+
$var1: 1;
|
698
|
+
$var3: 3;
|
699
|
+
|
700
|
+
.foo {
|
701
|
+
$var1: x !global;
|
702
|
+
$var2: y !global;
|
703
|
+
@each $var3 in _ {
|
704
|
+
$var3: z !global;
|
705
|
+
}
|
706
|
+
}
|
707
|
+
|
708
|
+
.bar {
|
709
|
+
a: $var1;
|
710
|
+
b: $var2;
|
711
|
+
c: $var3;
|
712
|
+
}
|
713
|
+
SCSS
|
714
|
+
end
|
715
|
+
|
716
|
+
def test_setting_global_variable_locally_with_default
|
717
|
+
assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
|
718
|
+
.bar {
|
719
|
+
a: 1;
|
720
|
+
b: y;
|
721
|
+
c: z; }
|
722
|
+
CSS
|
723
|
+
$var1: 1;
|
724
|
+
|
725
|
+
.foo {
|
726
|
+
$var1: x !global !default;
|
727
|
+
$var2: y !global !default;
|
728
|
+
@each $var3 in _ {
|
729
|
+
$var3: z !global !default;
|
730
|
+
}
|
731
|
+
}
|
732
|
+
|
733
|
+
.bar {
|
734
|
+
a: $var1;
|
735
|
+
b: $var2;
|
736
|
+
c: $var3;
|
737
|
+
}
|
738
|
+
SCSS
|
739
|
+
end
|
740
|
+
|
741
|
+
def test_setting_local_variable
|
742
|
+
assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
|
743
|
+
.a {
|
744
|
+
value: inside; }
|
745
|
+
|
746
|
+
.b {
|
747
|
+
value: outside; }
|
748
|
+
CSS
|
749
|
+
$var: outside;
|
750
|
+
|
751
|
+
.a {
|
752
|
+
$var: inside;
|
753
|
+
value: $var;
|
754
|
+
}
|
755
|
+
|
756
|
+
.b {
|
757
|
+
value: $var;
|
758
|
+
}
|
759
|
+
SCSS
|
760
|
+
end
|
761
|
+
|
762
|
+
def test_setting_local_variable_from_inner_scope
|
763
|
+
assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
|
764
|
+
.a .b {
|
765
|
+
value: inside; }
|
766
|
+
.a .c {
|
767
|
+
value: inside; }
|
768
|
+
CSS
|
769
|
+
.a {
|
770
|
+
$var: outside;
|
771
|
+
|
772
|
+
.b {
|
773
|
+
$var: inside;
|
774
|
+
value: $var;
|
775
|
+
}
|
776
|
+
|
777
|
+
.c {
|
778
|
+
value: $var;
|
779
|
+
}
|
780
|
+
}
|
781
|
+
SCSS
|
782
|
+
end
|
783
|
+
|
784
|
+
def test_color_format_is_preserved_by_default
|
785
|
+
assert_equal "blue", resolve("blue")
|
786
|
+
assert_equal "bLuE", resolve("bLuE")
|
787
|
+
assert_equal "#00f", resolve("#00f")
|
788
|
+
assert_equal "blue #00F", resolve("blue #00F")
|
789
|
+
assert_equal "blue", resolve("nth(blue #00F, 1)")
|
790
|
+
assert_equal "#00F", resolve("nth(blue #00F, 2)")
|
791
|
+
end
|
792
|
+
|
793
|
+
def test_color_format_isnt_always_preserved_in_compressed_style
|
794
|
+
assert_equal "red", resolve("red", :style => :compressed)
|
795
|
+
assert_equal "red", resolve("#f00", :style => :compressed)
|
796
|
+
assert_equal "red red", resolve("red #f00", :style => :compressed)
|
797
|
+
assert_equal "red", resolve("nth(red #f00, 2)", :style => :compressed)
|
798
|
+
end
|
799
|
+
|
800
|
+
def test_color_format_is_sometimes_preserved_in_compressed_style
|
801
|
+
assert_equal "ReD", resolve("ReD", :style => :compressed)
|
802
|
+
assert_equal "blue", resolve("blue", :style => :compressed)
|
803
|
+
assert_equal "#00f", resolve("#00f", :style => :compressed)
|
804
|
+
end
|
805
|
+
|
806
|
+
def test_color_format_isnt_preserved_when_modified
|
807
|
+
assert_equal "magenta", resolve("#f00 + #00f")
|
808
|
+
end
|
809
|
+
|
810
|
+
def test_ids
|
811
|
+
assert_equal "#foo", resolve("#foo")
|
812
|
+
assert_equal "#abcd", resolve("#abcd")
|
813
|
+
assert_equal "#abc-def", resolve("#abc-def")
|
814
|
+
assert_equal "#abc_def", resolve("#abc_def")
|
815
|
+
assert_equal "#uvw-xyz", resolve("#uvw-xyz")
|
816
|
+
assert_equal "#uvw_xyz", resolve("#uvw_xyz")
|
817
|
+
assert_equal "#uvwxyz", resolve("#uvw + xyz")
|
818
|
+
end
|
819
|
+
|
820
|
+
def test_scientific_notation
|
821
|
+
assert_equal "2000", resolve("2e3")
|
822
|
+
assert_equal "2000", resolve("2E3")
|
823
|
+
assert_equal "2000", resolve("2e+3")
|
824
|
+
assert_equal "2000em", resolve("2e3em")
|
825
|
+
assert_equal "25000000000", resolve("2.5e10")
|
826
|
+
assert_equal "0.1234", resolve("1234e-4")
|
827
|
+
assert_equal "12.34", resolve("1.234e1")
|
828
|
+
end
|
829
|
+
|
830
|
+
def test_identifier_units
|
831
|
+
assert_equal "5-foo", resolve("2-foo + 3-foo")
|
832
|
+
assert_equal "5-foo-", resolve("2-foo- + 3-foo-")
|
833
|
+
assert_equal "5-\\u2603", resolve("2-\\u2603 + 3-\\u2603")
|
834
|
+
end
|
835
|
+
|
836
|
+
def test_backslash_newline_in_string
|
837
|
+
assert_equal 'foobar', resolve("\"foo\\\nbar\"")
|
838
|
+
assert_equal 'foobar', resolve("'foo\\\nbar'")
|
839
|
+
end
|
840
|
+
|
841
|
+
def test_unclosed_special_fun
|
842
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(foo()": expected ")", was ""') do
|
843
|
+
resolve("calc(foo()")
|
844
|
+
end
|
845
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{\')\'}": expected ")", was ""') do
|
846
|
+
resolve("calc(\#{')'}")
|
847
|
+
end
|
848
|
+
assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{foo": expected "}", was ""') do
|
849
|
+
resolve("calc(\#{foo")
|
850
|
+
end
|
851
|
+
end
|
852
|
+
|
853
|
+
def test_special_fun_with_interpolation
|
854
|
+
assert_equal "calc())", resolve("calc(\#{')'})")
|
855
|
+
assert_equal "calc(# {foo})", resolve("calc(# {foo})")
|
856
|
+
end
|
857
|
+
|
858
|
+
# Regression Tests
|
859
|
+
|
860
|
+
def test_repeatedly_modified_color
|
861
|
+
assert_equal(<<CSS, render(<<SASS))
|
862
|
+
a {
|
863
|
+
link-color: #161C14;
|
864
|
+
link-color-hover: black;
|
865
|
+
link-color-tap: rgba(22, 28, 20, 0.3); }
|
866
|
+
CSS
|
867
|
+
$green: #161C14
|
868
|
+
$link-color: $green
|
869
|
+
$link-color-hover: darken($link-color, 10%)
|
870
|
+
$link-color-tap: rgba($green, 0.3)
|
871
|
+
|
872
|
+
a
|
873
|
+
link-color: $link-color
|
874
|
+
link-color-hover: $link-color-hover
|
875
|
+
link-color-tap: $link-color-tap
|
876
|
+
SASS
|
877
|
+
end
|
878
|
+
|
879
|
+
def test_inspect_divided_numbers
|
880
|
+
assert_equal "1px/2px", resolve("inspect(1px/2px)")
|
881
|
+
assert_equal "0.5", resolve("inspect((1px/2px))")
|
882
|
+
end
|
883
|
+
|
884
|
+
def test_minus_without_whitespace
|
885
|
+
assert_equal "5px", resolve("15px-10px")
|
886
|
+
assert_equal "5px-", resolve("15px--10px-")
|
887
|
+
end
|
888
|
+
|
889
|
+
def test_minus_preceded_by_comment
|
890
|
+
assert_equal "15px -10px", resolve("15px/**/-10px")
|
891
|
+
end
|
892
|
+
|
893
|
+
def test_user_defined_function_forces_division
|
894
|
+
assert_equal(<<CSS, render(<<SASS))
|
895
|
+
a {
|
896
|
+
b: 10px; }
|
897
|
+
CSS
|
898
|
+
@function foo()
|
899
|
+
@return 20px
|
900
|
+
|
901
|
+
a
|
902
|
+
b: (foo() / 2)
|
903
|
+
SASS
|
904
|
+
|
905
|
+
assert_equal(<<CSS, render(<<SASS))
|
906
|
+
a {
|
907
|
+
b: 10px; }
|
908
|
+
CSS
|
909
|
+
@function foo()
|
910
|
+
@return 20px
|
911
|
+
|
912
|
+
a
|
913
|
+
b: foo() / 2
|
914
|
+
SASS
|
915
|
+
end
|
916
|
+
|
917
|
+
def test_funcall_has_higher_precedence_than_color_name
|
918
|
+
assert_equal "teal(12)", resolve("teal(12)")
|
919
|
+
assert_equal "tealbang(12)", resolve("tealbang(12)")
|
920
|
+
assert_equal "teal-bang(12)", resolve("teal-bang(12)")
|
921
|
+
assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
|
922
|
+
end
|
923
|
+
|
924
|
+
def test_funcall_has_higher_precedence_than_true_false_null
|
925
|
+
assert_equal "teal(12)", resolve("teal(12)")
|
926
|
+
assert_equal "tealbang(12)", resolve("tealbang(12)")
|
927
|
+
assert_equal "teal-bang(12)", resolve("teal-bang(12)")
|
928
|
+
assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
|
929
|
+
end
|
930
|
+
|
931
|
+
def test_and_or_not_disallowed_as_function_names
|
932
|
+
%w[and or not].each do |name|
|
933
|
+
assert_raise_message(Sass::SyntaxError, "Invalid function name \"#{name}\".") do
|
934
|
+
render(<<SASS)
|
935
|
+
@function #{name}()
|
936
|
+
@return null
|
937
|
+
SASS
|
938
|
+
end
|
939
|
+
end
|
940
|
+
end
|
941
|
+
|
942
|
+
def test_interpolation_after_hash
|
943
|
+
assert_equal "#2", resolve('"##{1 + 1}"')
|
944
|
+
end
|
945
|
+
|
946
|
+
def test_misplaced_comma_in_funcall
|
947
|
+
assert_raise_message(Sass::SyntaxError,
|
948
|
+
'Invalid CSS after "foo(bar, ": expected function argument, was ")"') {eval('foo(bar, )')}
|
949
|
+
end
|
950
|
+
|
951
|
+
def test_color_prefixed_identifier
|
952
|
+
assert_equal "tealbang", resolve("tealbang")
|
953
|
+
assert_equal "teal-bang", resolve("teal-bang")
|
954
|
+
end
|
955
|
+
|
956
|
+
def test_op_prefixed_identifier
|
957
|
+
assert_equal "notbang", resolve("notbang")
|
958
|
+
assert_equal "not-bang", resolve("not-bang")
|
959
|
+
assert_equal "or-bang", resolve("or-bang")
|
960
|
+
assert_equal "and-bang", resolve("and-bang")
|
961
|
+
end
|
962
|
+
|
963
|
+
def test_number_initialization
|
964
|
+
assert_equal Sass::Script::Value::Number.new(10, ["px"]), Sass::Script::Value::Number.new(10, "px")
|
965
|
+
assert_equal Sass::Script::Value::Number.new(10, ["px"], ["em"]), Sass::Script::Value::Number.new(10, "px", "em")
|
966
|
+
end
|
967
|
+
|
968
|
+
def test_is_unit
|
969
|
+
assert Sass::Script::Value::Number.new(10, "px").is_unit?("px")
|
970
|
+
assert Sass::Script::Value::Number.new(10).is_unit?(nil)
|
971
|
+
assert !Sass::Script::Value::Number.new(10, "px", "em").is_unit?("px")
|
972
|
+
assert !Sass::Script::Value::Number.new(10, [], "em").is_unit?("em")
|
973
|
+
assert !Sass::Script::Value::Number.new(10, ["px", "em"]).is_unit?("px")
|
974
|
+
end
|
975
|
+
|
976
|
+
def test_rename_redirect
|
977
|
+
assert_no_warning do
|
978
|
+
assert_equal Sass::Script::Value::Base, Sass::Script::Literal
|
979
|
+
assert_equal Sass::Script::Tree::Node, Sass::Script::Node
|
980
|
+
assert_equal Sass::Script::Tree::Operation, Sass::Script::Operation
|
981
|
+
assert_equal Sass::Script::Value::String, Sass::Script::String
|
982
|
+
end
|
983
|
+
end
|
984
|
+
|
985
|
+
def test_number_printing
|
986
|
+
assert_equal "1", resolve("1")
|
987
|
+
assert_equal "1", resolve("1.0")
|
988
|
+
assert_equal "1000000000", resolve("1000000000")
|
989
|
+
assert_equal "0.00001", resolve("0.00001")
|
990
|
+
assert_equal "1.12121", resolve("1.121214")
|
991
|
+
assert_equal "1.12122", resolve("1.121215")
|
992
|
+
assert_equal "Infinity", resolve("(1.0/0.0)")
|
993
|
+
assert_equal "-Infinity", resolve("(-1.0/0.0)")
|
994
|
+
assert_equal "NaN", resolve("(0.0/0.0)")
|
995
|
+
end
|
996
|
+
|
997
|
+
private
|
998
|
+
|
999
|
+
def resolve(str, opts = {}, environment = env)
|
1000
|
+
munge_filename opts
|
1001
|
+
val = eval(str, opts, environment)
|
1002
|
+
assert_kind_of Sass::Script::Value::Base, val
|
1003
|
+
val.is_a?(Sass::Script::Value::String) ? val.value : val.to_s
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
def resolve_quoted(str, opts = {}, environment = env)
|
1007
|
+
munge_filename opts
|
1008
|
+
val = eval(str, opts, environment)
|
1009
|
+
assert_kind_of Sass::Script::Value::Base, val
|
1010
|
+
val.to_s
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def assert_unquoted(str, opts = {}, environment = env)
|
1014
|
+
munge_filename opts
|
1015
|
+
val = eval(str, opts, environment)
|
1016
|
+
assert_kind_of Sass::Script::Value::String, val
|
1017
|
+
assert_equal :identifier, val.type
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
def assert_quoted(str, opts = {}, environment = env)
|
1021
|
+
munge_filename opts
|
1022
|
+
val = eval(str, opts, environment)
|
1023
|
+
assert_kind_of Sass::Script::Value::String, val
|
1024
|
+
assert_equal :string, val.type
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
def eval(str, opts = {}, environment = env)
|
1028
|
+
munge_filename opts
|
1029
|
+
Sass::Script.parse(str, opts.delete(:line) || 1,
|
1030
|
+
opts.delete(:offset) || 0, opts).
|
1031
|
+
perform(Sass::Environment.new(environment, opts))
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
def render(sass, options = {})
|
1035
|
+
munge_filename options
|
1036
|
+
Sass::Engine.new(sass, options).render
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
def env(hash = {})
|
1040
|
+
env = Sass::Environment.new
|
1041
|
+
hash.each {|k, v| env.set_var(k, v)}
|
1042
|
+
env
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def selector(str)
|
1046
|
+
parser = Sass::SCSS::StaticParser.new(
|
1047
|
+
str, filename_for_test, Sass::Importers::Filesystem.new('.'))
|
1048
|
+
parser.parse_selector
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
def test_null_is_a_singleton
|
1052
|
+
assert_same Sass::Script::Value::Null.new, Sass::Script::Value::Null.new
|
1053
|
+
end
|
1054
|
+
end
|