sass 3.1.0 → 3.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 (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -0,0 +1 @@
1
+ partial {value: whatever()}
@@ -0,0 +1 @@
1
+ @import "double_import_loop1"
@@ -0,0 +1,11 @@
1
+ @mixin imported-mixin {
2
+ imported-mixin: filename();
3
+ }
4
+
5
+ @function imported-function() {
6
+ @return filename();
7
+ }
8
+
9
+ filename {
10
+ imported: filename();
11
+ }
@@ -0,0 +1,3 @@
1
+ @mixin foo
2
+ a
3
+ @content
@@ -0,0 +1 @@
1
+ .foo {partial: yes}
@@ -0,0 +1,3 @@
1
+ bork
2
+ /* foo */
3
+ :bork $bork
@@ -0,0 +1,3 @@
1
+ @import "cached_import_option_partial";
2
+
3
+ main {value: whatever()}
@@ -0,0 +1 @@
1
+ @import "double_import_loop2"
@@ -0,0 +1,18 @@
1
+ @import "filename_fn_import";
2
+
3
+ @mixin local-mixin {
4
+ local-mixin: filename();
5
+ }
6
+
7
+ @function local-function() {
8
+ @return filename();
9
+ }
10
+
11
+ filename {
12
+ local: filename();
13
+ @include local-mixin;
14
+ local-function: local-function();
15
+
16
+ @include imported-mixin;
17
+ imported-function: imported-function();
18
+ }
@@ -1,6 +1,8 @@
1
1
  .foo
2
2
  a: b
3
3
 
4
+ @import "foo.css"
5
+
4
6
  // Even though the imported file is in IBM866,
5
7
  // since the root file is in UTF-8/ASCII
6
8
  // the output will end up being UTF-8.
@@ -1,4 +1,6 @@
1
1
  .foo
2
2
  a: b
3
3
 
4
+ @import "foo.css"
5
+
4
6
  @import "imported_charset_ibm866"
@@ -3,6 +3,8 @@
3
3
  .foo
4
4
  a: b
5
5
 
6
+ @import "foo.css"
7
+
6
8
  // Even though the imported file is in UTF-8,
7
9
  // since the root file is in IBM866
8
10
  // the output will end up being IBM866.
@@ -0,0 +1,4 @@
1
+ @import imported_content
2
+
3
+ @include foo
4
+ b: c
@@ -0,0 +1,2 @@
1
+ .foo
2
+ ext: sass
@@ -0,0 +1 @@
1
+ .foo {ext: scss}
@@ -0,0 +1 @@
1
+ .foo {partial: no}
@@ -0,0 +1 @@
1
+ @import "single_import_loop"
@@ -0,0 +1 @@
1
+ @import "../subdir/import_up2.scss";
@@ -0,0 +1 @@
1
+ @import "../subdir/import_up3.scss";
@@ -3,6 +3,6 @@ $:.unshift test_dir unless $:.include?(test_dir)
3
3
 
4
4
  class Test::Unit::TestCase
5
5
  def absolutize(file)
6
- "#{File.dirname(__FILE__)}/#{file}"
6
+ File.expand_path("#{File.dirname(__FILE__)}/#{file}")
7
7
  end
8
8
  end
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/../../test_helper'
4
+
5
+ unless Sass::Util.ruby1_8?
6
+ class MultibyteStringScannerTest < Test::Unit::TestCase
7
+ def setup
8
+ @scanner = Sass::Util::MultibyteStringScanner.new("cölorfül")
9
+ end
10
+
11
+ def test_initial
12
+ assert_scanner_state 0, 0, nil, nil
13
+ end
14
+
15
+ def test_check
16
+ assert_equal 'cö', @scanner.check(/../)
17
+ assert_scanner_state 0, 0, 2, 3
18
+ assert_equal 0, @scanner.pos
19
+ assert_equal 0, @scanner.pos
20
+ assert_equal 2, @scanner.matched_size
21
+ assert_equal 3, @scanner.byte_matched_size
22
+ end
23
+
24
+ def test_check_until
25
+ assert_equal 'cölorfü', @scanner.check_until(/f./)
26
+ assert_scanner_state 0, 0, 2, 3
27
+ end
28
+
29
+ def test_getch
30
+ assert_equal 'c', @scanner.getch
31
+ assert_equal 'ö', @scanner.getch
32
+ assert_scanner_state 2, 3, 1, 2
33
+ end
34
+
35
+ def test_match?
36
+ assert_equal 2, @scanner.match?(/../)
37
+ assert_scanner_state 0, 0, 2, 3
38
+ end
39
+
40
+ def test_peek
41
+ assert_equal 'cö', @scanner.peek(2)
42
+ assert_scanner_state 0, 0, nil, nil
43
+ end
44
+
45
+ def test_rest_size
46
+ assert_equal 'cö', @scanner.scan(/../)
47
+ assert_equal 6, @scanner.rest_size
48
+ end
49
+
50
+ def test_scan
51
+ assert_equal 'cö', @scanner.scan(/../)
52
+ assert_scanner_state 2, 3, 2, 3
53
+ end
54
+
55
+ def test_scan_until
56
+ assert_equal 'cölorfü', @scanner.scan_until(/f./)
57
+ assert_scanner_state 7, 9, 2, 3
58
+ end
59
+
60
+ def test_skip
61
+ assert_equal 2, @scanner.skip(/../)
62
+ assert_scanner_state 2, 3, 2, 3
63
+ end
64
+
65
+ def test_skip_until
66
+ assert_equal 7, @scanner.skip_until(/f./)
67
+ assert_scanner_state 7, 9, 2, 3
68
+ end
69
+
70
+ def test_set_pos
71
+ @scanner.pos = 7
72
+ assert_scanner_state 7, 9, nil, nil
73
+ @scanner.pos = 6
74
+ assert_scanner_state 6, 7, nil, nil
75
+ @scanner.pos = 1
76
+ assert_scanner_state 1, 1, nil, nil
77
+ end
78
+
79
+ def test_reset
80
+ @scanner.scan(/../)
81
+ @scanner.reset
82
+ assert_scanner_state 0, 0, nil, nil
83
+ end
84
+
85
+ def test_scan_full
86
+ assert_equal 'cö', @scanner.scan_full(/../, true, true)
87
+ assert_scanner_state 2, 3, 2, 3
88
+
89
+ @scanner.reset
90
+ assert_equal 'cö', @scanner.scan_full(/../, false, true)
91
+ assert_scanner_state 0, 0, 2, 3
92
+
93
+ @scanner.reset
94
+ assert_nil @scanner.scan_full(/../, true, false)
95
+ assert_scanner_state 2, 3, 2, 3
96
+
97
+ @scanner.reset
98
+ assert_nil @scanner.scan_full(/../, false, false)
99
+ assert_scanner_state 0, 0, 2, 3
100
+ end
101
+
102
+ def test_search_full
103
+ assert_equal 'cölorfü', @scanner.search_full(/f./, true, true)
104
+ assert_scanner_state 7, 9, 2, 3
105
+
106
+ @scanner.reset
107
+ assert_equal 'cölorfü', @scanner.search_full(/f./, false, true)
108
+ assert_scanner_state 0, 0, 2, 3
109
+
110
+ @scanner.reset
111
+ assert_nil @scanner.search_full(/f./, true, false)
112
+ assert_scanner_state 7, 9, 2, 3
113
+
114
+ @scanner.reset
115
+ assert_nil @scanner.search_full(/f./, false, false)
116
+ assert_scanner_state 0, 0, 2, 3
117
+ end
118
+
119
+ def test_set_string
120
+ @scanner.scan(/../)
121
+ @scanner.string = 'föóbâr'
122
+ assert_scanner_state 0, 0, nil, nil
123
+ end
124
+
125
+ def test_terminate
126
+ @scanner.scan(/../)
127
+ @scanner.terminate
128
+ assert_scanner_state 8, 10, nil, nil
129
+ end
130
+
131
+ def test_unscan
132
+ @scanner.scan(/../)
133
+ @scanner.scan_until(/f./)
134
+ @scanner.unscan
135
+ assert_scanner_state 2, 3, nil, nil
136
+ end
137
+
138
+ private
139
+
140
+ def assert_scanner_state(pos, byte_pos, matched_size, byte_matched_size)
141
+ assert_equal pos, @scanner.pos, 'pos'
142
+ assert_equal byte_pos, @scanner.byte_pos, 'byte_pos'
143
+ assert_equal matched_size, @scanner.matched_size, 'matched_size'
144
+ assert_equal byte_matched_size, @scanner.byte_matched_size, 'byte_matched_size'
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../test_helper'
3
+ require 'sass/util/normalized_map'
4
+
5
+ class NormalizedMapTest < Test::Unit::TestCase
6
+ extend PublicApiLinter
7
+
8
+ lint_api Hash, Sass::Util::NormalizedMap
9
+
10
+ def lint_instance
11
+ Sass::Util::NormalizedMap.new
12
+ end
13
+
14
+ def test_normalized_map_errors_unless_explicitly_implemented
15
+ assert Sass.tests_running
16
+ assert_raise_message(ArgumentError, "The method invert must be implemented explicitly") do
17
+ Sass::Util::NormalizedMap.new.invert
18
+ end
19
+ end
20
+
21
+ def test_normalized_map_does_not_error_when_released
22
+ Sass.tests_running = false
23
+ assert_equal({}, Sass::Util::NormalizedMap.new.invert)
24
+ ensure
25
+ Sass.tests_running = true
26
+ end
27
+
28
+ def test_basic_lifecycle
29
+ m = Sass::Util::NormalizedMap.new
30
+ m["a-b"] = 1
31
+ assert_equal ["a_b"], m.keys
32
+ assert_equal 1, m["a_b"]
33
+ assert_equal 1, m["a-b"]
34
+ assert m.has_key?("a_b")
35
+ assert m.has_key?("a-b")
36
+ assert_equal({"a-b" => 1}, m.as_stored)
37
+ assert_equal 1, m.delete("a-b")
38
+ assert !m.has_key?("a-b")
39
+ m["a_b"] = 2
40
+ assert_equal({"a_b" => 2}, m.as_stored)
41
+ end
42
+
43
+ def test_dup
44
+ m = Sass::Util::NormalizedMap.new
45
+ m["a-b"] = 1
46
+ m2 = m.dup
47
+ m.delete("a-b")
48
+ assert !m.has_key?("a-b")
49
+ assert m2.has_key?("a-b")
50
+ end
51
+ end
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require File.dirname(__FILE__) + '/../test_helper'
3
3
  require 'pathname'
4
+ require 'tmpdir'
4
5
 
5
6
  class UtilTest < Test::Unit::TestCase
6
7
  include Sass::Util
@@ -41,6 +42,15 @@ class UtilTest < Test::Unit::TestCase
41
42
  }, map_hash({:foo => 1, :bar => 2, :baz => 3}) {|k, v| [k.to_s, v.to_s]})
42
43
  end
43
44
 
45
+ def test_map_hash_with_normalized_map
46
+ map = NormalizedMap.new("foo-bar" => 1, "baz_bang" => 2)
47
+ result = map_hash(map) {|k, v| [k, v.to_s]}
48
+ assert_equal("1", result["foo-bar"])
49
+ assert_equal("1", result["foo_bar"])
50
+ assert_equal("2", result["baz-bang"])
51
+ assert_equal("2", result["baz_bang"])
52
+ end
53
+
44
54
  def test_powerset
45
55
  return unless Set[Set[]] == Set[Set[]] # There's a bug in Ruby 1.8.6 that breaks nested set equality
46
56
  assert_equal([[].to_set].to_set,
@@ -120,6 +130,23 @@ class UtilTest < Test::Unit::TestCase
120
130
  lcs([-5, 3, 2, 8], [-4, 1, 8]) {|a, b| (a - b).abs <= 1 && [a, b].max})
121
131
  end
122
132
 
133
+ def test_group_by_to_a
134
+ assert_equal([[1, [1, 3, 5, 7]], [0, [2, 4, 6, 8]]],
135
+ group_by_to_a(1..8) {|i| i % 2})
136
+ assert_equal([[1, [1, 4, 7, 10]], [2, [2, 5, 8, 11]], [0, [3, 6, 9, 12]]],
137
+ group_by_to_a(1..12) {|i| i % 3})
138
+ end
139
+
140
+ def test_subsequence
141
+ assert(subsequence?([1, 2, 3], [1, 2, 3]))
142
+ assert(subsequence?([1, 2, 3], [1, :a, 2, :b, 3]))
143
+ assert(subsequence?([1, 2, 3], [:a, 1, :b, :c, 2, :d, 3, :e, :f]))
144
+
145
+ assert(!subsequence?([1, 2, 3], [1, 2]))
146
+ assert(!subsequence?([1, 2, 3], [1, 3, 2]))
147
+ assert(!subsequence?([1, 2, 3], [3, 2, 1]))
148
+ end
149
+
123
150
  def test_silence_warnings
124
151
  old_stderr, $stderr = $stderr, StringIO.new
125
152
  warn "Out"
@@ -159,6 +186,12 @@ class UtilTest < Test::Unit::TestCase
159
186
  enum_cons(%w[foo bar baz], 2).map {|s1, s2| "#{s1}#{s2}"})
160
187
  end
161
188
 
189
+ def test_extract
190
+ arr = [1, 2, 3, 4, 5]
191
+ assert_equal([1, 3, 5], extract!(arr) {|e| e % 2 == 1})
192
+ assert_equal([2, 4], arr)
193
+ end
194
+
162
195
  def test_ord
163
196
  assert_equal(102, ord("f"))
164
197
  assert_equal(98, ord("bar"))
@@ -178,6 +211,13 @@ class UtilTest < Test::Unit::TestCase
178
211
  assert_equal([1, 2, 3, 4], flatten([[[1], 2], [3], 4], 2))
179
212
  end
180
213
 
214
+ def test_flatten_vertically
215
+ assert_equal([1, 2, 3], flatten_vertically([1, 2, 3]))
216
+ assert_equal([1, 3, 5, 2, 4, 6], flatten_vertically([[1, 2], [3, 4], [5, 6]]))
217
+ assert_equal([1, 2, 4, 3, 5, 6], flatten_vertically([1, [2, 3], [4, 5, 6]]))
218
+ assert_equal([1, 4, 6, 2, 5, 3], flatten_vertically([[1, 2, 3], [4, 5], 6]))
219
+ end
220
+
181
221
  def test_set_hash
182
222
  assert(set_hash(Set[1, 2, 3]) == set_hash(Set[3, 2, 1]))
183
223
  assert(set_hash(Set[1, 2, 3]) == set_hash(Set[1, 2, 3]))
@@ -208,6 +248,26 @@ class UtilTest < Test::Unit::TestCase
208
248
  assert(set_eql?(s1, s2))
209
249
  end
210
250
 
251
+ def test_extract_and_inject_values
252
+ test = lambda {|arr| assert_equal(arr, with_extracted_values(arr) {|str| str})}
253
+
254
+ test[['foo bar']]
255
+ test[['foo {12} bar']]
256
+ test[['foo {{12} bar']]
257
+ test[['foo {{1', 12, '2} bar']]
258
+ test[['foo 1', 2, '{3', 4, 5, 6, '{7}', 8]]
259
+ test[['foo 1', [2, 3, 4], ' bar']]
260
+ test[['foo ', 1, "\n bar\n", [2, 3, 4], "\n baz"]]
261
+ end
262
+
263
+ def nested_caller_info_fn
264
+ caller_info
265
+ end
266
+
267
+ def double_nested_caller_info_fn
268
+ nested_caller_info_fn
269
+ end
270
+
211
271
  def test_caller_info
212
272
  assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle'"))
213
273
  assert_equal(["/tmp/foo.rb", 12, nil], caller_info("/tmp/foo.rb:12"))
@@ -215,6 +275,22 @@ class UtilTest < Test::Unit::TestCase
215
275
  assert_equal(["", 12, "boop"], caller_info(":12: in `boop'"))
216
276
  assert_equal(["/tmp/foo.rb", -12, "fizzle"], caller_info("/tmp/foo.rb:-12: in `fizzle'"))
217
277
  assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle {}'"))
278
+
279
+ info = nested_caller_info_fn
280
+ assert_equal(__FILE__, info[0])
281
+ assert_equal("test_caller_info", info[2])
282
+
283
+ info = proc {nested_caller_info_fn}.call
284
+ assert_equal(__FILE__, info[0])
285
+ assert_match(/^(block in )?test_caller_info$/, info[2])
286
+
287
+ info = double_nested_caller_info_fn
288
+ assert_equal(__FILE__, info[0])
289
+ assert_equal("double_nested_caller_info_fn", info[2])
290
+
291
+ info = proc {double_nested_caller_info_fn}.call
292
+ assert_equal(__FILE__, info[0])
293
+ assert_equal("double_nested_caller_info_fn", info[2])
218
294
  end
219
295
 
220
296
  def test_version_gt
@@ -244,6 +320,15 @@ class UtilTest < Test::Unit::TestCase
244
320
  def foo
245
321
  Sass::Util.abstract(self)
246
322
  end
323
+ def old_method
324
+ Sass::Util.deprecated(self)
325
+ end
326
+ def old_method_with_custom_message
327
+ Sass::Util.deprecated(self, "Call FooBar#new_method instead.")
328
+ end
329
+ def self.another_old_method
330
+ Sass::Util.deprecated(self)
331
+ end
247
332
  end
248
333
 
249
334
  def test_abstract
@@ -251,4 +336,102 @@ class UtilTest < Test::Unit::TestCase
251
336
  "UtilTest::FooBar must implement #foo") {FooBar.new.foo}
252
337
  end
253
338
 
339
+ def test_deprecated
340
+ assert_warning("DEPRECATION WARNING: UtilTest::FooBar#old_method will be removed in a future version of Sass.") { FooBar.new.old_method }
341
+ assert_warning(<<WARNING) { FooBar.new.old_method_with_custom_message }
342
+ DEPRECATION WARNING: UtilTest::FooBar#old_method_with_custom_message will be removed in a future version of Sass.
343
+ Call FooBar#new_method instead.
344
+ WARNING
345
+ assert_warning("DEPRECATION WARNING: UtilTest::FooBar.another_old_method will be removed in a future version of Sass.") { FooBar.another_old_method }
346
+ end
347
+
348
+ def test_json_escape_string
349
+ assert_json_string "", ""
350
+ alphanum = (("0".."9").to_a).concat(("a".."z").to_a).concat(("A".."Z").to_a).join
351
+ assert_json_string alphanum, alphanum
352
+ assert_json_string "'\"\\'", "'\\\"\\\\'"
353
+ assert_json_string "\b\f\n\r\t", "\\b\\f\\n\\r\\t"
354
+ end
355
+
356
+ def assert_json_string(source, target)
357
+ assert_equal target, json_escape_string(source)
358
+ end
359
+
360
+ def test_json_value_of
361
+ assert_json_value 0, "0"
362
+ assert_json_value(-42, "-42")
363
+ assert_json_value 42, "42"
364
+ assert_json_value true, "true"
365
+ assert_json_value false, "false"
366
+ assert_json_value "", "\"\""
367
+ assert_json_value "\"\"", "\"\\\"\\\"\""
368
+ assert_json_value "Multi\nLine\rString", "\"Multi\\nLine\\rString\""
369
+ assert_json_value [1, "some\nstr,ing", false, nil], "[1,\"some\\nstr,ing\",false,null]"
370
+ end
371
+
372
+ def assert_json_value(source, target)
373
+ assert_equal target, json_value_of(source)
374
+ end
375
+
376
+ def test_vlq
377
+ assert_equal "A", encode_vlq(0)
378
+ assert_equal "e", encode_vlq(15)
379
+ assert_equal "gB", encode_vlq(16)
380
+ assert_equal "wH", encode_vlq(120)
381
+ end
382
+
383
+ def assert_vlq_encodes(int, vlq)
384
+ vlq_from_decimal_array = decimal_array.map {|d| encode_vlq(d)}.join
385
+ decimal_array_from_vlq = decode_vlq(vlq)
386
+ assert_equal vlq, vlq_from_decimal_array
387
+ assert_equal decimal_array, decimal_array_from_vlq
388
+ end
389
+
390
+ def test_atomic_writes
391
+ # when using normal writes, this test fails about 90% of the time.
392
+ filename = File.join(Dir.tmpdir, "test_atomic")
393
+ 5.times do
394
+ writes_to_perform = %w(1 2 3 4 5 6 7 8 9).map {|i| "#{i}\n" * 100_000}
395
+ threads = writes_to_perform.map do |to_write|
396
+ Thread.new do
397
+ # To see this test fail with a normal write,
398
+ # change to the standard file open mechanism:
399
+ # open(filename, "w") do |f|
400
+ atomic_create_and_write_file(filename) do |f|
401
+ f.write(to_write)
402
+ end
403
+ end
404
+ end
405
+ loop do
406
+ contents = File.exist?(filename) ? File.read(filename) : nil
407
+ next if contents.nil? || contents.size == 0
408
+ unless writes_to_perform.include?(contents)
409
+ if contents.size != writes_to_perform.first.size
410
+ fail "Incomplete write detected: was #{contents.size} characters, " +
411
+ "should have been #{writes_to_perform.first.size}"
412
+ else
413
+ fail "Corrupted read/write detected"
414
+ end
415
+ end
416
+ break if threads.all? {|t| !t.alive?}
417
+ end
418
+ threads.each {|t| t.join}
419
+ end
420
+ end
421
+
422
+ class FakeError < RuntimeError; end
423
+
424
+ def test_atomic_writes_handles_exceptions
425
+ filename = File.join(Dir.tmpdir, "test_atomic_exception")
426
+ FileUtils.rm_f(filename)
427
+ tmp_filename = nil
428
+ assert_raises FakeError do
429
+ atomic_create_and_write_file(filename) do |f|
430
+ tmp_filename = f.path
431
+ raise FakeError.new "Borken"
432
+ end
433
+ end
434
+ assert !File.exist?(filename)
435
+ assert !File.exist?(tmp_filename)
436
+ end
254
437
  end