drnic-haml 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.yardopts +5 -0
- data/CONTRIBUTING +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +347 -0
- data/REVISION +1 -0
- data/Rakefile +371 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/css2sass +7 -0
- data/bin/haml +9 -0
- data/bin/html2haml +7 -0
- data/bin/sass +8 -0
- data/extra/haml-mode.el +663 -0
- data/extra/sass-mode.el +205 -0
- data/extra/update_watch.rb +13 -0
- data/init.rb +8 -0
- data/lib/haml.rb +40 -0
- data/lib/haml/buffer.rb +307 -0
- data/lib/haml/engine.rb +301 -0
- data/lib/haml/error.rb +22 -0
- data/lib/haml/exec.rb +470 -0
- data/lib/haml/filters.rb +341 -0
- data/lib/haml/helpers.rb +560 -0
- data/lib/haml/helpers/action_view_extensions.rb +40 -0
- data/lib/haml/helpers/action_view_mods.rb +176 -0
- data/lib/haml/herb.rb +96 -0
- data/lib/haml/html.rb +308 -0
- data/lib/haml/precompiler.rb +997 -0
- data/lib/haml/shared.rb +78 -0
- data/lib/haml/template.rb +51 -0
- data/lib/haml/template/patch.rb +58 -0
- data/lib/haml/template/plugin.rb +71 -0
- data/lib/haml/util.rb +244 -0
- data/lib/haml/version.rb +64 -0
- data/lib/sass.rb +24 -0
- data/lib/sass/css.rb +423 -0
- data/lib/sass/engine.rb +491 -0
- data/lib/sass/environment.rb +79 -0
- data/lib/sass/error.rb +162 -0
- data/lib/sass/files.rb +133 -0
- data/lib/sass/plugin.rb +170 -0
- data/lib/sass/plugin/merb.rb +57 -0
- data/lib/sass/plugin/rails.rb +23 -0
- data/lib/sass/repl.rb +58 -0
- data/lib/sass/script.rb +55 -0
- data/lib/sass/script/bool.rb +17 -0
- data/lib/sass/script/color.rb +183 -0
- data/lib/sass/script/funcall.rb +50 -0
- data/lib/sass/script/functions.rb +199 -0
- data/lib/sass/script/lexer.rb +191 -0
- data/lib/sass/script/literal.rb +177 -0
- data/lib/sass/script/node.rb +14 -0
- data/lib/sass/script/number.rb +381 -0
- data/lib/sass/script/operation.rb +45 -0
- data/lib/sass/script/parser.rb +222 -0
- data/lib/sass/script/string.rb +12 -0
- data/lib/sass/script/unary_operation.rb +34 -0
- data/lib/sass/script/variable.rb +31 -0
- data/lib/sass/tree/comment_node.rb +84 -0
- data/lib/sass/tree/debug_node.rb +30 -0
- data/lib/sass/tree/directive_node.rb +70 -0
- data/lib/sass/tree/for_node.rb +48 -0
- data/lib/sass/tree/if_node.rb +54 -0
- data/lib/sass/tree/import_node.rb +69 -0
- data/lib/sass/tree/mixin_def_node.rb +29 -0
- data/lib/sass/tree/mixin_node.rb +48 -0
- data/lib/sass/tree/node.rb +252 -0
- data/lib/sass/tree/prop_node.rb +106 -0
- data/lib/sass/tree/root_node.rb +56 -0
- data/lib/sass/tree/rule_node.rb +220 -0
- data/lib/sass/tree/variable_node.rb +34 -0
- data/lib/sass/tree/while_node.rb +31 -0
- data/rails/init.rb +1 -0
- data/test/benchmark.rb +99 -0
- data/test/haml/engine_test.rb +1129 -0
- data/test/haml/helper_test.rb +282 -0
- data/test/haml/html2haml_test.rb +258 -0
- data/test/haml/markaby/standard.mab +52 -0
- data/test/haml/mocks/article.rb +6 -0
- data/test/haml/results/content_for_layout.xhtml +12 -0
- data/test/haml/results/eval_suppressed.xhtml +9 -0
- data/test/haml/results/filters.xhtml +62 -0
- data/test/haml/results/helpers.xhtml +93 -0
- data/test/haml/results/helpful.xhtml +10 -0
- data/test/haml/results/just_stuff.xhtml +68 -0
- data/test/haml/results/list.xhtml +12 -0
- data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
- data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
- data/test/haml/results/original_engine.xhtml +20 -0
- data/test/haml/results/partial_layout.xhtml +5 -0
- data/test/haml/results/partials.xhtml +21 -0
- data/test/haml/results/render_layout.xhtml +3 -0
- data/test/haml/results/silent_script.xhtml +74 -0
- data/test/haml/results/standard.xhtml +162 -0
- data/test/haml/results/tag_parsing.xhtml +23 -0
- data/test/haml/results/very_basic.xhtml +5 -0
- data/test/haml/results/whitespace_handling.xhtml +89 -0
- data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
- data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
- data/test/haml/rhtml/action_view.rhtml +62 -0
- data/test/haml/rhtml/standard.rhtml +54 -0
- data/test/haml/spec_test.rb +44 -0
- data/test/haml/template_test.rb +217 -0
- data/test/haml/templates/_av_partial_1.haml +9 -0
- data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
- data/test/haml/templates/_av_partial_2.haml +5 -0
- data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
- data/test/haml/templates/_layout.erb +3 -0
- data/test/haml/templates/_layout_for_partial.haml +3 -0
- data/test/haml/templates/_partial.haml +8 -0
- data/test/haml/templates/_text_area.haml +3 -0
- data/test/haml/templates/action_view.haml +47 -0
- data/test/haml/templates/action_view_ugly.haml +47 -0
- data/test/haml/templates/breakage.haml +8 -0
- data/test/haml/templates/content_for_layout.haml +8 -0
- data/test/haml/templates/eval_suppressed.haml +11 -0
- data/test/haml/templates/filters.haml +66 -0
- data/test/haml/templates/helpers.haml +95 -0
- data/test/haml/templates/helpful.haml +11 -0
- data/test/haml/templates/just_stuff.haml +83 -0
- data/test/haml/templates/list.haml +12 -0
- data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
- data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
- data/test/haml/templates/original_engine.haml +17 -0
- data/test/haml/templates/partial_layout.haml +3 -0
- data/test/haml/templates/partialize.haml +1 -0
- data/test/haml/templates/partials.haml +12 -0
- data/test/haml/templates/render_layout.haml +2 -0
- data/test/haml/templates/silent_script.haml +40 -0
- data/test/haml/templates/standard.haml +42 -0
- data/test/haml/templates/standard_ugly.haml +42 -0
- data/test/haml/templates/tag_parsing.haml +21 -0
- data/test/haml/templates/very_basic.haml +4 -0
- data/test/haml/templates/whitespace_handling.haml +87 -0
- data/test/haml/util_test.rb +92 -0
- data/test/linked_rails.rb +12 -0
- data/test/sass/css2sass_test.rb +294 -0
- data/test/sass/engine_test.rb +956 -0
- data/test/sass/functions_test.rb +126 -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 +229 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +87 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/import.css +29 -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/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -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/script_test.rb +261 -0
- data/test/sass/templates/_partial.sass +2 -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/compact.sass +17 -0
- data/test/sass/templates/complex.sass +307 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/import.sass +11 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -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/parent_ref.sass +25 -0
- data/test/sass/templates/script.sass +101 -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/test_helper.rb +44 -0
- metadata +298 -0
|
@@ -0,0 +1,956 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
3
|
+
require 'sass/engine'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
|
|
6
|
+
class SassEngineTest < Test::Unit::TestCase
|
|
7
|
+
# A map of erroneous Sass documents to the error messages they should produce.
|
|
8
|
+
# The error messages may be arrays;
|
|
9
|
+
# if so, the second element should be the line number that should be reported for the error.
|
|
10
|
+
# If this isn't provided, the tests will assume the line number should be the last line of the document.
|
|
11
|
+
EXCEPTION_MAP = {
|
|
12
|
+
"!a = 1 + " => 'Expected expression, was end of text.',
|
|
13
|
+
"!a = 1 + 2 +" => 'Expected expression, was end of text.',
|
|
14
|
+
"!a = 1 + 2 + %" => 'Expected expression, was mod token.',
|
|
15
|
+
"!a = foo(\"bar\"" => 'Expected rparen token, was end of text.',
|
|
16
|
+
"!a = 1 }" => 'Unexpected end_interpolation token.',
|
|
17
|
+
"!a = 1 }foo\"" => 'Unexpected end_interpolation token.',
|
|
18
|
+
":" => 'Invalid property: ":".',
|
|
19
|
+
": a" => 'Invalid property: ": a".',
|
|
20
|
+
":= a" => 'Invalid property: ":= a".',
|
|
21
|
+
"a\n :b" => 'Invalid property: ":b " (no value).',
|
|
22
|
+
"a\n b:" => 'Invalid property: "b: " (no value).',
|
|
23
|
+
"a\n :b: c" => 'Invalid property: ":b: c".',
|
|
24
|
+
"a\n :b:c d" => 'Invalid property: ":b:c d".',
|
|
25
|
+
"a\n :b=c d" => 'Invalid property: ":b=c d".',
|
|
26
|
+
"a\n :b c;" => 'Invalid property: ":b c;" (no ";" required at end-of-line).',
|
|
27
|
+
"a\n b: c;" => 'Invalid property: "b: c;" (no ";" required at end-of-line).',
|
|
28
|
+
"a\n b : c" => 'Invalid property: "b : c".',
|
|
29
|
+
"a\n b=c: d" => 'Invalid property: "b=c: d".',
|
|
30
|
+
":a" => 'Properties aren\'t allowed at the root of a document.',
|
|
31
|
+
"!" => 'Invalid variable: "!".',
|
|
32
|
+
"!a" => 'Invalid variable: "!a".',
|
|
33
|
+
"! a" => 'Invalid variable: "! a".',
|
|
34
|
+
"!a b" => 'Invalid variable: "!a b".',
|
|
35
|
+
"!a = 1b + 2c" => "Incompatible units: 'c' and 'b'.",
|
|
36
|
+
"!a = 1b < 2c" => "Incompatible units: 'c' and 'b'.",
|
|
37
|
+
"!a = 1b > 2c" => "Incompatible units: 'c' and 'b'.",
|
|
38
|
+
"!a = 1b <= 2c" => "Incompatible units: 'c' and 'b'.",
|
|
39
|
+
"!a = 1b >= 2c" => "Incompatible units: 'c' and 'b'.",
|
|
40
|
+
"a\n :b= 1b * 2c" => "2b*c isn't a valid CSS value.",
|
|
41
|
+
"a\n :b= 1b % 2c" => "Cannot modulo by a number with units: 2c.",
|
|
42
|
+
"!a = 2px + #ccc" => "Cannot add a number with units (2px) to a color (#cccccc).",
|
|
43
|
+
"!a = #ccc + 2px" => "Cannot add a number with units (2px) to a color (#cccccc).",
|
|
44
|
+
"& a\n :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
|
|
45
|
+
"a\n :b\n c" => "Illegal nesting: Only properties may be nested beneath properties.",
|
|
46
|
+
"a,\n :b c" => ["Rules can\'t end in commas.", 1],
|
|
47
|
+
"a," => "Rules can\'t end in commas.",
|
|
48
|
+
"a,\n!b = 1" => ["Rules can\'t end in commas.", 1],
|
|
49
|
+
"!a = b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
|
|
50
|
+
"@import foo.sass" => "File to import not found or unreadable: foo.sass.",
|
|
51
|
+
"@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
|
|
52
|
+
"foo\n @import templates/basic" => "Import directives may only be used at the root of a document.",
|
|
53
|
+
"foo\n @import #{File.dirname(__FILE__)}/templates/basic" => "Import directives may only be used at the root of a document.",
|
|
54
|
+
%Q{!foo = "bar" "baz" !} => %Q{Syntax error in '"bar" "baz" !' at character 20.},
|
|
55
|
+
"=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.",
|
|
56
|
+
".bar\n =foo\n :color red\n" => ["Mixins may only be defined at the root of a document.", 2],
|
|
57
|
+
"=foo\n :color red\n.bar\n +foo\n :color red" => "Illegal nesting: Nothing may be nested beneath mixin directives.",
|
|
58
|
+
" a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1],
|
|
59
|
+
" \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4],
|
|
60
|
+
"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],
|
|
61
|
+
"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],
|
|
62
|
+
"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],
|
|
63
|
+
"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],
|
|
64
|
+
"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],
|
|
65
|
+
"a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
|
|
66
|
+
"a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
|
|
67
|
+
"a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
|
|
68
|
+
"=a(" => 'Expected rparen token, was end of text.',
|
|
69
|
+
"=a(b)" => 'Expected rparen token, was ident token.',
|
|
70
|
+
"=a(,)" => "Expected rparen token, was comma token.",
|
|
71
|
+
"=a(!)" => "Syntax error in '(!)' at character 4.",
|
|
72
|
+
"=a(!foo bar)" => "Expected rparen token, was ident token.",
|
|
73
|
+
"=foo\n bar: baz\n+foo" => ["Properties aren't allowed at the root of a document.", 2],
|
|
74
|
+
"a-\#{!b\n c: d" => ["Expected end_interpolation token, was end of text.", 1],
|
|
75
|
+
"=a(!b = 1, !c)" => "Required argument !c must come before any optional arguments.",
|
|
76
|
+
"=a(!b = 1)\n :a= !b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
|
|
77
|
+
"=a(!b)\n :a= !b\ndiv\n +a" => "Mixin a is missing parameter !b.",
|
|
78
|
+
"@else\n a\n b: c" => ["@else must come after @if.", 1],
|
|
79
|
+
"@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
|
|
80
|
+
"@if false\n@else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
|
|
81
|
+
"a\n !b = 12\nc\n d = !b" => 'Undefined variable: "!b".',
|
|
82
|
+
"=foo\n !b = 12\nc\n +foo\n d = !b" => 'Undefined variable: "!b".',
|
|
83
|
+
'@for !a from "foo" to 1' => '"foo" is not an integer.',
|
|
84
|
+
'@for !a from 1 to "2"' => '"2" is not an integer.',
|
|
85
|
+
'@for !a from 1 to "foo"' => '"foo" is not an integer.',
|
|
86
|
+
'@for !a from 1 to 1.232323' => '1.232 is not an integer.',
|
|
87
|
+
'@for !a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
|
|
88
|
+
'@if' => "Invalid if directive '@if': expected expression.",
|
|
89
|
+
'@while' => "Invalid while directive '@while': expected expression.",
|
|
90
|
+
'@debug' => "Invalid debug directive '@debug': expected expression.",
|
|
91
|
+
|
|
92
|
+
# Regression tests
|
|
93
|
+
"a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
|
|
94
|
+
"& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
|
|
95
|
+
"a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3],
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
def teardown
|
|
99
|
+
clean_up_sassc
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_basic_render
|
|
103
|
+
renders_correctly "basic", { :style => :compact }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_empty_render
|
|
107
|
+
assert_equal "", render("")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_multiple_calls_to_render
|
|
111
|
+
sass = Sass::Engine.new("a\n b: c")
|
|
112
|
+
assert_equal sass.render, sass.render
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_alternate_styles
|
|
116
|
+
renders_correctly "expanded", { :style => :expanded }
|
|
117
|
+
renders_correctly "compact", { :style => :compact }
|
|
118
|
+
renders_correctly "nested", { :style => :nested }
|
|
119
|
+
renders_correctly "compressed", { :style => :compressed }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def test_flexible_tabulation
|
|
123
|
+
assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
|
|
124
|
+
render("p\n a: b\n q\n c: d\n"))
|
|
125
|
+
assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
|
|
126
|
+
render("p\n\ta: b\n\tq\n\t\tc: d\n"))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
EXCEPTION_MAP.each do |key, value|
|
|
130
|
+
define_method("test_exception (#{key.inspect})") do
|
|
131
|
+
line = 10
|
|
132
|
+
begin
|
|
133
|
+
silence_warnings {Sass::Engine.new(key, :filename => __FILE__, :line => line).render}
|
|
134
|
+
rescue Sass::SyntaxError => err
|
|
135
|
+
value = [value] unless value.is_a?(Array)
|
|
136
|
+
|
|
137
|
+
assert_equal(value.first, err.message, "Line: #{key}")
|
|
138
|
+
assert_equal(__FILE__, err.sass_filename)
|
|
139
|
+
assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
|
|
140
|
+
assert_match(/#{Regexp.escape(__FILE__)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
|
|
141
|
+
else
|
|
142
|
+
assert(false, "Exception not raised for\n#{key}")
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def test_exception_line
|
|
148
|
+
to_render = <<SASS
|
|
149
|
+
rule
|
|
150
|
+
:prop val
|
|
151
|
+
// comment!
|
|
152
|
+
|
|
153
|
+
:broken
|
|
154
|
+
SASS
|
|
155
|
+
begin
|
|
156
|
+
Sass::Engine.new(to_render).render
|
|
157
|
+
rescue Sass::SyntaxError => err
|
|
158
|
+
assert_equal(5, err.sass_line)
|
|
159
|
+
else
|
|
160
|
+
assert(false, "Exception not raised for '#{to_render}'!")
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_exception_location
|
|
165
|
+
to_render = <<SASS
|
|
166
|
+
rule
|
|
167
|
+
:prop val
|
|
168
|
+
// comment!
|
|
169
|
+
|
|
170
|
+
:broken
|
|
171
|
+
SASS
|
|
172
|
+
begin
|
|
173
|
+
Sass::Engine.new(to_render, :filename => __FILE__, :line => (__LINE__-7)).render
|
|
174
|
+
rescue Sass::SyntaxError => err
|
|
175
|
+
assert_equal(__FILE__, err.sass_filename)
|
|
176
|
+
assert_equal((__LINE__-6), err.sass_line)
|
|
177
|
+
else
|
|
178
|
+
assert(false, "Exception not raised for '#{to_render}'!")
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def test_imported_exception
|
|
183
|
+
[1, 2, 3].each do |i|
|
|
184
|
+
begin
|
|
185
|
+
Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
|
|
186
|
+
rescue Sass::SyntaxError => err
|
|
187
|
+
assert_equal(2, err.sass_line)
|
|
188
|
+
assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
|
|
189
|
+
|
|
190
|
+
assert_equal(err.sass_filename, err.sass_backtrace.first[:filename])
|
|
191
|
+
assert_equal(err.sass_line, err.sass_backtrace.first[:line])
|
|
192
|
+
|
|
193
|
+
assert_nil(err.sass_backtrace[1][:filename])
|
|
194
|
+
assert_equal(1, err.sass_backtrace[1][:line])
|
|
195
|
+
|
|
196
|
+
assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
|
|
197
|
+
assert_equal("(sass):1", err.backtrace[1])
|
|
198
|
+
else
|
|
199
|
+
assert(false, "Exception not raised for imported template: bork#{i}")
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def test_double_imported_exception
|
|
205
|
+
[1, 2, 3].each do |i|
|
|
206
|
+
begin
|
|
207
|
+
Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
|
|
208
|
+
rescue Sass::SyntaxError => err
|
|
209
|
+
assert_equal(2, err.sass_line)
|
|
210
|
+
assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
|
|
211
|
+
|
|
212
|
+
assert_equal(err.sass_filename, err.sass_backtrace.first[:filename])
|
|
213
|
+
assert_equal(err.sass_line, err.sass_backtrace.first[:line])
|
|
214
|
+
|
|
215
|
+
assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename])
|
|
216
|
+
assert_equal(2, err.sass_backtrace[1][:line])
|
|
217
|
+
|
|
218
|
+
assert_nil(err.sass_backtrace[2][:filename])
|
|
219
|
+
assert_equal(1, err.sass_backtrace[2][:line])
|
|
220
|
+
|
|
221
|
+
assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
|
|
222
|
+
assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1])
|
|
223
|
+
assert_equal("(sass):1", err.backtrace[2])
|
|
224
|
+
else
|
|
225
|
+
assert(false, "Exception not raised for imported template: bork#{i}")
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def test_exception_css_with_offset
|
|
231
|
+
opts = {:full_exception => true, :line => 362}
|
|
232
|
+
render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts)
|
|
233
|
+
rescue Sass::SyntaxError => e
|
|
234
|
+
assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..15].join("\n"))
|
|
235
|
+
/*
|
|
236
|
+
Syntax error: Invalid property: "e: " (no value).
|
|
237
|
+
on line 383 of test_exception_css_with_offset_inline.sass
|
|
238
|
+
|
|
239
|
+
378: a
|
|
240
|
+
379: b: c
|
|
241
|
+
380: a
|
|
242
|
+
381: b: c
|
|
243
|
+
382: d
|
|
244
|
+
383: e:
|
|
245
|
+
384: f
|
|
246
|
+
385: g: h
|
|
247
|
+
386: f
|
|
248
|
+
387: g: h
|
|
249
|
+
388: f
|
|
250
|
+
CSS
|
|
251
|
+
else
|
|
252
|
+
assert(false, "Exception not raised for test_exception_css_with_offset")
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def test_css_import
|
|
256
|
+
assert_equal("@import url(./fonts.css) screen;\n", render("@import url(./fonts.css) screen"))
|
|
257
|
+
assert_equal("@import \"./fonts.css\" screen;\n", render("@import \"./fonts.css\" screen"))
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def test_sass_import
|
|
261
|
+
assert !File.exists?(sassc_path("importee"))
|
|
262
|
+
renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] }
|
|
263
|
+
assert File.exists?(sassc_path("importee"))
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def test_no_cache
|
|
267
|
+
assert !File.exists?(sassc_path("importee"))
|
|
268
|
+
renders_correctly("import", {
|
|
269
|
+
:style => :compact, :cache => false,
|
|
270
|
+
:load_paths => [File.dirname(__FILE__) + "/templates"],
|
|
271
|
+
})
|
|
272
|
+
assert !File.exists?(sassc_path("importee"))
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def test_units
|
|
276
|
+
renders_correctly "units"
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def test_default_function
|
|
280
|
+
assert_equal("foo {\n bar: url(foo.png); }\n", render(%Q{foo\n bar = url("foo.png")\n}));
|
|
281
|
+
assert_equal("foo {\n bar: url(); }\n", render("foo\n bar = url()\n"));
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def test_string_minus
|
|
285
|
+
assert_equal("foo {\n bar: baz-boom-bat; }\n", render(%Q{foo\n bar = "baz"-"boom"-"bat"}))
|
|
286
|
+
assert_equal("foo {\n bar: -baz-boom; }\n", render(%Q{foo\n bar = -"baz"-"boom"}))
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def test_string_div
|
|
290
|
+
assert_equal("foo {\n bar: baz/boom/bat; }\n", render(%Q{foo\n bar = "baz"/"boom"/"bat"}))
|
|
291
|
+
assert_equal("foo {\n bar: /baz/boom; }\n", render(%Q{foo\n bar = /"baz"/"boom"}))
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def test_basic_multiline_selector
|
|
295
|
+
assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
|
|
296
|
+
render("#foo #bar,\n#baz #boom\n :foo bar"))
|
|
297
|
+
assert_equal("#foo #bar,\n#foo #baz {\n foo: bar; }\n",
|
|
298
|
+
render("#foo\n #bar,\n #baz\n :foo bar"))
|
|
299
|
+
assert_equal("#foo,\n#bar {\n foo: bar; }\n #foo #baz,\n #bar #baz {\n foo: bar; }\n",
|
|
300
|
+
render("#foo,\n#bar\n :foo bar\n #baz\n :foo bar"))
|
|
301
|
+
assert_equal("#foo #bar, #baz #boom { foo: bar; }\n",
|
|
302
|
+
render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compact))
|
|
303
|
+
|
|
304
|
+
assert_equal("#foo #bar,#baz #boom{foo:bar}\n",
|
|
305
|
+
render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compressed))
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def test_complex_multiline_selector
|
|
309
|
+
renders_correctly "multiline"
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def test_colon_only
|
|
313
|
+
begin
|
|
314
|
+
render("a\n b: c", :property_syntax => :old)
|
|
315
|
+
rescue Sass::SyntaxError => e
|
|
316
|
+
assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
|
|
317
|
+
e.message)
|
|
318
|
+
assert_equal(2, e.sass_line)
|
|
319
|
+
else
|
|
320
|
+
assert(false, "SyntaxError not raised for :property_syntax => :old")
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
begin
|
|
324
|
+
render("a\n :b c", :property_syntax => :new)
|
|
325
|
+
assert_equal(2, e.sass_line)
|
|
326
|
+
rescue Sass::SyntaxError => e
|
|
327
|
+
assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
|
|
328
|
+
e.message)
|
|
329
|
+
else
|
|
330
|
+
assert(false, "SyntaxError not raised for :property_syntax => :new")
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def test_pseudo_elements
|
|
335
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
336
|
+
::first-line {
|
|
337
|
+
size: 10em; }
|
|
338
|
+
CSS
|
|
339
|
+
::first-line
|
|
340
|
+
size: 10em
|
|
341
|
+
SASS
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def test_directive
|
|
345
|
+
assert_equal("@a b;\n", render("@a b"))
|
|
346
|
+
|
|
347
|
+
assert_equal("@a {\n b: c; }\n", render("@a\n :b c"))
|
|
348
|
+
assert_equal("@a { b: c; }\n", render("@a\n :b c", :style => :compact))
|
|
349
|
+
assert_equal("@a {\n b: c;\n}\n", render("@a\n :b c", :style => :expanded))
|
|
350
|
+
assert_equal("@a{b:c}\n", render("@a\n :b c", :style => :compressed))
|
|
351
|
+
|
|
352
|
+
assert_equal("@a {\n b: c;\n d: e; }\n",
|
|
353
|
+
render("@a\n :b c\n :d e"))
|
|
354
|
+
assert_equal("@a { b: c; d: e; }\n",
|
|
355
|
+
render("@a\n :b c\n :d e", :style => :compact))
|
|
356
|
+
assert_equal("@a {\n b: c;\n d: e;\n}\n",
|
|
357
|
+
render("@a\n :b c\n :d e", :style => :expanded))
|
|
358
|
+
assert_equal("@a{b:c;d:e}\n",
|
|
359
|
+
render("@a\n :b c\n :d e", :style => :compressed))
|
|
360
|
+
|
|
361
|
+
assert_equal("@a {\n #b {\n c: d; } }\n",
|
|
362
|
+
render("@a\n #b\n :c d"))
|
|
363
|
+
assert_equal("@a { #b { c: d; } }\n",
|
|
364
|
+
render("@a\n #b\n :c d", :style => :compact))
|
|
365
|
+
assert_equal("@a {\n #b {\n c: d;\n }\n}\n",
|
|
366
|
+
render("@a\n #b\n :c d", :style => :expanded))
|
|
367
|
+
assert_equal("@a{#b{c:d}}\n",
|
|
368
|
+
render("@a\n #b\n :c d", :style => :compressed))
|
|
369
|
+
|
|
370
|
+
assert_equal("@a {\n #b {\n a: b; }\n #b #c {\n d: e; } }\n",
|
|
371
|
+
render("@a\n #b\n :a b\n #c\n :d e"))
|
|
372
|
+
assert_equal("@a { #b { a: b; }\n #b #c { d: e; } }\n",
|
|
373
|
+
render("@a\n #b\n :a b\n #c\n :d e", :style => :compact))
|
|
374
|
+
assert_equal("@a {\n #b {\n a: b;\n }\n #b #c {\n d: e;\n }\n}\n",
|
|
375
|
+
render("@a\n #b\n :a b\n #c\n :d e", :style => :expanded))
|
|
376
|
+
assert_equal("@a{#b{a:b}#b #c{d:e}}\n",
|
|
377
|
+
render("@a\n #b\n :a b\n #c\n :d e", :style => :compressed))
|
|
378
|
+
|
|
379
|
+
assert_equal("@a {\n #foo,\n #bar {\n b: c; } }\n",
|
|
380
|
+
render("@a\n #foo, \n #bar\n :b c"))
|
|
381
|
+
assert_equal("@a { #foo, #bar { b: c; } }\n",
|
|
382
|
+
render("@a\n #foo, \n #bar\n :b c", :style => :compact))
|
|
383
|
+
assert_equal("@a {\n #foo,\n #bar {\n b: c;\n }\n}\n",
|
|
384
|
+
render("@a\n #foo, \n #bar\n :b c", :style => :expanded))
|
|
385
|
+
assert_equal("@a{#foo,#bar{b:c}}\n",
|
|
386
|
+
render("@a\n #foo, \n #bar\n :b c", :style => :compressed))
|
|
387
|
+
|
|
388
|
+
to_render = <<END
|
|
389
|
+
@a
|
|
390
|
+
:b c
|
|
391
|
+
#d
|
|
392
|
+
:e f
|
|
393
|
+
:g h
|
|
394
|
+
END
|
|
395
|
+
rendered = <<END
|
|
396
|
+
@a { b: c;
|
|
397
|
+
#d { e: f; }
|
|
398
|
+
g: h; }
|
|
399
|
+
END
|
|
400
|
+
assert_equal(rendered, render(to_render, :style => :compact))
|
|
401
|
+
|
|
402
|
+
assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def test_line_annotations
|
|
406
|
+
assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
|
|
407
|
+
/* line 2, test_line_annotations_inline.sass */
|
|
408
|
+
foo bar { foo: bar; }
|
|
409
|
+
/* line 5, test_line_annotations_inline.sass */
|
|
410
|
+
foo baz { blip: blop; }
|
|
411
|
+
|
|
412
|
+
/* line 9, test_line_annotations_inline.sass */
|
|
413
|
+
floodle { flop: blop; }
|
|
414
|
+
|
|
415
|
+
/* line 18, test_line_annotations_inline.sass */
|
|
416
|
+
bup { mix: on; }
|
|
417
|
+
/* line 15, test_line_annotations_inline.sass */
|
|
418
|
+
bup mixin { moop: mup; }
|
|
419
|
+
|
|
420
|
+
/* line 22, test_line_annotations_inline.sass */
|
|
421
|
+
bip hop, skip hop { a: b; }
|
|
422
|
+
CSS
|
|
423
|
+
foo
|
|
424
|
+
bar
|
|
425
|
+
foo: bar
|
|
426
|
+
|
|
427
|
+
baz
|
|
428
|
+
blip: blop
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
floodle
|
|
432
|
+
|
|
433
|
+
flop: blop
|
|
434
|
+
|
|
435
|
+
=mxn
|
|
436
|
+
mix: on
|
|
437
|
+
mixin
|
|
438
|
+
moop: mup
|
|
439
|
+
|
|
440
|
+
bup
|
|
441
|
+
+mxn
|
|
442
|
+
|
|
443
|
+
bip, skip
|
|
444
|
+
hop
|
|
445
|
+
a: b
|
|
446
|
+
SASS
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def test_line_annotations_with_filename
|
|
450
|
+
renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + "/templates"]
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
def test_empty_first_line
|
|
454
|
+
assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def test_escaped_rule
|
|
458
|
+
assert_equal(":focus {\n a: b; }\n", render("\\:focus\n a: b"))
|
|
459
|
+
assert_equal("a {\n b: c; }\n a :focus {\n d: e; }\n", render("\\a\n b: c\n \\:focus\n d: e"))
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
def test_cr_newline
|
|
463
|
+
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"))
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def test_or_eq
|
|
467
|
+
assert_equal("foo {\n a: b; }\n", render(%Q{!foo = "b"\n!foo ||= "c"\nfoo\n a = !foo}))
|
|
468
|
+
assert_equal("foo {\n a: b; }\n", render(%Q{!foo ||= "b"\nfoo\n a = !foo}))
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
def test_mixins
|
|
472
|
+
renders_correctly "mixins", { :style => :expanded }
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def test_mixins_dont_interfere_with_sibling_combinator
|
|
476
|
+
assert_equal("foo + bar {\n a: b; }\nfoo + baz {\n c: d; }\n",
|
|
477
|
+
render("foo\n +\n bar\n a: b\n baz\n c: d"))
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def test_mixin_args
|
|
481
|
+
assert_equal("blat {\n baz: hi; }\n", render(<<SASS))
|
|
482
|
+
=foo(!bar)
|
|
483
|
+
baz = !bar
|
|
484
|
+
blat
|
|
485
|
+
+foo(\"hi\")
|
|
486
|
+
SASS
|
|
487
|
+
assert_equal("blat {\n baz: 3; }\n", render(<<SASS))
|
|
488
|
+
=foo(!a, !b)
|
|
489
|
+
baz = !a + !b
|
|
490
|
+
blat
|
|
491
|
+
+foo(1, 2)
|
|
492
|
+
SASS
|
|
493
|
+
assert_equal("blat {\n baz: 4;\n baz: 3;\n baz: 5;\n bang: 3; }\n", render(<<SASS))
|
|
494
|
+
=foo(!c = (6 + 4) / 2)
|
|
495
|
+
baz = !c
|
|
496
|
+
!c = 3
|
|
497
|
+
blat
|
|
498
|
+
+foo(!c + 1)
|
|
499
|
+
+foo((!c + 3)/2)
|
|
500
|
+
+foo
|
|
501
|
+
bang = !c
|
|
502
|
+
SASS
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def test_default_values_for_mixin_arguments
|
|
506
|
+
assert_equal("white {\n color: white; }\n\nblack {\n color: black; }\n", render(<<SASS))
|
|
507
|
+
=foo(!a = #FFF)
|
|
508
|
+
:color= !a
|
|
509
|
+
white
|
|
510
|
+
+foo
|
|
511
|
+
black
|
|
512
|
+
+foo(#000)
|
|
513
|
+
SASS
|
|
514
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
515
|
+
one {
|
|
516
|
+
color: white;
|
|
517
|
+
padding: 1px;
|
|
518
|
+
margin: 4px; }
|
|
519
|
+
|
|
520
|
+
two {
|
|
521
|
+
color: white;
|
|
522
|
+
padding: 2px;
|
|
523
|
+
margin: 5px; }
|
|
524
|
+
|
|
525
|
+
three {
|
|
526
|
+
color: white;
|
|
527
|
+
padding: 2px;
|
|
528
|
+
margin: 3px; }
|
|
529
|
+
CSS
|
|
530
|
+
!a = 5px
|
|
531
|
+
=foo(!a, !b = 1px, !c = 3px + !b)
|
|
532
|
+
:color= !a
|
|
533
|
+
:padding= !b
|
|
534
|
+
:margin= !c
|
|
535
|
+
one
|
|
536
|
+
+foo(#fff)
|
|
537
|
+
two
|
|
538
|
+
+foo(#fff, 2px)
|
|
539
|
+
three
|
|
540
|
+
+foo(#fff, 2px, 3px)
|
|
541
|
+
SASS
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def test_interpolation
|
|
545
|
+
assert_equal("a-1 {\n b-2-3: c-3; }\n", render(<<SASS))
|
|
546
|
+
!a = 1
|
|
547
|
+
!b = 2
|
|
548
|
+
!c = 3
|
|
549
|
+
a-\#{!a}
|
|
550
|
+
b-\#{!b}-\#{!c}: c-\#{!a + !b}
|
|
551
|
+
SASS
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
def test_if_directive
|
|
555
|
+
assert_equal("a {\n b: 1; }\n", render(<<SASS))
|
|
556
|
+
!var = true
|
|
557
|
+
a
|
|
558
|
+
@if !var
|
|
559
|
+
b: 1
|
|
560
|
+
@if not !var
|
|
561
|
+
b: 2
|
|
562
|
+
SASS
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def test_for
|
|
566
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
567
|
+
a-0 {
|
|
568
|
+
2i: 0; }
|
|
569
|
+
|
|
570
|
+
a-1 {
|
|
571
|
+
2i: 2; }
|
|
572
|
+
|
|
573
|
+
a-2 {
|
|
574
|
+
2i: 4; }
|
|
575
|
+
|
|
576
|
+
a-3 {
|
|
577
|
+
2i: 6; }
|
|
578
|
+
|
|
579
|
+
b-1 {
|
|
580
|
+
j-1: 0; }
|
|
581
|
+
|
|
582
|
+
b-2 {
|
|
583
|
+
j-1: 1; }
|
|
584
|
+
|
|
585
|
+
b-3 {
|
|
586
|
+
j-1: 2; }
|
|
587
|
+
|
|
588
|
+
b-4 {
|
|
589
|
+
j-1: 3; }
|
|
590
|
+
CSS
|
|
591
|
+
!a = 3
|
|
592
|
+
@for !i from 0 to !a + 1
|
|
593
|
+
a-\#{!i}
|
|
594
|
+
2i = 2 * !i
|
|
595
|
+
|
|
596
|
+
@for !j from 1 through 4
|
|
597
|
+
b-\#{!j}
|
|
598
|
+
j-1 = !j - 1
|
|
599
|
+
SASS
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def test_while
|
|
603
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
604
|
+
a-5 {
|
|
605
|
+
blooble: gloop; }
|
|
606
|
+
|
|
607
|
+
a-4 {
|
|
608
|
+
blooble: gloop; }
|
|
609
|
+
|
|
610
|
+
a-3 {
|
|
611
|
+
blooble: gloop; }
|
|
612
|
+
|
|
613
|
+
a-2 {
|
|
614
|
+
blooble: gloop; }
|
|
615
|
+
|
|
616
|
+
a-1 {
|
|
617
|
+
blooble: gloop; }
|
|
618
|
+
CSS
|
|
619
|
+
!a = 5
|
|
620
|
+
@while !a != 0
|
|
621
|
+
a-\#{!a}
|
|
622
|
+
blooble: gloop
|
|
623
|
+
!a = !a - 1
|
|
624
|
+
SASS
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def test_else
|
|
628
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
629
|
+
a {
|
|
630
|
+
t1: t;
|
|
631
|
+
t2: t;
|
|
632
|
+
t3: t;
|
|
633
|
+
t4: t; }
|
|
634
|
+
CSS
|
|
635
|
+
a
|
|
636
|
+
@if true
|
|
637
|
+
t1: t
|
|
638
|
+
@else
|
|
639
|
+
f1: f
|
|
640
|
+
|
|
641
|
+
@if false
|
|
642
|
+
f2: f
|
|
643
|
+
@else
|
|
644
|
+
t2: t
|
|
645
|
+
|
|
646
|
+
@if false
|
|
647
|
+
f3: f1
|
|
648
|
+
@else if 1 + 1 == 3
|
|
649
|
+
f3: f2
|
|
650
|
+
@else
|
|
651
|
+
t3: t
|
|
652
|
+
|
|
653
|
+
@if false
|
|
654
|
+
f4: f1
|
|
655
|
+
@else if 1 + 1 == 2
|
|
656
|
+
t4: t
|
|
657
|
+
@else
|
|
658
|
+
f4: f2
|
|
659
|
+
|
|
660
|
+
@if false
|
|
661
|
+
f5: f1
|
|
662
|
+
@else if false
|
|
663
|
+
f5: f2
|
|
664
|
+
SASS
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
def test_variable_reassignment
|
|
668
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
669
|
+
a {
|
|
670
|
+
b: 1;
|
|
671
|
+
c: 2; }
|
|
672
|
+
CSS
|
|
673
|
+
!a = 1
|
|
674
|
+
a
|
|
675
|
+
b = !a
|
|
676
|
+
!a = 2
|
|
677
|
+
c = !a
|
|
678
|
+
SASS
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def test_variable_scope
|
|
682
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
683
|
+
a {
|
|
684
|
+
b-1: c;
|
|
685
|
+
b-2: c;
|
|
686
|
+
d: 12; }
|
|
687
|
+
|
|
688
|
+
b {
|
|
689
|
+
d: 17; }
|
|
690
|
+
CSS
|
|
691
|
+
!i = 12
|
|
692
|
+
a
|
|
693
|
+
@for !i from 1 through 2
|
|
694
|
+
b-\#{!i}: c
|
|
695
|
+
d = !i
|
|
696
|
+
|
|
697
|
+
=foo
|
|
698
|
+
!i = 17
|
|
699
|
+
|
|
700
|
+
b
|
|
701
|
+
+foo
|
|
702
|
+
d = !i
|
|
703
|
+
SASS
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
def test_argument_error
|
|
707
|
+
assert_raise(Sass::SyntaxError) { render("a\n b = hsl(1)") }
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
def test_comments_at_the_top_of_a_document
|
|
711
|
+
render(<<SASS)
|
|
712
|
+
//
|
|
713
|
+
This is a comment that
|
|
714
|
+
continues to the second line.
|
|
715
|
+
foo
|
|
716
|
+
bar: baz
|
|
717
|
+
SASS
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
def test_loud_comments_containing_a_comment_close
|
|
721
|
+
actual_css = render(<<SASS)
|
|
722
|
+
/*
|
|
723
|
+
This is a comment that
|
|
724
|
+
continues to the second line. */
|
|
725
|
+
foo
|
|
726
|
+
bar: baz
|
|
727
|
+
SASS
|
|
728
|
+
assert_equal(<<CSS, actual_css)
|
|
729
|
+
/* This is a comment that
|
|
730
|
+
* continues to the second line. */
|
|
731
|
+
foo {
|
|
732
|
+
bar: baz; }
|
|
733
|
+
CSS
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def test_quoted_colon
|
|
737
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
738
|
+
a b[foo="bar: baz"] {
|
|
739
|
+
c: d; }
|
|
740
|
+
CSS
|
|
741
|
+
a
|
|
742
|
+
b[foo="bar: baz"]
|
|
743
|
+
c: d
|
|
744
|
+
SASS
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
def test_quoted_comma
|
|
748
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
749
|
+
a b[foo="bar, baz"] {
|
|
750
|
+
c: d; }
|
|
751
|
+
CSS
|
|
752
|
+
a
|
|
753
|
+
b[foo="bar, baz"]
|
|
754
|
+
c: d
|
|
755
|
+
SASS
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
def test_quoted_ampersand
|
|
759
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
760
|
+
a b[foo="bar & baz"] {
|
|
761
|
+
c: d; }
|
|
762
|
+
CSS
|
|
763
|
+
a
|
|
764
|
+
b[foo="bar & baz"]
|
|
765
|
+
c: d
|
|
766
|
+
SASS
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
def test_empty_selector_warning
|
|
770
|
+
assert_warning(<<END) {render("foo bar")}
|
|
771
|
+
WARNING on line 1:
|
|
772
|
+
Selector "foo bar" doesn't have any properties and will not be rendered.
|
|
773
|
+
END
|
|
774
|
+
|
|
775
|
+
assert_warning(<<END) {render(<<SASS)}
|
|
776
|
+
WARNING on line 3:
|
|
777
|
+
Selector
|
|
778
|
+
foo, bar, baz,
|
|
779
|
+
bang, bip, bop
|
|
780
|
+
doesn't have any properties and will not be rendered.
|
|
781
|
+
END
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
foo, bar, baz,
|
|
785
|
+
bang, bip, bop
|
|
786
|
+
SASS
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
# Regression tests
|
|
790
|
+
|
|
791
|
+
def test_parens_in_mixins
|
|
792
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
793
|
+
.foo {
|
|
794
|
+
color: #01ff7f;
|
|
795
|
+
background-color: #000102; }
|
|
796
|
+
CSS
|
|
797
|
+
=foo(!c1, !c2 = rgb(0, 1, 2))
|
|
798
|
+
color = !c1
|
|
799
|
+
background-color = !c2
|
|
800
|
+
|
|
801
|
+
.foo
|
|
802
|
+
+foo(rgb(1,255,127))
|
|
803
|
+
SASS
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
def test_comment_beneath_prop
|
|
807
|
+
assert_equal(<<RESULT, render(<<SOURCE))
|
|
808
|
+
.box {
|
|
809
|
+
border-style: solid; }
|
|
810
|
+
RESULT
|
|
811
|
+
.box
|
|
812
|
+
:border
|
|
813
|
+
//:color black
|
|
814
|
+
:style solid
|
|
815
|
+
SOURCE
|
|
816
|
+
|
|
817
|
+
assert_equal(<<RESULT, render(<<SOURCE))
|
|
818
|
+
.box {
|
|
819
|
+
/* :color black */
|
|
820
|
+
border-style: solid; }
|
|
821
|
+
RESULT
|
|
822
|
+
.box
|
|
823
|
+
:border
|
|
824
|
+
/*:color black
|
|
825
|
+
:style solid
|
|
826
|
+
SOURCE
|
|
827
|
+
|
|
828
|
+
assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
|
|
829
|
+
.box{border-style:solid}
|
|
830
|
+
RESULT
|
|
831
|
+
.box
|
|
832
|
+
:border
|
|
833
|
+
/*:color black
|
|
834
|
+
:style solid
|
|
835
|
+
SOURCE
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
def test_compressed_comment_beneath_directive
|
|
839
|
+
assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
|
|
840
|
+
@foo{a:b}
|
|
841
|
+
RESULT
|
|
842
|
+
@foo
|
|
843
|
+
a: b
|
|
844
|
+
/*b: c
|
|
845
|
+
SOURCE
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
def test_comment_with_crazy_indentation
|
|
849
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
850
|
+
/* This is a loud comment:
|
|
851
|
+
* Where the indentation is wonky. */
|
|
852
|
+
.comment {
|
|
853
|
+
width: 1px; }
|
|
854
|
+
CSS
|
|
855
|
+
/*
|
|
856
|
+
This is a loud comment:
|
|
857
|
+
Where the indentation is wonky.
|
|
858
|
+
//
|
|
859
|
+
This is a silent comment:
|
|
860
|
+
Where the indentation is wonky.
|
|
861
|
+
.comment
|
|
862
|
+
width: 1px
|
|
863
|
+
SASS
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
def test_plus_with_space
|
|
867
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
868
|
+
a + b {
|
|
869
|
+
color: green; }
|
|
870
|
+
CSS
|
|
871
|
+
a
|
|
872
|
+
+ b
|
|
873
|
+
color: green
|
|
874
|
+
SASS
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
def test_empty_line_comment
|
|
878
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
879
|
+
/* Foo
|
|
880
|
+
*
|
|
881
|
+
* Bar */
|
|
882
|
+
CSS
|
|
883
|
+
/*
|
|
884
|
+
Foo
|
|
885
|
+
|
|
886
|
+
Bar
|
|
887
|
+
SASS
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
def test_empty_comment
|
|
891
|
+
assert_equal(<<CSS, render(<<SASS))
|
|
892
|
+
/* */
|
|
893
|
+
a {
|
|
894
|
+
/* */
|
|
895
|
+
b: c; }
|
|
896
|
+
CSS
|
|
897
|
+
/*
|
|
898
|
+
a
|
|
899
|
+
/*
|
|
900
|
+
b: c
|
|
901
|
+
SASS
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
# Encodings
|
|
905
|
+
|
|
906
|
+
unless Haml::Util.ruby1_8?
|
|
907
|
+
def test_encoding_error
|
|
908
|
+
render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
|
|
909
|
+
assert(false, "Expected exception")
|
|
910
|
+
rescue Sass::SyntaxError => e
|
|
911
|
+
assert_equal(3, e.sass_line)
|
|
912
|
+
assert_equal('Invalid UTF-8 character "\xFE"', e.message)
|
|
913
|
+
end
|
|
914
|
+
|
|
915
|
+
def test_ascii_incompatible_encoding_error
|
|
916
|
+
template = "foo\nbar\nb_z".encode("utf-16le")
|
|
917
|
+
template[9] = "\xFE".force_encoding("utf-16le")
|
|
918
|
+
render(template)
|
|
919
|
+
assert(false, "Expected exception")
|
|
920
|
+
rescue Sass::SyntaxError => e
|
|
921
|
+
assert_equal(3, e.sass_line)
|
|
922
|
+
assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
|
|
923
|
+
end
|
|
924
|
+
end
|
|
925
|
+
|
|
926
|
+
private
|
|
927
|
+
|
|
928
|
+
def render(sass, options = {})
|
|
929
|
+
munge_filename options
|
|
930
|
+
Sass::Engine.new(sass, options).render
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
def renders_correctly(name, options={})
|
|
934
|
+
sass_file = load_file(name, "sass")
|
|
935
|
+
css_file = load_file(name, "css")
|
|
936
|
+
options[:filename] ||= filename(name, "sass")
|
|
937
|
+
options[:css_filename] ||= filename(name, "css")
|
|
938
|
+
css_result = Sass::Engine.new(sass_file, options).render
|
|
939
|
+
assert_equal css_file, css_result
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
def load_file(name, type = "sass")
|
|
943
|
+
@result = ''
|
|
944
|
+
File.new(filename(name, type)).each_line { |l| @result += l }
|
|
945
|
+
@result
|
|
946
|
+
end
|
|
947
|
+
|
|
948
|
+
def filename(name, type)
|
|
949
|
+
File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
def sassc_path(template)
|
|
953
|
+
sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
|
|
954
|
+
Sass::Files.send(:sassc_filename, sassc_path, Sass::Engine::DEFAULT_OPTIONS)
|
|
955
|
+
end
|
|
956
|
+
end
|