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