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.
Files changed (190) hide show
  1. data/.yardopts +5 -0
  2. data/CONTRIBUTING +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +347 -0
  5. data/REVISION +1 -0
  6. data/Rakefile +371 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/css2sass +7 -0
  10. data/bin/haml +9 -0
  11. data/bin/html2haml +7 -0
  12. data/bin/sass +8 -0
  13. data/extra/haml-mode.el +663 -0
  14. data/extra/sass-mode.el +205 -0
  15. data/extra/update_watch.rb +13 -0
  16. data/init.rb +8 -0
  17. data/lib/haml.rb +40 -0
  18. data/lib/haml/buffer.rb +307 -0
  19. data/lib/haml/engine.rb +301 -0
  20. data/lib/haml/error.rb +22 -0
  21. data/lib/haml/exec.rb +470 -0
  22. data/lib/haml/filters.rb +341 -0
  23. data/lib/haml/helpers.rb +560 -0
  24. data/lib/haml/helpers/action_view_extensions.rb +40 -0
  25. data/lib/haml/helpers/action_view_mods.rb +176 -0
  26. data/lib/haml/herb.rb +96 -0
  27. data/lib/haml/html.rb +308 -0
  28. data/lib/haml/precompiler.rb +997 -0
  29. data/lib/haml/shared.rb +78 -0
  30. data/lib/haml/template.rb +51 -0
  31. data/lib/haml/template/patch.rb +58 -0
  32. data/lib/haml/template/plugin.rb +71 -0
  33. data/lib/haml/util.rb +244 -0
  34. data/lib/haml/version.rb +64 -0
  35. data/lib/sass.rb +24 -0
  36. data/lib/sass/css.rb +423 -0
  37. data/lib/sass/engine.rb +491 -0
  38. data/lib/sass/environment.rb +79 -0
  39. data/lib/sass/error.rb +162 -0
  40. data/lib/sass/files.rb +133 -0
  41. data/lib/sass/plugin.rb +170 -0
  42. data/lib/sass/plugin/merb.rb +57 -0
  43. data/lib/sass/plugin/rails.rb +23 -0
  44. data/lib/sass/repl.rb +58 -0
  45. data/lib/sass/script.rb +55 -0
  46. data/lib/sass/script/bool.rb +17 -0
  47. data/lib/sass/script/color.rb +183 -0
  48. data/lib/sass/script/funcall.rb +50 -0
  49. data/lib/sass/script/functions.rb +199 -0
  50. data/lib/sass/script/lexer.rb +191 -0
  51. data/lib/sass/script/literal.rb +177 -0
  52. data/lib/sass/script/node.rb +14 -0
  53. data/lib/sass/script/number.rb +381 -0
  54. data/lib/sass/script/operation.rb +45 -0
  55. data/lib/sass/script/parser.rb +222 -0
  56. data/lib/sass/script/string.rb +12 -0
  57. data/lib/sass/script/unary_operation.rb +34 -0
  58. data/lib/sass/script/variable.rb +31 -0
  59. data/lib/sass/tree/comment_node.rb +84 -0
  60. data/lib/sass/tree/debug_node.rb +30 -0
  61. data/lib/sass/tree/directive_node.rb +70 -0
  62. data/lib/sass/tree/for_node.rb +48 -0
  63. data/lib/sass/tree/if_node.rb +54 -0
  64. data/lib/sass/tree/import_node.rb +69 -0
  65. data/lib/sass/tree/mixin_def_node.rb +29 -0
  66. data/lib/sass/tree/mixin_node.rb +48 -0
  67. data/lib/sass/tree/node.rb +252 -0
  68. data/lib/sass/tree/prop_node.rb +106 -0
  69. data/lib/sass/tree/root_node.rb +56 -0
  70. data/lib/sass/tree/rule_node.rb +220 -0
  71. data/lib/sass/tree/variable_node.rb +34 -0
  72. data/lib/sass/tree/while_node.rb +31 -0
  73. data/rails/init.rb +1 -0
  74. data/test/benchmark.rb +99 -0
  75. data/test/haml/engine_test.rb +1129 -0
  76. data/test/haml/helper_test.rb +282 -0
  77. data/test/haml/html2haml_test.rb +258 -0
  78. data/test/haml/markaby/standard.mab +52 -0
  79. data/test/haml/mocks/article.rb +6 -0
  80. data/test/haml/results/content_for_layout.xhtml +12 -0
  81. data/test/haml/results/eval_suppressed.xhtml +9 -0
  82. data/test/haml/results/filters.xhtml +62 -0
  83. data/test/haml/results/helpers.xhtml +93 -0
  84. data/test/haml/results/helpful.xhtml +10 -0
  85. data/test/haml/results/just_stuff.xhtml +68 -0
  86. data/test/haml/results/list.xhtml +12 -0
  87. data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  88. data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  89. data/test/haml/results/original_engine.xhtml +20 -0
  90. data/test/haml/results/partial_layout.xhtml +5 -0
  91. data/test/haml/results/partials.xhtml +21 -0
  92. data/test/haml/results/render_layout.xhtml +3 -0
  93. data/test/haml/results/silent_script.xhtml +74 -0
  94. data/test/haml/results/standard.xhtml +162 -0
  95. data/test/haml/results/tag_parsing.xhtml +23 -0
  96. data/test/haml/results/very_basic.xhtml +5 -0
  97. data/test/haml/results/whitespace_handling.xhtml +89 -0
  98. data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  99. data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  100. data/test/haml/rhtml/action_view.rhtml +62 -0
  101. data/test/haml/rhtml/standard.rhtml +54 -0
  102. data/test/haml/spec_test.rb +44 -0
  103. data/test/haml/template_test.rb +217 -0
  104. data/test/haml/templates/_av_partial_1.haml +9 -0
  105. data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
  106. data/test/haml/templates/_av_partial_2.haml +5 -0
  107. data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
  108. data/test/haml/templates/_layout.erb +3 -0
  109. data/test/haml/templates/_layout_for_partial.haml +3 -0
  110. data/test/haml/templates/_partial.haml +8 -0
  111. data/test/haml/templates/_text_area.haml +3 -0
  112. data/test/haml/templates/action_view.haml +47 -0
  113. data/test/haml/templates/action_view_ugly.haml +47 -0
  114. data/test/haml/templates/breakage.haml +8 -0
  115. data/test/haml/templates/content_for_layout.haml +8 -0
  116. data/test/haml/templates/eval_suppressed.haml +11 -0
  117. data/test/haml/templates/filters.haml +66 -0
  118. data/test/haml/templates/helpers.haml +95 -0
  119. data/test/haml/templates/helpful.haml +11 -0
  120. data/test/haml/templates/just_stuff.haml +83 -0
  121. data/test/haml/templates/list.haml +12 -0
  122. data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  123. data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  124. data/test/haml/templates/original_engine.haml +17 -0
  125. data/test/haml/templates/partial_layout.haml +3 -0
  126. data/test/haml/templates/partialize.haml +1 -0
  127. data/test/haml/templates/partials.haml +12 -0
  128. data/test/haml/templates/render_layout.haml +2 -0
  129. data/test/haml/templates/silent_script.haml +40 -0
  130. data/test/haml/templates/standard.haml +42 -0
  131. data/test/haml/templates/standard_ugly.haml +42 -0
  132. data/test/haml/templates/tag_parsing.haml +21 -0
  133. data/test/haml/templates/very_basic.haml +4 -0
  134. data/test/haml/templates/whitespace_handling.haml +87 -0
  135. data/test/haml/util_test.rb +92 -0
  136. data/test/linked_rails.rb +12 -0
  137. data/test/sass/css2sass_test.rb +294 -0
  138. data/test/sass/engine_test.rb +956 -0
  139. data/test/sass/functions_test.rb +126 -0
  140. data/test/sass/more_results/more1.css +9 -0
  141. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  142. data/test/sass/more_results/more_import.css +29 -0
  143. data/test/sass/more_templates/_more_partial.sass +2 -0
  144. data/test/sass/more_templates/more1.sass +23 -0
  145. data/test/sass/more_templates/more_import.sass +11 -0
  146. data/test/sass/plugin_test.rb +229 -0
  147. data/test/sass/results/alt.css +4 -0
  148. data/test/sass/results/basic.css +9 -0
  149. data/test/sass/results/compact.css +5 -0
  150. data/test/sass/results/complex.css +87 -0
  151. data/test/sass/results/compressed.css +1 -0
  152. data/test/sass/results/expanded.css +19 -0
  153. data/test/sass/results/import.css +29 -0
  154. data/test/sass/results/line_numbers.css +49 -0
  155. data/test/sass/results/mixins.css +95 -0
  156. data/test/sass/results/multiline.css +24 -0
  157. data/test/sass/results/nested.css +22 -0
  158. data/test/sass/results/parent_ref.css +13 -0
  159. data/test/sass/results/script.css +16 -0
  160. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  161. data/test/sass/results/subdir/subdir.css +3 -0
  162. data/test/sass/results/units.css +11 -0
  163. data/test/sass/script_test.rb +261 -0
  164. data/test/sass/templates/_partial.sass +2 -0
  165. data/test/sass/templates/alt.sass +16 -0
  166. data/test/sass/templates/basic.sass +23 -0
  167. data/test/sass/templates/bork1.sass +2 -0
  168. data/test/sass/templates/bork2.sass +2 -0
  169. data/test/sass/templates/bork3.sass +2 -0
  170. data/test/sass/templates/compact.sass +17 -0
  171. data/test/sass/templates/complex.sass +307 -0
  172. data/test/sass/templates/compressed.sass +15 -0
  173. data/test/sass/templates/expanded.sass +17 -0
  174. data/test/sass/templates/import.sass +11 -0
  175. data/test/sass/templates/importee.sass +19 -0
  176. data/test/sass/templates/line_numbers.sass +13 -0
  177. data/test/sass/templates/mixins.sass +76 -0
  178. data/test/sass/templates/multiline.sass +20 -0
  179. data/test/sass/templates/nested.sass +25 -0
  180. data/test/sass/templates/nested_bork1.sass +2 -0
  181. data/test/sass/templates/nested_bork2.sass +2 -0
  182. data/test/sass/templates/nested_bork3.sass +2 -0
  183. data/test/sass/templates/parent_ref.sass +25 -0
  184. data/test/sass/templates/script.sass +101 -0
  185. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  186. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  187. data/test/sass/templates/subdir/subdir.sass +6 -0
  188. data/test/sass/templates/units.sass +11 -0
  189. data/test/test_helper.rb +44 -0
  190. 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