aliddle-sass 1.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 (238) hide show
  1. data/.yardopts +11 -0
  2. data/CONTRIBUTING +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +201 -0
  5. data/Rakefile +347 -0
  6. data/VERSION +1 -0
  7. data/VERSION_NAME +1 -0
  8. data/bin/sass +9 -0
  9. data/bin/sass-convert +8 -0
  10. data/bin/scss +9 -0
  11. data/extra/update_watch.rb +13 -0
  12. data/init.rb +18 -0
  13. data/lib/sass.rb +95 -0
  14. data/lib/sass/cache_stores.rb +15 -0
  15. data/lib/sass/cache_stores/base.rb +88 -0
  16. data/lib/sass/cache_stores/chain.rb +33 -0
  17. data/lib/sass/cache_stores/filesystem.rb +60 -0
  18. data/lib/sass/cache_stores/memory.rb +47 -0
  19. data/lib/sass/cache_stores/null.rb +25 -0
  20. data/lib/sass/callbacks.rb +66 -0
  21. data/lib/sass/css.rb +409 -0
  22. data/lib/sass/engine.rb +928 -0
  23. data/lib/sass/environment.rb +101 -0
  24. data/lib/sass/error.rb +201 -0
  25. data/lib/sass/exec.rb +707 -0
  26. data/lib/sass/importers.rb +22 -0
  27. data/lib/sass/importers/base.rb +139 -0
  28. data/lib/sass/importers/filesystem.rb +190 -0
  29. data/lib/sass/logger.rb +15 -0
  30. data/lib/sass/logger/base.rb +32 -0
  31. data/lib/sass/logger/log_level.rb +49 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin.rb +132 -0
  34. data/lib/sass/plugin/compiler.rb +406 -0
  35. data/lib/sass/plugin/configuration.rb +123 -0
  36. data/lib/sass/plugin/generic.rb +15 -0
  37. data/lib/sass/plugin/merb.rb +48 -0
  38. data/lib/sass/plugin/rack.rb +60 -0
  39. data/lib/sass/plugin/rails.rb +47 -0
  40. data/lib/sass/plugin/staleness_checker.rb +183 -0
  41. data/lib/sass/railtie.rb +9 -0
  42. data/lib/sass/repl.rb +57 -0
  43. data/lib/sass/root.rb +7 -0
  44. data/lib/sass/script.rb +39 -0
  45. data/lib/sass/script/arg_list.rb +52 -0
  46. data/lib/sass/script/bool.rb +18 -0
  47. data/lib/sass/script/color.rb +606 -0
  48. data/lib/sass/script/css_lexer.rb +29 -0
  49. data/lib/sass/script/css_parser.rb +31 -0
  50. data/lib/sass/script/funcall.rb +237 -0
  51. data/lib/sass/script/functions.rb +1543 -0
  52. data/lib/sass/script/interpolation.rb +79 -0
  53. data/lib/sass/script/lexer.rb +348 -0
  54. data/lib/sass/script/list.rb +85 -0
  55. data/lib/sass/script/literal.rb +221 -0
  56. data/lib/sass/script/node.rb +99 -0
  57. data/lib/sass/script/null.rb +37 -0
  58. data/lib/sass/script/number.rb +453 -0
  59. data/lib/sass/script/operation.rb +110 -0
  60. data/lib/sass/script/parser.rb +495 -0
  61. data/lib/sass/script/string.rb +51 -0
  62. data/lib/sass/script/string_interpolation.rb +103 -0
  63. data/lib/sass/script/unary_operation.rb +69 -0
  64. data/lib/sass/script/variable.rb +58 -0
  65. data/lib/sass/scss.rb +16 -0
  66. data/lib/sass/scss/css_parser.rb +36 -0
  67. data/lib/sass/scss/parser.rb +1179 -0
  68. data/lib/sass/scss/rx.rb +133 -0
  69. data/lib/sass/scss/script_lexer.rb +15 -0
  70. data/lib/sass/scss/script_parser.rb +25 -0
  71. data/lib/sass/scss/static_parser.rb +54 -0
  72. data/lib/sass/selector.rb +452 -0
  73. data/lib/sass/selector/abstract_sequence.rb +94 -0
  74. data/lib/sass/selector/comma_sequence.rb +92 -0
  75. data/lib/sass/selector/sequence.rb +507 -0
  76. data/lib/sass/selector/simple.rb +119 -0
  77. data/lib/sass/selector/simple_sequence.rb +212 -0
  78. data/lib/sass/shared.rb +76 -0
  79. data/lib/sass/supports.rb +229 -0
  80. data/lib/sass/tree/charset_node.rb +22 -0
  81. data/lib/sass/tree/comment_node.rb +82 -0
  82. data/lib/sass/tree/content_node.rb +9 -0
  83. data/lib/sass/tree/css_import_node.rb +60 -0
  84. data/lib/sass/tree/debug_node.rb +18 -0
  85. data/lib/sass/tree/directive_node.rb +42 -0
  86. data/lib/sass/tree/each_node.rb +24 -0
  87. data/lib/sass/tree/extend_node.rb +36 -0
  88. data/lib/sass/tree/for_node.rb +36 -0
  89. data/lib/sass/tree/function_node.rb +34 -0
  90. data/lib/sass/tree/if_node.rb +52 -0
  91. data/lib/sass/tree/import_node.rb +75 -0
  92. data/lib/sass/tree/media_node.rb +58 -0
  93. data/lib/sass/tree/mixin_def_node.rb +38 -0
  94. data/lib/sass/tree/mixin_node.rb +39 -0
  95. data/lib/sass/tree/node.rb +196 -0
  96. data/lib/sass/tree/prop_node.rb +152 -0
  97. data/lib/sass/tree/return_node.rb +18 -0
  98. data/lib/sass/tree/root_node.rb +28 -0
  99. data/lib/sass/tree/rule_node.rb +132 -0
  100. data/lib/sass/tree/supports_node.rb +51 -0
  101. data/lib/sass/tree/trace_node.rb +32 -0
  102. data/lib/sass/tree/variable_node.rb +30 -0
  103. data/lib/sass/tree/visitors/base.rb +75 -0
  104. data/lib/sass/tree/visitors/check_nesting.rb +147 -0
  105. data/lib/sass/tree/visitors/convert.rb +316 -0
  106. data/lib/sass/tree/visitors/cssize.rb +229 -0
  107. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  108. data/lib/sass/tree/visitors/extend.rb +68 -0
  109. data/lib/sass/tree/visitors/perform.rb +446 -0
  110. data/lib/sass/tree/visitors/set_options.rb +125 -0
  111. data/lib/sass/tree/visitors/to_css.rb +230 -0
  112. data/lib/sass/tree/warn_node.rb +18 -0
  113. data/lib/sass/tree/while_node.rb +18 -0
  114. data/lib/sass/util.rb +906 -0
  115. data/lib/sass/util/multibyte_string_scanner.rb +155 -0
  116. data/lib/sass/util/subset_map.rb +109 -0
  117. data/lib/sass/util/test.rb +10 -0
  118. data/lib/sass/version.rb +126 -0
  119. data/rails/init.rb +1 -0
  120. data/test/Gemfile +3 -0
  121. data/test/Gemfile.lock +10 -0
  122. data/test/sass/cache_test.rb +89 -0
  123. data/test/sass/callbacks_test.rb +61 -0
  124. data/test/sass/conversion_test.rb +1760 -0
  125. data/test/sass/css2sass_test.rb +439 -0
  126. data/test/sass/data/hsl-rgb.txt +319 -0
  127. data/test/sass/engine_test.rb +3243 -0
  128. data/test/sass/exec_test.rb +86 -0
  129. data/test/sass/extend_test.rb +1461 -0
  130. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  131. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  132. data/test/sass/functions_test.rb +1139 -0
  133. data/test/sass/importer_test.rb +192 -0
  134. data/test/sass/logger_test.rb +58 -0
  135. data/test/sass/mock_importer.rb +49 -0
  136. data/test/sass/more_results/more1.css +9 -0
  137. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  138. data/test/sass/more_results/more_import.css +29 -0
  139. data/test/sass/more_templates/_more_partial.sass +2 -0
  140. data/test/sass/more_templates/more1.sass +23 -0
  141. data/test/sass/more_templates/more_import.sass +11 -0
  142. data/test/sass/plugin_test.rb +550 -0
  143. data/test/sass/results/alt.css +4 -0
  144. data/test/sass/results/basic.css +9 -0
  145. data/test/sass/results/cached_import_option.css +3 -0
  146. data/test/sass/results/compact.css +5 -0
  147. data/test/sass/results/complex.css +86 -0
  148. data/test/sass/results/compressed.css +1 -0
  149. data/test/sass/results/expanded.css +19 -0
  150. data/test/sass/results/filename_fn.css +3 -0
  151. data/test/sass/results/if.css +3 -0
  152. data/test/sass/results/import.css +31 -0
  153. data/test/sass/results/import_charset.css +5 -0
  154. data/test/sass/results/import_charset_1_8.css +5 -0
  155. data/test/sass/results/import_charset_ibm866.css +5 -0
  156. data/test/sass/results/import_content.css +1 -0
  157. data/test/sass/results/line_numbers.css +49 -0
  158. data/test/sass/results/mixins.css +95 -0
  159. data/test/sass/results/multiline.css +24 -0
  160. data/test/sass/results/nested.css +22 -0
  161. data/test/sass/results/options.css +1 -0
  162. data/test/sass/results/parent_ref.css +13 -0
  163. data/test/sass/results/script.css +16 -0
  164. data/test/sass/results/scss_import.css +31 -0
  165. data/test/sass/results/scss_importee.css +2 -0
  166. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  167. data/test/sass/results/subdir/subdir.css +3 -0
  168. data/test/sass/results/units.css +11 -0
  169. data/test/sass/results/warn.css +0 -0
  170. data/test/sass/results/warn_imported.css +0 -0
  171. data/test/sass/script_conversion_test.rb +299 -0
  172. data/test/sass/script_test.rb +591 -0
  173. data/test/sass/scss/css_test.rb +1093 -0
  174. data/test/sass/scss/rx_test.rb +156 -0
  175. data/test/sass/scss/scss_test.rb +2043 -0
  176. data/test/sass/scss/test_helper.rb +37 -0
  177. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  178. data/test/sass/templates/_double_import_loop2.sass +1 -0
  179. data/test/sass/templates/_filename_fn_import.scss +11 -0
  180. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  181. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  182. data/test/sass/templates/_imported_content.sass +3 -0
  183. data/test/sass/templates/_partial.sass +2 -0
  184. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  185. data/test/sass/templates/alt.sass +16 -0
  186. data/test/sass/templates/basic.sass +23 -0
  187. data/test/sass/templates/bork1.sass +2 -0
  188. data/test/sass/templates/bork2.sass +2 -0
  189. data/test/sass/templates/bork3.sass +2 -0
  190. data/test/sass/templates/bork4.sass +2 -0
  191. data/test/sass/templates/bork5.sass +3 -0
  192. data/test/sass/templates/cached_import_option.scss +3 -0
  193. data/test/sass/templates/compact.sass +17 -0
  194. data/test/sass/templates/complex.sass +305 -0
  195. data/test/sass/templates/compressed.sass +15 -0
  196. data/test/sass/templates/double_import_loop1.sass +1 -0
  197. data/test/sass/templates/expanded.sass +17 -0
  198. data/test/sass/templates/filename_fn.scss +18 -0
  199. data/test/sass/templates/if.sass +11 -0
  200. data/test/sass/templates/import.sass +12 -0
  201. data/test/sass/templates/import_charset.sass +9 -0
  202. data/test/sass/templates/import_charset_1_8.sass +6 -0
  203. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  204. data/test/sass/templates/import_content.sass +4 -0
  205. data/test/sass/templates/importee.less +2 -0
  206. data/test/sass/templates/importee.sass +19 -0
  207. data/test/sass/templates/line_numbers.sass +13 -0
  208. data/test/sass/templates/mixin_bork.sass +5 -0
  209. data/test/sass/templates/mixins.sass +76 -0
  210. data/test/sass/templates/multiline.sass +20 -0
  211. data/test/sass/templates/nested.sass +25 -0
  212. data/test/sass/templates/nested_bork1.sass +2 -0
  213. data/test/sass/templates/nested_bork2.sass +2 -0
  214. data/test/sass/templates/nested_bork3.sass +2 -0
  215. data/test/sass/templates/nested_bork4.sass +2 -0
  216. data/test/sass/templates/nested_import.sass +2 -0
  217. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  218. data/test/sass/templates/options.sass +2 -0
  219. data/test/sass/templates/parent_ref.sass +25 -0
  220. data/test/sass/templates/same_name_different_ext.sass +2 -0
  221. data/test/sass/templates/same_name_different_ext.scss +1 -0
  222. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  223. data/test/sass/templates/script.sass +101 -0
  224. data/test/sass/templates/scss_import.scss +11 -0
  225. data/test/sass/templates/scss_importee.scss +1 -0
  226. data/test/sass/templates/single_import_loop.sass +1 -0
  227. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  228. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  229. data/test/sass/templates/subdir/subdir.sass +6 -0
  230. data/test/sass/templates/units.sass +11 -0
  231. data/test/sass/templates/warn.sass +3 -0
  232. data/test/sass/templates/warn_imported.sass +4 -0
  233. data/test/sass/test_helper.rb +8 -0
  234. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  235. data/test/sass/util/subset_map_test.rb +91 -0
  236. data/test/sass/util_test.rb +313 -0
  237. data/test/test_helper.rb +80 -0
  238. metadata +348 -0
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+ require File.dirname(__FILE__) + '/test_helper'
4
+
5
+ require 'sass/plugin'
6
+
7
+ class ImporterTest < Test::Unit::TestCase
8
+
9
+ class FruitImporter < Sass::Importers::Base
10
+ def find(name, context = nil)
11
+ if name =~ %r{fruits/(\w+)(\.s[ac]ss)?}
12
+ fruit = $1
13
+ color = case $1
14
+ when "apple"
15
+ "red"
16
+ when "orange"
17
+ "orange"
18
+ else
19
+ "blue"
20
+ end
21
+ contents = %Q{
22
+ $#{fruit}-color: #{color} !default;
23
+ @mixin #{fruit} {
24
+ color: $#{fruit}-color;
25
+ }
26
+ }
27
+ Sass::Engine.new(contents, :filename => name, :syntax => :scss, :importer => self)
28
+ end
29
+ end
30
+
31
+ def key(name, context)
32
+ [self.class.name, name]
33
+ end
34
+ end
35
+
36
+ # This class proves that you can override the extension scheme for importers
37
+ class ReversedExtImporter < Sass::Importers::Filesystem
38
+ def extensions
39
+ {"sscs" => :scss, "ssas" => :sass}
40
+ end
41
+ end
42
+
43
+ # This importer maps one import to another import
44
+ # based on the mappings passed to importer's constructor.
45
+ class IndirectImporter < Sass::Importers::Base
46
+ def initialize(mappings, mtimes)
47
+ @mappings = mappings
48
+ @mtimes = mtimes
49
+ end
50
+ def find_relative(uri, base, options)
51
+ nil
52
+ end
53
+ def find(name, options)
54
+ if @mappings.has_key?(name)
55
+ Sass::Engine.new(
56
+ %Q[@import "#{@mappings[name]}";],
57
+ options.merge(
58
+ :filename => name,
59
+ :syntax => :scss,
60
+ :importer => self
61
+ )
62
+ )
63
+ end
64
+ end
65
+ def mtime(uri, options)
66
+ @mtimes.fetch(uri, @mtimes.has_key?(uri) ? Time.now : nil)
67
+ end
68
+ def key(uri, options)
69
+ [self.class.name, uri]
70
+ end
71
+ def to_s
72
+ "IndirectImporter(#{@mappings.keys.join(", ")})"
73
+ end
74
+ end
75
+
76
+ # This importer maps the import to single class
77
+ # based on the mappings passed to importer's constructor.
78
+ class ClassImporter < Sass::Importers::Base
79
+ def initialize(mappings, mtimes)
80
+ @mappings = mappings
81
+ @mtimes = mtimes
82
+ end
83
+ def find_relative(uri, base, options)
84
+ nil
85
+ end
86
+ def find(name, options)
87
+ if @mappings.has_key?(name)
88
+ Sass::Engine.new(
89
+ %Q[.#{name}{#{@mappings[name]}}],
90
+ options.merge(
91
+ :filename => name,
92
+ :syntax => :scss,
93
+ :importer => self
94
+ )
95
+ )
96
+ end
97
+ end
98
+ def mtime(uri, options)
99
+ @mtimes.fetch(uri, @mtimes.has_key?(uri) ? Time.now : nil)
100
+ end
101
+ def key(uri, options)
102
+ [self.class.name, uri]
103
+ end
104
+ def to_s
105
+ "ClassImporter(#{@mappings.keys.join(", ")})"
106
+ end
107
+ end
108
+
109
+ def test_can_resolve_generated_imports
110
+ scss_file = %Q{
111
+ $pear-color: green;
112
+ @import "fruits/apple"; @import "fruits/orange"; @import "fruits/pear";
113
+ .apple { @include apple; }
114
+ .orange { @include orange; }
115
+ .pear { @include pear; }
116
+ }
117
+ css_file = <<CSS
118
+ .apple { color: red; }
119
+
120
+ .orange { color: orange; }
121
+
122
+ .pear { color: green; }
123
+ CSS
124
+ options = {:style => :compact, :load_paths => [FruitImporter.new], :syntax => :scss}
125
+ assert_equal css_file, Sass::Engine.new(scss_file, options).render
126
+ end
127
+
128
+ def test_extension_overrides
129
+ FileUtils.mkdir_p(absolutize("tmp"))
130
+ open(absolutize("tmp/foo.ssas"), "w") {|f| f.write(".foo\n reversed: true\n")}
131
+ open(absolutize("tmp/bar.sscs"), "w") {|f| f.write(".bar {reversed: true}\n")}
132
+ scss_file = %Q{
133
+ @import "foo", "bar";
134
+ @import "foo.ssas", "bar.sscs";
135
+ }
136
+ css_file = <<CSS
137
+ .foo { reversed: true; }
138
+
139
+ .bar { reversed: true; }
140
+
141
+ .foo { reversed: true; }
142
+
143
+ .bar { reversed: true; }
144
+ CSS
145
+ options = {:style => :compact, :load_paths => [ReversedExtImporter.new(absolutize("tmp"))], :syntax => :scss}
146
+ assert_equal css_file, Sass::Engine.new(scss_file, options).render
147
+ ensure
148
+ FileUtils.rm_rf(absolutize("tmp"))
149
+ end
150
+
151
+ def test_staleness_check_across_importers
152
+ file_system_importer = Sass::Importers::Filesystem.new(fixture_dir)
153
+ # Make sure the first import is older
154
+ indirect_importer = IndirectImporter.new({"apple" => "pear"}, {"apple" => Time.now - 1})
155
+ # Make css file is newer so the dependencies are the only way for the css file to be out of date.
156
+ FileUtils.touch(fixture_file("test_staleness_check_across_importers.css"))
157
+ # Make sure the first import is older
158
+ class_importer = ClassImporter.new({"pear" => %Q{color: green;}}, {"pear" => Time.now + 1})
159
+
160
+ options = {
161
+ :style => :compact,
162
+ :filename => fixture_file("test_staleness_check_across_importers.scss"),
163
+ :importer => file_system_importer,
164
+ :load_paths => [file_system_importer, indirect_importer, class_importer],
165
+ :syntax => :scss
166
+ }
167
+
168
+ assert_equal File.read(fixture_file("test_staleness_check_across_importers.css")),
169
+ Sass::Engine.new(File.read(fixture_file("test_staleness_check_across_importers.scss")), options).render
170
+
171
+ checker = Sass::Plugin::StalenessChecker.new(options)
172
+
173
+ assert checker.stylesheet_needs_update?(
174
+ fixture_file("test_staleness_check_across_importers.css"),
175
+ fixture_file("test_staleness_check_across_importers.scss"),
176
+ file_system_importer
177
+ )
178
+ end
179
+
180
+ def fixture_dir
181
+ File.join(File.dirname(__FILE__), "fixtures")
182
+ end
183
+
184
+ def fixture_file(path)
185
+ File.join(fixture_dir, path)
186
+ end
187
+
188
+ def test_absolute_files_across_template_locations
189
+ importer = Sass::Importers::Filesystem.new(absolutize 'templates')
190
+ assert_not_nil importer.mtime(absolutize('more_templates/more1.sass'), {})
191
+ end
192
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+ require 'pathname'
4
+
5
+ class LoggerTest < Test::Unit::TestCase
6
+
7
+ class InterceptedLogger < Sass::Logger::Base
8
+
9
+ attr_accessor :messages
10
+
11
+ def initialize(*args)
12
+ super
13
+ self.messages = []
14
+ end
15
+
16
+ def reset!
17
+ self.messages = []
18
+ end
19
+
20
+ def _log(*args)
21
+ messages << [args]
22
+ end
23
+
24
+ end
25
+
26
+ def test_global_sass_logger_instance_exists
27
+ assert Sass.logger.respond_to?(:warn)
28
+ end
29
+
30
+ def test_log_level_orders
31
+ logged_levels = {
32
+ :trace => [ [], [:trace, :debug, :info, :warn, :error]],
33
+ :debug => [ [:trace], [:debug, :info, :warn, :error]],
34
+ :info => [ [:trace, :debug], [:info, :warn, :error]],
35
+ :warn => [ [:trace, :debug, :info], [:warn, :error]],
36
+ :error => [ [:trace, :debug, :info, :warn], [:error]]
37
+ }
38
+ logged_levels.each do |level, (should_not_be_logged, should_be_logged)|
39
+ logger = Sass::Logger::Base.new(level)
40
+ should_not_be_logged.each do |should_level|
41
+ assert !logger.logging_level?(should_level)
42
+ end
43
+ should_be_logged.each do |should_level|
44
+ assert logger.logging_level?(should_level)
45
+ end
46
+ end
47
+ end
48
+
49
+ def test_logging_can_be_disabled
50
+ logger = InterceptedLogger.new
51
+ logger.error("message #1")
52
+ assert_equal 1, logger.messages.size
53
+ logger.reset!
54
+ logger.disabled = true
55
+ logger.error("message #2")
56
+ assert_equal 0, logger.messages.size
57
+ end
58
+ end
@@ -0,0 +1,49 @@
1
+ class MockImporter < Sass::Importers::Base
2
+ def initialize(name = "mock")
3
+ @name = name
4
+ @imports = Hash.new({})
5
+ end
6
+
7
+ def find_relative(uri, base, options)
8
+ nil
9
+ end
10
+
11
+ def find(uri, options)
12
+ contents = @imports[uri][:contents]
13
+ return unless contents
14
+ options[:syntax] = @imports[uri][:syntax]
15
+ options[:filename] = uri
16
+ options[:importer] = self
17
+ @imports[uri][:engine] = Sass::Engine.new(contents, options)
18
+ end
19
+
20
+ def mtime(uri, options)
21
+ @imports[uri][:mtime]
22
+ end
23
+
24
+ def key(uri, options)
25
+ ["mock", uri]
26
+ end
27
+
28
+ def to_s
29
+ @name
30
+ end
31
+
32
+ # Methods for testing
33
+
34
+ def add_import(uri, contents, syntax = :scss, mtime = Time.now - 10)
35
+ @imports[uri] = {
36
+ :contents => contents,
37
+ :mtime => mtime,
38
+ :syntax => syntax
39
+ }
40
+ end
41
+
42
+ def touch(uri)
43
+ @imports[uri][:mtime] = Time.now
44
+ end
45
+
46
+ def engine(uri)
47
+ @imports[uri][:engine]
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ body { font: Arial; background: blue; }
2
+
3
+ #page { width: 700px; height: 100; }
4
+ #page #header { height: 300px; }
5
+ #page #header h1 { font-size: 50px; color: blue; }
6
+
7
+ #content.user.show #container.top #column.left { width: 100px; }
8
+ #content.user.show #container.top #column.right { width: 600px; }
9
+ #content.user.show #container.bottom { background: brown; }
@@ -0,0 +1,26 @@
1
+ /* line 3, ../more_templates/more1.sass */
2
+ body {
3
+ font: Arial;
4
+ background: blue; }
5
+
6
+ /* line 7, ../more_templates/more1.sass */
7
+ #page {
8
+ width: 700px;
9
+ height: 100; }
10
+ /* line 10, ../more_templates/more1.sass */
11
+ #page #header {
12
+ height: 300px; }
13
+ /* line 12, ../more_templates/more1.sass */
14
+ #page #header h1 {
15
+ font-size: 50px;
16
+ color: blue; }
17
+
18
+ /* line 18, ../more_templates/more1.sass */
19
+ #content.user.show #container.top #column.left {
20
+ width: 100px; }
21
+ /* line 20, ../more_templates/more1.sass */
22
+ #content.user.show #container.top #column.right {
23
+ width: 600px; }
24
+ /* line 22, ../more_templates/more1.sass */
25
+ #content.user.show #container.bottom {
26
+ background: brown; }
@@ -0,0 +1,29 @@
1
+ @import url(basic.css);
2
+ @import url(../results/complex.css);
3
+ imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
4
+
5
+ body { font: Arial; background: blue; }
6
+
7
+ #page { width: 700px; height: 100; }
8
+ #page #header { height: 300px; }
9
+ #page #header h1 { font-size: 50px; color: blue; }
10
+
11
+ #content.user.show #container.top #column.left { width: 100px; }
12
+ #content.user.show #container.top #column.right { width: 600px; }
13
+ #content.user.show #container.bottom { background: brown; }
14
+
15
+ midrule { inthe: middle; }
16
+
17
+ body { font: Arial; background: blue; }
18
+
19
+ #page { width: 700px; height: 100; }
20
+ #page #header { height: 300px; }
21
+ #page #header h1 { font-size: 50px; color: blue; }
22
+
23
+ #content.user.show #container.top #column.left { width: 100px; }
24
+ #content.user.show #container.top #column.right { width: 600px; }
25
+ #content.user.show #container.bottom { background: brown; }
26
+
27
+ #foo { background-color: #bbaaff; }
28
+
29
+ nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
@@ -0,0 +1,2 @@
1
+ #foo
2
+ :background-color #baf
@@ -0,0 +1,23 @@
1
+
2
+
3
+ body
4
+ :font Arial
5
+ :background blue
6
+
7
+ #page
8
+ :width 700px
9
+ :height 100
10
+ #header
11
+ :height 300px
12
+ h1
13
+ :font-size 50px
14
+ :color blue
15
+
16
+ #content.user.show
17
+ #container.top
18
+ #column.left
19
+ :width 100px
20
+ #column.right
21
+ :width 600px
22
+ #container.bottom
23
+ :background brown
@@ -0,0 +1,11 @@
1
+ $preconst: hello
2
+
3
+ =premixin
4
+ pre-mixin: here
5
+
6
+ @import importee, basic, basic.css, ../results/complex.css, more_partial
7
+
8
+ nonimported
9
+ :myconst $preconst
10
+ :otherconst $postconst
11
+ +postmixin
@@ -0,0 +1,550 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../test_helper'
3
+ require File.dirname(__FILE__) + '/test_helper'
4
+ require 'sass/plugin'
5
+ require 'fileutils'
6
+
7
+ module Sass::Script::Functions
8
+ def filename
9
+ filename = options[:filename].gsub(%r{.*((/[^/]+){4})}, '\1')
10
+ Sass::Script::String.new(filename)
11
+ end
12
+
13
+ def whatever
14
+ custom = options[:custom]
15
+ whatever = custom && custom[:whatever]
16
+ Sass::Script::String.new(whatever || "incorrect")
17
+ end
18
+ end
19
+
20
+ class SassPluginTest < Test::Unit::TestCase
21
+ @@templates = %w{
22
+ complex script parent_ref import scss_import alt
23
+ subdir/subdir subdir/nested_subdir/nested_subdir
24
+ options import_content filename_fn
25
+ }
26
+ @@templates += %w[import_charset import_charset_ibm866] unless Sass::Util.ruby1_8?
27
+ @@templates << 'import_charset_1_8' if Sass::Util.ruby1_8?
28
+
29
+ @@cache_store = Sass::CacheStores::Memory.new
30
+
31
+ def setup
32
+ FileUtils.mkdir_p tempfile_loc
33
+ FileUtils.mkdir_p tempfile_loc(nil,"more_")
34
+ set_plugin_opts
35
+ check_for_updates!
36
+ reset_mtimes
37
+ end
38
+
39
+ def teardown
40
+ clean_up_sassc
41
+ Sass::Plugin.reset!
42
+ FileUtils.rm_r tempfile_loc
43
+ FileUtils.rm_r tempfile_loc(nil,"more_")
44
+ end
45
+
46
+ @@templates.each do |name|
47
+ define_method("test_template_renders_correctly (#{name})") do
48
+ assert_renders_correctly(name)
49
+ end
50
+ end
51
+
52
+ def test_no_update
53
+ File.delete(tempfile_loc('basic'))
54
+ assert_needs_update 'basic'
55
+ check_for_updates!
56
+ assert_stylesheet_updated 'basic'
57
+ end
58
+
59
+ def test_update_needed_when_modified
60
+ touch 'basic'
61
+ assert_needs_update 'basic'
62
+ check_for_updates!
63
+ assert_stylesheet_updated 'basic'
64
+ end
65
+
66
+ def test_update_needed_when_dependency_modified
67
+ touch 'basic'
68
+ assert_needs_update 'import'
69
+ check_for_updates!
70
+ assert_stylesheet_updated 'basic'
71
+ assert_stylesheet_updated 'import'
72
+ end
73
+
74
+ def test_update_needed_when_scss_dependency_modified
75
+ touch 'scss_importee'
76
+ assert_needs_update 'import'
77
+ check_for_updates!
78
+ assert_stylesheet_updated 'scss_importee'
79
+ assert_stylesheet_updated 'import'
80
+ end
81
+
82
+ def test_scss_update_needed_when_dependency_modified
83
+ touch 'basic'
84
+ assert_needs_update 'scss_import'
85
+ check_for_updates!
86
+ assert_stylesheet_updated 'basic'
87
+ assert_stylesheet_updated 'scss_import'
88
+ end
89
+
90
+ def test_update_needed_when_nested_import_dependency_modified
91
+ touch 'basic'
92
+ assert_needs_update 'nested_import'
93
+ check_for_updates!
94
+ assert_stylesheet_updated 'basic'
95
+ assert_stylesheet_updated 'scss_import'
96
+ end
97
+
98
+ def test_no_updates_when_always_check_and_always_update_both_false
99
+ Sass::Plugin.options[:always_update] = false
100
+ Sass::Plugin.options[:always_check] = false
101
+
102
+ touch 'basic'
103
+ assert_needs_update 'basic'
104
+ check_for_updates!
105
+
106
+ # Check it's still stale
107
+ assert_needs_update 'basic'
108
+ end
109
+
110
+ def test_full_exception_handling
111
+ File.delete(tempfile_loc('bork1'))
112
+ check_for_updates!
113
+ File.open(tempfile_loc('bork1')) do |file|
114
+ assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
115
+ /*
116
+ Syntax error: Undefined variable: "$bork".
117
+ on line 2 of #{template_loc('bork1')}
118
+
119
+ 1: bork
120
+ 2: :bork $bork
121
+ CSS
122
+ end
123
+ File.delete(tempfile_loc('bork1'))
124
+ end
125
+
126
+ def test_full_exception_with_block_comment
127
+ File.delete(tempfile_loc('bork5'))
128
+ check_for_updates!
129
+ File.open(tempfile_loc('bork5')) do |file|
130
+ assert_equal(<<CSS.strip, file.read.split("\n")[0...7].join("\n"))
131
+ /*
132
+ Syntax error: Undefined variable: "$bork".
133
+ on line 3 of #{template_loc('bork5')}
134
+
135
+ 1: bork
136
+ 2: /* foo *\\/
137
+ 3: :bork $bork
138
+ CSS
139
+ end
140
+ File.delete(tempfile_loc('bork1'))
141
+ end
142
+
143
+ def test_single_level_import_loop
144
+ File.delete(tempfile_loc('single_import_loop'))
145
+ check_for_updates!
146
+ File.open(tempfile_loc('single_import_loop')) do |file|
147
+ assert_equal(<<CSS.strip, file.read.split("\n")[0...2].join("\n"))
148
+ /*
149
+ Syntax error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
150
+ CSS
151
+ end
152
+ end
153
+
154
+ def test_double_level_import_loop
155
+ File.delete(tempfile_loc('double_import_loop1'))
156
+ check_for_updates!
157
+ File.open(tempfile_loc('double_import_loop1')) do |file|
158
+ assert_equal(<<CSS.strip, file.read.split("\n")[0...4].join("\n"))
159
+ /*
160
+ Syntax error: An @import loop has been found:
161
+ #{template_loc('double_import_loop1')} imports #{template_loc('_double_import_loop2')}
162
+ #{template_loc('_double_import_loop2')} imports #{template_loc('double_import_loop1')}
163
+ CSS
164
+ end
165
+ end
166
+
167
+ def test_nonfull_exception_handling
168
+ old_full_exception = Sass::Plugin.options[:full_exception]
169
+ Sass::Plugin.options[:full_exception] = false
170
+
171
+ File.delete(tempfile_loc('bork1'))
172
+ assert_raise(Sass::SyntaxError) {check_for_updates!}
173
+ ensure
174
+ Sass::Plugin.options[:full_exception] = old_full_exception
175
+ end
176
+
177
+ def test_two_template_directories
178
+ set_plugin_opts :template_location => {
179
+ template_loc => tempfile_loc,
180
+ template_loc(nil,'more_') => tempfile_loc(nil,'more_')
181
+ }
182
+ check_for_updates!
183
+ ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') }
184
+ end
185
+
186
+ def test_two_template_directories_with_line_annotations
187
+ set_plugin_opts :line_comments => true,
188
+ :style => :nested,
189
+ :template_location => {
190
+ template_loc => tempfile_loc,
191
+ template_loc(nil,'more_') => tempfile_loc(nil,'more_')
192
+ }
193
+ check_for_updates!
194
+ assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_')
195
+ end
196
+
197
+ def test_doesnt_render_partials
198
+ assert !File.exists?(tempfile_loc('_partial'))
199
+ end
200
+
201
+ def test_template_location_array
202
+ assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array
203
+ end
204
+
205
+ def test_add_template_location
206
+ Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
207
+ assert_equal(
208
+ [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
209
+ Sass::Plugin.template_location_array)
210
+
211
+ touch 'more1', 'more_'
212
+ touch 'basic'
213
+ assert_needs_update "more1", "more_"
214
+ assert_needs_update "basic"
215
+ check_for_updates!
216
+ assert_doesnt_need_update "more1", "more_"
217
+ assert_doesnt_need_update "basic"
218
+ end
219
+
220
+ def test_remove_template_location
221
+ Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
222
+ Sass::Plugin.remove_template_location(template_loc, tempfile_loc)
223
+ assert_equal(
224
+ [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
225
+ Sass::Plugin.template_location_array)
226
+
227
+ touch 'more1', 'more_'
228
+ touch 'basic'
229
+ assert_needs_update "more1", "more_"
230
+ assert_needs_update "basic"
231
+ check_for_updates!
232
+ assert_doesnt_need_update "more1", "more_"
233
+ assert_needs_update "basic"
234
+ end
235
+
236
+ def test_import_same_name
237
+ assert_warning <<WARNING do
238
+ WARNING: In #{template_loc}:
239
+ There are multiple files that match the name "same_name_different_partiality.scss":
240
+ _same_name_different_partiality.scss
241
+ same_name_different_partiality.scss
242
+ WARNING
243
+ touch "_same_name_different_partiality"
244
+ assert_needs_update "same_name_different_partiality"
245
+ end
246
+ end
247
+
248
+ # Callbacks
249
+
250
+ def test_updating_stylesheets_callback
251
+ # Should run even when there's nothing to update
252
+ Sass::Plugin.options[:template_location] = nil
253
+ assert_callback :updating_stylesheets, []
254
+ end
255
+
256
+ def test_updating_stylesheets_callback_with_never_update
257
+ Sass::Plugin.options[:never_update] = true
258
+ assert_no_callback :updating_stylesheets
259
+ end
260
+
261
+ def test_updated_stylesheet_callback_for_updated_template
262
+ Sass::Plugin.options[:always_update] = false
263
+ touch 'basic'
264
+ assert_no_callback :updated_stylesheet, template_loc("complex"), tempfile_loc("complex") do
265
+ assert_callbacks(
266
+ [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
267
+ [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
268
+ end
269
+ end
270
+
271
+ def test_updated_stylesheet_callback_for_fresh_template
272
+ Sass::Plugin.options[:always_update] = false
273
+ assert_no_callback :updated_stylesheet
274
+ end
275
+
276
+ def test_updated_stylesheet_callback_for_error_template
277
+ Sass::Plugin.options[:always_update] = false
278
+ touch 'bork1'
279
+ assert_no_callback :updated_stylesheet
280
+ end
281
+
282
+ def test_not_updating_stylesheet_callback_for_fresh_template
283
+ Sass::Plugin.options[:always_update] = false
284
+ assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic")
285
+ end
286
+
287
+ def test_not_updating_stylesheet_callback_for_updated_template
288
+ Sass::Plugin.options[:always_update] = false
289
+ assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do
290
+ assert_no_callbacks(
291
+ [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
292
+ [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
293
+ end
294
+ end
295
+
296
+ def test_not_updating_stylesheet_callback_with_never_update
297
+ Sass::Plugin.options[:never_update] = true
298
+ assert_no_callback :not_updating_stylesheet
299
+ end
300
+
301
+ def test_not_updating_stylesheet_callback_for_partial
302
+ Sass::Plugin.options[:always_update] = false
303
+ assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial")
304
+ end
305
+
306
+ def test_not_updating_stylesheet_callback_for_error
307
+ Sass::Plugin.options[:always_update] = false
308
+ touch 'bork1'
309
+ assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1")
310
+ end
311
+
312
+ def test_compilation_error_callback
313
+ Sass::Plugin.options[:always_update] = false
314
+ touch 'bork1'
315
+ assert_callback(:compilation_error,
316
+ lambda {|e| e.message == 'Undefined variable: "$bork".'},
317
+ template_loc("bork1"), tempfile_loc("bork1"))
318
+ end
319
+
320
+ def test_compilation_error_callback_for_file_access
321
+ Sass::Plugin.options[:always_update] = false
322
+ assert_callback(:compilation_error,
323
+ lambda {|e| e.is_a?(Errno::ENOENT)},
324
+ template_loc("nonexistent"), tempfile_loc("nonexistent")) do
325
+ Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]])
326
+ end
327
+ end
328
+
329
+ def test_creating_directory_callback
330
+ Sass::Plugin.options[:always_update] = false
331
+ dir = File.join(tempfile_loc, "subdir", "nested_subdir")
332
+ FileUtils.rm_r dir
333
+ assert_callback :creating_directory, dir
334
+ end
335
+
336
+ ## Regression
337
+
338
+ def test_cached_dependencies_update
339
+ FileUtils.mv(template_loc("basic"), template_loc("basic", "more_"))
340
+ set_plugin_opts :load_paths => [template_loc(nil, "more_")]
341
+
342
+ touch 'basic', 'more_'
343
+ assert_needs_update "import"
344
+ check_for_updates!
345
+ assert_renders_correctly("import")
346
+ ensure
347
+ FileUtils.mv(template_loc("basic", "more_"), template_loc("basic"))
348
+ end
349
+
350
+ def test_cached_relative_import
351
+ old_always_update = Sass::Plugin.options[:always_update]
352
+ Sass::Plugin.options[:always_update] = true
353
+ check_for_updates!
354
+ assert_renders_correctly('subdir/subdir')
355
+ ensure
356
+ Sass::Plugin.options[:always_update] = old_always_update
357
+ end
358
+
359
+ def test_cached_if
360
+ set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache')
361
+ check_for_updates!
362
+ assert_renders_correctly 'if'
363
+ check_for_updates!
364
+ assert_renders_correctly 'if'
365
+ ensure
366
+ set_plugin_opts
367
+ end
368
+
369
+ def test_cached_import_option
370
+ set_plugin_opts :custom => {:whatever => "correct"}
371
+ check_for_updates!
372
+ assert_renders_correctly "cached_import_option"
373
+
374
+ @@cache_store.reset!
375
+ set_plugin_opts :custom => nil, :always_update => false
376
+ check_for_updates!
377
+ assert_renders_correctly "cached_import_option"
378
+
379
+ set_plugin_opts :custom => {:whatever => "correct"}, :always_update => true
380
+ check_for_updates!
381
+ assert_renders_correctly "cached_import_option"
382
+ ensure
383
+ set_plugin_opts :custom => nil
384
+ end
385
+
386
+ private
387
+
388
+ def assert_renders_correctly(*arguments)
389
+ options = arguments.last.is_a?(Hash) ? arguments.pop : {}
390
+ prefix = options[:prefix]
391
+ result_name = arguments.shift
392
+ tempfile_name = arguments.shift || result_name
393
+
394
+ expected_str = File.read(result_loc(result_name, prefix))
395
+ actual_str = File.read(tempfile_loc(tempfile_name, prefix))
396
+ unless Sass::Util.ruby1_8?
397
+ expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
398
+ actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
399
+ end
400
+ expected_lines = expected_str.split("\n")
401
+ actual_lines = actual_str.split("\n")
402
+
403
+ if actual_lines.first == "/*" && expected_lines.first != "/*"
404
+ assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n"))
405
+ end
406
+
407
+ expected_lines.zip(actual_lines).each_with_index do |pair, line|
408
+ message = "template: #{result_name}\nline: #{line + 1}"
409
+ assert_equal(pair.first, pair.last, message)
410
+ end
411
+ if expected_lines.size < actual_lines.size
412
+ assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}")
413
+ end
414
+ end
415
+
416
+ def assert_stylesheet_updated(name)
417
+ assert_doesnt_need_update name
418
+
419
+ # Make sure it isn't an exception
420
+ expected_lines = File.read(result_loc(name)).split("\n")
421
+ actual_lines = File.read(tempfile_loc(name)).split("\n")
422
+ if actual_lines.first == "/*" && expected_lines.first != "/*"
423
+ assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n"))
424
+ end
425
+ end
426
+
427
+ def assert_callback(name, *expected_args)
428
+ run = false
429
+ received_args = nil
430
+ Sass::Plugin.send("on_#{name}") do |*args|
431
+ received_args = args
432
+ run ||= expected_args.zip(received_args).all? do |ea, ra|
433
+ ea.respond_to?(:call) ? ea.call(ra) : ea == ra
434
+ end
435
+ end
436
+
437
+ if block_given?
438
+ Sass::Util.silence_sass_warnings {yield}
439
+ else
440
+ check_for_updates!
441
+ end
442
+
443
+ assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}\nHowever, it got:\n #{received_args.inspect}"
444
+ end
445
+
446
+ def assert_no_callback(name, *unexpected_args)
447
+ Sass::Plugin.send("on_#{name}") do |*a|
448
+ next unless unexpected_args.empty? || a == unexpected_args
449
+
450
+ msg = "Expected #{name} callback not to be run"
451
+ if !unexpected_args.empty?
452
+ msg << " with arguments #{unexpected_args.inspect}"
453
+ elsif !a.empty?
454
+ msg << ",\n was run with arguments #{a.inspect}"
455
+ end
456
+
457
+ flunk msg
458
+ end
459
+
460
+ if block_given?
461
+ yield
462
+ else
463
+ check_for_updates!
464
+ end
465
+ end
466
+
467
+ def assert_callbacks(*args)
468
+ return check_for_updates! if args.empty?
469
+ assert_callback(*args.pop) {assert_callbacks(*args)}
470
+ end
471
+
472
+ def assert_no_callbacks(*args)
473
+ return check_for_updates! if args.empty?
474
+ assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
475
+ end
476
+
477
+ def check_for_updates!
478
+ Sass::Util.silence_sass_warnings do
479
+ Sass::Plugin.check_for_updates
480
+ end
481
+ end
482
+
483
+ def assert_needs_update(*args)
484
+ assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
485
+ "Expected #{template_loc(*args)} to need an update.")
486
+ end
487
+
488
+ def assert_doesnt_need_update(*args)
489
+ assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
490
+ "Expected #{template_loc(*args)} not to need an update.")
491
+ end
492
+
493
+ def touch(*args)
494
+ FileUtils.touch(template_loc(*args))
495
+ end
496
+
497
+ def reset_mtimes
498
+ Sass::Plugin::StalenessChecker.dependencies_cache = {}
499
+ atime = Time.now
500
+ mtime = Time.now - 5
501
+ Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
502
+ end
503
+
504
+ def template_loc(name = nil, prefix = nil)
505
+ if name
506
+ scss = absolutize "#{prefix}templates/#{name}.scss"
507
+ File.exists?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass")
508
+ else
509
+ absolutize "#{prefix}templates"
510
+ end
511
+ end
512
+
513
+ def tempfile_loc(name = nil, prefix = nil)
514
+ if name
515
+ absolutize "#{prefix}tmp/#{name}.css"
516
+ else
517
+ absolutize "#{prefix}tmp"
518
+ end
519
+ end
520
+
521
+ def result_loc(name = nil, prefix = nil)
522
+ if name
523
+ absolutize "#{prefix}results/#{name}.css"
524
+ else
525
+ absolutize "#{prefix}results"
526
+ end
527
+ end
528
+
529
+ def set_plugin_opts(overrides = {})
530
+ Sass::Plugin.options.merge!(
531
+ :template_location => template_loc,
532
+ :css_location => tempfile_loc,
533
+ :style => :compact,
534
+ :always_update => true,
535
+ :never_update => false,
536
+ :full_exception => true,
537
+ :cache_store => @@cache_store
538
+ )
539
+ Sass::Plugin.options.merge!(overrides)
540
+ end
541
+ end
542
+
543
+ class Sass::Engine
544
+ alias_method :old_render, :render
545
+
546
+ def render
547
+ raise "bork bork bork!" if @template[0] == "{bork now!}"
548
+ old_render
549
+ end
550
+ end