sass 3.6.0 → 3.7.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 (138) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTING.md +1 -1
  3. data/README.md +10 -0
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/lib/sass/script/css_parser.rb +4 -1
  7. data/lib/sass/script/functions.rb +15 -25
  8. data/lib/sass/script/lexer.rb +45 -7
  9. data/lib/sass/script/parser.rb +259 -93
  10. data/lib/sass/scss/parser.rb +43 -16
  11. data/lib/sass/scss/static_parser.rb +15 -15
  12. data/lib/sass/util.rb +31 -0
  13. metadata +8 -156
  14. data/Rakefile +0 -364
  15. data/test/sass-spec.yml +0 -3
  16. data/test/sass/cache_test.rb +0 -130
  17. data/test/sass/callbacks_test.rb +0 -60
  18. data/test/sass/compiler_test.rb +0 -225
  19. data/test/sass/conversion_test.rb +0 -2138
  20. data/test/sass/css2sass_test.rb +0 -523
  21. data/test/sass/css_variable_test.rb +0 -237
  22. data/test/sass/data/hsl-rgb.txt +0 -319
  23. data/test/sass/encoding_test.rb +0 -188
  24. data/test/sass/engine_test.rb +0 -3499
  25. data/test/sass/exec_test.rb +0 -95
  26. data/test/sass/extend_test.rb +0 -1679
  27. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  28. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  29. data/test/sass/functions_test.rb +0 -2021
  30. data/test/sass/importer_test.rb +0 -420
  31. data/test/sass/logger_test.rb +0 -57
  32. data/test/sass/mock_importer.rb +0 -49
  33. data/test/sass/more_results/more1.css +0 -9
  34. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  35. data/test/sass/more_results/more_import.css +0 -29
  36. data/test/sass/more_templates/_more_partial.sass +0 -2
  37. data/test/sass/more_templates/more1.sass +0 -23
  38. data/test/sass/more_templates/more_import.sass +0 -11
  39. data/test/sass/plugin_test.rb +0 -552
  40. data/test/sass/results/alt.css +0 -4
  41. data/test/sass/results/basic.css +0 -9
  42. data/test/sass/results/cached_import_option.css +0 -3
  43. data/test/sass/results/compact.css +0 -5
  44. data/test/sass/results/complex.css +0 -86
  45. data/test/sass/results/compressed.css +0 -1
  46. data/test/sass/results/expanded.css +0 -19
  47. data/test/sass/results/filename_fn.css +0 -3
  48. data/test/sass/results/if.css +0 -3
  49. data/test/sass/results/import.css +0 -31
  50. data/test/sass/results/import_charset.css +0 -5
  51. data/test/sass/results/import_charset_ibm866.css +0 -5
  52. data/test/sass/results/import_content.css +0 -1
  53. data/test/sass/results/line_numbers.css +0 -49
  54. data/test/sass/results/mixins.css +0 -95
  55. data/test/sass/results/multiline.css +0 -24
  56. data/test/sass/results/nested.css +0 -22
  57. data/test/sass/results/options.css +0 -1
  58. data/test/sass/results/parent_ref.css +0 -13
  59. data/test/sass/results/script.css +0 -16
  60. data/test/sass/results/scss_import.css +0 -31
  61. data/test/sass/results/scss_importee.css +0 -2
  62. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  63. data/test/sass/results/subdir/subdir.css +0 -3
  64. data/test/sass/results/units.css +0 -11
  65. data/test/sass/results/warn.css +0 -0
  66. data/test/sass/results/warn_imported.css +0 -0
  67. data/test/sass/script_conversion_test.rb +0 -365
  68. data/test/sass/script_test.rb +0 -1427
  69. data/test/sass/scss/css_test.rb +0 -1266
  70. data/test/sass/scss/rx_test.rb +0 -159
  71. data/test/sass/scss/scss_test.rb +0 -4238
  72. data/test/sass/scss/test_helper.rb +0 -37
  73. data/test/sass/source_map_test.rb +0 -1063
  74. data/test/sass/superselector_test.rb +0 -209
  75. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  76. data/test/sass/templates/_double_import_loop2.sass +0 -1
  77. data/test/sass/templates/_filename_fn_import.scss +0 -11
  78. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  79. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  80. data/test/sass/templates/_imported_content.sass +0 -3
  81. data/test/sass/templates/_partial.sass +0 -2
  82. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  83. data/test/sass/templates/alt.sass +0 -16
  84. data/test/sass/templates/basic.sass +0 -23
  85. data/test/sass/templates/bork1.sass +0 -2
  86. data/test/sass/templates/bork2.sass +0 -2
  87. data/test/sass/templates/bork3.sass +0 -2
  88. data/test/sass/templates/bork4.sass +0 -2
  89. data/test/sass/templates/bork5.sass +0 -3
  90. data/test/sass/templates/cached_import_option.scss +0 -3
  91. data/test/sass/templates/compact.sass +0 -17
  92. data/test/sass/templates/complex.sass +0 -305
  93. data/test/sass/templates/compressed.sass +0 -15
  94. data/test/sass/templates/double_import_loop1.sass +0 -1
  95. data/test/sass/templates/expanded.sass +0 -17
  96. data/test/sass/templates/filename_fn.scss +0 -18
  97. data/test/sass/templates/if.sass +0 -11
  98. data/test/sass/templates/import.sass +0 -12
  99. data/test/sass/templates/import_charset.sass +0 -9
  100. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  101. data/test/sass/templates/import_content.sass +0 -4
  102. data/test/sass/templates/importee.less +0 -2
  103. data/test/sass/templates/importee.sass +0 -19
  104. data/test/sass/templates/line_numbers.sass +0 -13
  105. data/test/sass/templates/mixin_bork.sass +0 -5
  106. data/test/sass/templates/mixins.sass +0 -76
  107. data/test/sass/templates/multiline.sass +0 -20
  108. data/test/sass/templates/nested.sass +0 -25
  109. data/test/sass/templates/nested_bork1.sass +0 -2
  110. data/test/sass/templates/nested_bork2.sass +0 -2
  111. data/test/sass/templates/nested_bork3.sass +0 -2
  112. data/test/sass/templates/nested_bork4.sass +0 -2
  113. data/test/sass/templates/nested_import.sass +0 -2
  114. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  115. data/test/sass/templates/options.sass +0 -2
  116. data/test/sass/templates/parent_ref.sass +0 -25
  117. data/test/sass/templates/same_name_different_ext.sass +0 -2
  118. data/test/sass/templates/same_name_different_ext.scss +0 -1
  119. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  120. data/test/sass/templates/script.sass +0 -101
  121. data/test/sass/templates/scss_import.scss +0 -12
  122. data/test/sass/templates/scss_importee.scss +0 -1
  123. data/test/sass/templates/single_import_loop.sass +0 -1
  124. data/test/sass/templates/subdir/import_up1.scss +0 -1
  125. data/test/sass/templates/subdir/import_up2.scss +0 -1
  126. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  127. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  128. data/test/sass/templates/subdir/subdir.sass +0 -6
  129. data/test/sass/templates/units.sass +0 -11
  130. data/test/sass/templates/warn.sass +0 -3
  131. data/test/sass/templates/warn_imported.sass +0 -4
  132. data/test/sass/test_helper.rb +0 -8
  133. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  134. data/test/sass/util/normalized_map_test.rb +0 -50
  135. data/test/sass/util/subset_map_test.rb +0 -90
  136. data/test/sass/util_test.rb +0 -393
  137. data/test/sass/value_helpers_test.rb +0 -178
  138. data/test/test_helper.rb +0 -149
@@ -1,12 +0,0 @@
1
- $preconst: hello;
2
-
3
- @mixin premixin {pre-mixin: here}
4
-
5
- @import "importee.sass", "scss_importee", "basic.sass", "basic.css", "../results/complex.css";
6
- @import "part\
7
- ial.sass";
8
-
9
- nonimported {
10
- myconst: $preconst;
11
- otherconst: $postconst;
12
- @include postmixin; }
@@ -1 +0,0 @@
1
- scss {imported: yes}
@@ -1 +0,0 @@
1
- @import "single_import_loop"
@@ -1 +0,0 @@
1
- @import "../subdir/import_up2.scss";
@@ -1 +0,0 @@
1
- @import "../subdir/import_up3.scss";
@@ -1,2 +0,0 @@
1
- #nested
2
- relative: true
@@ -1,6 +0,0 @@
1
- @import nested_subdir/nested_partial.sass
2
-
3
- #subdir
4
- font:
5
- size: 20px
6
- weight: bold
@@ -1,11 +0,0 @@
1
- b
2
- foo: 0.5 * 10px
3
- bar: 10zzz * 12px / 5zzz
4
- baz: percentage(12.0px / 18px)
5
- many-units: 10.0zzz / 3yyy * 12px / 5zzz * 3yyy / 3px * 4em
6
- mm: 5mm + 1cm
7
- pc: 1pc + 12pt
8
- pt: 72pt - 2in
9
- inches: 1in + 2.54cm
10
- more-inches: 1in + ((72pt * 2in) + (36pt * 1in)) / 2.54cm
11
- mixed: (1 + (1em * 6px / 3in)) * 4in / 2em
@@ -1,3 +0,0 @@
1
- @warn "In the main file"
2
- @import warn_imported.sass
3
- +emits-a-warning
@@ -1,4 +0,0 @@
1
- @warn "Imported"
2
-
3
- =emits-a-warning
4
- @warn "In an imported mixin"
@@ -1,8 +0,0 @@
1
- test_dir = File.dirname(__FILE__)
2
- $:.unshift test_dir unless $:.include?(test_dir)
3
-
4
- class MiniTest::Test
5
- def absolutize(file)
6
- File.expand_path("#{File.dirname(__FILE__)}/#{file}")
7
- end
8
- end
@@ -1,152 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../test_helper'
3
-
4
- class MultibyteStringScannerTest < MiniTest::Test
5
- def setup
6
- @scanner = Sass::Util::MultibyteStringScanner.new("cölorfül")
7
- end
8
-
9
- def test_initial
10
- assert_scanner_state 0, 0, nil, nil
11
- end
12
-
13
- def test_check
14
- assert_equal 'cö', @scanner.check(/../)
15
- assert_scanner_state 0, 0, 2, 3
16
- assert_equal 0, @scanner.pos
17
- assert_equal 0, @scanner.pos
18
- assert_equal 2, @scanner.matched_size
19
- assert_equal 3, @scanner.byte_matched_size
20
- end
21
-
22
- def test_check_until
23
- assert_equal 'cölorfü', @scanner.check_until(/f./)
24
- assert_scanner_state 0, 0, 2, 3
25
- end
26
-
27
- def test_getch
28
- assert_equal 'c', @scanner.getch
29
- assert_equal 'ö', @scanner.getch
30
- assert_scanner_state 2, 3, 1, 2
31
- end
32
-
33
- def test_match?
34
- assert_equal 2, @scanner.match?(/../)
35
- assert_scanner_state 0, 0, 2, 3
36
- end
37
-
38
- def test_peek
39
- assert_equal 'cö', @scanner.peek(2)
40
- assert_scanner_state 0, 0, nil, nil
41
- end
42
-
43
- def test_rest_size
44
- assert_equal 'cö', @scanner.scan(/../)
45
- assert_equal 6, @scanner.rest_size
46
- end
47
-
48
- def test_scan
49
- assert_equal 'cö', @scanner.scan(/../)
50
- assert_scanner_state 2, 3, 2, 3
51
- end
52
-
53
- def test_scan_until
54
- assert_equal 'cölorfü', @scanner.scan_until(/f./)
55
- assert_scanner_state 7, 9, 2, 3
56
- end
57
-
58
- def test_skip
59
- assert_equal 2, @scanner.skip(/../)
60
- assert_scanner_state 2, 3, 2, 3
61
- end
62
-
63
- def test_skip_until
64
- assert_equal 7, @scanner.skip_until(/f./)
65
- assert_scanner_state 7, 9, 2, 3
66
- end
67
-
68
- def test_set_pos
69
- @scanner.pos = 7
70
- assert_scanner_state 7, 9, nil, nil
71
- @scanner.pos = 6
72
- assert_scanner_state 6, 7, nil, nil
73
- @scanner.pos = 1
74
- assert_scanner_state 1, 1, nil, nil
75
- end
76
-
77
- def test_reset
78
- @scanner.scan(/../)
79
- @scanner.reset
80
- assert_scanner_state 0, 0, nil, nil
81
- end
82
-
83
- def test_scan_full
84
- assert_equal 'cö', @scanner.scan_full(/../, true, true)
85
- assert_scanner_state 2, 3, 2, 3
86
-
87
- @scanner.reset
88
- assert_equal 'cö', @scanner.scan_full(/../, false, true)
89
- assert_scanner_state 0, 0, 2, 3
90
-
91
- @scanner.reset
92
- assert_nil @scanner.scan_full(/../, true, false)
93
- assert_scanner_state 2, 3, 2, 3
94
-
95
- @scanner.reset
96
- assert_nil @scanner.scan_full(/../, false, false)
97
- assert_scanner_state 0, 0, 2, 3
98
- end
99
-
100
- def test_search_full
101
- assert_equal 'cölorfü', @scanner.search_full(/f./, true, true)
102
- assert_scanner_state 7, 9, 2, 3
103
-
104
- @scanner.reset
105
- assert_equal 'cölorfü', @scanner.search_full(/f./, false, true)
106
- assert_scanner_state 0, 0, 2, 3
107
-
108
- @scanner.reset
109
- assert_nil @scanner.search_full(/f./, true, false)
110
- assert_scanner_state 7, 9, 2, 3
111
-
112
- @scanner.reset
113
- assert_nil @scanner.search_full(/f./, false, false)
114
- assert_scanner_state 0, 0, 2, 3
115
- end
116
-
117
- def test_set_string
118
- @scanner.scan(/../)
119
- @scanner.string = 'föóbâr'
120
- assert_scanner_state 0, 0, nil, nil
121
- end
122
-
123
- def test_terminate
124
- @scanner.scan(/../)
125
- @scanner.terminate
126
- assert_scanner_state 8, 10, nil, nil
127
- end
128
-
129
- def test_unscan
130
- @scanner.scan(/../)
131
- @scanner.scan_until(/f./)
132
- @scanner.unscan
133
- assert_scanner_state 2, 3, nil, nil
134
- end
135
-
136
- private
137
-
138
- def assert_scanner_state(pos, byte_pos, matched_size, byte_matched_size)
139
- assert_equal pos, @scanner.pos, 'pos'
140
- assert_equal byte_pos, @scanner.byte_pos, 'byte_pos'
141
- if matched_size.nil?
142
- assert_nil @scanner.matched_size, 'matched_size'
143
- else
144
- assert_equal matched_size, @scanner.matched_size, 'matched_size'
145
- end
146
- if byte_matched_size.nil?
147
- assert_nil @scanner.byte_matched_size, 'byte_matched_size'
148
- else
149
- assert_equal byte_matched_size, @scanner.byte_matched_size, 'byte_matched_size'
150
- end
151
- end
152
- end
@@ -1,50 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../test_helper'
2
- require 'sass/util/normalized_map'
3
-
4
- class NormalizedMapTest < MiniTest::Test
5
- extend PublicApiLinter
6
-
7
- lint_api Hash, Sass::Util::NormalizedMap
8
-
9
- def lint_instance
10
- Sass::Util::NormalizedMap.new
11
- end
12
-
13
- def test_normalized_map_errors_unless_explicitly_implemented
14
- assert Sass.tests_running
15
- assert_raise_message(ArgumentError, "The method invert must be implemented explicitly") do
16
- Sass::Util::NormalizedMap.new.invert
17
- end
18
- end
19
-
20
- def test_normalized_map_does_not_error_when_released
21
- Sass.tests_running = false
22
- assert_equal({}, Sass::Util::NormalizedMap.new.invert)
23
- ensure
24
- Sass.tests_running = true
25
- end
26
-
27
- def test_basic_lifecycle
28
- m = Sass::Util::NormalizedMap.new
29
- m["a-b"] = 1
30
- assert_equal ["a_b"], m.keys
31
- assert_equal 1, m["a_b"]
32
- assert_equal 1, m["a-b"]
33
- assert m.has_key?("a_b")
34
- assert m.has_key?("a-b")
35
- assert_equal({"a-b" => 1}, m.as_stored)
36
- assert_equal 1, m.delete("a-b")
37
- assert !m.has_key?("a-b")
38
- m["a_b"] = 2
39
- assert_equal({"a_b" => 2}, m.as_stored)
40
- end
41
-
42
- def test_dup
43
- m = Sass::Util::NormalizedMap.new
44
- m["a-b"] = 1
45
- m2 = m.dup
46
- m.delete("a-b")
47
- assert !m.has_key?("a-b")
48
- assert m2.has_key?("a-b")
49
- end
50
- end
@@ -1,90 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../test_helper'
2
-
3
- class SubsetMapTest < MiniTest::Test
4
- def setup
5
- @ssm = Sass::Util::SubsetMap.new
6
- @ssm[Set[1, 2]] = "Foo"
7
- @ssm[Set["fizz", "fazz"]] = "Bar"
8
-
9
- @ssm[Set[:foo, :bar]] = "Baz"
10
- @ssm[Set[:foo, :bar, :baz]] = "Bang"
11
-
12
- @ssm[Set[:bip, :bop, :blip]] = "Qux"
13
- @ssm[Set[:bip, :bop]] = "Thram"
14
- end
15
-
16
- def test_equal_keys
17
- assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2])
18
- assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"])
19
- end
20
-
21
- def test_subset_keys
22
- assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"])
23
- assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3])
24
- end
25
-
26
- def test_superset_keys
27
- assert_equal [], @ssm.get(Set[1])
28
- assert_equal [], @ssm.get(Set[2])
29
- assert_equal [], @ssm.get(Set["fizz"])
30
- assert_equal [], @ssm.get(Set["fazz"])
31
- end
32
-
33
- def test_disjoint_keys
34
- assert_equal [], @ssm.get(Set[3, 4])
35
- assert_equal [], @ssm.get(Set["fuzz", "frizz"])
36
- assert_equal [], @ssm.get(Set["gran", 15])
37
- end
38
-
39
- def test_semi_disjoint_keys
40
- assert_equal [], @ssm.get(Set[2, 3])
41
- assert_equal [], @ssm.get(Set["fizz", "fuzz"])
42
- assert_equal [], @ssm.get(Set[1, "fazz"])
43
- end
44
-
45
- def test_empty_key_set
46
- assert_raises(ArgumentError) {@ssm[Set[]] = "Fail"}
47
- end
48
-
49
- def test_empty_key_get
50
- assert_equal [], @ssm.get(Set[])
51
- end
52
-
53
- def test_multiple_subsets
54
- assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"])
55
- assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", "fuzz"])
56
-
57
- assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar])
58
- assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz])
59
- end
60
-
61
- def test_bracket_bracket
62
- assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]]
63
- assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]]
64
- end
65
-
66
- def test_order_preserved
67
- @ssm[Set[10, 11, 12]] = 1
68
- @ssm[Set[10, 11]] = 2
69
- @ssm[Set[11]] = 3
70
- @ssm[Set[11, 12]] = 4
71
- @ssm[Set[9, 10, 11, 12, 13]] = 5
72
- @ssm[Set[10, 13]] = 6
73
-
74
- assert_equal(
75
- [[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]],
76
- [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]],
77
- @ssm.get(Set[9, 10, 11, 12, 13]))
78
- end
79
-
80
- def test_multiple_equal_values
81
- @ssm[Set[11, 12]] = 1
82
- @ssm[Set[12, 13]] = 2
83
- @ssm[Set[13, 14]] = 1
84
- @ssm[Set[14, 15]] = 1
85
-
86
- assert_equal(
87
- [[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]],
88
- @ssm.get(Set[11, 12, 13, 14, 15]))
89
- end
90
- end
@@ -1,393 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
- require 'pathname'
3
- require 'tmpdir'
4
-
5
- class UtilTest < MiniTest::Test
6
- include Sass::Util
7
-
8
- def test_scope
9
- assert(File.exist?(scope("Rakefile")))
10
- end
11
-
12
- def test_map_keys
13
- assert_equal({
14
- "foo" => 1,
15
- "bar" => 2,
16
- "baz" => 3
17
- }, map_keys({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
18
- end
19
-
20
- def test_map_vals
21
- assert_equal({
22
- :foo => "1",
23
- :bar => "2",
24
- :baz => "3"
25
- }, map_vals({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
26
- end
27
-
28
- def test_map_hash
29
- assert_equal({
30
- "foo" => "1",
31
- "bar" => "2",
32
- "baz" => "3"
33
- }, map_hash({:foo => 1, :bar => 2, :baz => 3}) {|k, v| [k.to_s, v.to_s]})
34
- end
35
-
36
- def test_map_hash_with_normalized_map
37
- map = NormalizedMap.new("foo-bar" => 1, "baz_bang" => 2)
38
- result = map_hash(map) {|k, v| [k, v.to_s]}
39
- assert_equal("1", result["foo-bar"])
40
- assert_equal("1", result["foo_bar"])
41
- assert_equal("2", result["baz-bang"])
42
- assert_equal("2", result["baz_bang"])
43
- end
44
-
45
- def test_powerset
46
- assert_equal([[].to_set].to_set,
47
- powerset([]))
48
- assert_equal([[].to_set, [1].to_set].to_set,
49
- powerset([1]))
50
- assert_equal([[].to_set, [1].to_set, [2].to_set, [1, 2].to_set].to_set,
51
- powerset([1, 2]))
52
- assert_equal([[].to_set, [1].to_set, [2].to_set, [3].to_set,
53
- [1, 2].to_set, [2, 3].to_set, [1, 3].to_set, [1, 2, 3].to_set].to_set,
54
- powerset([1, 2, 3]))
55
- end
56
-
57
- def test_restrict
58
- assert_equal(0.5, restrict(0.5, 0..1))
59
- assert_equal(1, restrict(2, 0..1))
60
- assert_equal(1.3, restrict(2, 0..1.3))
61
- assert_equal(0, restrict(-1, 0..1))
62
- end
63
-
64
- def test_merge_adjacent_strings
65
- assert_equal(["foo bar baz", :bang, "biz bop", 12],
66
- merge_adjacent_strings(["foo ", "bar ", "baz", :bang, "biz", " bop", 12]))
67
- str = "foo"
68
- assert_equal(["foo foo foo", :bang, "foo foo", 12],
69
- merge_adjacent_strings([str, " ", str, " ", str, :bang, str, " ", str, 12]))
70
- end
71
-
72
- def test_replace_subseq
73
- assert_equal([1, 2, :a, :b, 5],
74
- replace_subseq([1, 2, 3, 4, 5], [3, 4], [:a, :b]))
75
- assert_equal([1, 2, 3, 4, 5],
76
- replace_subseq([1, 2, 3, 4, 5], [3, 4, 6], [:a, :b]))
77
- assert_equal([1, 2, 3, 4, 5],
78
- replace_subseq([1, 2, 3, 4, 5], [4, 5, 6], [:a, :b]))
79
- end
80
-
81
- def test_intersperse
82
- assert_equal(["foo", " ", "bar", " ", "baz"],
83
- intersperse(%w[foo bar baz], " "))
84
- assert_equal([], intersperse([], " "))
85
- end
86
-
87
- def test_substitute
88
- assert_equal(["foo", "bar", "baz", 3, 4],
89
- substitute([1, 2, 3, 4], [1, 2], ["foo", "bar", "baz"]))
90
- assert_equal([1, "foo", "bar", "baz", 4],
91
- substitute([1, 2, 3, 4], [2, 3], ["foo", "bar", "baz"]))
92
- assert_equal([1, 2, "foo", "bar", "baz"],
93
- substitute([1, 2, 3, 4], [3, 4], ["foo", "bar", "baz"]))
94
-
95
- assert_equal([1, "foo", "bar", "baz", 2, 3, 4],
96
- substitute([1, 2, 2, 2, 3, 4], [2, 2], ["foo", "bar", "baz"]))
97
- end
98
-
99
- def test_strip_string_array
100
- assert_equal(["foo ", " bar ", " baz"],
101
- strip_string_array([" foo ", " bar ", " baz "]))
102
- assert_equal([:foo, " bar ", " baz"],
103
- strip_string_array([:foo, " bar ", " baz "]))
104
- assert_equal(["foo ", " bar ", :baz],
105
- strip_string_array([" foo ", " bar ", :baz]))
106
- end
107
-
108
- def test_paths
109
- assert_equal([[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5]],
110
- paths([[1, 2], [3, 4], [5]]))
111
- assert_equal([[]], paths([]))
112
- assert_equal([[1, 2, 3]], paths([[1], [2], [3]]))
113
- end
114
-
115
- def test_lcs
116
- assert_equal([1, 2, 3], lcs([1, 2, 3], [1, 2, 3]))
117
- assert_equal([], lcs([], [1, 2, 3]))
118
- assert_equal([], lcs([1, 2, 3], []))
119
- assert_equal([1, 2, 3], lcs([5, 1, 4, 2, 3, 17], [0, 0, 1, 2, 6, 3]))
120
-
121
- assert_equal([1], lcs([1, 2, 3, 4], [4, 3, 2, 1]))
122
- assert_equal([1, 2], lcs([1, 2, 3, 4], [3, 4, 1, 2]))
123
- end
124
-
125
- def test_lcs_with_block
126
- assert_equal(["1", "2", "3"],
127
- lcs([1, 4, 2, 5, 3], [1, 2, 3]) {|a, b| a == b && a.to_s})
128
- assert_equal([-4, 2, 8],
129
- lcs([-5, 3, 2, 8], [-4, 1, 8]) {|a, b| (a - b).abs <= 1 && [a, b].max})
130
- end
131
-
132
- def test_subsequence
133
- assert(subsequence?([1, 2, 3], [1, 2, 3]))
134
- assert(subsequence?([1, 2, 3], [1, :a, 2, :b, 3]))
135
- assert(subsequence?([1, 2, 3], [:a, 1, :b, :c, 2, :d, 3, :e, :f]))
136
-
137
- assert(!subsequence?([1, 2, 3], [1, 2]))
138
- assert(!subsequence?([1, 2, 3], [1, 3, 2]))
139
- assert(!subsequence?([1, 2, 3], [3, 2, 1]))
140
- end
141
-
142
- def test_sass_warn
143
- assert_warning("Foo!") {sass_warn "Foo!"}
144
- end
145
-
146
- def test_silence_sass_warnings
147
- old_stderr, $stderr = $stderr, StringIO.new
148
- silence_sass_warnings {warn "Out"}
149
- assert_equal("Out\n", $stderr.string)
150
- silence_sass_warnings {sass_warn "In"}
151
- assert_equal("Out\n", $stderr.string)
152
- ensure
153
- $stderr = old_stderr
154
- end
155
-
156
- def test_extract
157
- arr = [1, 2, 3, 4, 5]
158
- assert_equal([1, 3, 5], extract!(arr) {|e| e % 2 == 1})
159
- assert_equal([2, 4], arr)
160
- end
161
-
162
- def test_flatten_vertically
163
- assert_equal([1, 2, 3], flatten_vertically([1, 2, 3]))
164
- assert_equal([1, 3, 5, 2, 4, 6], flatten_vertically([[1, 2], [3, 4], [5, 6]]))
165
- assert_equal([1, 2, 4, 3, 5, 6], flatten_vertically([1, [2, 3], [4, 5, 6]]))
166
- assert_equal([1, 4, 6, 2, 5, 3], flatten_vertically([[1, 2, 3], [4, 5], 6]))
167
- end
168
-
169
- def test_extract_and_inject_values
170
- test = lambda {|arr| assert_equal(arr, with_extracted_values(arr) {|str| str})}
171
-
172
- test[['foo bar']]
173
- test[['foo {12} bar']]
174
- test[['foo {{12} bar']]
175
- test[['foo {{1', 12, '2} bar']]
176
- test[['foo 1', 2, '{3', 4, 5, 6, '{7}', 8]]
177
- test[['foo 1', [2, 3, 4], ' bar']]
178
- test[['foo ', 1, "\n bar\n", [2, 3, 4], "\n baz"]]
179
- end
180
-
181
- def nested_caller_info_fn
182
- caller_info
183
- end
184
-
185
- def double_nested_caller_info_fn
186
- nested_caller_info_fn
187
- end
188
-
189
- def test_caller_info
190
- assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle'"))
191
- assert_equal(["/tmp/foo.rb", 12, nil], caller_info("/tmp/foo.rb:12"))
192
- assert_equal(["C:/tmp/foo.rb", 12, nil], caller_info("C:/tmp/foo.rb:12"))
193
- assert_equal(["(sass)", 12, "blah"], caller_info("(sass):12: in `blah'"))
194
- assert_equal(["", 12, "boop"], caller_info(":12: in `boop'"))
195
- assert_equal(["/tmp/foo.rb", -12, "fizzle"], caller_info("/tmp/foo.rb:-12: in `fizzle'"))
196
- assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle {}'"))
197
- assert_equal(["C:/tmp/foo.rb", 12, "fizzle"], caller_info("C:/tmp/foo.rb:12: in `fizzle {}'"))
198
-
199
- info = nested_caller_info_fn
200
- assert_equal(__FILE__, info[0])
201
- assert_equal("test_caller_info", info[2])
202
-
203
- info = proc {nested_caller_info_fn}.call
204
- assert_equal(__FILE__, info[0])
205
- assert_match(/^(block in )?test_caller_info$/, info[2])
206
-
207
- info = double_nested_caller_info_fn
208
- assert_equal(__FILE__, info[0])
209
- assert_equal("double_nested_caller_info_fn", info[2])
210
-
211
- info = proc {double_nested_caller_info_fn}.call
212
- assert_equal(__FILE__, info[0])
213
- assert_equal("double_nested_caller_info_fn", info[2])
214
- end
215
-
216
- def test_version_gt
217
- assert_version_gt("2.0.0", "1.0.0")
218
- assert_version_gt("1.1.0", "1.0.0")
219
- assert_version_gt("1.0.1", "1.0.0")
220
- assert_version_gt("1.0.0", "1.0.0.rc")
221
- assert_version_gt("1.0.0.1", "1.0.0.rc")
222
- assert_version_gt("1.0.0.rc", "0.9.9")
223
- assert_version_gt("1.0.0.beta", "1.0.0.alpha")
224
-
225
- assert_version_eq("1.0.0", "1.0.0")
226
- assert_version_eq("1.0.0", "1.0.0.0")
227
- end
228
-
229
- def assert_version_gt(v1, v2)
230
- #assert(version_gt(v1, v2), "Expected #{v1} > #{v2}")
231
- assert(!version_gt(v2, v1), "Expected #{v2} < #{v1}")
232
- end
233
-
234
- def assert_version_eq(v1, v2)
235
- assert(!version_gt(v1, v2), "Expected #{v1} = #{v2}")
236
- assert(!version_gt(v2, v1), "Expected #{v2} = #{v1}")
237
- end
238
-
239
- class FooBar
240
- def foo
241
- Sass::Util.abstract(self)
242
- end
243
- def old_method
244
- Sass::Util.deprecated(self)
245
- end
246
- def old_method_with_custom_message
247
- Sass::Util.deprecated(self, "Call FooBar#new_method instead.")
248
- end
249
- def self.another_old_method
250
- Sass::Util.deprecated(self)
251
- end
252
- end
253
-
254
- def test_abstract
255
- assert_raise_message(NotImplementedError,
256
- "UtilTest::FooBar must implement #foo") {FooBar.new.foo}
257
- end
258
-
259
- def test_deprecated
260
- assert_warning("DEPRECATION WARNING: UtilTest::FooBar#old_method will be removed in a future version of Sass.") { FooBar.new.old_method }
261
- assert_warning(<<WARNING) { FooBar.new.old_method_with_custom_message }
262
- DEPRECATION WARNING: UtilTest::FooBar#old_method_with_custom_message will be removed in a future version of Sass.
263
- Call FooBar#new_method instead.
264
- WARNING
265
- assert_warning("DEPRECATION WARNING: UtilTest::FooBar.another_old_method will be removed in a future version of Sass.") { FooBar.another_old_method }
266
- end
267
-
268
- def test_json_escape_string
269
- assert_json_string "", ""
270
- alphanum = (("0".."9").to_a).concat(("a".."z").to_a).concat(("A".."Z").to_a).join
271
- assert_json_string alphanum, alphanum
272
- assert_json_string "'\"\\'", "'\\\"\\\\'"
273
- assert_json_string "\b\f\n\r\t", "\\b\\f\\n\\r\\t"
274
- end
275
-
276
- def assert_json_string(source, target)
277
- assert_equal target, json_escape_string(source)
278
- end
279
-
280
- def test_json_value_of
281
- assert_json_value 0, "0"
282
- assert_json_value(-42, "-42")
283
- assert_json_value 42, "42"
284
- assert_json_value true, "true"
285
- assert_json_value false, "false"
286
- assert_json_value "", "\"\""
287
- assert_json_value "\"\"", "\"\\\"\\\"\""
288
- assert_json_value "Multi\nLine\rString", "\"Multi\\nLine\\rString\""
289
- assert_json_value [1, "some\nstr,ing", false, nil], "[1,\"some\\nstr,ing\",false,null]"
290
- end
291
-
292
- def assert_json_value(source, target)
293
- assert_equal target, json_value_of(source)
294
- end
295
-
296
- def test_vlq
297
- assert_equal "A", encode_vlq(0)
298
- assert_equal "e", encode_vlq(15)
299
- assert_equal "gB", encode_vlq(16)
300
- assert_equal "wH", encode_vlq(120)
301
- end
302
-
303
- def assert_vlq_encodes(int, vlq)
304
- vlq_from_decimal_array = decimal_array.map {|d| encode_vlq(d)}.join
305
- decimal_array_from_vlq = decode_vlq(vlq)
306
- assert_equal vlq, vlq_from_decimal_array
307
- assert_equal decimal_array, decimal_array_from_vlq
308
- end
309
-
310
- def test_round_respects_precision
311
- original_precision = Sass::Script::Value::Number.precision
312
- assert_equal 0, Sass::Util.round(0.4999999999)
313
- # 10 9s doesn't work because 0.49999999999 - 0.5 is very slightly greater
314
- # than -0.1e11 due to float nonsense.
315
- assert_equal 1, Sass::Util.round(0.499999999999)
316
- Sass::Script::Value::Number.precision = 6
317
- assert_equal 0, Sass::Util.round(0.499999)
318
- assert_equal 1, Sass::Util.round(0.49999999)
319
- ensure
320
- Sass::Script::Value::Number.precision = original_precision
321
- end
322
-
323
- def test_atomic_writes
324
- # when using normal writes, this test fails about 90% of the time.
325
- filename = File.join(Dir.tmpdir, "test_atomic")
326
- 5.times do
327
- writes_to_perform = %w(1 2 3 4 5 6 7 8 9).map {|i| "#{i}\n" * 100_000}
328
- threads = writes_to_perform.map do |to_write|
329
- Thread.new do
330
- # To see this test fail with a normal write,
331
- # change to the standard file open mechanism:
332
- # open(filename, "w") do |f|
333
- atomic_create_and_write_file(filename) do |f|
334
- f.write(to_write)
335
- end
336
- end
337
- end
338
- loop do
339
- contents = File.exist?(filename) ? File.read(filename) : nil
340
- next if contents.nil? || contents.size == 0
341
- unless writes_to_perform.include?(contents)
342
- if contents.size != writes_to_perform.first.size
343
- fail "Incomplete write detected: was #{contents.size} characters, " +
344
- "should have been #{writes_to_perform.first.size}"
345
- else
346
- fail "Corrupted read/write detected"
347
- end
348
- end
349
- break if threads.all? {|t| !t.alive?}
350
- end
351
- threads.each {|t| t.join}
352
- end
353
- ensure
354
- Sass::Util.retry_on_windows {File.delete filename if File.exist?(filename)}
355
- end
356
-
357
- def test_atomic_write_permissions
358
- atomic_filename = File.join(Dir.tmpdir, "test_atomic_perms.atomic")
359
- normal_filename = File.join(Dir.tmpdir, "test_atomic_perms.normal")
360
- atomic_create_and_write_file(atomic_filename) {|f| f.write("whatever\n") }
361
- open(normal_filename, "wb") {|f| f.write("whatever\n") }
362
- assert_equal File.stat(normal_filename).mode.to_s(8), File.stat(atomic_filename).mode.to_s(8)
363
- ensure
364
- File.unlink(atomic_filename) rescue nil
365
- File.unlink(normal_filename) rescue nil
366
- end
367
-
368
- def test_atomic_writes_respect_umask
369
- atomic_filename = File.join(Dir.tmpdir, "test_atomic_perms.atomic")
370
- atomic_create_and_write_file(atomic_filename) do |f|
371
- f.write("whatever\n")
372
- end
373
- assert_equal 0, File.stat(atomic_filename).mode & File.umask
374
- ensure
375
- File.unlink(atomic_filename)
376
- end
377
-
378
- class FakeError < RuntimeError; end
379
-
380
- def test_atomic_writes_handles_exceptions
381
- filename = File.join(Dir.tmpdir, "test_atomic_exception")
382
- FileUtils.rm_f(filename)
383
- tmp_filename = nil
384
- assert_raises FakeError do
385
- atomic_create_and_write_file(filename) do |f|
386
- tmp_filename = f.path
387
- raise FakeError.new "Borken"
388
- end
389
- end
390
- assert !File.exist?(filename)
391
- assert !File.exist?(tmp_filename)
392
- end
393
- end