sass 3.5.2 → 3.7.4

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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +1 -1
  3. data/CONTRIBUTING.md +3 -3
  4. data/README.md +17 -9
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/extra/sass-spec-ref.sh +9 -1
  8. data/lib/sass/engine.rb +1 -9
  9. data/lib/sass/exec/base.rb +0 -2
  10. data/lib/sass/exec/sass_scss.rb +1 -5
  11. data/lib/sass/importers/filesystem.rb +4 -2
  12. data/lib/sass/logger/base.rb +11 -0
  13. data/lib/sass/script/css_parser.rb +4 -1
  14. data/lib/sass/script/functions.rb +76 -41
  15. data/lib/sass/script/lexer.rb +62 -19
  16. data/lib/sass/script/parser.rb +260 -93
  17. data/lib/sass/script/tree/funcall.rb +0 -4
  18. data/lib/sass/script/tree/interpolation.rb +0 -3
  19. data/lib/sass/script/tree/operation.rb +1 -1
  20. data/lib/sass/script/value/color.rb +3 -2
  21. data/lib/sass/script/value/helpers.rb +8 -2
  22. data/lib/sass/script/value/number.rb +2 -1
  23. data/lib/sass/scss/css_parser.rb +6 -1
  24. data/lib/sass/scss/parser.rb +48 -18
  25. data/lib/sass/scss/rx.rb +1 -1
  26. data/lib/sass/scss/static_parser.rb +15 -18
  27. data/lib/sass/selector/comma_sequence.rb +2 -1
  28. data/lib/sass/selector/pseudo.rb +1 -1
  29. data/lib/sass/selector/sequence.rb +0 -4
  30. data/lib/sass/source/map.rb +0 -4
  31. data/lib/sass/tree/rule_node.rb +3 -6
  32. data/lib/sass/tree/visitors/perform.rb +2 -6
  33. data/lib/sass/tree/visitors/to_css.rb +4 -11
  34. data/lib/sass/util.rb +60 -20
  35. data/lib/sass/version.rb +0 -2
  36. metadata +38 -162
  37. data/Rakefile +0 -338
  38. data/lib/test.css +0 -4
  39. data/lib/test.css.map +0 -7
  40. data/test/sass-spec.yml +0 -3
  41. data/test/sass/cache_test.rb +0 -130
  42. data/test/sass/callbacks_test.rb +0 -60
  43. data/test/sass/compiler_test.rb +0 -225
  44. data/test/sass/conversion_test.rb +0 -2138
  45. data/test/sass/css2sass_test.rb +0 -523
  46. data/test/sass/css_variable_test.rb +0 -237
  47. data/test/sass/data/hsl-rgb.txt +0 -319
  48. data/test/sass/encoding_test.rb +0 -188
  49. data/test/sass/engine_test.rb +0 -3499
  50. data/test/sass/exec_test.rb +0 -95
  51. data/test/sass/extend_test.rb +0 -1678
  52. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  53. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  54. data/test/sass/functions_test.rb +0 -2021
  55. data/test/sass/importer_test.rb +0 -420
  56. data/test/sass/logger_test.rb +0 -57
  57. data/test/sass/mock_importer.rb +0 -49
  58. data/test/sass/more_results/more1.css +0 -9
  59. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  60. data/test/sass/more_results/more_import.css +0 -29
  61. data/test/sass/more_templates/_more_partial.sass +0 -2
  62. data/test/sass/more_templates/more1.sass +0 -23
  63. data/test/sass/more_templates/more_import.sass +0 -11
  64. data/test/sass/plugin_test.rb +0 -552
  65. data/test/sass/results/alt.css +0 -4
  66. data/test/sass/results/basic.css +0 -9
  67. data/test/sass/results/cached_import_option.css +0 -3
  68. data/test/sass/results/compact.css +0 -5
  69. data/test/sass/results/complex.css +0 -86
  70. data/test/sass/results/compressed.css +0 -1
  71. data/test/sass/results/expanded.css +0 -19
  72. data/test/sass/results/filename_fn.css +0 -3
  73. data/test/sass/results/if.css +0 -3
  74. data/test/sass/results/import.css +0 -31
  75. data/test/sass/results/import_charset.css +0 -5
  76. data/test/sass/results/import_charset_ibm866.css +0 -5
  77. data/test/sass/results/import_content.css +0 -1
  78. data/test/sass/results/line_numbers.css +0 -49
  79. data/test/sass/results/mixins.css +0 -95
  80. data/test/sass/results/multiline.css +0 -24
  81. data/test/sass/results/nested.css +0 -22
  82. data/test/sass/results/options.css +0 -1
  83. data/test/sass/results/parent_ref.css +0 -13
  84. data/test/sass/results/script.css +0 -16
  85. data/test/sass/results/scss_import.css +0 -31
  86. data/test/sass/results/scss_importee.css +0 -2
  87. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  88. data/test/sass/results/subdir/subdir.css +0 -3
  89. data/test/sass/results/units.css +0 -11
  90. data/test/sass/results/warn.css +0 -0
  91. data/test/sass/results/warn_imported.css +0 -0
  92. data/test/sass/script_conversion_test.rb +0 -365
  93. data/test/sass/script_test.rb +0 -1429
  94. data/test/sass/scss/css_test.rb +0 -1266
  95. data/test/sass/scss/rx_test.rb +0 -159
  96. data/test/sass/scss/scss_test.rb +0 -4238
  97. data/test/sass/scss/test_helper.rb +0 -37
  98. data/test/sass/source_map_test.rb +0 -1052
  99. data/test/sass/superselector_test.rb +0 -209
  100. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  101. data/test/sass/templates/_double_import_loop2.sass +0 -1
  102. data/test/sass/templates/_filename_fn_import.scss +0 -11
  103. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  104. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  105. data/test/sass/templates/_imported_content.sass +0 -3
  106. data/test/sass/templates/_partial.sass +0 -2
  107. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  108. data/test/sass/templates/alt.sass +0 -16
  109. data/test/sass/templates/basic.sass +0 -23
  110. data/test/sass/templates/bork1.sass +0 -2
  111. data/test/sass/templates/bork2.sass +0 -2
  112. data/test/sass/templates/bork3.sass +0 -2
  113. data/test/sass/templates/bork4.sass +0 -2
  114. data/test/sass/templates/bork5.sass +0 -3
  115. data/test/sass/templates/cached_import_option.scss +0 -3
  116. data/test/sass/templates/compact.sass +0 -17
  117. data/test/sass/templates/complex.sass +0 -305
  118. data/test/sass/templates/compressed.sass +0 -15
  119. data/test/sass/templates/double_import_loop1.sass +0 -1
  120. data/test/sass/templates/expanded.sass +0 -17
  121. data/test/sass/templates/filename_fn.scss +0 -18
  122. data/test/sass/templates/if.sass +0 -11
  123. data/test/sass/templates/import.sass +0 -12
  124. data/test/sass/templates/import_charset.sass +0 -9
  125. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  126. data/test/sass/templates/import_content.sass +0 -4
  127. data/test/sass/templates/importee.less +0 -2
  128. data/test/sass/templates/importee.sass +0 -19
  129. data/test/sass/templates/line_numbers.sass +0 -13
  130. data/test/sass/templates/mixin_bork.sass +0 -5
  131. data/test/sass/templates/mixins.sass +0 -76
  132. data/test/sass/templates/multiline.sass +0 -20
  133. data/test/sass/templates/nested.sass +0 -25
  134. data/test/sass/templates/nested_bork1.sass +0 -2
  135. data/test/sass/templates/nested_bork2.sass +0 -2
  136. data/test/sass/templates/nested_bork3.sass +0 -2
  137. data/test/sass/templates/nested_bork4.sass +0 -2
  138. data/test/sass/templates/nested_import.sass +0 -2
  139. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  140. data/test/sass/templates/options.sass +0 -2
  141. data/test/sass/templates/parent_ref.sass +0 -25
  142. data/test/sass/templates/same_name_different_ext.sass +0 -2
  143. data/test/sass/templates/same_name_different_ext.scss +0 -1
  144. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/script.sass +0 -101
  146. data/test/sass/templates/scss_import.scss +0 -12
  147. data/test/sass/templates/scss_importee.scss +0 -1
  148. data/test/sass/templates/single_import_loop.sass +0 -1
  149. data/test/sass/templates/subdir/import_up1.scss +0 -1
  150. data/test/sass/templates/subdir/import_up2.scss +0 -1
  151. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  152. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  153. data/test/sass/templates/subdir/subdir.sass +0 -6
  154. data/test/sass/templates/units.sass +0 -11
  155. data/test/sass/templates/warn.sass +0 -3
  156. data/test/sass/templates/warn_imported.sass +0 -4
  157. data/test/sass/test_helper.rb +0 -8
  158. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  159. data/test/sass/util/normalized_map_test.rb +0 -50
  160. data/test/sass/util/subset_map_test.rb +0 -90
  161. data/test/sass/util_test.rb +0 -403
  162. data/test/sass/value_helpers_test.rb +0 -178
  163. data/test/test_helper.rb +0 -149
@@ -1,188 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../test_helper'
3
- require File.dirname(__FILE__) + '/test_helper'
4
- require 'sass/util/test'
5
-
6
- class EncodingTest < MiniTest::Test
7
- include Sass::Util::Test
8
-
9
- def test_encoding_error
10
- render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
11
- assert(false, "Expected exception")
12
- rescue Sass::SyntaxError => e
13
- assert_equal(3, e.sass_line)
14
- assert_equal('Invalid UTF-8 character "\xFE"', e.message)
15
- end
16
-
17
- def test_ascii_incompatible_encoding_error
18
- template = "foo\nbar\nb_z".encode("utf-16le")
19
- template[9] = "\xFE".force_encoding("utf-16le")
20
- render(template)
21
- assert(false, "Expected exception")
22
- rescue Sass::SyntaxError => e
23
- assert_equal(3, e.sass_line)
24
- assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
25
- end
26
-
27
- def test_prefers_charset_to_ruby_encoding
28
- assert_renders_encoded(<<CSS, <<SASS.encode("IBM866").force_encoding("UTF-8"))
29
- @charset "UTF-8";
30
- fЖЖ {
31
- a: b; }
32
- CSS
33
- @charset "ibm866"
34
- fЖЖ
35
- a: b
36
- SASS
37
- end
38
-
39
- def test_uses_ruby_encoding_without_charset
40
- assert_renders_encoded(<<CSS, <<SASS.encode("IBM866"))
41
- @charset "UTF-8";
42
- тАЬ {
43
- a: b; }
44
- CSS
45
- тАЬ
46
- a: b
47
- SASS
48
- end
49
-
50
- def test_multibyte_charset_without_bom_declared_as_binary
51
- engine = Sass::Engine.new(<<SASS.encode("UTF-16LE").force_encoding("BINARY"))
52
- @charset "utf-16le"
53
- fóó
54
- a: b
55
- SASS
56
- # Since multibyte encodings' @charset declarations aren't
57
- # ASCII-compatible, we have to interpret the files as UTF-8 which will
58
- # inevitably fail.
59
- assert_raise_message(Sass::SyntaxError, "Invalid UTF-8 character \"\\xF3\"") {engine.render}
60
- end
61
-
62
- def test_multibyte_charset_without_bom_declared_as_utf_8
63
- engine = Sass::Engine.new(<<SASS.encode("UTF-16LE").force_encoding("UTF-8"))
64
- @charset "utf-16le"
65
- fóó
66
- a: b
67
- SASS
68
- # Since multibyte encodings' @charset declarations aren't
69
- # ASCII-compatible, we have to interpret the files as UTF-8 which will
70
- # inevitably fail.
71
- assert_raise_message(Sass::SyntaxError, "Invalid UTF-8 character \"\\xF3\"") {engine.render}
72
- end
73
-
74
- def test_utf_16le_with_bom
75
- assert_renders_encoded(<<CSS, <<SASS.encode("UTF-16LE").force_encoding("BINARY"))
76
- @charset "UTF-8";
77
- fóó {
78
- a: b; }
79
- CSS
80
- \uFEFFfóó
81
- a: b
82
- SASS
83
- end
84
-
85
- def test_utf_16be_with_bom
86
- assert_renders_encoded(<<CSS, <<SASS.encode("UTF-16BE").force_encoding("BINARY"))
87
- @charset "UTF-8";
88
- fóó {
89
- a: b; }
90
- CSS
91
- \uFEFFfóó
92
- a: b
93
- SASS
94
- end
95
-
96
- def test_utf_8_with_bom
97
- assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
98
- @charset "UTF-8";
99
- fóó {
100
- a: b; }
101
- CSS
102
- \uFEFFfóó
103
- a: b
104
- SASS
105
- end
106
-
107
- def test_charset_with_multibyte_encoding
108
- engine = Sass::Engine.new(<<SASS)
109
- @charset "utf-32be"
110
- fóó
111
- a: b
112
- SASS
113
- # The charset declaration is just false here, so we should get an
114
- # encoding error.
115
- assert_raise_message(Sass::SyntaxError, "Invalid UTF-32BE character \"\\xC3\"") {engine.render}
116
- end
117
-
118
- def test_charset_with_special_case_encoding
119
- # For some reason, a file with an ASCII-compatible UTF-16 charset
120
- # declaration is specced to be parsed as UTF-8.
121
- assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
122
- @charset "UTF-8";
123
- fóó {
124
- a: b; }
125
- CSS
126
- @charset "utf-16"
127
- fóó
128
- a: b
129
- SASS
130
- end
131
-
132
- def test_compressed_output_uses_bom
133
- assert_equal("\uFEFFfóó{a:b}\n", render(<<SASS, :style => :compressed))
134
- fóó
135
- a: b
136
- SASS
137
- end
138
-
139
- def test_newline_normalization
140
- assert_equal("/* foo\nbar\nbaz\nbang\nqux */\n",
141
- render("/* foo\nbar\r\nbaz\fbang\rqux */", :syntax => :scss))
142
- end
143
-
144
- def test_null_normalization
145
- assert_equal(<<CSS, render("/* foo\x00bar\x00baz */", :syntax => :scss))
146
- @charset "UTF-8";
147
- /* foo�bar�baz */
148
- CSS
149
- end
150
-
151
- # Regression
152
-
153
- def test_multibyte_prop_name
154
- assert_equal(<<CSS, render(<<SASS))
155
- @charset "UTF-8";
156
- #bar {
157
- cölor: blue; }
158
- CSS
159
- #bar
160
- cölor: blue
161
- SASS
162
- end
163
-
164
- def test_multibyte_and_interpolation
165
- assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
166
- #bar {
167
- background: a 0%; }
168
- CSS
169
- #bar {
170
- // 
171
- background: \#{a} 0%;
172
- }
173
- SCSS
174
- end
175
-
176
- private
177
-
178
- def assert_renders_encoded(css, sass)
179
- result = render(sass)
180
- assert_equal css.encoding, result.encoding
181
- assert_equal css, result
182
- end
183
-
184
- def render(sass, options = {})
185
- munge_filename options
186
- Sass::Engine.new(sass, options).render
187
- end
188
- end
@@ -1,3499 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../test_helper'
3
- require File.dirname(__FILE__) + '/test_helper'
4
- require 'sass/engine'
5
- require 'stringio'
6
- require 'mock_importer'
7
- require 'pathname'
8
-
9
- module Sass::Script::Functions::UserFunctions
10
- def option(name)
11
- Sass::Script::Value::String.new(@options[name.value.to_sym].to_s)
12
- end
13
-
14
- def set_a_variable(name, value)
15
- environment.set_var(name.value, value)
16
- return Sass::Script::Value::Null.new
17
- end
18
-
19
- def set_a_global_variable(name, value)
20
- environment.set_global_var(name.value, value)
21
- return Sass::Script::Value::Null.new
22
- end
23
-
24
- def get_a_variable(name)
25
- environment.var(name.value) || Sass::Script::Value::String.new("undefined")
26
- end
27
- end
28
-
29
- module Sass::Script::Functions
30
- include Sass::Script::Functions::UserFunctions
31
- end
32
-
33
- class SassEngineTest < MiniTest::Test
34
- FAKE_FILE_NAME = __FILE__.gsub(/rb$/,"sass")
35
- # A map of erroneous Sass documents to the error messages they should produce.
36
- # The error messages may be arrays;
37
- # if so, the second element should be the line number that should be reported for the error.
38
- # If this isn't provided, the tests will assume the line number should be the last line of the document.
39
- EXCEPTION_MAP = {
40
- "$a: 1 + " => 'Invalid CSS after "1 +": expected expression (e.g. 1px, bold), was ""',
41
- "$a: 1 + 2 +" => 'Invalid CSS after "1 + 2 +": expected expression (e.g. 1px, bold), was ""',
42
- "$a: 1 + 2 + %" => 'Invalid CSS after "1 + 2 + ": expected expression (e.g. 1px, bold), was "%"',
43
- "$a: foo(\"bar\"" => 'Invalid CSS after "foo("bar"": expected ")", was ""',
44
- "$a: 1 }" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}"',
45
- "$a: 1 }foo\"" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}foo""',
46
- ":" => 'Invalid property: ":".',
47
- ": a" => 'Invalid property: ": a".',
48
- "a\n :b" => <<MSG,
49
- Invalid property: ":b" (no value).
50
- If ":b" should be a selector, use "\\:b" instead.
51
- MSG
52
- "a\n b:" => 'Invalid property: "b:" (no value).',
53
- "a\n :b: c" => 'Invalid property: ":b: c".',
54
- "a\n :b:c d" => 'Invalid property: ":b:c d".',
55
- "a\n :b c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
56
- "a\n b: c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
57
- ".foo ^bar\n a: b" => ['Invalid CSS after ".foo ": expected selector, was "^bar"', 1],
58
- "a\n @extend .foo ^bar" => 'Invalid CSS after ".foo ": expected selector, was "^bar"',
59
- "a\n @extend .foo .bar" => "Can't extend .foo .bar: can't extend nested selectors",
60
- "a\n @extend >" => "Can't extend >: invalid selector",
61
- "a\n @extend &.foo" => "Can't extend &.foo: can't extend parent selectors",
62
- "a: b" => 'Properties are only allowed within rules, directives, mixin includes, or other properties.',
63
- ":a b" => 'Properties are only allowed within rules, directives, mixin includes, or other properties.',
64
- "$" => 'Invalid variable: "$".',
65
- "$a" => 'Invalid variable: "$a".',
66
- "$ a" => 'Invalid variable: "$ a".',
67
- "$a b" => 'Invalid variable: "$a b".',
68
- "$a: 1b + 2c" => "Incompatible units: 'c' and 'b'.",
69
- "$a: 1b < 2c" => "Incompatible units: 'c' and 'b'.",
70
- "$a: 1b > 2c" => "Incompatible units: 'c' and 'b'.",
71
- "$a: 1b <= 2c" => "Incompatible units: 'c' and 'b'.",
72
- "$a: 1b >= 2c" => "Incompatible units: 'c' and 'b'.",
73
- "a\n b: 1b * 2c" => "2b*c isn't a valid CSS value.",
74
- "a\n b: 1b % 2c" => "Incompatible units: 'c' and 'b'.",
75
- "$a: 2px + #ccc" => "Cannot add a number with units (2px) to a color (#ccc).",
76
- "$a: #ccc + 2px" => "Cannot add a number with units (2px) to a color (#ccc).",
77
- "& a\n :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
78
- "a\n :b\n c" => "Illegal nesting: Only properties may be nested beneath properties.",
79
- "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
80
- "@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
81
- "foo\n @import foo.css" => "CSS import directives may only be used at the root of a document.",
82
- "@if true\n @import foo" => "Import directives may not be used within control directives or mixins.",
83
- "@if true\n .foo\n @import foo" => "Import directives may not be used within control directives or mixins.",
84
- "@mixin foo\n @import foo" => "Import directives may not be used within control directives or mixins.",
85
- "@mixin foo\n .foo\n @import foo" => "Import directives may not be used within control directives or mixins.",
86
- "@import foo;" => "Invalid @import: expected end of line, was \";\".",
87
- '$foo: "bar" "baz" !' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "!"},
88
- '$foo: "bar" "baz" $' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "$"}, #'
89
- "=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.",
90
- "=foo\n :color red\n.bar\n +bang_bop" => "Undefined mixin 'bang_bop'.",
91
- "=foo\n :color red\n.bar\n +bang-bop" => "Undefined mixin 'bang-bop'.",
92
- ".foo\n =foo\n :color red\n.bar\n +foo" => "Undefined mixin 'foo'.",
93
- " a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1],
94
- " \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4],
95
- "a\n b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 3],
96
- "a\n b: c\na\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 4],
97
- "a\n\t\tb: c\n\tb: c" => ["Inconsistent indentation: 1 tab was used for indentation, but the rest of the document was indented using 2 tabs.", 3],
98
- "a\n b: c\n b: c" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 3],
99
- "a\n b: c\n a\n d: e" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 4],
100
- "a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
101
- "=a(" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ""',
102
- "=a(b)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "b)"',
103
- "=a(,)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ",)"',
104
- "=a($)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "$)"',
105
- "=a($foo bar)" => 'Invalid CSS after "($foo ": expected ")", was "bar)"',
106
- "=foo\n bar: baz\n+foo" => ["Properties are only allowed within rules, directives, mixin includes, or other properties.", 2],
107
- "a-\#{$b\n c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1],
108
- "=a($b: 1, $c)" => "Required argument $c must come before any optional arguments.",
109
- "=a($b: 1)\n a: $b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
110
- "=a($b: 1)\n a: $b\ndiv\n +a(1,$c: 3)" => "Mixin a doesn't have an argument named $c.",
111
- "=a($b)\n a: $b\ndiv\n +a" => "Mixin a is missing argument $b.",
112
- "@function foo()\n 1 + 2" => "Functions can only contain variable declarations and control directives.",
113
- "@function foo()\n foo: bar" => "Functions can only contain variable declarations and control directives.",
114
- "@function foo()\n foo: bar\n @return 3" => ["Functions can only contain variable declarations and control directives.", 2],
115
- "@function foo\n @return 1" => ['Invalid CSS after "": expected "(", was ""', 1],
116
- "@function foo(\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ""', 1],
117
- "@function foo(b)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "b)"', 1],
118
- "@function foo(,)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ",)"', 1],
119
- "@function foo($)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "$)"', 1],
120
- "@function foo()\n @return" => 'Invalid @return: expected expression.',
121
- "@function foo()\n @return 1\n $var: val" => 'Illegal nesting: Nothing may be nested beneath return directives.',
122
- "@function foo($a)\n @return 1\na\n b: foo()" => 'Function foo is missing argument $a.',
123
- "@function foo()\n @return 1\na\n b: foo(2)" => 'Function foo takes 0 arguments but 1 was passed.',
124
- "@function foo()\n @return 1\na\n b: foo($a: 1)" => "Function foo doesn't have an argument named $a.",
125
- "@function foo()\n @return 1\na\n b: foo($a: 1, $b: 2)" => "Function foo doesn't have the following arguments: $a, $b.",
126
- "@return 1" => '@return may only be used within a function.',
127
- "@if true\n @return 1" => '@return may only be used within a function.',
128
- "@mixin foo\n @return 1\n@include foo" => ['@return may only be used within a function.', 2],
129
- "@else\n a\n b: c" => ["@else must come after @if.", 1],
130
- "@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
131
- "@if false\n@else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
132
- "a\n $b: 12\nc\n d: $b" => 'Undefined variable: "$b".',
133
- "=foo\n $b: 12\nc\n +foo\n d: $b" => 'Undefined variable: "$b".',
134
- "c\n d: $b-foo" => 'Undefined variable: "$b-foo".',
135
- "c\n d: $b_foo" => 'Undefined variable: "$b_foo".',
136
- '@for $a from "foo" to 1' => '"foo" is not an integer.',
137
- '@for $a from 1 to "2"' => '"2" is not an integer.',
138
- '@for $a from 1 to "foo"' => '"foo" is not an integer.',
139
- '@for $a from 1 to 1.23232323232' => '1.2323232323 is not an integer.',
140
- '@for $a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
141
- '@if' => "Invalid if directive '@if': expected expression.",
142
- '@while' => "Invalid while directive '@while': expected expression.",
143
- '@debug' => "Invalid debug directive '@debug': expected expression.",
144
- %Q{@debug "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath debug directives.",
145
- '@error' => "Invalid error directive '@error': expected expression.",
146
- %Q{@error "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath error directives.",
147
- '@warn' => "Invalid warn directive '@warn': expected expression.",
148
- %Q{@warn "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath warn directives.",
149
- "/* foo\n bar\n baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this line was indented by 2 spaces.",
150
- '+foo(1 + 1: 2)' => 'Invalid CSS after "(1 + 1": expected comma, was ": 2)"',
151
- '+foo($var: )' => 'Invalid CSS after "($var: ": expected mixin argument, was ")"',
152
- '+foo($var: a, $var: b)' => 'Keyword argument "$var" passed more than once',
153
- '+foo($var-var: a, $var_var: b)' => 'Keyword argument "$var_var" passed more than once',
154
- '+foo($var_var: a, $var-var: b)' => 'Keyword argument "$var-var" passed more than once',
155
- "a\n b: foo(1 + 1: 2)" => 'Invalid CSS after "foo(1 + 1": expected comma, was ": 2)"',
156
- "a\n b: foo($var: )" => 'Invalid CSS after "foo($var: ": expected function argument, was ")"',
157
- "a\n b: foo($var: a, $var: b)" => 'Keyword argument "$var" passed more than once',
158
- "a\n b: foo($var-var: a, $var_var: b)" => 'Keyword argument "$var_var" passed more than once',
159
- "a\n b: foo($var_var: a, $var-var: b)" => 'Keyword argument "$var-var" passed more than once',
160
- "@if foo\n @extend .bar" => ["Extend directives may only be used within rules.", 2],
161
- "$var: true\n@while $var\n @extend .bar\n $var: false" => ["Extend directives may only be used within rules.", 3],
162
- "@for $i from 0 to 1\n @extend .bar" => ["Extend directives may only be used within rules.", 2],
163
- "@mixin foo\n @extend .bar\n@include foo" => ["Extend directives may only be used within rules.", 2],
164
- "foo %\n a: b" => ['Invalid CSS after "foo %": expected placeholder name, was ""', 1],
165
- "=foo\n @content error" => "Invalid content directive. Trailing characters found: \"error\".",
166
- "=foo\n @content\n b: c" => "Illegal nesting: Nothing may be nested beneath @content directives.",
167
- "@content" => '@content may only be used within a mixin.',
168
- "=simple\n .simple\n color: red\n+simple\n color: blue" => ['Mixin "simple" does not accept a content block.', 4],
169
- "@import \"foo\" // bar" => "Invalid CSS after \"\"foo\" \": expected media query list, was \"// bar\"",
170
- "@at-root\n a: b" => "Properties are only allowed within rules, directives, mixin includes, or other properties.",
171
-
172
- # Regression tests
173
- "a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
174
- "& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
175
- "a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3],
176
- "@" => "Invalid directive: '@'.",
177
- "$r: 20em * #ccc" => ["Cannot multiply a number with units (20em) to a color (#ccc).", 1],
178
- "$r: #ccc / 1em" => ["Cannot divide a number with units (1em) to a color (#ccc).", 1],
179
- }
180
-
181
- def teardown
182
- clean_up_sassc
183
- end
184
-
185
- def test_basic_render
186
- renders_correctly "basic", { :style => :compact }
187
- end
188
-
189
- def test_empty_render
190
- assert_equal "", render("")
191
- end
192
-
193
- def test_multiple_calls_to_render
194
- sass = Sass::Engine.new("a\n b: c")
195
- assert_equal sass.render, sass.render
196
- end
197
-
198
- def test_alternate_styles
199
- renders_correctly "expanded", { :style => :expanded }
200
- renders_correctly "compact", { :style => :compact }
201
- renders_correctly "nested", { :style => :nested }
202
- renders_correctly "compressed", { :style => :compressed }
203
- end
204
-
205
- def test_compile
206
- assert_equal "div { hello: world; }\n", Sass.compile("$who: world\ndiv\n hello: $who", :syntax => :sass, :style => :compact)
207
- assert_equal "div { hello: world; }\n", Sass.compile("$who: world; div { hello: $who }", :style => :compact)
208
- end
209
-
210
- def test_compile_file
211
- FileUtils.mkdir_p(absolutize("tmp"))
212
- open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")}
213
- open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
214
- assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.sass"), :style => :compact)
215
- assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.scss"), :style => :compact)
216
- ensure
217
- FileUtils.rm_rf(absolutize("tmp"))
218
- end
219
-
220
- def test_compile_file_to_css_file
221
- FileUtils.mkdir_p(absolutize("tmp"))
222
- open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")}
223
- open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
224
- Sass.compile_file(absolutize("tmp/test_compile_file.sass"), absolutize("tmp/test_compile_file_sass.css"), :style => :compact)
225
- Sass.compile_file(absolutize("tmp/test_compile_file.scss"), absolutize("tmp/test_compile_file_scss.css"), :style => :compact)
226
- assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_sass.css"))
227
- assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_scss.css"))
228
- ensure
229
- FileUtils.rm_rf(absolutize("tmp"))
230
- end
231
-
232
- def test_flexible_tabulation
233
- assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
234
- render("p\n a: b\n q\n c: d\n"))
235
- assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
236
- render("p\n\ta: b\n\tq\n\t\tc: d\n"))
237
- end
238
-
239
- def test_import_same_name_different_ext
240
- assert_raise_message Sass::SyntaxError, <<ERROR do
241
- It's not clear which file to import for '@import "same_name_different_ext"'.
242
- Candidates:
243
- same_name_different_ext.sass
244
- same_name_different_ext.scss
245
- Please delete or rename all but one of these files.
246
- ERROR
247
- options = {:load_paths => [File.dirname(__FILE__) + '/templates/']}
248
- munge_filename options
249
- Sass::Engine.new("@import 'same_name_different_ext'", options).render
250
- end
251
- end
252
-
253
- def test_import_same_name_different_partiality
254
- assert_raise_message Sass::SyntaxError, <<ERROR do
255
- It's not clear which file to import for '@import "same_name_different_partiality"'.
256
- Candidates:
257
- _same_name_different_partiality.scss
258
- same_name_different_partiality.scss
259
- Please delete or rename all but one of these files.
260
- ERROR
261
- options = {:load_paths => [File.dirname(__FILE__) + '/templates/']}
262
- munge_filename options
263
- Sass::Engine.new("@import 'same_name_different_partiality'", options).render
264
- end
265
- end
266
-
267
- EXCEPTION_MAP.each do |key, value|
268
- define_method("test_exception (#{key.inspect})") do
269
- line = 10
270
- begin
271
- silence_warnings {Sass::Engine.new(key, :filename => FAKE_FILE_NAME, :line => line).render}
272
- rescue Sass::SyntaxError => err
273
- value = [value] unless value.is_a?(Array)
274
-
275
- assert_equal(value.first.rstrip, err.message, "Line: #{key}")
276
- assert_equal(FAKE_FILE_NAME, err.sass_filename)
277
- assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
278
- assert_match(/#{Regexp.escape(FAKE_FILE_NAME)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
279
- else
280
- assert(false, "Exception not raised for\n#{key}")
281
- end
282
- end
283
- end
284
-
285
- def test_exception_line
286
- to_render = <<SASS
287
- rule
288
- prop: val
289
- // comment!
290
-
291
- broken:
292
- SASS
293
- begin
294
- Sass::Engine.new(to_render).render
295
- rescue Sass::SyntaxError => err
296
- assert_equal(5, err.sass_line)
297
- else
298
- assert(false, "Exception not raised for '#{to_render}'!")
299
- end
300
- end
301
-
302
- def test_exception_location
303
- to_render = <<SASS
304
- rule
305
- prop: val
306
- // comment!
307
-
308
- broken:
309
- SASS
310
- begin
311
- Sass::Engine.new(to_render, :filename => FAKE_FILE_NAME, :line => (__LINE__-7)).render
312
- rescue Sass::SyntaxError => err
313
- assert_equal(FAKE_FILE_NAME, err.sass_filename)
314
- assert_equal((__LINE__-6), err.sass_line)
315
- else
316
- assert(false, "Exception not raised for '#{to_render}'!")
317
- end
318
- end
319
-
320
- def test_imported_exception
321
- [1, 2, 3, 4].each do |i|
322
- begin
323
- Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
324
- rescue Sass::SyntaxError => err
325
- assert_equal(2, err.sass_line)
326
- assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
327
-
328
- assert_hash_has(err.sass_backtrace.first,
329
- :filename => err.sass_filename, :line => err.sass_line)
330
-
331
- assert_nil(err.sass_backtrace[1][:filename])
332
- assert_equal(1, err.sass_backtrace[1][:line])
333
-
334
- assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
335
- assert_equal("(sass):1", err.backtrace[1])
336
- else
337
- assert(false, "Exception not raised for imported template: bork#{i}")
338
- end
339
- end
340
- end
341
-
342
- def test_double_imported_exception
343
- [1, 2, 3, 4].each do |i|
344
- begin
345
- Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
346
- rescue Sass::SyntaxError => err
347
- assert_equal(2, err.sass_line)
348
- assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
349
-
350
- assert_hash_has(err.sass_backtrace.first,
351
- :filename => err.sass_filename, :line => err.sass_line)
352
-
353
- assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename])
354
- assert_equal(2, err.sass_backtrace[1][:line])
355
-
356
- assert_nil(err.sass_backtrace[2][:filename])
357
- assert_equal(1, err.sass_backtrace[2][:line])
358
-
359
- assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
360
- assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1])
361
- assert_equal("(sass):1", err.backtrace[2])
362
- else
363
- assert(false, "Exception not raised for imported template: bork#{i}")
364
- end
365
- end
366
- end
367
-
368
- def test_selector_tracing
369
- actual_css = render(<<-SCSS, :syntax => :scss, :trace_selectors => true)
370
- @mixin mixed {
371
- .mixed { color: red; }
372
- }
373
- .context {
374
- @include mixed;
375
- }
376
- SCSS
377
- assert_equal(<<CSS,actual_css)
378
- /* on line 2 of test_selector_tracing_inline.scss, in `mixed'
379
- from line 5 of test_selector_tracing_inline.scss */
380
- .context .mixed {
381
- color: red; }
382
- CSS
383
- end
384
-
385
- def test_mixin_exception
386
- render(<<SASS)
387
- =error-mixin($a)
388
- color: $a * 1em * 1px
389
-
390
- =outer-mixin($a)
391
- +error-mixin($a)
392
-
393
- .error
394
- +outer-mixin(12)
395
- SASS
396
- assert(false, "Exception not raised")
397
- rescue Sass::SyntaxError => err
398
- assert_equal(2, err.sass_line)
399
- assert_equal(filename_for_test, err.sass_filename)
400
- assert_equal("error-mixin", err.sass_mixin)
401
-
402
- assert_hash_has(err.sass_backtrace.first, :line => err.sass_line,
403
- :filename => err.sass_filename, :mixin => err.sass_mixin)
404
- assert_hash_has(err.sass_backtrace[1], :line => 5,
405
- :filename => filename_for_test, :mixin => "outer-mixin")
406
- assert_hash_has(err.sass_backtrace[2], :line => 8,
407
- :filename => filename_for_test, :mixin => nil)
408
-
409
- assert_equal("#{filename_for_test}:2:in `error-mixin'", err.backtrace.first)
410
- assert_equal("#{filename_for_test}:5:in `outer-mixin'", err.backtrace[1])
411
- assert_equal("#{filename_for_test}:8", err.backtrace[2])
412
- end
413
-
414
- def test_mixin_callsite_exception
415
- render(<<SASS)
416
- =one-arg-mixin($a)
417
- color: $a
418
-
419
- =outer-mixin($a)
420
- +one-arg-mixin($a, 12)
421
-
422
- .error
423
- +outer-mixin(12)
424
- SASS
425
- assert(false, "Exception not raised")
426
- rescue Sass::SyntaxError => err
427
- assert_hash_has(err.sass_backtrace.first, :line => 5,
428
- :filename => filename_for_test, :mixin => "one-arg-mixin")
429
- assert_hash_has(err.sass_backtrace[1], :line => 5,
430
- :filename => filename_for_test, :mixin => "outer-mixin")
431
- assert_hash_has(err.sass_backtrace[2], :line => 8,
432
- :filename => filename_for_test, :mixin => nil)
433
- end
434
-
435
- def test_mixin_exception_cssize
436
- render(<<SASS)
437
- =parent-ref-mixin
438
- & foo
439
- a: b
440
-
441
- =outer-mixin
442
- +parent-ref-mixin
443
-
444
- +outer-mixin
445
- SASS
446
- assert(false, "Exception not raised")
447
- rescue Sass::SyntaxError => err
448
- assert_hash_has(err.sass_backtrace.first, :line => 2,
449
- :filename => filename_for_test, :mixin => "parent-ref-mixin")
450
- assert_hash_has(err.sass_backtrace[1], :line => 6,
451
- :filename => filename_for_test, :mixin => "outer-mixin")
452
- assert_hash_has(err.sass_backtrace[2], :line => 8,
453
- :filename => filename_for_test, :mixin => nil)
454
- end
455
-
456
- def test_mixin_and_import_exception
457
- Sass::Engine.new("@import nested_mixin_bork", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
458
- assert(false, "Exception not raised")
459
- rescue Sass::SyntaxError => err
460
- assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace.first[:filename])
461
- assert_hash_has(err.sass_backtrace.first, :mixin => "error-mixin", :line => 4)
462
-
463
- assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[1][:filename])
464
- assert_hash_has(err.sass_backtrace[1], :mixin => "outer-mixin", :line => 2)
465
-
466
- assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[2][:filename])
467
- assert_hash_has(err.sass_backtrace[2], :mixin => nil, :line => 5)
468
-
469
- assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace[3][:filename])
470
- assert_hash_has(err.sass_backtrace[3], :mixin => nil, :line => 6)
471
-
472
- assert_hash_has(err.sass_backtrace[4], :filename => nil, :mixin => nil, :line => 1)
473
- end
474
-
475
- def test_recursive_mixin
476
- assert_equal <<CSS, render(<<SASS)
477
- .foo .bar .baz {
478
- color: blue; }
479
- .foo .bar .qux {
480
- color: red; }
481
- .foo .zap {
482
- color: green; }
483
- CSS
484
- @mixin map-to-rule($map-or-color)
485
- @if type-of($map-or-color) == map
486
- @each $key, $value in $map-or-color
487
- .\#{$key}
488
- @include map-to-rule($value)
489
- @else
490
- color: $map-or-color
491
-
492
- @include map-to-rule((foo: (bar: (baz: blue, qux: red), zap: green)))
493
- SASS
494
- end
495
-
496
- def test_double_import_loop_exception
497
- importer = MockImporter.new
498
- importer.add_import("foo", "@import 'bar'")
499
- importer.add_import("bar", "@import 'foo'")
500
-
501
- engine = Sass::Engine.new('@import "foo"', :filename => filename_for_test,
502
- :load_paths => [importer], :importer => importer)
503
-
504
- assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) {engine.render}
505
- An @import loop has been found:
506
- #{filename_for_test} imports foo
507
- foo imports bar
508
- bar imports foo
509
- ERR
510
- end
511
-
512
- def test_deep_import_loop_exception
513
- importer = MockImporter.new
514
- importer.add_import("foo", "@import 'bar'")
515
- importer.add_import("bar", "@import 'baz'")
516
- importer.add_import("baz", "@import 'foo'")
517
-
518
- engine = Sass::Engine.new('@import "foo"', :filename => filename_for_test,
519
- :load_paths => [importer], :importer => importer)
520
-
521
- assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) {engine.render}
522
- An @import loop has been found:
523
- #{filename_for_test} imports foo
524
- foo imports bar
525
- bar imports baz
526
- baz imports foo
527
- ERR
528
- end
529
-
530
- def test_exception_css_with_offset
531
- opts = {:full_exception => true, :line => 362}
532
- render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts)
533
- rescue Sass::SyntaxError => e
534
- assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts[:line]).split("\n")[0..15].join("\n"))
535
- /*
536
- Error: Invalid property: "e:" (no value).
537
- on line 383 of test_exception_css_with_offset_inline.sass
538
-
539
- 378: a
540
- 379: b: c
541
- 380: a
542
- 381: b: c
543
- 382: d
544
- 383: e:
545
- 384: f
546
- 385: g: h
547
- 386: f
548
- 387: g: h
549
- 388: f
550
- CSS
551
- else
552
- assert(false, "Exception not raised for test_exception_css_with_offset")
553
- end
554
-
555
- def test_exception_css_with_mixins
556
- render(<<SASS, :full_exception => true)
557
- =error-mixin($a)
558
- color: $a * 1em * 1px
559
-
560
- =outer-mixin($a)
561
- +error-mixin($a)
562
-
563
- .error
564
- +outer-mixin(12)
565
- SASS
566
- rescue Sass::SyntaxError => e
567
- assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e).split("\n")[0..13].join("\n"))
568
- /*
569
- Error: 12em*px isn't a valid CSS value.
570
- on line 2 of test_exception_css_with_mixins_inline.sass, in `error-mixin'
571
- from line 5 of test_exception_css_with_mixins_inline.sass, in `outer-mixin'
572
- from line 8 of test_exception_css_with_mixins_inline.sass
573
-
574
- 1: =error-mixin($a)
575
- 2: color: $a * 1em * 1px
576
- 3:
577
- 4: =outer-mixin($a)
578
- 5: +error-mixin($a)
579
- 6:
580
- 7: .error
581
- CSS
582
- else
583
- assert(false, "Exception not raised")
584
- end
585
-
586
- def test_cssize_exception_css
587
- render(<<SASS, :full_exception => true)
588
- .filler
589
- stuff: "stuff!"
590
-
591
- a: b
592
-
593
- .more.filler
594
- a: b
595
- SASS
596
- rescue Sass::SyntaxError => e
597
- assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e).split("\n")[0..11].join("\n"))
598
- /*
599
- Error: Properties are only allowed within rules, directives, mixin includes, or other properties.
600
- on line 4 of test_cssize_exception_css_inline.sass
601
-
602
- 1: .filler
603
- 2: stuff: "stuff!"
604
- 3:
605
- 4: a: b
606
- 5:
607
- 6: .more.filler
608
- 7: a: b
609
- CSS
610
- else
611
- assert(false, "Exception not raised")
612
- end
613
-
614
- def test_css_import
615
- assert_equal("@import url(./fonts.css);\n", render("@import \"./fonts.css\""))
616
- end
617
-
618
- def test_http_import
619
- assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n",
620
- render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\""))
621
- end
622
-
623
- def test_protocol_relative_import
624
- assert_equal("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";\n",
625
- render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\""))
626
- end
627
-
628
- def test_import_with_interpolation
629
- assert_equal(<<CSS, render(<<SASS))
630
- @import url("http://fonts.googleapis.com/css?family=Droid+Sans");
631
- CSS
632
- $family: unquote("Droid+Sans")
633
- @import url("http://fonts.googleapis.com/css?family=\#{$family}")
634
- SASS
635
- end
636
-
637
- def test_import_with_dynamic_media_query
638
- assert_equal(<<CSS, render(<<SASS))
639
- @import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
640
- CSS
641
- $media: print
642
- $key: -webkit-min-device-pixel-ratio
643
- $value: 20
644
- @import "foo" \#{$media} and ($key + "-foo": $value + 5)
645
- SASS
646
- end
647
-
648
- def test_url_import
649
- assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass)"))
650
- end
651
-
652
- def test_sass_import
653
- sassc_file = sassc_path("importee")
654
- assert !File.exist?(sassc_file)
655
- renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] }
656
- assert File.exist?(sassc_file)
657
- end
658
-
659
- def test_sass_pathname_import
660
- sassc_file = sassc_path("importee")
661
- assert !File.exist?(sassc_file)
662
- renders_correctly("import",
663
- :style => :compact,
664
- :load_paths => [Pathname.new(File.dirname(__FILE__) + "/templates")])
665
- assert File.exist?(sassc_file)
666
- end
667
-
668
- def test_import_from_global_load_paths
669
- importer = MockImporter.new
670
- importer.add_import("imported", "div{color:red}")
671
- Sass.load_paths << importer
672
-
673
- assert_equal "div {\n color: red; }\n", Sass::Engine.new('@import "imported"', :importer => importer).render
674
- ensure
675
- Sass.load_paths.clear
676
- end
677
-
678
- def test_nonexistent_import
679
- assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) do
680
- File to import not found or unreadable: nonexistent.sass.
681
- ERR
682
- render("@import nonexistent.sass")
683
- end
684
- end
685
-
686
- def test_nonexistent_extensionless_import
687
- assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) do
688
- File to import not found or unreadable: nonexistent.
689
- ERR
690
- render("@import nonexistent")
691
- end
692
- end
693
-
694
- def test_no_cache
695
- assert !File.exist?(sassc_path("importee"))
696
- renders_correctly("import", {
697
- :style => :compact, :cache => false,
698
- :load_paths => [File.dirname(__FILE__) + "/templates"],
699
- })
700
- assert !File.exist?(sassc_path("importee"))
701
- end
702
-
703
- def test_import_in_rule
704
- assert_equal(<<CSS, render(<<SASS, :load_paths => [File.dirname(__FILE__) + '/templates/']))
705
- .foo #foo {
706
- background-color: #baf; }
707
-
708
- .bar {
709
- a: b; }
710
- .bar #foo {
711
- background-color: #baf; }
712
- CSS
713
- .foo
714
- @import partial
715
-
716
- .bar
717
- a: b
718
- @import partial
719
- SASS
720
- end
721
-
722
- def test_units
723
- renders_correctly "units"
724
- end
725
-
726
- def test_default_function
727
- assert_equal(<<CSS, render(<<SASS))
728
- foo {
729
- bar: url("foo.png"); }
730
- CSS
731
- foo
732
- bar: url("foo.png")
733
- SASS
734
- assert_equal("foo {\n bar: url(); }\n", render("foo\n bar: url()\n"));
735
- end
736
-
737
- def test_string_minus
738
- assert_equal("foo {\n bar: baz-boom-bat; }\n", render(%Q{foo\n bar: baz-boom-bat}))
739
- assert_equal("foo {\n bar: -baz-boom; }\n", render(%Q{foo\n bar: -baz-boom}))
740
- end
741
-
742
- def test_string_div
743
- assert_equal("foo {\n bar: baz/boom/bat; }\n", render(%Q{foo\n bar: baz/boom/bat}))
744
- assert_equal("foo {\n bar: /baz/boom; }\n", render(%Q{foo\n bar: /baz/boom}))
745
- end
746
-
747
- def test_basic_multiline_selector
748
- assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
749
- render("#foo #bar,\n#baz #boom\n foo: bar"))
750
- assert_equal("#foo #bar,\n#foo #baz {\n foo: bar; }\n",
751
- render("#foo\n #bar,\n #baz\n foo: bar"))
752
- assert_equal("#foo,\n#bar {\n foo: bar; }\n #foo #baz,\n #bar #baz {\n foo: bar; }\n",
753
- render("#foo,\n#bar\n foo: bar\n #baz\n foo: bar"))
754
- assert_equal("#foo #bar, #baz #boom { foo: bar; }\n",
755
- render("#foo #bar,\n#baz #boom\n foo: bar", :style => :compact))
756
-
757
- assert_equal("#foo #bar,#baz #boom{foo:bar}\n",
758
- render("#foo #bar,\n#baz #boom\n foo: bar", :style => :compressed))
759
-
760
- assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
761
- render("#foo #bar,,\n,#baz #boom,\n foo: bar"))
762
-
763
- assert_equal("#bip #bop {\n foo: bar; }\n",
764
- render("#bip #bop,, ,\n foo: bar"))
765
- end
766
-
767
- def test_complex_multiline_selector
768
- renders_correctly "multiline"
769
- end
770
-
771
- def test_colon_only
772
- begin
773
- render("a\n b: c", :property_syntax => :old)
774
- rescue Sass::SyntaxError => e
775
- assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
776
- e.message)
777
- assert_equal(2, e.sass_line)
778
- else
779
- assert(false, "SyntaxError not raised for :property_syntax => :old")
780
- end
781
-
782
- begin
783
- silence_warnings {render("a\n :b c", :property_syntax => :new)}
784
- assert_equal(2, e.sass_line)
785
- rescue Sass::SyntaxError => e
786
- assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
787
- e.message)
788
- else
789
- assert(false, "SyntaxError not raised for :property_syntax => :new")
790
- end
791
- end
792
-
793
- def test_pseudo_elements
794
- assert_equal(<<CSS, render(<<SASS))
795
- ::first-line {
796
- size: 10em; }
797
- CSS
798
- ::first-line
799
- size: 10em
800
- SASS
801
- end
802
-
803
- def test_directive
804
- assert_equal("@a b;\n", render("@a b"))
805
-
806
- assert_equal("@a {\n b: c; }\n", render("@a\n b: c"))
807
- assert_equal("@a { b: c; }\n", render("@a\n b: c", :style => :compact))
808
- assert_equal("@a {\n b: c;\n}\n", render("@a\n b: c", :style => :expanded))
809
- assert_equal("@a{b:c}\n", render("@a\n b: c", :style => :compressed))
810
-
811
- assert_equal("@a {\n b: c;\n d: e; }\n",
812
- render("@a\n b: c\n d: e"))
813
- assert_equal("@a { b: c; d: e; }\n",
814
- render("@a\n b: c\n d: e", :style => :compact))
815
- assert_equal("@a {\n b: c;\n d: e;\n}\n",
816
- render("@a\n b: c\n d: e", :style => :expanded))
817
- assert_equal("@a{b:c;d:e}\n",
818
- render("@a\n b: c\n d: e", :style => :compressed))
819
-
820
- assert_equal("@a {\n #b {\n c: d; } }\n",
821
- render("@a\n #b\n c: d"))
822
- assert_equal("@a { #b { c: d; } }\n",
823
- render("@a\n #b\n c: d", :style => :compact))
824
- assert_equal("@a {\n #b {\n c: d;\n }\n}\n",
825
- render("@a\n #b\n c: d", :style => :expanded))
826
- assert_equal("@a{#b{c:d}}\n",
827
- render("@a\n #b\n c: d", :style => :compressed))
828
-
829
- assert_equal("@a {\n #b {\n a: b; }\n #b #c {\n d: e; } }\n",
830
- render("@a\n #b\n a: b\n #c\n d: e"))
831
- assert_equal("@a { #b { a: b; }\n #b #c { d: e; } }\n",
832
- render("@a\n #b\n a: b\n #c\n d: e", :style => :compact))
833
- assert_equal("@a {\n #b {\n a: b;\n }\n #b #c {\n d: e;\n }\n}\n",
834
- render("@a\n #b\n a: b\n #c\n d: e", :style => :expanded))
835
- assert_equal("@a{#b{a:b}#b #c{d:e}}\n",
836
- render("@a\n #b\n a: b\n #c\n d: e", :style => :compressed))
837
-
838
- assert_equal("@a {\n #foo,\n #bar {\n b: c; } }\n",
839
- render("@a\n #foo, \n #bar\n b: c"))
840
- assert_equal("@a { #foo, #bar { b: c; } }\n",
841
- render("@a\n #foo, \n #bar\n b: c", :style => :compact))
842
- assert_equal("@a {\n #foo,\n #bar {\n b: c;\n }\n}\n",
843
- render("@a\n #foo, \n #bar\n b: c", :style => :expanded))
844
- assert_equal("@a{#foo,#bar{b:c}}\n",
845
- render("@a\n #foo, \n #bar\n b: c", :style => :compressed))
846
-
847
- to_render = <<END
848
- @a
849
- b: c
850
- #d
851
- e: f
852
- g: h
853
- END
854
- rendered = <<END
855
- @a { b: c;
856
- #d { e: f; }
857
- g: h; }
858
- END
859
- assert_equal(rendered, render(to_render, :style => :compact))
860
-
861
- assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
862
- end
863
-
864
- def test_property_hacks
865
- assert_equal(<<CSS, render(<<SASS))
866
- foo {
867
- _name: val;
868
- *name: val;
869
- #name: val;
870
- .name: val;
871
- name/**/: val;
872
- name/*\\**/: val;
873
- name: val; }
874
- CSS
875
- foo
876
- _name: val
877
- *name: val
878
- #name: val
879
- .name: val
880
- name/**/: val
881
- name/*\\**/: val
882
- name: val
883
- SASS
884
- end
885
-
886
- def test_properties_with_space_after_colon
887
- assert_equal <<CSS, render(<<SASS)
888
- foo {
889
- bar: baz;
890
- bizz: bap; }
891
- CSS
892
- foo
893
- bar : baz
894
- bizz : bap
895
- SASS
896
- end
897
-
898
- def test_line_annotations
899
- assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
900
- /* line 2, test_line_annotations_inline.sass */
901
- foo bar { foo: bar; }
902
- /* line 5, test_line_annotations_inline.sass */
903
- foo baz { blip: blop; }
904
-
905
- /* line 9, test_line_annotations_inline.sass */
906
- floodle { flop: blop; }
907
-
908
- /* line 18, test_line_annotations_inline.sass */
909
- bup { mix: on; }
910
- /* line 15, test_line_annotations_inline.sass */
911
- bup mixin { moop: mup; }
912
-
913
- /* line 22, test_line_annotations_inline.sass */
914
- bip hop, skip hop { a: b; }
915
- CSS
916
- foo
917
- bar
918
- foo: bar
919
-
920
- baz
921
- blip: blop
922
-
923
-
924
- floodle
925
-
926
- flop: blop
927
-
928
- =mxn
929
- mix: on
930
- mixin
931
- moop: mup
932
-
933
- bup
934
- +mxn
935
-
936
- bip, skip
937
- hop
938
- a: b
939
- SASS
940
- end
941
-
942
- def test_line_annotations_with_filename
943
- renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + "/templates"]
944
- end
945
-
946
- def test_debug_info
947
- esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_inline.sass"))
948
-
949
- assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compact))
950
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000032}}
951
- foo bar { foo: bar; }
952
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000035}}
953
- foo baz { blip: blop; }
954
-
955
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000039}}
956
- floodle { flop: blop; }
957
-
958
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000318}}
959
- bup { mix: on; }
960
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000315}}
961
- bup mixin { moop: mup; }
962
-
963
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000322}}
964
- bip hop, skip hop { a: b; }
965
- CSS
966
- foo
967
- bar
968
- foo: bar
969
-
970
- baz
971
- blip: blop
972
-
973
-
974
- floodle
975
-
976
- flop: blop
977
-
978
- =mxn
979
- mix: on
980
- mixin
981
- moop: mup
982
-
983
- bup
984
- +mxn
985
-
986
- bip, skip
987
- hop
988
- a: b
989
- SASS
990
- end
991
-
992
- def test_debug_info_without_filename
993
- assert_equal(<<CSS, Sass::Engine.new(<<SASS, :debug_info => true).render)
994
- @media -sass-debug-info{filename{}line{font-family:\\000031}}
995
- foo {
996
- a: b; }
997
- CSS
998
- foo
999
- a: b
1000
- SASS
1001
- end
1002
-
1003
- def test_debug_info_with_compressed
1004
- assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compressed))
1005
- foo{a:b}
1006
- CSS
1007
- foo
1008
- a: b
1009
- SASS
1010
- end
1011
-
1012
- def test_debug_info_with_line_annotations
1013
- esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_with_line_annotations_inline.sass"))
1014
-
1015
- assert_equal(<<CSS, render(<<SASS, :debug_info => true, :line_comments => true))
1016
- @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000031}}
1017
- foo {
1018
- a: b; }
1019
- CSS
1020
- foo
1021
- a: b
1022
- SASS
1023
- end
1024
-
1025
- def test_debug_info_in_keyframes
1026
- assert_equal(<<CSS, render(<<SASS, :debug_info => true))
1027
- @-webkit-keyframes warm {
1028
- from {
1029
- color: black; }
1030
- to {
1031
- color: red; } }
1032
- CSS
1033
- @-webkit-keyframes warm
1034
- from
1035
- color: black
1036
- to
1037
- color: red
1038
- SASS
1039
- end
1040
-
1041
- def test_empty_first_line
1042
- assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
1043
- end
1044
-
1045
- def test_escaped_rule
1046
- assert_equal(":focus {\n a: b; }\n", render("\\:focus\n a: b"))
1047
- assert_equal("a {\n b: c; }\n a :focus {\n d: e; }\n", render("\\a\n b: c\n \\:focus\n d: e"))
1048
- end
1049
-
1050
- def test_cr_newline
1051
- assert_equal("foo {\n a: b;\n c: d;\n e: f; }\n", render("foo\r a: b\r\n c: d\n\r e: f"))
1052
- end
1053
-
1054
- def test_property_with_content_and_nested_props
1055
- assert_equal(<<CSS, render(<<SASS))
1056
- foo {
1057
- a: b;
1058
- a-c: d;
1059
- a-c-e: f; }
1060
- CSS
1061
- foo
1062
- a: b
1063
- c: d
1064
- e: f
1065
- SASS
1066
-
1067
- assert_equal(<<CSS, render(<<SASS))
1068
- foo {
1069
- a: b;
1070
- a-c-e: f; }
1071
- CSS
1072
- foo
1073
- a: b
1074
- c:
1075
- e: f
1076
- SASS
1077
- end
1078
-
1079
- def test_guarded_assign
1080
- assert_equal("foo {\n a: b; }\n", render(%Q{$foo: b\n$foo: c !default\nfoo\n a: $foo}))
1081
- assert_equal("foo {\n a: b; }\n", render(%Q{$foo: b !default\nfoo\n a: $foo}))
1082
- assert_equal("foo {\n a: b; }\n", render(%Q{$foo: null\n$foo: b !default\nfoo\n a: $foo}))
1083
- end
1084
-
1085
- def test_mixins
1086
- renders_correctly "mixins", { :style => :expanded }
1087
- end
1088
-
1089
- def test_directive_style_mixins
1090
- assert_equal <<CSS, render(<<SASS)
1091
- bar {
1092
- prop: baz; }
1093
- CSS
1094
- @mixin foo($arg)
1095
- prop: $arg
1096
-
1097
- bar
1098
- @include foo(baz)
1099
- SASS
1100
- end
1101
-
1102
- def test_mixins_dont_interfere_with_sibling_combinator
1103
- assert_equal("foo + bar {\n a: b; }\nfoo + baz {\n c: d; }\n",
1104
- render("foo\n +\n bar\n a: b\n baz\n c: d"))
1105
- end
1106
-
1107
- def test_mixin_args
1108
- assert_equal("blat {\n baz: hi; }\n", render(<<SASS))
1109
- =foo($bar)
1110
- baz: $bar
1111
- blat
1112
- +foo(hi)
1113
- SASS
1114
- assert_equal("blat {\n baz: 3; }\n", render(<<SASS))
1115
- =foo($a, $b)
1116
- baz: $a + $b
1117
- blat
1118
- +foo(1, 2)
1119
- SASS
1120
- assert_equal("blat {\n baz: 4;\n baz: 3;\n baz: 5;\n bang: 3; }\n", render(<<SASS))
1121
- =foo($c: (6 + 4) / 2)
1122
- baz: $c
1123
- $c: 3
1124
- blat
1125
- +foo($c + 1)
1126
- +foo(($c + 3)/2)
1127
- +foo
1128
- bang: $c
1129
- SASS
1130
- end
1131
-
1132
- def test_default_values_for_mixin_arguments
1133
- assert_equal(<<CSS, render(<<SASS))
1134
- white {
1135
- color: #FFF; }
1136
-
1137
- black {
1138
- color: #000; }
1139
- CSS
1140
- =foo($a: #FFF)
1141
- color: $a
1142
- white
1143
- +foo
1144
- black
1145
- +foo(#000)
1146
- SASS
1147
- assert_equal(<<CSS, render(<<SASS))
1148
- one {
1149
- color: #fff;
1150
- padding: 1px;
1151
- margin: 4px; }
1152
-
1153
- two {
1154
- color: #fff;
1155
- padding: 2px;
1156
- margin: 5px; }
1157
-
1158
- three {
1159
- color: #fff;
1160
- padding: 2px;
1161
- margin: 3px; }
1162
- CSS
1163
- $a: 5px
1164
- =foo($a, $b: 1px, $c: 3px + $b)
1165
- color: $a
1166
- padding: $b
1167
- margin: $c
1168
- one
1169
- +foo(#fff)
1170
- two
1171
- +foo(#fff, 2px)
1172
- three
1173
- +foo(#fff, 2px, 3px)
1174
- SASS
1175
- assert_equal(<<CSS, render(<<SASS))
1176
- one {
1177
- color: #fff;
1178
- padding: 1px;
1179
- margin: 4px; }
1180
-
1181
- two {
1182
- color: #fff;
1183
- padding: 2px;
1184
- margin: 5px; }
1185
-
1186
- three {
1187
- color: #fff;
1188
- padding: 2px;
1189
- margin: 3px; }
1190
- CSS
1191
- $a: 5px
1192
- =foo($a, $b: 1px, $c: null)
1193
- $c: 3px + $b !default
1194
- color: $a
1195
- padding: $b
1196
- margin: $c
1197
- one
1198
- +foo(#fff)
1199
- two
1200
- +foo(#fff, 2px)
1201
- three
1202
- +foo(#fff, 2px, 3px)
1203
- SASS
1204
- end
1205
-
1206
- def test_hyphen_underscore_insensitive_mixins
1207
- assert_equal(<<CSS, render(<<SASS))
1208
- a {
1209
- b: 12;
1210
- c: foo; }
1211
- CSS
1212
- =mixin-hyphen
1213
- b: 12
1214
-
1215
- =mixin_under
1216
- c: foo
1217
-
1218
- a
1219
- +mixin_hyphen
1220
- +mixin-under
1221
- SASS
1222
- end
1223
-
1224
- def test_css_identifier_mixin
1225
- assert_equal(<<CSS, render(<<SASS))
1226
- a {
1227
- foo: 12; }
1228
- CSS
1229
- =\\{foo\\(12\\)($a)
1230
- foo: $a
1231
-
1232
- a
1233
- +\\{foo\\(12\\)(12)
1234
- SASS
1235
- end
1236
-
1237
- def test_basic_function
1238
- assert_equal(<<CSS, render(<<SASS))
1239
- bar {
1240
- a: 3; }
1241
- CSS
1242
- @function foo()
1243
- @return 1 + 2
1244
-
1245
- bar
1246
- a: foo()
1247
- SASS
1248
- end
1249
-
1250
- def test_function_args
1251
- assert_equal(<<CSS, render(<<SASS))
1252
- bar {
1253
- a: 3; }
1254
- CSS
1255
- @function plus($var1, $var2)
1256
- @return $var1 + $var2
1257
-
1258
- bar
1259
- a: plus(1, 2)
1260
- SASS
1261
- end
1262
-
1263
- def test_function_arg_default
1264
- assert_equal(<<CSS, render(<<SASS))
1265
- bar {
1266
- a: 3; }
1267
- CSS
1268
- @function plus($var1, $var2: 2)
1269
- @return $var1 + $var2
1270
-
1271
- bar
1272
- a: plus(1)
1273
- SASS
1274
- end
1275
-
1276
- def test_function_arg_keyword
1277
- assert_equal(<<CSS, render(<<SASS))
1278
- bar {
1279
- a: 1bar; }
1280
- CSS
1281
- @function plus($var1: 1, $var2: 2)
1282
- @return $var1 + $var2
1283
-
1284
- bar
1285
- a: plus($var2: bar)
1286
- SASS
1287
- end
1288
-
1289
- def test_function_with_missing_argument
1290
- render(<<SASS)
1291
- @function plus($var1, $var2)
1292
- @return $var1 + $var2
1293
-
1294
- bar
1295
- a: plus($var2: bar)
1296
- SASS
1297
- flunk("Expected exception")
1298
- rescue Sass::SyntaxError => e
1299
- assert_equal("Function plus is missing argument $var1.", e.message)
1300
- end
1301
-
1302
- def test_function_with_extra_argument
1303
- render(<<SASS)
1304
- @function plus($var1, $var2)
1305
- @return $var1 + $var2
1306
-
1307
- bar
1308
- a: plus($var1: foo, $var2: bar, $var3: baz)
1309
- SASS
1310
- flunk("Expected exception")
1311
- rescue Sass::SyntaxError => e
1312
- assert_equal("Function plus doesn't have an argument named $var3.", e.message)
1313
- end
1314
-
1315
- def test_function_with_positional_and_keyword_argument
1316
- render(<<SASS)
1317
- @function plus($var1, $var2)
1318
- @return $var1 + $var2
1319
-
1320
- bar
1321
- a: plus(foo, bar, $var2: baz)
1322
- SASS
1323
- flunk("Expected exception")
1324
- rescue Sass::SyntaxError => e
1325
- assert_equal("Function plus was passed argument $var2 both by position and by name.", e.message)
1326
- end
1327
-
1328
- def test_function_with_keyword_before_positional_argument
1329
- render(<<SASS)
1330
- @function plus($var1, $var2)
1331
- @return $var1 + $var2
1332
-
1333
- bar
1334
- a: plus($var2: foo, bar)
1335
- SASS
1336
- flunk("Expected exception")
1337
- rescue Sass::SyntaxError => e
1338
- assert_equal("Positional arguments must come before keyword arguments.", e.message)
1339
- end
1340
-
1341
- def test_function_with_if
1342
- assert_equal(<<CSS, render(<<SASS))
1343
- bar {
1344
- a: foo;
1345
- b: bar; }
1346
- CSS
1347
- @function my-if($cond, $val1, $val2)
1348
- @if $cond
1349
- @return $val1
1350
- @else
1351
- @return $val2
1352
-
1353
- bar
1354
- a: my-if(true, foo, bar)
1355
- b: my-if(false, foo, bar)
1356
- SASS
1357
- end
1358
-
1359
- def test_function_with_var
1360
- assert_equal(<<CSS, render(<<SASS))
1361
- bar {
1362
- a: 1; }
1363
- CSS
1364
- @function foo($val1, $val2)
1365
- $intermediate: $val1 + $val2
1366
- @return $intermediate/3
1367
-
1368
- bar
1369
- a: foo(1, 2)
1370
- SASS
1371
- end
1372
-
1373
- def test_user_defined_function_variable_scope
1374
- render(<<SASS)
1375
- bar
1376
- -no-op: set-a-variable(variable, 5)
1377
- a: $variable
1378
- SASS
1379
- flunk("Exception not raised for test_user_defined_function_variable_scope")
1380
- rescue Sass::SyntaxError => e
1381
- assert_equal('Undefined variable: "$variable".', e.message)
1382
- end
1383
-
1384
- def test_user_defined_function_can_change_global_variable
1385
- assert_equal(<<CSS, render(<<SASS))
1386
- bar {
1387
- a: 5; }
1388
- CSS
1389
- $variable: 0
1390
- bar
1391
- $local: 10
1392
- -no-op: set-a-global-variable(variable, 5)
1393
- a: $variable
1394
- SASS
1395
- end
1396
-
1397
- def test_user_defined_function_cannot_read_local_variable
1398
- assert_equal(<<CSS, render(<<SASS))
1399
- bar {
1400
- global: 0;
1401
- local: undefined; }
1402
- CSS
1403
- $global: 0
1404
- bar
1405
- $local: 10
1406
- global: get-a-variable(global)
1407
- local: get-a-variable(local)
1408
- SASS
1409
- end
1410
-
1411
- def test_control_directive_in_nested_property
1412
- assert_equal(<<CSS, render(<<SASS))
1413
- foo {
1414
- a-b: c; }
1415
- CSS
1416
- foo
1417
- a:
1418
- @if true
1419
- b: c
1420
- SASS
1421
- end
1422
-
1423
- def test_interpolation
1424
- assert_equal("a-1 {\n b-2-3: c-3; }\n", render(<<SASS))
1425
- $a: 1
1426
- $b: 2
1427
- $c: 3
1428
- a-\#{$a}
1429
- b-\#{$b}-\#{$c}: c-\#{$a + $b}
1430
- SASS
1431
- end
1432
-
1433
- def test_complex_property_interpolation
1434
- assert_equal(<<CSS, render(<<SASS))
1435
- a-1 {
1436
- b-2 3-fizzap18: c-3; }
1437
- CSS
1438
- $a: 1
1439
- $b: 2
1440
- $c: 3
1441
- a-\#{$a}
1442
- b-\#{$b $c}-\#{fizzap + ($c + 15)}: c-\#{$a + $b}
1443
- SASS
1444
- end
1445
-
1446
- def test_if_directive
1447
- assert_equal("a {\n b: 1; }\n", render(<<SASS))
1448
- $var: true
1449
- a
1450
- @if $var
1451
- b: 1
1452
- @if not $var
1453
- b: 2
1454
- SASS
1455
-
1456
- assert_equal("a {\n b: 2; }\n", render(<<SASS))
1457
- $var: null
1458
- a
1459
- @if $var
1460
- b: 1
1461
- @if not $var
1462
- b: 2
1463
- SASS
1464
- end
1465
-
1466
- def test_for
1467
- assert_equal(<<CSS, render(<<SASS))
1468
- a-0 {
1469
- two-i: 0; }
1470
-
1471
- a-1 {
1472
- two-i: 2; }
1473
-
1474
- a-2 {
1475
- two-i: 4; }
1476
-
1477
- a-3 {
1478
- two-i: 6; }
1479
-
1480
- b-1 {
1481
- j-1: 0; }
1482
-
1483
- b-2 {
1484
- j-1: 1; }
1485
-
1486
- b-3 {
1487
- j-1: 2; }
1488
-
1489
- b-4 {
1490
- j-1: 3; }
1491
- CSS
1492
- $a: 3
1493
- @for $i from 0 to $a + 1
1494
- a-\#{$i}
1495
- two-i: 2 * $i
1496
-
1497
- @for $j from 1 through 4
1498
- b-\#{$j}
1499
- j-1: $j - 1
1500
- SASS
1501
- end
1502
-
1503
- def test_while
1504
- assert_equal(<<CSS, render(<<SASS))
1505
- a-5 {
1506
- blooble: gloop; }
1507
-
1508
- a-4 {
1509
- blooble: gloop; }
1510
-
1511
- a-3 {
1512
- blooble: gloop; }
1513
-
1514
- a-2 {
1515
- blooble: gloop; }
1516
-
1517
- a-1 {
1518
- blooble: gloop; }
1519
- CSS
1520
- $a: 5
1521
- @while $a != 0
1522
- a-\#{$a}
1523
- blooble: gloop
1524
- $a: $a - 1 !global
1525
- SASS
1526
- end
1527
-
1528
- def test_else
1529
- assert_equal(<<CSS, render(<<SASS))
1530
- a {
1531
- t1: t;
1532
- t2: t;
1533
- t3: t;
1534
- t4: t; }
1535
- CSS
1536
- a
1537
- @if true
1538
- t1: t
1539
- @else
1540
- f1: f
1541
-
1542
- @if false
1543
- f2: f
1544
- @else
1545
- t2: t
1546
-
1547
- @if false
1548
- f3: f1
1549
- @else if 1 + 1 == 3
1550
- f3: f2
1551
- @else
1552
- t3: t
1553
-
1554
- @if false
1555
- f4: f1
1556
- @else if 1 + 1 == 2
1557
- t4: t
1558
- @else
1559
- f4: f2
1560
-
1561
- @if false
1562
- f5: f1
1563
- @else if false
1564
- f5: f2
1565
- SASS
1566
- end
1567
-
1568
- def test_each
1569
- assert_equal(<<CSS, render(<<SASS))
1570
- a {
1571
- b: 1px;
1572
- b: 2px;
1573
- b: 3px;
1574
- b: 4px;
1575
- c: foo;
1576
- c: bar;
1577
- c: baz;
1578
- c: bang;
1579
- d: blue; }
1580
- CSS
1581
- a
1582
- @each $number in 1px 2px 3px 4px
1583
- b: $number
1584
- @each $str in foo, bar, baz, bang
1585
- c: $str
1586
- @each $single in blue
1587
- d: $single
1588
- SASS
1589
- end
1590
-
1591
- def test_destructuring_each
1592
- assert_equal <<CSS, render(<<SCSS)
1593
- a {
1594
- foo: 1px;
1595
- bar: 2px;
1596
- baz: 3px; }
1597
-
1598
- c {
1599
- foo: "Value is bar";
1600
- bar: "Value is baz";
1601
- bang: "Value is "; }
1602
- CSS
1603
- a
1604
- @each $name, $number in (foo: 1px, bar: 2px, baz: 3px)
1605
- \#{$name}: $number
1606
- c
1607
- @each $key, $value in (foo bar) (bar, baz) bang
1608
- \#{$key}: "Value is \#{$value}"
1609
- SCSS
1610
- end
1611
-
1612
- def test_variable_reassignment
1613
- assert_equal(<<CSS, render(<<SASS))
1614
- a {
1615
- b: 1;
1616
- c: 2; }
1617
- CSS
1618
- a
1619
- $a: 1
1620
- b: $a
1621
- $a: 2
1622
- c: $a
1623
- SASS
1624
- end
1625
-
1626
- def test_hyphen_underscore_insensitive_variables
1627
- assert_equal(<<CSS, render(<<SASS))
1628
- d {
1629
- e: 13;
1630
- f: foobar; }
1631
- CSS
1632
- $var-hyphen: 12
1633
- $var_under: foo
1634
-
1635
- $var_hyphen: 1 + $var_hyphen
1636
- $var-under: $var-under + bar
1637
-
1638
- d
1639
- e: $var-hyphen
1640
- f: $var_under
1641
- SASS
1642
- end
1643
-
1644
- def test_css_identifier_variable
1645
- assert_equal(<<CSS, render(<<SASS))
1646
- a {
1647
- b: 12; }
1648
- CSS
1649
- $\\{foo\\(12\\): 12
1650
-
1651
- a
1652
- b: $\\{foo\\(12\\)
1653
- SASS
1654
- end
1655
-
1656
- def test_important
1657
- assert_equal(<<CSS, render(<<SASS))
1658
- a {
1659
- b: 12px !important; }
1660
- CSS
1661
- $foo: 12px
1662
- a
1663
- b: $foo !important
1664
- SASS
1665
- end
1666
-
1667
- def test_argument_error
1668
- assert_raises(Sass::SyntaxError) { render("a\n b: hsl(1)") }
1669
- end
1670
-
1671
- def test_comments_at_the_top_of_a_document
1672
- render(<<SASS)
1673
- //
1674
- This is a comment that
1675
- continues to the second line.
1676
- foo
1677
- bar: baz
1678
- SASS
1679
- end
1680
-
1681
- def test_loud_comments_containing_a_comment_close
1682
- actual_css = render(<<SASS)
1683
- /*
1684
- This is a comment that
1685
- continues to the second line. */
1686
- foo
1687
- bar: baz
1688
- SASS
1689
- assert_equal(<<CSS, actual_css)
1690
- /* This is a comment that
1691
- * continues to the second line. */
1692
- foo {
1693
- bar: baz; }
1694
- CSS
1695
- end
1696
-
1697
- def test_loud_comments_with_starred_lines
1698
- assert_equal(<<CSS, render(<<SASS))
1699
- /* This is a comment that
1700
- * continues to the second line.
1701
- * And even to the third! */
1702
- CSS
1703
- /* This is a comment that
1704
- * continues to the second line.
1705
- * And even to the third!
1706
- SASS
1707
- end
1708
-
1709
- def test_loud_comments_with_no_space_after_starred_lines
1710
- assert_equal(<<CSS, render(<<SASS))
1711
- /*bip bop
1712
- *beep boop
1713
- *bap blimp */
1714
- CSS
1715
- /*bip bop
1716
- *beep boop
1717
- *bap blimp
1718
- SASS
1719
- end
1720
-
1721
- def test_comment_indentation_at_beginning_of_doc
1722
- assert_equal <<CSS, render(<<SASS)
1723
- /* foo
1724
- * bar
1725
- * baz */
1726
- foo {
1727
- a: b; }
1728
- CSS
1729
- /* foo
1730
- bar
1731
- baz
1732
- foo
1733
- a: b
1734
- SASS
1735
- end
1736
-
1737
- def test_unusual_comment_indentation
1738
- assert_equal <<CSS, render(<<SASS)
1739
- foo {
1740
- /* foo
1741
- * bar
1742
- * baz */ }
1743
- CSS
1744
- foo
1745
- /* foo
1746
- bar
1747
- baz
1748
- SASS
1749
- end
1750
-
1751
- def test_loud_comment_with_close
1752
- assert_equal <<CSS, render(<<SASS)
1753
- foo {
1754
- /* foo
1755
- * bar */ }
1756
- CSS
1757
- foo
1758
- /* foo
1759
- bar */
1760
- SASS
1761
- end
1762
-
1763
- def test_loud_comment_with_separate_line_close
1764
- assert_equal <<CSS, render(<<SASS)
1765
- foo {
1766
- /* foo
1767
- * bar
1768
- */ }
1769
- CSS
1770
- foo
1771
- /* foo
1772
- * bar
1773
- */
1774
- SASS
1775
- end
1776
-
1777
- def test_loud_comment_in_compressed_mode
1778
- assert_equal <<CSS, render(<<SASS, :style => :compressed)
1779
- foo{color:blue;/*! foo
1780
- * bar
1781
- */}
1782
- CSS
1783
- foo
1784
- color: blue
1785
- /*! foo
1786
- * bar
1787
- */
1788
- SASS
1789
- end
1790
-
1791
- def test_loud_comment_is_evaluated
1792
- assert_equal <<CSS, render(<<SASS)
1793
- /*! Hue: 327.2164948454deg */
1794
- CSS
1795
- /*! Hue: \#{hue(#f836a0)}
1796
- SASS
1797
- end
1798
-
1799
- def test_attribute_selector_with_spaces
1800
- assert_equal(<<CSS, render(<<SASS))
1801
- a b[foo=bar] {
1802
- c: d; }
1803
- CSS
1804
- a
1805
- b[foo = bar]
1806
- c: d
1807
- SASS
1808
- end
1809
-
1810
- def test_quoted_colon
1811
- assert_equal(<<CSS, render(<<SASS))
1812
- a b[foo="bar: baz"] {
1813
- c: d; }
1814
- CSS
1815
- a
1816
- b[foo="bar: baz"]
1817
- c: d
1818
- SASS
1819
- end
1820
-
1821
- def test_quoted_comma
1822
- assert_equal(<<CSS, render(<<SASS))
1823
- a b[foo="bar, baz"] {
1824
- c: d; }
1825
- CSS
1826
- a
1827
- b[foo="bar, baz"]
1828
- c: d
1829
- SASS
1830
- end
1831
-
1832
- def test_quoted_ampersand
1833
- assert_equal(<<CSS, render(<<SASS))
1834
- a b[foo="bar & baz"] {
1835
- c: d; }
1836
- CSS
1837
- a
1838
- b[foo="bar & baz"]
1839
- c: d
1840
- SASS
1841
- end
1842
-
1843
- def test_empty_selector_warning
1844
- assert_warning(<<END) {render("foo bar")}
1845
- WARNING on line 1 of test_empty_selector_warning_inline.sass:
1846
- This selector doesn't have any properties and will not be rendered.
1847
- END
1848
- end
1849
-
1850
- def test_nonprinting_empty_property
1851
- assert_equal(<<CSS, render(<<SASS))
1852
- a {
1853
- c: "";
1854
- e: f; }
1855
- CSS
1856
- $null-value: null
1857
- $empty-string: ''
1858
- $empty-list: (null)
1859
- a
1860
- b: $null-value
1861
- c: $empty-string
1862
- d: $empty-list
1863
- e: f
1864
-
1865
- g
1866
- h: null
1867
- SASS
1868
- end
1869
-
1870
- def test_root_level_pseudo_class_with_new_properties
1871
- assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
1872
- :focus {
1873
- outline: 0; }
1874
- CSS
1875
- :focus
1876
- outline: 0
1877
- SASS
1878
- end
1879
-
1880
- def test_pseudo_class_with_new_properties
1881
- assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
1882
- p :focus {
1883
- outline: 0; }
1884
- CSS
1885
- p
1886
- :focus
1887
- outline: 0
1888
- SASS
1889
- end
1890
-
1891
- def test_nil_option
1892
- assert_equal(<<CSS, render(<<SASS, :format => nil))
1893
- foo {
1894
- a: b; }
1895
- CSS
1896
- foo
1897
- a: b
1898
- SASS
1899
- end
1900
-
1901
- def test_interpolation_in_raw_functions
1902
- assert_equal(<<CSS, render(<<SASS))
1903
- foo {
1904
- filter: progid:Microsoft.foo.bar.Baz(flip=foobar, bang=#00ff00cc); }
1905
- CSS
1906
- foo
1907
- filter: progid:Microsoft.foo.bar.Baz(flip=\#{foo + bar}, bang=#00ff00cc)
1908
- SASS
1909
- end
1910
-
1911
- # SassScript string behavior
1912
-
1913
- def test_plus_preserves_quotedness
1914
- assert_equal(<<CSS, render(<<SASS))
1915
- foo {
1916
- a: "foo1";
1917
- b: "1foo";
1918
- c: foo1;
1919
- d: 1foo;
1920
- e: "foobar";
1921
- f: foobar; }
1922
- CSS
1923
- foo
1924
- a: "foo" + 1
1925
- b: 1 + "foo"
1926
- c: foo + 1
1927
- d: 1 + foo
1928
- e: "foo" + bar
1929
- f: foo + "bar"
1930
- SASS
1931
- end
1932
-
1933
- def test_colon_properties_preserve_quotedness
1934
- assert_equal(<<CSS, render(<<SASS))
1935
- foo {
1936
- a: "foo";
1937
- b: bar;
1938
- c: "foo" bar;
1939
- d: foo, "bar"; }
1940
- CSS
1941
- foo
1942
- a: "foo"
1943
- b: bar
1944
- c: "foo" bar
1945
- d: foo, "bar"
1946
- SASS
1947
- end
1948
-
1949
- def test_colon_variables_preserve_quotedness
1950
- assert_equal(<<CSS, render(<<SASS))
1951
- foo {
1952
- a: "foo";
1953
- b: bar; }
1954
- CSS
1955
- $a: "foo"
1956
- $b: bar
1957
-
1958
- foo
1959
- a: $a
1960
- b: $b
1961
- SASS
1962
- end
1963
-
1964
- def test_colon_args_preserve_quotedness
1965
- assert_equal(<<CSS, render(<<SASS))
1966
- foo {
1967
- a: "foo";
1968
- b: bar;
1969
- c: "foo" bar;
1970
- d: foo, "bar"; }
1971
- CSS
1972
- =foo($a: "foo", $b: bar, $c: "foo" bar, $d: (foo, "bar"))
1973
- foo
1974
- a: $a
1975
- b: $b
1976
- c: $c
1977
- d: $d
1978
-
1979
- +foo
1980
- SASS
1981
- end
1982
-
1983
- def test_interpolation_unquotes_strings
1984
- assert_equal(<<CSS, render(<<SASS))
1985
- .foo-bar {
1986
- a: b; }
1987
- CSS
1988
- .foo-\#{"bar"}
1989
- a: b
1990
- SASS
1991
-
1992
- assert_equal(<<CSS, render(<<SASS))
1993
- .foo {
1994
- a: b c; }
1995
- CSS
1996
- .foo
1997
- a: b \#{"c"}
1998
- SASS
1999
- end
2000
-
2001
- def test_interpolation_unquotes_strings_in_vars
2002
- assert_equal(<<CSS, render(<<SASS))
2003
- .foo-bar {
2004
- a: b; }
2005
- CSS
2006
- $var: "bar"
2007
-
2008
- .foo-\#{$var}
2009
- a: b
2010
- SASS
2011
- end
2012
-
2013
- def test_interpolation_deep_unquotes_strings
2014
- assert_equal(<<CSS, render(<<SASS))
2015
- .foo {
2016
- a: bar baz; }
2017
- CSS
2018
- .foo
2019
- a: \#{"bar" "baz"}
2020
- SASS
2021
- end
2022
-
2023
- def test_warn_directive
2024
- expected_warning = <<EXPECTATION
2025
- WARNING: this is a warning
2026
- on line 4 of test_warn_directive_inline.sass
2027
-
2028
- WARNING: this is a mixin warning
2029
- on line 2 of test_warn_directive_inline.sass, in `foo'
2030
- from line 7 of test_warn_directive_inline.sass
2031
- EXPECTATION
2032
- assert_warning expected_warning do
2033
- assert_equal <<CSS, render(<<SASS)
2034
- bar {
2035
- c: d; }
2036
- CSS
2037
- =foo
2038
- @warn "this is a mixin warning"
2039
-
2040
- @warn "this is a warning"
2041
- bar
2042
- c: d
2043
- +foo
2044
- SASS
2045
- end
2046
- end
2047
-
2048
- def test_warn_directive_when_quiet
2049
- assert_warning "" do
2050
- assert_equal <<CSS, render(<<SASS, :quiet => true)
2051
- CSS
2052
- @warn "this is a warning"
2053
- SASS
2054
- end
2055
- end
2056
-
2057
- def test_warn_with_imports
2058
- prefix = Sass::Util.cleanpath(File.dirname(__FILE__)).to_s
2059
- expected_warning = <<WARN
2060
- WARNING: In the main file
2061
- on line 1 of #{prefix}/templates/warn.sass
2062
-
2063
- WARNING: Imported
2064
- on line 1 of #{prefix}/templates/warn_imported.sass
2065
- from line 2 of #{prefix}/templates/warn.sass
2066
-
2067
- WARNING: In an imported mixin
2068
- on line 4 of #{prefix}/templates/warn_imported.sass, in `emits-a-warning'
2069
- from line 3 of #{prefix}/templates/warn.sass
2070
- WARN
2071
- assert_warning expected_warning do
2072
- renders_correctly "warn", :style => :compact, :load_paths => ["#{prefix}/templates"]
2073
- end
2074
- end
2075
-
2076
- def test_media_bubbling
2077
- assert_equal <<CSS, render(<<SASS)
2078
- .foo {
2079
- a: b; }
2080
- @media bar {
2081
- .foo {
2082
- c: d; } }
2083
- .foo .baz {
2084
- e: f; }
2085
- @media bip {
2086
- .foo .baz {
2087
- g: h; } }
2088
-
2089
- .other {
2090
- i: j; }
2091
- CSS
2092
- .foo
2093
- a: b
2094
- @media bar
2095
- c: d
2096
- .baz
2097
- e: f
2098
- @media bip
2099
- g: h
2100
-
2101
- .other
2102
- i: j
2103
- SASS
2104
-
2105
- assert_equal <<CSS, render(<<SASS, :style => :compact)
2106
- .foo { a: b; }
2107
- @media bar { .foo { c: d; } }
2108
- .foo .baz { e: f; }
2109
- @media bip { .foo .baz { g: h; } }
2110
-
2111
- .other { i: j; }
2112
- CSS
2113
- .foo
2114
- a: b
2115
- @media bar
2116
- c: d
2117
- .baz
2118
- e: f
2119
- @media bip
2120
- g: h
2121
-
2122
- .other
2123
- i: j
2124
- SASS
2125
-
2126
- assert_equal <<CSS, render(<<SASS, :style => :expanded)
2127
- .foo {
2128
- a: b;
2129
- }
2130
- @media bar {
2131
- .foo {
2132
- c: d;
2133
- }
2134
- }
2135
- .foo .baz {
2136
- e: f;
2137
- }
2138
- @media bip {
2139
- .foo .baz {
2140
- g: h;
2141
- }
2142
- }
2143
-
2144
- .other {
2145
- i: j;
2146
- }
2147
- CSS
2148
- .foo
2149
- a: b
2150
- @media bar
2151
- c: d
2152
- .baz
2153
- e: f
2154
- @media bip
2155
- g: h
2156
-
2157
- .other
2158
- i: j
2159
- SASS
2160
- end
2161
-
2162
- def test_double_media_bubbling
2163
- assert_equal <<CSS, render(<<SASS)
2164
- @media bar and (a: b) {
2165
- .foo {
2166
- c: d; } }
2167
- CSS
2168
- @media bar
2169
- @media (a: b)
2170
- .foo
2171
- c: d
2172
- SASS
2173
-
2174
- assert_equal <<CSS, render(<<SASS)
2175
- @media bar {
2176
- .foo {
2177
- a: b; } }
2178
- @media bar and (a: b) {
2179
- .foo {
2180
- c: d; } }
2181
- CSS
2182
- .foo
2183
- @media bar
2184
- a: b
2185
- @media (a: b)
2186
- c: d
2187
- SASS
2188
- end
2189
-
2190
- def test_double_media_bubbling_with_commas
2191
- assert_equal <<CSS, render(<<SASS)
2192
- @media (a: b) and (e: f), (c: d) and (e: f), (a: b) and (g: h), (c: d) and (g: h) {
2193
- .foo {
2194
- c: d; } }
2195
- CSS
2196
- @media (a: b), (c: d)
2197
- @media (e: f), (g: h)
2198
- .foo
2199
- c: d
2200
- SASS
2201
- end
2202
-
2203
- def test_double_media_bubbling_with_surrounding_rules
2204
- assert_equal <<CSS, render(<<SASS)
2205
- @media (min-width: 0) {
2206
- a {
2207
- a: a; }
2208
-
2209
- b {
2210
- before: b;
2211
- after: b; } }
2212
- @media (min-width: 0) and (max-width: 5000px) {
2213
- b {
2214
- x: x; } }
2215
-
2216
- @media (min-width: 0) {
2217
- c {
2218
- c: c; } }
2219
- CSS
2220
- @media (min-width: 0)
2221
- a
2222
- a: a
2223
- b
2224
- before: b
2225
- @media (max-width: 5000px)
2226
- x: x
2227
- after: b
2228
- c
2229
- c: c
2230
- SASS
2231
- end
2232
-
2233
- def test_rule_media_rule_bubbling
2234
- assert_equal <<CSS, render(<<SASS)
2235
- @media bar {
2236
- .foo {
2237
- a: b;
2238
- e: f; }
2239
- .foo .baz {
2240
- c: d; } }
2241
- CSS
2242
- .foo
2243
- @media bar
2244
- a: b
2245
- .baz
2246
- c: d
2247
- e: f
2248
- SASS
2249
- end
2250
-
2251
- def test_nested_media_around_properties
2252
- assert_equal <<CSS, render(<<SASS)
2253
- .outside {
2254
- color: red;
2255
- background: blue; }
2256
- @media print {
2257
- .outside {
2258
- color: black; } }
2259
- @media print and (a: b) {
2260
- .outside .inside {
2261
- border: 1px solid black; } }
2262
-
2263
- .outside .middle {
2264
- display: block; }
2265
- CSS
2266
- .outside
2267
- color: red
2268
- @media print
2269
- color: black
2270
- .inside
2271
- @media (a: b)
2272
- border: 1px solid black
2273
- background: blue
2274
- .middle
2275
- display: block
2276
- SASS
2277
- end
2278
-
2279
- def test_media_with_parent_references
2280
- sass_str = <<SASS
2281
- .outside
2282
- @media print
2283
- &.inside
2284
- border: 1px solid black
2285
- SASS
2286
- css_str = <<CSS
2287
- @media print {
2288
- .outside.inside {
2289
- border: 1px solid black; } }
2290
- CSS
2291
- assert_equal css_str, render(sass_str)
2292
- end
2293
-
2294
- def test_eliminated_media_bubbling
2295
- assert_equal <<CSS, render(<<SASS)
2296
- @media screen {
2297
- a: b; }
2298
- CSS
2299
- @media screen
2300
- a: b
2301
- @media print
2302
- c: d
2303
- SASS
2304
-
2305
- assert_equal <<CSS, render(<<SASS)
2306
- @media not print {
2307
- a: b; }
2308
- CSS
2309
- @media not print
2310
- a: b
2311
- @media print
2312
- c: d
2313
- SASS
2314
-
2315
- assert_equal <<CSS, render(<<SASS)
2316
- @media not print {
2317
- a: b; }
2318
- CSS
2319
- @media not print
2320
- a: b
2321
- @media not screen
2322
- c: d
2323
- SASS
2324
- end
2325
-
2326
- def test_non_eliminated_media_bubbling
2327
- assert_equal <<CSS, render(<<SASS)
2328
- @media screen {
2329
- a: b; }
2330
- @media screen and (a: b) {
2331
- c: d; }
2332
- CSS
2333
- @media screen
2334
- a: b
2335
- @media screen and (a: b)
2336
- c: d
2337
- SASS
2338
-
2339
- assert_equal <<CSS, render(<<SASS)
2340
- @media not print {
2341
- a: b; }
2342
- @media screen {
2343
- c: d; }
2344
- CSS
2345
- @media not print
2346
- a: b
2347
- @media screen
2348
- c: d
2349
- SASS
2350
-
2351
- assert_equal <<CSS, render(<<SASS)
2352
- @media only screen {
2353
- a: b; }
2354
- @media only screen and (a: b) {
2355
- c: d; }
2356
- CSS
2357
- @media only screen
2358
- a: b
2359
- @media screen and (a: b)
2360
- c: d
2361
- SASS
2362
- end
2363
-
2364
- def test_directive_interpolation
2365
- assert_equal <<CSS, render(<<SASS)
2366
- @foo bar12 qux {
2367
- a: b; }
2368
- CSS
2369
- $baz: 12
2370
- @foo bar\#{$baz} qux
2371
- a: b
2372
- SASS
2373
- end
2374
-
2375
- def test_media_interpolation
2376
- assert_equal <<CSS, render(<<SASS)
2377
- @media bar12 {
2378
- a: b; }
2379
- CSS
2380
- $baz: 12
2381
- @media bar\#{$baz}
2382
- a: b
2383
- SASS
2384
- end
2385
-
2386
- def test_variables_in_media
2387
- assert_equal <<CSS, render(<<SASS)
2388
- @media screen and (-webkit-min-device-pixel-ratio-foo: 25), only print {
2389
- a: b; }
2390
- CSS
2391
- $media1: screen
2392
- $media2: print
2393
- $var: -webkit-min-device-pixel-ratio
2394
- $val: 20
2395
- @media \#{$media1} and ($var + "-foo": $val + 5), only \#{$media2}
2396
- a: b
2397
- SASS
2398
- end
2399
-
2400
- def test_at_root
2401
- assert_equal <<CSS, render(<<SASS)
2402
- .bar {
2403
- a: b; }
2404
- CSS
2405
- .foo
2406
- @at-root
2407
- .bar
2408
- a: b
2409
- SASS
2410
- end
2411
-
2412
- def test_at_root_with_selector
2413
- assert_equal <<CSS, render(<<SASS)
2414
- .bar {
2415
- a: b; }
2416
- CSS
2417
- .foo
2418
- @at-root .bar
2419
- a: b
2420
- SASS
2421
- end
2422
-
2423
- def test_at_root_with_query
2424
- assert_equal <<CSS, render(<<SASS)
2425
- .foo .bar {
2426
- a: b; }
2427
- CSS
2428
- .foo
2429
- @media screen
2430
- @at-root (without: media)
2431
- .bar
2432
- a: b
2433
- SASS
2434
- end
2435
-
2436
- def test_variable_assignment_with_global
2437
- assert_no_warning {assert_equal(<<CSS, render(<<SASS))}
2438
- .foo {
2439
- a: x; }
2440
-
2441
- .bar {
2442
- b: x; }
2443
- CSS
2444
- $var: 1
2445
-
2446
- .foo
2447
- $var: x !global
2448
- a: $var
2449
-
2450
- .bar
2451
- b: $var
2452
- SASS
2453
- end
2454
-
2455
- # Regression tests
2456
-
2457
- def test_interpolation_in_multiline_selector
2458
- assert_equal(<<CSS, render(<<SASS))
2459
- .foo,
2460
- .bar {
2461
- a: b; }
2462
- CSS
2463
- .foo,
2464
- \#{".bar"}
2465
- a: b
2466
- SASS
2467
- end
2468
-
2469
- def test_list_separator_with_arg_list
2470
- assert_equal(<<CSS, render(<<SASS))
2471
- .test {
2472
- separator: comma; }
2473
- CSS
2474
- @mixin arglist-test($args...)
2475
- separator: list-separator($args)
2476
-
2477
- .test
2478
- @include arglist-test(this, is, comma, separated)
2479
- SASS
2480
- end
2481
-
2482
- def test_parent_mixin_in_content_nested
2483
- assert_equal(<<CSS, render(<<SASS))
2484
- a {
2485
- b: c; }
2486
- CSS
2487
- =foo
2488
- @content
2489
-
2490
- =bar
2491
- +foo
2492
- +foo
2493
- a
2494
- b: c
2495
-
2496
- +bar
2497
- SASS
2498
- end
2499
-
2500
- def test_supports_bubbles
2501
- assert_equal <<CSS, render(<<SASS)
2502
- parent {
2503
- background: orange; }
2504
- @supports (perspective: 10px) or (-moz-perspective: 10px) {
2505
- parent child {
2506
- background: blue; } }
2507
- CSS
2508
- parent
2509
- background: orange
2510
- @supports (perspective: 10px) or (-moz-perspective: 10px)
2511
- child
2512
- background: blue
2513
- SASS
2514
- end
2515
-
2516
- def test_line_numbers_with_dos_line_endings
2517
- assert_equal <<CSS, render(<<SASS, :line_comments => true)
2518
- /* line 5, test_line_numbers_with_dos_line_endings_inline.sass */
2519
- .foo {
2520
- a: b; }
2521
- CSS
2522
- \r
2523
- \r
2524
- \r
2525
- \r
2526
- .foo
2527
- a: b
2528
- SASS
2529
- end
2530
-
2531
- def test_variable_in_media_in_mixin
2532
- assert_equal <<CSS, render(<<SASS)
2533
- @media screen and (min-width: 10px) {
2534
- body {
2535
- background: red; } }
2536
- @media screen and (min-width: 20px) {
2537
- body {
2538
- background: blue; } }
2539
- CSS
2540
- @mixin respond-to($width)
2541
- @media screen and (min-width: $width)
2542
- @content
2543
-
2544
- body
2545
- @include respond-to(10px)
2546
- background: red
2547
- @include respond-to(20px)
2548
- background: blue
2549
- SASS
2550
- end
2551
-
2552
- def test_interpolated_comment_in_mixin
2553
- assert_equal <<CSS, render(<<SASS)
2554
- /*! color: red */
2555
- .foo {
2556
- color: red; }
2557
-
2558
- /*! color: blue */
2559
- .foo {
2560
- color: blue; }
2561
-
2562
- /*! color: green */
2563
- .foo {
2564
- color: green; }
2565
- CSS
2566
- =foo($var)
2567
- /*! color: \#{$var}
2568
- .foo
2569
- color: $var
2570
-
2571
- +foo(red)
2572
- +foo(blue)
2573
- +foo(green)
2574
- SASS
2575
- end
2576
-
2577
- def test_parens_in_mixins
2578
- assert_equal(<<CSS, render(<<SASS))
2579
- .foo {
2580
- color: #01ff7f;
2581
- background-color: #000102; }
2582
- CSS
2583
- =foo($c1, $c2: rgb(0, 1, 2))
2584
- color: $c1
2585
- background-color: $c2
2586
-
2587
- .foo
2588
- +foo(rgb(1,255,127))
2589
- SASS
2590
- end
2591
-
2592
- def test_comment_beneath_prop
2593
- assert_equal(<<RESULT, render(<<SOURCE))
2594
- .box {
2595
- border-style: solid; }
2596
- RESULT
2597
- .box
2598
- border:
2599
- //color: black
2600
- style: solid
2601
- SOURCE
2602
-
2603
- assert_equal(<<RESULT, render(<<SOURCE))
2604
- .box {
2605
- /* color: black */
2606
- border-style: solid; }
2607
- RESULT
2608
- .box
2609
- border:
2610
- /* color: black
2611
- style: solid
2612
- SOURCE
2613
-
2614
- assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
2615
- .box{border-style:solid}
2616
- RESULT
2617
- .box
2618
- border:
2619
- /*color: black
2620
- style: solid
2621
- SOURCE
2622
- end
2623
-
2624
- def test_compressed_comment_beneath_directive
2625
- assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
2626
- @foo{a:b}
2627
- RESULT
2628
- @foo
2629
- a: b
2630
- /*b: c
2631
- SOURCE
2632
- end
2633
-
2634
- def test_comment_with_crazy_indentation
2635
- assert_equal(<<CSS, render(<<SASS))
2636
- /* This is a loud comment:
2637
- * Where the indentation is wonky. */
2638
- .comment {
2639
- width: 1px; }
2640
- CSS
2641
- /*
2642
- This is a loud comment:
2643
- Where the indentation is wonky.
2644
- //
2645
- This is a silent comment:
2646
- Where the indentation is wonky.
2647
- .comment
2648
- width: 1px
2649
- SASS
2650
- end
2651
-
2652
- def test_plus_with_space
2653
- assert_equal(<<CSS, render(<<SASS))
2654
- a + b {
2655
- color: green; }
2656
- CSS
2657
- a
2658
- + b
2659
- color: green
2660
- SASS
2661
- end
2662
-
2663
- def test_empty_line_comment
2664
- assert_equal(<<CSS, render(<<SASS))
2665
- /* Foo
2666
- *
2667
- * Bar */
2668
- CSS
2669
- /*
2670
- Foo
2671
-
2672
- Bar
2673
- SASS
2674
- end
2675
-
2676
- def test_empty_comment
2677
- assert_equal(<<CSS, render(<<SASS))
2678
- /* */
2679
- a {
2680
- /* */
2681
- b: c; }
2682
- CSS
2683
- /*
2684
- a
2685
- /*
2686
- b: c
2687
- SASS
2688
- end
2689
-
2690
- def test_options_available_in_environment
2691
- assert_equal(<<CSS, render(<<SASS))
2692
- a {
2693
- b: nested; }
2694
- CSS
2695
- a
2696
- b: option("style")
2697
- SASS
2698
- end
2699
-
2700
- def test_import_with_commas_in_url
2701
- assert_equal <<CSS, render(<<SASS)
2702
- @import url(foo.css?bar,baz);
2703
- CSS
2704
- @import url(foo.css?bar,baz)
2705
- SASS
2706
- end
2707
-
2708
- def test_silent_comment_in_prop_val_after_important
2709
- assert_equal(<<CSS, render(<<SASS))
2710
- .advanced {
2711
- display: none !important; }
2712
- CSS
2713
- .advanced
2714
- display: none !important // yeah, yeah. it's not really a style anyway.
2715
- SASS
2716
- end
2717
-
2718
- def test_mixin_with_keyword_args
2719
- assert_equal <<CSS, render(<<SASS)
2720
- .mixed {
2721
- required: foo;
2722
- arg1: default-val1;
2723
- arg2: non-default-val2; }
2724
- CSS
2725
- =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2726
- required: $required
2727
- arg1: $arg1
2728
- arg2: $arg2
2729
- .mixed
2730
- +a-mixin(foo, $arg2: non-default-val2)
2731
- SASS
2732
- end
2733
-
2734
- def test_mixin_with_keyword_arg_variable_value
2735
- assert_equal <<CSS, render(<<SASS)
2736
- .mixed {
2737
- required: foo;
2738
- arg1: default-val1;
2739
- arg2: a-value; }
2740
- CSS
2741
- =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2742
- required: $required
2743
- arg1: $arg1
2744
- arg2: $arg2
2745
- .mixed
2746
- $a-value: a-value
2747
- +a-mixin(foo, $arg2: $a-value)
2748
- SASS
2749
- end
2750
-
2751
- def test_mixin_keyword_args_handle_variable_underscore_dash_equivalence
2752
- assert_equal <<CSS, render(<<SASS)
2753
- .mixed {
2754
- required: foo;
2755
- arg1: non-default-val1;
2756
- arg2: non-default-val2; }
2757
- CSS
2758
- =a-mixin($required, $arg-1: default-val1, $arg_2: default-val2)
2759
- required: $required
2760
- arg1: $arg_1
2761
- arg2: $arg-2
2762
- .mixed
2763
- +a-mixin(foo, $arg-2: non-default-val2, $arg_1: non-default-val1)
2764
- SASS
2765
- end
2766
-
2767
- def test_passing_required_args_as_a_keyword_arg
2768
- assert_equal <<CSS, render(<<SASS)
2769
- .mixed {
2770
- required: foo;
2771
- arg1: default-val1;
2772
- arg2: default-val2; }
2773
- CSS
2774
- =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2775
- required: $required
2776
- arg1: $arg1
2777
- arg2: $arg2
2778
- .mixed
2779
- +a-mixin($required: foo)
2780
- SASS
2781
- end
2782
-
2783
- def test_passing_all_as_keyword_args_in_opposite_order
2784
- assert_equal <<CSS, render(<<SASS)
2785
- .mixed {
2786
- required: foo;
2787
- arg1: non-default-val1;
2788
- arg2: non-default-val2; }
2789
- CSS
2790
- =a-mixin($required, $arg1: default-val1, $arg2: default-val2)
2791
- required: $required
2792
- arg1: $arg1
2793
- arg2: $arg2
2794
- .mixed
2795
- +a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo)
2796
- SASS
2797
- end
2798
-
2799
- def test_function_output_with_comma
2800
- assert_equal <<CSS, render(<<SASS)
2801
- foo {
2802
- a: b(c), d(e); }
2803
- CSS
2804
- foo
2805
- a: b(c), d(e)
2806
- SASS
2807
- end
2808
-
2809
- def test_interpolation_with_comma
2810
- assert_equal <<CSS, render(<<SASS)
2811
- foo {
2812
- a: foo, bar; }
2813
- CSS
2814
- $foo: foo
2815
- foo
2816
- a: \#{$foo}, bar
2817
- SASS
2818
- end
2819
-
2820
- def test_string_interpolation_with_comma
2821
- assert_equal <<CSS, render(<<SASS)
2822
- foo {
2823
- a: "bip foo bap", bar; }
2824
- CSS
2825
- $foo: foo
2826
- foo
2827
- a: "bip \#{$foo} bap", bar
2828
- SASS
2829
- end
2830
-
2831
- def test_unknown_directive
2832
- assert_equal <<CSS, render(<<SASS)
2833
- @baz {
2834
- c: d; }
2835
- CSS
2836
- @baz
2837
- c: d
2838
- SASS
2839
- end
2840
-
2841
- def test_loud_comment_interpolations_can_be_escaped
2842
- assert_equal <<CSS, render(<<SASS)
2843
- /* \#{foo} */
2844
- CSS
2845
- /* \\\#{foo}
2846
- SASS
2847
- assert_equal <<CSS, render(<<SASS)
2848
- /*! \#{foo} */
2849
- CSS
2850
- /*! \\\#{foo}
2851
- SASS
2852
- end
2853
-
2854
- def test_selector_compression
2855
- assert_equal <<CSS, render(<<SASS, :style => :compressed)
2856
- a>b,c+d,:-moz-any(e,f,g){h:i}
2857
- CSS
2858
- a > b, c + d, :-moz-any(e, f, g)
2859
- h: i
2860
- SASS
2861
- end
2862
-
2863
- def test_comment_like_selector
2864
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "/": expected identifier, was " foo"') {render(<<SASS)}
2865
- / foo
2866
- a: b
2867
- SASS
2868
- end
2869
-
2870
- def test_nested_empty_directive
2871
- assert_equal <<CSS, render(<<SASS)
2872
- @media screen {
2873
- .foo {
2874
- a: b; }
2875
-
2876
- @unknown-directive; }
2877
- CSS
2878
- @media screen
2879
- .foo
2880
- a: b
2881
-
2882
- @unknown-directive
2883
- SASS
2884
- end
2885
-
2886
- def test_original_filename_set
2887
- importer = MockImporter.new
2888
- importer.add_import("imported", "div{color:red}")
2889
-
2890
- original_filename = filename_for_test
2891
- engine = Sass::Engine.new('@import "imported"; div{color:blue}',
2892
- :filename => original_filename, :load_paths => [importer], :syntax => :scss, :importer => importer)
2893
- engine.render
2894
-
2895
- assert_equal original_filename, engine.options[:original_filename]
2896
- assert_equal original_filename, importer.engine("imported").options[:original_filename]
2897
- end
2898
-
2899
- def test_changing_precision
2900
- old_precision = Sass::Script::Value::Number.precision
2901
- begin
2902
- Sass::Script::Value::Number.precision = 8
2903
- assert_equal <<CSS, render(<<SASS)
2904
- div {
2905
- maximum: 1.00000001;
2906
- too-much: 1; }
2907
- CSS
2908
- div
2909
- maximum : 1.00000001
2910
- too-much: 1.000000001
2911
- SASS
2912
- ensure
2913
- Sass::Script::Value::Number.precision = old_precision
2914
- end
2915
- end
2916
-
2917
- def test_content
2918
- assert_equal <<CSS, render(<<SASS)
2919
- .children {
2920
- background-color: red;
2921
- color: blue;
2922
- border-color: red; }
2923
- CSS
2924
- $color: blue
2925
- =context($class, $color: red)
2926
- .\#{$class}
2927
- background-color: $color
2928
- @content
2929
- border-color: $color
2930
- +context(children)
2931
- color: $color
2932
- SASS
2933
- end
2934
-
2935
- def test_selector_in_content
2936
- assert_equal <<CSS, render(<<SASS)
2937
- .parent {
2938
- background-color: red;
2939
- border-color: red; }
2940
- .parent .children {
2941
- color: blue; }
2942
- CSS
2943
- $color: blue
2944
- =context($class, $color: red)
2945
- .\#{$class}
2946
- background-color: $color
2947
- @content
2948
- border-color: $color
2949
- +context(parent)
2950
- .children
2951
- color: $color
2952
- SASS
2953
- end
2954
-
2955
- def test_using_parent_mixin_in_content
2956
- assert_equal <<CSS, render(<<SASS)
2957
- .parent {
2958
- before-color: red;
2959
- after-color: red; }
2960
- .parent .sibling {
2961
- before-color: yellow;
2962
- after-color: yellow; }
2963
- .parent .sibling .child {
2964
- before-color: green;
2965
- color: blue;
2966
- after-color: green; }
2967
- CSS
2968
- $color: blue
2969
- =context($class, $color: red)
2970
- .\#{$class}
2971
- before-color: $color
2972
- @content
2973
- after-color: $color
2974
- +context(parent)
2975
- +context(sibling, $color: yellow)
2976
- +context(child, $color: green)
2977
- color: $color
2978
- SASS
2979
- end
2980
-
2981
- def test_content_more_than_once
2982
- assert_equal <<CSS, render(<<SASS)
2983
- .once {
2984
- color: blue; }
2985
-
2986
- .twice {
2987
- color: blue; }
2988
- CSS
2989
- $color: blue
2990
- =context($class, $color: red)
2991
- .once
2992
- @content
2993
- .twice
2994
- @content
2995
- +context(parent)
2996
- color: $color
2997
- SASS
2998
- end
2999
-
3000
- def test_content_with_variable
3001
- assert_equal <<CSS, render(<<SASS)
3002
- .foo {
3003
- a: 1px; }
3004
- CSS
3005
- =foo
3006
- .foo
3007
- @content
3008
- +foo
3009
- $a: 1px
3010
- a: $a
3011
- SASS
3012
- end
3013
-
3014
- def test_nested_content_blocks
3015
- assert_equal <<CSS, render(<<SASS)
3016
- .foo {
3017
- a: foo; }
3018
- .foo .bar {
3019
- a: bar; }
3020
- .foo .bar .baz {
3021
- a: baz; }
3022
- .foo .bar .baz .outside {
3023
- a: outside;
3024
- color: red; }
3025
- CSS
3026
- $a: outside
3027
- =baz($a: baz)
3028
- .baz
3029
- a: $a
3030
- @content
3031
- =bar($a: bar)
3032
- .bar
3033
- a: $a
3034
- +baz
3035
- @content
3036
- =foo($a: foo)
3037
- .foo
3038
- a: $a
3039
- +bar
3040
- @content
3041
- +foo
3042
- .outside
3043
- a: $a
3044
- color: red
3045
- SASS
3046
- end
3047
-
3048
- def test_content_not_seen_through_mixin
3049
- assert_equal <<CSS, render(<<SASS)
3050
- a foo {
3051
- mixin: foo;
3052
- a: b; }
3053
- a foo bar {
3054
- mixin: bar; }
3055
- CSS
3056
- =foo
3057
- foo
3058
- mixin: foo
3059
- @content
3060
- +bar
3061
- =bar
3062
- bar
3063
- mixin: bar
3064
- @content
3065
- a
3066
- +foo
3067
- a: b
3068
- SASS
3069
- end
3070
-
3071
- def test_content_backtrace_for_perform
3072
- render(<<SASS)
3073
- =foo
3074
- @content
3075
-
3076
- a
3077
- +foo
3078
- b: 1em + 2px
3079
- SASS
3080
- assert(false, "Expected exception")
3081
- rescue Sass::SyntaxError => e
3082
- assert_equal([
3083
- {:mixin => '@content', :line => 6, :filename => 'test_content_backtrace_for_perform_inline.sass'},
3084
- {:mixin => 'foo', :line => 2, :filename => 'test_content_backtrace_for_perform_inline.sass'},
3085
- {:line => 5, :filename => 'test_content_backtrace_for_perform_inline.sass'},
3086
- ], e.sass_backtrace)
3087
- end
3088
-
3089
- def test_content_backtrace_for_cssize
3090
- render(<<SASS)
3091
- =foo
3092
- @content
3093
-
3094
- a
3095
- +foo
3096
- @extend foo bar baz
3097
- SASS
3098
- assert(false, "Expected exception")
3099
- rescue Sass::SyntaxError => e
3100
- assert_equal([
3101
- {:mixin => '@content', :line => 6, :filename => 'test_content_backtrace_for_cssize_inline.sass'},
3102
- {:mixin => 'foo', :line => 2, :filename => 'test_content_backtrace_for_cssize_inline.sass'},
3103
- {:line => 5, :filename => 'test_content_backtrace_for_cssize_inline.sass'},
3104
- ], e.sass_backtrace)
3105
- end
3106
-
3107
- def test_mixin_with_args_and_varargs_passed_no_var_args
3108
- assert_equal <<CSS, render(<<SASS, :syntax => :scss)
3109
- .foo {
3110
- a: 1;
3111
- b: 2;
3112
- c: 3; }
3113
- CSS
3114
- @mixin three-or-more-args($a, $b, $c, $rest...) {
3115
- a: $a;
3116
- b: $b;
3117
- c: $c;
3118
- }
3119
-
3120
- .foo {
3121
- @include three-or-more-args($a: 1, $b: 2, $c: 3);
3122
- }
3123
- SASS
3124
-
3125
- end
3126
-
3127
- def test_debug_inspects_sass_objects
3128
- assert_warning(<<END) {render("@debug (a: 1, b: 2)")}
3129
- test_debug_inspects_sass_objects_inline.sass:1 DEBUG: (a: 1, b: 2)
3130
- END
3131
- assert_warning(<<END) {render("$map: (a: 1, b: 2); @debug $map", :syntax => :scss)}
3132
- test_debug_inspects_sass_objects_inline.scss:1 DEBUG: (a: 1, b: 2)
3133
- END
3134
- end
3135
-
3136
- def test_error_throws_sass_objects
3137
- assert_raise_message(Sass::SyntaxError, "(a: 1, b: 2)") {render("@error (a: 1, b: 2)")}
3138
- assert_raise_message(Sass::SyntaxError, "(a: 1, b: 2)") do
3139
- render("$map: (a: 1, b: 2); @error $map", :syntax => :scss)
3140
- end
3141
- end
3142
-
3143
- def test_default_arg_before_splat
3144
- assert_equal <<CSS, render(<<SASS, :syntax => :scss)
3145
- .foo-positional {
3146
- a: 1;
3147
- b: 2;
3148
- positional-arguments: 3, 4;
3149
- keyword-arguments: (); }
3150
-
3151
- .foo-keywords {
3152
- a: true;
3153
- positional-arguments: ();
3154
- keyword-arguments: (c: c, d: d); }
3155
- CSS
3156
- @mixin foo($a: true, $b: null, $arguments...) {
3157
- a: $a;
3158
- b: $b;
3159
- positional-arguments: inspect($arguments);
3160
- keyword-arguments: inspect(keywords($arguments));
3161
- }
3162
- .foo-positional {
3163
- @include foo(1, 2, 3, 4);
3164
- }
3165
- .foo-keywords {
3166
- @include foo($c: c, $d: d);
3167
- }
3168
- SASS
3169
- end
3170
-
3171
- def test_keyframes
3172
- assert_equal <<CSS, render(<<SASS)
3173
- @keyframes identifier {
3174
- 0% {
3175
- top: 0;
3176
- left: 0; }
3177
- 30% {
3178
- top: 50px; }
3179
- 68%, 72% {
3180
- left: 50px; }
3181
- 100% {
3182
- top: 100px;
3183
- left: 100%; } }
3184
- CSS
3185
- @keyframes identifier
3186
- 0%
3187
- top: 0
3188
- left: 0
3189
- \#{"30%"}
3190
- top: 50px
3191
- 68%, 72%
3192
- left: 50px
3193
- 100%
3194
- top: 100px
3195
- left: 100%
3196
- SASS
3197
- end
3198
-
3199
- def test_prefixed_keyframes
3200
- assert_equal <<CSS, render(<<SASS)
3201
- @-moz-keyframes identifier {
3202
- 0% {
3203
- top: 0;
3204
- left: 0; }
3205
- 30% {
3206
- top: 50px; }
3207
- 68%, 72% {
3208
- left: 50px; }
3209
- 100% {
3210
- top: 100px;
3211
- left: 100%; } }
3212
- CSS
3213
- @-moz-keyframes identifier
3214
- 0%
3215
- top: 0
3216
- left: 0
3217
- \#{"30%"}
3218
- top: 50px
3219
- 68%, 72%
3220
- left: 50px
3221
- 100%
3222
- top: 100px
3223
- left: 100%
3224
- SASS
3225
- end
3226
-
3227
- def test_uppercase_keyframes
3228
- assert_equal <<CSS, render(<<SASS)
3229
- @KEYFRAMES identifier {
3230
- 0% {
3231
- top: 0;
3232
- left: 0; }
3233
- 30% {
3234
- top: 50px; }
3235
- 68%, 72% {
3236
- left: 50px; }
3237
- 100% {
3238
- top: 100px;
3239
- left: 100%; } }
3240
- CSS
3241
- @KEYFRAMES identifier
3242
- 0%
3243
- top: 0
3244
- left: 0
3245
- \#{"30%"}
3246
- top: 50px
3247
- 68%, 72%
3248
- left: 50px
3249
- 100%
3250
- top: 100px
3251
- left: 100%
3252
- SASS
3253
- end
3254
-
3255
- def test_compressed_unknown_directive
3256
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
3257
- x{@foo;a:b;@bar}
3258
- CSS
3259
- x
3260
- @foo
3261
- a: b
3262
- @bar
3263
- SASS
3264
- end
3265
-
3266
- def test_compressed_unknown_directive_in_directive
3267
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
3268
- @x{@foo;a:b;@bar}
3269
- CSS
3270
- @x
3271
- @foo
3272
- a: b
3273
- @bar
3274
- SASS
3275
- end
3276
-
3277
- def test_compressed_unknown_directive_with_children_in_directive
3278
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
3279
- @x{@foo{a:b}c:d;@bar{e:f}}
3280
- CSS
3281
- @x
3282
- @foo
3283
- a: b
3284
- c: d
3285
- @bar
3286
- e: f
3287
- SASS
3288
- end
3289
-
3290
- def test_compressed_rule_in_directive
3291
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
3292
- @x{foo{a:b}c:d;bar{e:f}}
3293
- CSS
3294
- @x
3295
- foo
3296
- a: b
3297
- c: d
3298
- bar
3299
- e: f
3300
- SASS
3301
- end
3302
-
3303
- def test_import_two_css_files_issue_1806
3304
- assert_equal(<<CSS, render(<<SASS, :syntax => :scss, :style => :compressed))
3305
- @import url(\"foo.css\");@import url(\"bar.css\");@import url(\"baz.css\")
3306
- CSS
3307
- @import url("foo.css");
3308
- @import url("bar.css");
3309
- @import url("baz.css");
3310
- SASS
3311
- end
3312
-
3313
- def test_numeric_formatting_of_integers
3314
- assert_equal(<<CSS, render(<<SASS, :syntax => :scss, :style => :compressed))
3315
- a{near:3.0000000001;plus:3;minus:3;negative:-3}
3316
- CSS
3317
- a {
3318
- near: (3 + 0.0000000001);
3319
- plus: (3 + 0.000000000001);
3320
- minus: (3 - 0.000000000001);
3321
- negative: (-3 + 0.000000000001);
3322
- }
3323
- SASS
3324
- end
3325
-
3326
- def test_escaped_semicolons_are_not_compressed
3327
- assert_equal(<<'CSS', render(<<'SASS', :syntax => :scss, :style => :compressed))
3328
- div{color:#f00000\9\0\;}
3329
- CSS
3330
- div {
3331
- color: #f00000\9\0\;
3332
- }
3333
- SASS
3334
- end
3335
-
3336
- def test_compressed_output_of_nth_selectors
3337
- assert_equal(<<CSS, render(<<SASS, :syntax => :scss, :style => :compressed))
3338
- :nth-of-type(2n-1),:nth-child(2n-1),:nth(2n-1),:nth-of-type(2n-1),:nth-of-type(2n-1){color:red}:nth-of-type(2n+1),:nth-child(2n+1),:nth(2n+1),:nth-of-type(2n+1),:nth-of-type(2n+1){color:red}
3339
- CSS
3340
- :nth-of-type(2n-1), :nth-child(2n- 1), :nth(2n -1), :nth-of-type(2n - 1), :nth-of-type( 2n - 1 ) {
3341
- color: red }
3342
- :nth-of-type(2n+1), :nth-child(2n+ 1), :nth(2n +1), :nth-of-type(2n + 1), :nth-of-type( 2n + 1 ) {
3343
- color: red }
3344
- SASS
3345
- end
3346
-
3347
- def test_descendant_selectors_with_leading_dash
3348
- assert_equal(<<CSS, render(<<SASS, :syntax => :scss, :style => :compressed))
3349
- a -b{color:red}
3350
- CSS
3351
- a -b {
3352
- color: red }
3353
- SASS
3354
- end
3355
-
3356
- def test_import_with_supports_clause_interp
3357
- assert_equal(<<CSS, render(<<'SASS', :style => :compressed))
3358
- @import url("fallback-layout.css") supports(not (display: flex))
3359
- CSS
3360
- $display-type: flex
3361
- @import url("fallback-layout.css") supports(not (display: #{$display-type}))
3362
- SASS
3363
- end
3364
-
3365
- def test_import_with_supports_clause
3366
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
3367
- @import url("fallback-layout.css") supports(not (display: flex))
3368
- CSS
3369
- @import url("fallback-layout.css") supports(not (display: flex))
3370
- SASS
3371
- end
3372
-
3373
- def test_compressed_commas_in_attribute_selectors
3374
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
3375
- .classname[a="1, 2, 3"],.another[b="4, 5, 6"]{color:red}
3376
- CSS
3377
- .classname[a="1, 2, 3"], .another[b="4, 5, 6"]
3378
- color: red
3379
- SASS
3380
- end
3381
-
3382
- def test_trailing_commas_in_arglists
3383
- assert_equal(<<CSS, render(<<SASS, :style => :nested))
3384
- .includes {
3385
- one-positional-arg: positional 1 a;
3386
- two-positional-args: positional 2 a b;
3387
- one-keyword-arg: keyword 1 z;
3388
- two-keyword-args: keyword 2 y z;
3389
- mixed-args: mixed 2 y z; }
3390
-
3391
- .calls {
3392
- one-positional-arg: positional 1 a;
3393
- two-positional-args: positional 2 a b;
3394
- one-keyword-arg: keyword 1 z;
3395
- two-keyword-args: keyword 2 y z;
3396
- mixed-args: mixed 2 y z; }
3397
- CSS
3398
- =one-positional-arg($a,)
3399
- one-positional-arg: positional 1 $a
3400
-
3401
- =two-positional-args($a, $b,)
3402
- two-positional-args: positional 2 $a $b
3403
-
3404
- =one-keyword-arg($a: a,)
3405
- one-keyword-arg: keyword 1 $a
3406
-
3407
- =two-keyword-args($a: a, $b: b,)
3408
- two-keyword-args: keyword 2 $a $b
3409
-
3410
- =mixed-args($a, $b: b,)
3411
- mixed-args: mixed 2 $a $b
3412
-
3413
- @function one-positional-arg($a)
3414
- @return positional 1 $a
3415
-
3416
- @function two-positional-args($a, $b)
3417
- @return positional 2 $a $b
3418
-
3419
- @function one-keyword-arg($a: a)
3420
- @return keyword 1 $a
3421
-
3422
- @function two-keyword-args($a: a, $b: b)
3423
- @return keyword 2 $a $b
3424
-
3425
- @function mixed-args($a, $b: b)
3426
- @return mixed 2 $a $b
3427
-
3428
-
3429
- .includes
3430
- +one-positional-arg(a,)
3431
- +two-positional-args(a, b,)
3432
- +one-keyword-arg($a: z,)
3433
- +two-keyword-args($a: y, $b: z,)
3434
- +mixed-args(y, $b: z,)
3435
-
3436
-
3437
- .calls
3438
- one-positional-arg: one-positional-arg(a)
3439
- two-positional-args: two-positional-args(a, b)
3440
- one-keyword-arg: one-keyword-arg($a: z)
3441
- two-keyword-args: two-keyword-args($a: y, $b: z)
3442
- mixed-args: mixed-args(y, $b: z)
3443
- SASS
3444
- end
3445
-
3446
- private
3447
-
3448
- def assert_hash_has(hash, expected)
3449
- expected.each do |k, v|
3450
- if v.nil?
3451
- assert_nil(hash[k])
3452
- else
3453
- assert_equal(v, hash[k])
3454
- end
3455
- end
3456
- end
3457
-
3458
- def assert_renders_encoded(css, sass)
3459
- result = render(sass)
3460
- assert_equal css.encoding, result.encoding
3461
- assert_equal css, result
3462
- end
3463
-
3464
- def render(sass, options = {})
3465
- munge_filename options
3466
- options[:importer] ||= MockImporter.new
3467
- Sass::Engine.new(sass, options).render
3468
- end
3469
-
3470
- def renders_correctly(name, options={})
3471
- sass_file = load_file(name, "sass")
3472
- css_file = load_file(name, "css")
3473
- options[:filename] ||= filename(name, "sass")
3474
- options[:syntax] ||= :sass
3475
- options[:css_filename] ||= filename(name, "css")
3476
- css_result = Sass::Engine.new(sass_file, options).render
3477
- assert_equal css_file, css_result
3478
- end
3479
-
3480
- def load_file(name, type = "sass")
3481
- @result = ''
3482
- File.new(filename(name, type)).each_line { |l| @result += l }
3483
- @result
3484
- end
3485
-
3486
- def filename(name, type)
3487
- path = File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
3488
- Sass::Util.cleanpath(path).to_s
3489
- end
3490
-
3491
- def sassc_path(template)
3492
- sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
3493
- engine = Sass::Engine.new("", :filename => sassc_path,
3494
- :importer => Sass::Importers::Filesystem.new("."))
3495
- key = engine.send(:sassc_key)
3496
- File.join(engine.options[:cache_location], key)
3497
- end
3498
- end
3499
-