oreorenasass 3.4.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 (268) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +11 -0
  3. data/CONTRIBUTING +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +221 -0
  6. data/Rakefile +370 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/sass +13 -0
  10. data/bin/sass-convert +12 -0
  11. data/bin/scss +13 -0
  12. data/extra/update_watch.rb +13 -0
  13. data/init.rb +18 -0
  14. data/lib/sass/cache_stores/base.rb +88 -0
  15. data/lib/sass/cache_stores/chain.rb +34 -0
  16. data/lib/sass/cache_stores/filesystem.rb +60 -0
  17. data/lib/sass/cache_stores/memory.rb +47 -0
  18. data/lib/sass/cache_stores/null.rb +25 -0
  19. data/lib/sass/cache_stores.rb +15 -0
  20. data/lib/sass/callbacks.rb +67 -0
  21. data/lib/sass/css.rb +407 -0
  22. data/lib/sass/engine.rb +1181 -0
  23. data/lib/sass/environment.rb +191 -0
  24. data/lib/sass/error.rb +198 -0
  25. data/lib/sass/exec/base.rb +187 -0
  26. data/lib/sass/exec/sass_convert.rb +264 -0
  27. data/lib/sass/exec/sass_scss.rb +424 -0
  28. data/lib/sass/exec.rb +9 -0
  29. data/lib/sass/features.rb +47 -0
  30. data/lib/sass/importers/base.rb +182 -0
  31. data/lib/sass/importers/filesystem.rb +211 -0
  32. data/lib/sass/importers.rb +22 -0
  33. data/lib/sass/logger/base.rb +30 -0
  34. data/lib/sass/logger/log_level.rb +45 -0
  35. data/lib/sass/logger.rb +12 -0
  36. data/lib/sass/media.rb +210 -0
  37. data/lib/sass/plugin/compiler.rb +565 -0
  38. data/lib/sass/plugin/configuration.rb +118 -0
  39. data/lib/sass/plugin/generic.rb +15 -0
  40. data/lib/sass/plugin/merb.rb +48 -0
  41. data/lib/sass/plugin/rack.rb +60 -0
  42. data/lib/sass/plugin/rails.rb +47 -0
  43. data/lib/sass/plugin/staleness_checker.rb +199 -0
  44. data/lib/sass/plugin.rb +133 -0
  45. data/lib/sass/railtie.rb +10 -0
  46. data/lib/sass/repl.rb +57 -0
  47. data/lib/sass/root.rb +7 -0
  48. data/lib/sass/script/css_lexer.rb +33 -0
  49. data/lib/sass/script/css_parser.rb +34 -0
  50. data/lib/sass/script/functions.rb +2626 -0
  51. data/lib/sass/script/lexer.rb +449 -0
  52. data/lib/sass/script/parser.rb +637 -0
  53. data/lib/sass/script/tree/funcall.rb +306 -0
  54. data/lib/sass/script/tree/interpolation.rb +118 -0
  55. data/lib/sass/script/tree/list_literal.rb +77 -0
  56. data/lib/sass/script/tree/literal.rb +45 -0
  57. data/lib/sass/script/tree/map_literal.rb +64 -0
  58. data/lib/sass/script/tree/node.rb +109 -0
  59. data/lib/sass/script/tree/operation.rb +103 -0
  60. data/lib/sass/script/tree/selector.rb +26 -0
  61. data/lib/sass/script/tree/string_interpolation.rb +104 -0
  62. data/lib/sass/script/tree/unary_operation.rb +69 -0
  63. data/lib/sass/script/tree/variable.rb +57 -0
  64. data/lib/sass/script/tree.rb +16 -0
  65. data/lib/sass/script/value/arg_list.rb +36 -0
  66. data/lib/sass/script/value/base.rb +240 -0
  67. data/lib/sass/script/value/bool.rb +35 -0
  68. data/lib/sass/script/value/color.rb +680 -0
  69. data/lib/sass/script/value/helpers.rb +262 -0
  70. data/lib/sass/script/value/list.rb +113 -0
  71. data/lib/sass/script/value/map.rb +70 -0
  72. data/lib/sass/script/value/null.rb +44 -0
  73. data/lib/sass/script/value/number.rb +530 -0
  74. data/lib/sass/script/value/string.rb +97 -0
  75. data/lib/sass/script/value.rb +11 -0
  76. data/lib/sass/script.rb +66 -0
  77. data/lib/sass/scss/css_parser.rb +42 -0
  78. data/lib/sass/scss/parser.rb +1209 -0
  79. data/lib/sass/scss/rx.rb +141 -0
  80. data/lib/sass/scss/script_lexer.rb +15 -0
  81. data/lib/sass/scss/script_parser.rb +25 -0
  82. data/lib/sass/scss/static_parser.rb +368 -0
  83. data/lib/sass/scss.rb +16 -0
  84. data/lib/sass/selector/abstract_sequence.rb +109 -0
  85. data/lib/sass/selector/comma_sequence.rb +175 -0
  86. data/lib/sass/selector/pseudo.rb +256 -0
  87. data/lib/sass/selector/sequence.rb +600 -0
  88. data/lib/sass/selector/simple.rb +117 -0
  89. data/lib/sass/selector/simple_sequence.rb +325 -0
  90. data/lib/sass/selector.rb +326 -0
  91. data/lib/sass/shared.rb +76 -0
  92. data/lib/sass/source/map.rb +210 -0
  93. data/lib/sass/source/position.rb +39 -0
  94. data/lib/sass/source/range.rb +41 -0
  95. data/lib/sass/stack.rb +120 -0
  96. data/lib/sass/supports.rb +227 -0
  97. data/lib/sass/tree/at_root_node.rb +83 -0
  98. data/lib/sass/tree/charset_node.rb +22 -0
  99. data/lib/sass/tree/comment_node.rb +82 -0
  100. data/lib/sass/tree/content_node.rb +9 -0
  101. data/lib/sass/tree/css_import_node.rb +60 -0
  102. data/lib/sass/tree/debug_node.rb +18 -0
  103. data/lib/sass/tree/directive_node.rb +59 -0
  104. data/lib/sass/tree/each_node.rb +24 -0
  105. data/lib/sass/tree/error_node.rb +18 -0
  106. data/lib/sass/tree/extend_node.rb +43 -0
  107. data/lib/sass/tree/for_node.rb +36 -0
  108. data/lib/sass/tree/function_node.rb +39 -0
  109. data/lib/sass/tree/if_node.rb +52 -0
  110. data/lib/sass/tree/import_node.rb +74 -0
  111. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  112. data/lib/sass/tree/media_node.rb +48 -0
  113. data/lib/sass/tree/mixin_def_node.rb +38 -0
  114. data/lib/sass/tree/mixin_node.rb +52 -0
  115. data/lib/sass/tree/node.rb +238 -0
  116. data/lib/sass/tree/prop_node.rb +171 -0
  117. data/lib/sass/tree/return_node.rb +19 -0
  118. data/lib/sass/tree/root_node.rb +44 -0
  119. data/lib/sass/tree/rule_node.rb +145 -0
  120. data/lib/sass/tree/supports_node.rb +38 -0
  121. data/lib/sass/tree/trace_node.rb +33 -0
  122. data/lib/sass/tree/variable_node.rb +36 -0
  123. data/lib/sass/tree/visitors/base.rb +72 -0
  124. data/lib/sass/tree/visitors/check_nesting.rb +177 -0
  125. data/lib/sass/tree/visitors/convert.rb +334 -0
  126. data/lib/sass/tree/visitors/cssize.rb +369 -0
  127. data/lib/sass/tree/visitors/deep_copy.rb +107 -0
  128. data/lib/sass/tree/visitors/extend.rb +68 -0
  129. data/lib/sass/tree/visitors/perform.rb +539 -0
  130. data/lib/sass/tree/visitors/set_options.rb +139 -0
  131. data/lib/sass/tree/visitors/to_css.rb +381 -0
  132. data/lib/sass/tree/warn_node.rb +18 -0
  133. data/lib/sass/tree/while_node.rb +18 -0
  134. data/lib/sass/util/cross_platform_random.rb +19 -0
  135. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  136. data/lib/sass/util/normalized_map.rb +130 -0
  137. data/lib/sass/util/ordered_hash.rb +192 -0
  138. data/lib/sass/util/subset_map.rb +110 -0
  139. data/lib/sass/util/test.rb +9 -0
  140. data/lib/sass/util.rb +1318 -0
  141. data/lib/sass/version.rb +124 -0
  142. data/lib/sass.rb +102 -0
  143. data/rails/init.rb +1 -0
  144. data/test/sass/cache_test.rb +131 -0
  145. data/test/sass/callbacks_test.rb +61 -0
  146. data/test/sass/compiler_test.rb +232 -0
  147. data/test/sass/conversion_test.rb +2054 -0
  148. data/test/sass/css2sass_test.rb +477 -0
  149. data/test/sass/data/hsl-rgb.txt +319 -0
  150. data/test/sass/encoding_test.rb +219 -0
  151. data/test/sass/engine_test.rb +3301 -0
  152. data/test/sass/exec_test.rb +86 -0
  153. data/test/sass/extend_test.rb +1661 -0
  154. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  155. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  156. data/test/sass/functions_test.rb +1926 -0
  157. data/test/sass/importer_test.rb +412 -0
  158. data/test/sass/logger_test.rb +58 -0
  159. data/test/sass/mock_importer.rb +49 -0
  160. data/test/sass/more_results/more1.css +9 -0
  161. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  162. data/test/sass/more_results/more_import.css +29 -0
  163. data/test/sass/more_templates/_more_partial.sass +2 -0
  164. data/test/sass/more_templates/more1.sass +23 -0
  165. data/test/sass/more_templates/more_import.sass +11 -0
  166. data/test/sass/plugin_test.rb +554 -0
  167. data/test/sass/results/alt.css +4 -0
  168. data/test/sass/results/basic.css +9 -0
  169. data/test/sass/results/cached_import_option.css +3 -0
  170. data/test/sass/results/compact.css +5 -0
  171. data/test/sass/results/complex.css +86 -0
  172. data/test/sass/results/compressed.css +1 -0
  173. data/test/sass/results/expanded.css +19 -0
  174. data/test/sass/results/filename_fn.css +3 -0
  175. data/test/sass/results/if.css +3 -0
  176. data/test/sass/results/import.css +31 -0
  177. data/test/sass/results/import_charset.css +5 -0
  178. data/test/sass/results/import_charset_1_8.css +5 -0
  179. data/test/sass/results/import_charset_ibm866.css +5 -0
  180. data/test/sass/results/import_content.css +1 -0
  181. data/test/sass/results/line_numbers.css +49 -0
  182. data/test/sass/results/mixins.css +95 -0
  183. data/test/sass/results/multiline.css +24 -0
  184. data/test/sass/results/nested.css +22 -0
  185. data/test/sass/results/options.css +1 -0
  186. data/test/sass/results/parent_ref.css +13 -0
  187. data/test/sass/results/script.css +16 -0
  188. data/test/sass/results/scss_import.css +31 -0
  189. data/test/sass/results/scss_importee.css +2 -0
  190. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  191. data/test/sass/results/subdir/subdir.css +3 -0
  192. data/test/sass/results/units.css +11 -0
  193. data/test/sass/results/warn.css +0 -0
  194. data/test/sass/results/warn_imported.css +0 -0
  195. data/test/sass/script_conversion_test.rb +328 -0
  196. data/test/sass/script_test.rb +1054 -0
  197. data/test/sass/scss/css_test.rb +1215 -0
  198. data/test/sass/scss/rx_test.rb +156 -0
  199. data/test/sass/scss/scss_test.rb +3900 -0
  200. data/test/sass/scss/test_helper.rb +37 -0
  201. data/test/sass/source_map_test.rb +977 -0
  202. data/test/sass/superselector_test.rb +191 -0
  203. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  204. data/test/sass/templates/_double_import_loop2.sass +1 -0
  205. data/test/sass/templates/_filename_fn_import.scss +11 -0
  206. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  207. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  208. data/test/sass/templates/_imported_content.sass +3 -0
  209. data/test/sass/templates/_partial.sass +2 -0
  210. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  211. data/test/sass/templates/alt.sass +16 -0
  212. data/test/sass/templates/basic.sass +23 -0
  213. data/test/sass/templates/bork1.sass +2 -0
  214. data/test/sass/templates/bork2.sass +2 -0
  215. data/test/sass/templates/bork3.sass +2 -0
  216. data/test/sass/templates/bork4.sass +2 -0
  217. data/test/sass/templates/bork5.sass +3 -0
  218. data/test/sass/templates/cached_import_option.scss +3 -0
  219. data/test/sass/templates/compact.sass +17 -0
  220. data/test/sass/templates/complex.sass +305 -0
  221. data/test/sass/templates/compressed.sass +15 -0
  222. data/test/sass/templates/double_import_loop1.sass +1 -0
  223. data/test/sass/templates/expanded.sass +17 -0
  224. data/test/sass/templates/filename_fn.scss +18 -0
  225. data/test/sass/templates/if.sass +11 -0
  226. data/test/sass/templates/import.sass +12 -0
  227. data/test/sass/templates/import_charset.sass +9 -0
  228. data/test/sass/templates/import_charset_1_8.sass +6 -0
  229. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  230. data/test/sass/templates/import_content.sass +4 -0
  231. data/test/sass/templates/importee.less +2 -0
  232. data/test/sass/templates/importee.sass +19 -0
  233. data/test/sass/templates/line_numbers.sass +13 -0
  234. data/test/sass/templates/mixin_bork.sass +5 -0
  235. data/test/sass/templates/mixins.sass +76 -0
  236. data/test/sass/templates/multiline.sass +20 -0
  237. data/test/sass/templates/nested.sass +25 -0
  238. data/test/sass/templates/nested_bork1.sass +2 -0
  239. data/test/sass/templates/nested_bork2.sass +2 -0
  240. data/test/sass/templates/nested_bork3.sass +2 -0
  241. data/test/sass/templates/nested_bork4.sass +2 -0
  242. data/test/sass/templates/nested_import.sass +2 -0
  243. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  244. data/test/sass/templates/options.sass +2 -0
  245. data/test/sass/templates/parent_ref.sass +25 -0
  246. data/test/sass/templates/same_name_different_ext.sass +2 -0
  247. data/test/sass/templates/same_name_different_ext.scss +1 -0
  248. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  249. data/test/sass/templates/script.sass +101 -0
  250. data/test/sass/templates/scss_import.scss +12 -0
  251. data/test/sass/templates/scss_importee.scss +1 -0
  252. data/test/sass/templates/single_import_loop.sass +1 -0
  253. data/test/sass/templates/subdir/import_up1.scss +1 -0
  254. data/test/sass/templates/subdir/import_up2.scss +1 -0
  255. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  256. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  257. data/test/sass/templates/subdir/subdir.sass +6 -0
  258. data/test/sass/templates/units.sass +11 -0
  259. data/test/sass/templates/warn.sass +3 -0
  260. data/test/sass/templates/warn_imported.sass +4 -0
  261. data/test/sass/test_helper.rb +8 -0
  262. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  263. data/test/sass/util/normalized_map_test.rb +51 -0
  264. data/test/sass/util/subset_map_test.rb +91 -0
  265. data/test/sass/util_test.rb +467 -0
  266. data/test/sass/value_helpers_test.rb +179 -0
  267. data/test/test_helper.rb +109 -0
  268. metadata +386 -0
@@ -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: #baf; }
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,554 @@
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::Value::String.new(filename)
11
+ end
12
+
13
+ def whatever
14
+ custom = options[:custom]
15
+ whatever = custom && custom[:whatever]
16
+ Sass::Script::Value::String.new(whatever || "incorrect")
17
+ end
18
+ end
19
+
20
+ class SassPluginTest < MiniTest::Test
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
+ 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
+ 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
+ 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
+ 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_import_name_cleanup
168
+ File.delete(tempfile_loc('subdir/import_up1'))
169
+ check_for_updates!
170
+ File.open(tempfile_loc('subdir/import_up1')) do |file|
171
+ assert_equal(<<CSS.strip, file.read.split("\n")[0...5].join("\n"))
172
+ /*
173
+ Error: File to import not found or unreadable: ../subdir/import_up3.scss.
174
+ Load path: #{template_loc}
175
+ on line 1 of #{template_loc 'subdir/import_up2'}
176
+ from line 1 of #{template_loc 'subdir/import_up1'}
177
+ CSS
178
+ end
179
+ end
180
+
181
+ def test_nonfull_exception_handling
182
+ old_full_exception = Sass::Plugin.options[:full_exception]
183
+ Sass::Plugin.options[:full_exception] = false
184
+
185
+ File.delete(tempfile_loc('bork1'))
186
+ assert_raises(Sass::SyntaxError) {check_for_updates!}
187
+ ensure
188
+ Sass::Plugin.options[:full_exception] = old_full_exception
189
+ end
190
+
191
+ def test_two_template_directories
192
+ set_plugin_opts :template_location => {
193
+ template_loc => tempfile_loc,
194
+ template_loc(nil,'more_') => tempfile_loc(nil,'more_')
195
+ }
196
+ check_for_updates!
197
+ ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') }
198
+ end
199
+
200
+ def test_two_template_directories_with_line_annotations
201
+ set_plugin_opts :line_comments => true,
202
+ :style => :nested,
203
+ :template_location => {
204
+ template_loc => tempfile_loc,
205
+ template_loc(nil,'more_') => tempfile_loc(nil,'more_')
206
+ }
207
+ check_for_updates!
208
+ assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_')
209
+ end
210
+
211
+ def test_doesnt_render_partials
212
+ assert !File.exist?(tempfile_loc('_partial'))
213
+ end
214
+
215
+ def test_template_location_array
216
+ assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array
217
+ end
218
+
219
+ def test_add_template_location
220
+ Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
221
+ assert_equal(
222
+ [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
223
+ Sass::Plugin.template_location_array)
224
+
225
+ touch 'more1', 'more_'
226
+ touch 'basic'
227
+ assert_needs_update "more1", "more_"
228
+ assert_needs_update "basic"
229
+ check_for_updates!
230
+ assert_doesnt_need_update "more1", "more_"
231
+ assert_doesnt_need_update "basic"
232
+ end
233
+
234
+ def test_remove_template_location
235
+ Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
236
+ Sass::Plugin.remove_template_location(template_loc, tempfile_loc)
237
+ assert_equal(
238
+ [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
239
+ Sass::Plugin.template_location_array)
240
+
241
+ touch 'more1', 'more_'
242
+ touch 'basic'
243
+ assert_needs_update "more1", "more_"
244
+ assert_needs_update "basic"
245
+ check_for_updates!
246
+ assert_doesnt_need_update "more1", "more_"
247
+ assert_needs_update "basic"
248
+ end
249
+
250
+ def test_import_same_name
251
+ assert_warning <<WARNING do
252
+ WARNING: In #{template_loc}:
253
+ There are multiple files that match the name "same_name_different_partiality.scss":
254
+ _same_name_different_partiality.scss
255
+ same_name_different_partiality.scss
256
+ WARNING
257
+ touch "_same_name_different_partiality"
258
+ assert_needs_update "same_name_different_partiality"
259
+ end
260
+ end
261
+
262
+ # Callbacks
263
+
264
+ def test_updated_stylesheet_callback_for_updated_template
265
+ Sass::Plugin.options[:always_update] = false
266
+ touch 'basic'
267
+ assert_no_callback :updated_stylesheet, template_loc("complex"), tempfile_loc("complex") do
268
+ assert_callbacks(
269
+ [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
270
+ [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
271
+ end
272
+ end
273
+
274
+ def test_updated_stylesheet_callback_for_fresh_template
275
+ Sass::Plugin.options[:always_update] = false
276
+ assert_no_callback :updated_stylesheet
277
+ end
278
+
279
+ def test_updated_stylesheet_callback_for_error_template
280
+ Sass::Plugin.options[:always_update] = false
281
+ touch 'bork1'
282
+ assert_no_callback :updated_stylesheet
283
+ end
284
+
285
+ def test_not_updating_stylesheet_callback_for_fresh_template
286
+ Sass::Plugin.options[:always_update] = false
287
+ assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic")
288
+ end
289
+
290
+ def test_not_updating_stylesheet_callback_for_updated_template
291
+ Sass::Plugin.options[:always_update] = false
292
+ assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do
293
+ assert_no_callbacks(
294
+ [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
295
+ [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
296
+ end
297
+ end
298
+
299
+ def test_not_updating_stylesheet_callback_with_never_update
300
+ Sass::Plugin.options[:never_update] = true
301
+ assert_no_callback :not_updating_stylesheet
302
+ end
303
+
304
+ def test_not_updating_stylesheet_callback_for_partial
305
+ Sass::Plugin.options[:always_update] = false
306
+ assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial")
307
+ end
308
+
309
+ def test_not_updating_stylesheet_callback_for_error
310
+ Sass::Plugin.options[:always_update] = false
311
+ touch 'bork1'
312
+ assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1")
313
+ end
314
+
315
+ def test_compilation_error_callback
316
+ Sass::Plugin.options[:always_update] = false
317
+ touch 'bork1'
318
+ assert_callback(:compilation_error,
319
+ lambda {|e| e.message == 'Undefined variable: "$bork".'},
320
+ template_loc("bork1"), tempfile_loc("bork1"))
321
+ end
322
+
323
+ def test_compilation_error_callback_for_file_access
324
+ Sass::Plugin.options[:always_update] = false
325
+ assert_callback(:compilation_error,
326
+ lambda {|e| e.is_a?(Errno::ENOENT)},
327
+ template_loc("nonexistent"), tempfile_loc("nonexistent")) do
328
+ Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]])
329
+ end
330
+ end
331
+
332
+ def test_creating_directory_callback
333
+ Sass::Plugin.options[:always_update] = false
334
+ dir = File.join(tempfile_loc, "subdir", "nested_subdir")
335
+ FileUtils.rm_r dir
336
+ assert_callback :creating_directory, dir
337
+ end
338
+
339
+ ## Regression
340
+
341
+ def test_cached_dependencies_update
342
+ FileUtils.mv(template_loc("basic"), template_loc("basic", "more_"))
343
+ set_plugin_opts :load_paths => [template_loc(nil, "more_")]
344
+
345
+ touch 'basic', 'more_'
346
+ assert_needs_update "import"
347
+ check_for_updates!
348
+ assert_renders_correctly("import")
349
+ ensure
350
+ FileUtils.mv(template_loc("basic", "more_"), template_loc("basic"))
351
+ end
352
+
353
+ def test_cached_relative_import
354
+ old_always_update = Sass::Plugin.options[:always_update]
355
+ Sass::Plugin.options[:always_update] = true
356
+ check_for_updates!
357
+ assert_renders_correctly('subdir/subdir')
358
+ ensure
359
+ Sass::Plugin.options[:always_update] = old_always_update
360
+ end
361
+
362
+ def test_cached_if
363
+ set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache')
364
+ check_for_updates!
365
+ assert_renders_correctly 'if'
366
+ check_for_updates!
367
+ assert_renders_correctly 'if'
368
+ ensure
369
+ set_plugin_opts
370
+ end
371
+
372
+ def test_cached_import_option
373
+ set_plugin_opts :custom => {:whatever => "correct"}
374
+ check_for_updates!
375
+ assert_renders_correctly "cached_import_option"
376
+
377
+ @@cache_store.reset!
378
+ set_plugin_opts :custom => nil, :always_update => false
379
+ check_for_updates!
380
+ assert_renders_correctly "cached_import_option"
381
+
382
+ set_plugin_opts :custom => {:whatever => "correct"}, :always_update => true
383
+ check_for_updates!
384
+ assert_renders_correctly "cached_import_option"
385
+ ensure
386
+ set_plugin_opts :custom => nil
387
+ end
388
+
389
+ private
390
+
391
+ def assert_renders_correctly(*arguments)
392
+ options = arguments.last.is_a?(Hash) ? arguments.pop : {}
393
+ prefix = options[:prefix]
394
+ result_name = arguments.shift
395
+ tempfile_name = arguments.shift || result_name
396
+
397
+ expected_str = File.read(result_loc(result_name, prefix))
398
+ actual_str = File.read(tempfile_loc(tempfile_name, prefix))
399
+ unless Sass::Util.ruby1_8?
400
+ expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
401
+ actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
402
+ end
403
+ expected_lines = expected_str.split("\n")
404
+ actual_lines = actual_str.split("\n")
405
+
406
+ if actual_lines.first == "/*" && expected_lines.first != "/*"
407
+ assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n"))
408
+ end
409
+
410
+ expected_lines.zip(actual_lines).each_with_index do |pair, line|
411
+ message = "template: #{result_name}\nline: #{line + 1}"
412
+ assert_equal(pair.first, pair.last, message)
413
+ end
414
+ if expected_lines.size < actual_lines.size
415
+ assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}")
416
+ end
417
+ end
418
+
419
+ def assert_stylesheet_updated(name)
420
+ assert_doesnt_need_update name
421
+
422
+ # Make sure it isn't an exception
423
+ expected_lines = File.read(result_loc(name)).split("\n")
424
+ actual_lines = File.read(tempfile_loc(name)).split("\n")
425
+ if actual_lines.first == "/*" && expected_lines.first != "/*"
426
+ assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n"))
427
+ end
428
+ end
429
+
430
+ def assert_callback(name, *expected_args)
431
+ run = false
432
+ received_args = nil
433
+ Sass::Plugin.send("on_#{name}") do |*args|
434
+ received_args = args
435
+ run ||= expected_args.zip(received_args).all? do |ea, ra|
436
+ ea.respond_to?(:call) ? ea.call(ra) : ea == ra
437
+ end
438
+ end
439
+
440
+ if block_given?
441
+ Sass::Util.silence_sass_warnings {yield}
442
+ else
443
+ check_for_updates!
444
+ end
445
+
446
+ assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}\nHowever, it got:\n #{received_args.inspect}"
447
+ end
448
+
449
+ def assert_no_callback(name, *unexpected_args)
450
+ Sass::Plugin.send("on_#{name}") do |*a|
451
+ next unless unexpected_args.empty? || a == unexpected_args
452
+
453
+ msg = "Expected #{name} callback not to be run"
454
+ if !unexpected_args.empty?
455
+ msg << " with arguments #{unexpected_args.inspect}"
456
+ elsif !a.empty?
457
+ msg << ",\n was run with arguments #{a.inspect}"
458
+ end
459
+
460
+ flunk msg
461
+ end
462
+
463
+ if block_given?
464
+ yield
465
+ else
466
+ check_for_updates!
467
+ end
468
+ end
469
+
470
+ def assert_callbacks(*args)
471
+ return check_for_updates! if args.empty?
472
+ assert_callback(*args.pop) {assert_callbacks(*args)}
473
+ end
474
+
475
+ def assert_no_callbacks(*args)
476
+ return check_for_updates! if args.empty?
477
+ assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
478
+ end
479
+
480
+ def check_for_updates!
481
+ Sass::Util.silence_sass_warnings do
482
+ Sass::Plugin.check_for_updates
483
+ end
484
+ end
485
+
486
+ def assert_needs_update(*args)
487
+ assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
488
+ "Expected #{template_loc(*args)} to need an update.")
489
+ end
490
+
491
+ def assert_doesnt_need_update(*args)
492
+ assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
493
+ "Expected #{template_loc(*args)} not to need an update.")
494
+ end
495
+
496
+ def touch(*args)
497
+ FileUtils.touch(template_loc(*args))
498
+ end
499
+
500
+ def reset_mtimes
501
+ Sass::Plugin::StalenessChecker.dependencies_cache = {}
502
+ atime = Time.now
503
+ mtime = Time.now - 5
504
+ Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
505
+ end
506
+
507
+ def template_loc(name = nil, prefix = nil)
508
+ if name
509
+ scss = absolutize "#{prefix}templates/#{name}.scss"
510
+ File.exist?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass")
511
+ else
512
+ absolutize "#{prefix}templates"
513
+ end
514
+ end
515
+
516
+ def tempfile_loc(name = nil, prefix = nil)
517
+ if name
518
+ absolutize "#{prefix}tmp/#{name}.css"
519
+ else
520
+ absolutize "#{prefix}tmp"
521
+ end
522
+ end
523
+
524
+ def result_loc(name = nil, prefix = nil)
525
+ if name
526
+ absolutize "#{prefix}results/#{name}.css"
527
+ else
528
+ absolutize "#{prefix}results"
529
+ end
530
+ end
531
+
532
+ def set_plugin_opts(overrides = {})
533
+ Sass::Plugin.options.merge!(
534
+ :template_location => template_loc,
535
+ :css_location => tempfile_loc,
536
+ :style => :compact,
537
+ :always_update => true,
538
+ :never_update => false,
539
+ :full_exception => true,
540
+ :cache_store => @@cache_store,
541
+ :sourcemap => :none
542
+ )
543
+ Sass::Plugin.options.merge!(overrides)
544
+ end
545
+ end
546
+
547
+ class Sass::Engine
548
+ alias_method :old_render, :render
549
+
550
+ def render
551
+ raise "bork bork bork!" if @template[0] == "{bork now!}"
552
+ old_render
553
+ end
554
+ end