sass 3.3.14 → 3.4.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +5 -5
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +0 -5
  10. data/lib/sass/css.rb +1 -3
  11. data/lib/sass/engine.rb +28 -39
  12. data/lib/sass/environment.rb +13 -17
  13. data/lib/sass/error.rb +6 -9
  14. data/lib/sass/exec.rb +5 -771
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +419 -0
  18. data/lib/sass/features.rb +6 -0
  19. data/lib/sass/importers.rb +0 -1
  20. data/lib/sass/importers/base.rb +5 -1
  21. data/lib/sass/importers/filesystem.rb +4 -21
  22. data/lib/sass/media.rb +1 -4
  23. data/lib/sass/plugin/compiler.rb +32 -136
  24. data/lib/sass/script/css_lexer.rb +1 -1
  25. data/lib/sass/script/functions.rb +363 -39
  26. data/lib/sass/script/lexer.rb +68 -50
  27. data/lib/sass/script/parser.rb +29 -14
  28. data/lib/sass/script/tree.rb +1 -0
  29. data/lib/sass/script/tree/funcall.rb +1 -1
  30. data/lib/sass/script/tree/interpolation.rb +19 -1
  31. data/lib/sass/script/tree/selector.rb +26 -0
  32. data/lib/sass/script/value.rb +0 -1
  33. data/lib/sass/script/value/bool.rb +0 -5
  34. data/lib/sass/script/value/color.rb +32 -12
  35. data/lib/sass/script/value/helpers.rb +107 -0
  36. data/lib/sass/script/value/list.rb +0 -15
  37. data/lib/sass/script/value/null.rb +0 -5
  38. data/lib/sass/script/value/number.rb +60 -14
  39. data/lib/sass/script/value/string.rb +53 -9
  40. data/lib/sass/scss/css_parser.rb +8 -2
  41. data/lib/sass/scss/parser.rb +175 -319
  42. data/lib/sass/scss/rx.rb +14 -5
  43. data/lib/sass/scss/static_parser.rb +298 -1
  44. data/lib/sass/selector.rb +56 -193
  45. data/lib/sass/selector/abstract_sequence.rb +28 -13
  46. data/lib/sass/selector/comma_sequence.rb +91 -12
  47. data/lib/sass/selector/pseudo.rb +256 -0
  48. data/lib/sass/selector/sequence.rb +99 -31
  49. data/lib/sass/selector/simple.rb +14 -25
  50. data/lib/sass/selector/simple_sequence.rb +101 -37
  51. data/lib/sass/shared.rb +1 -1
  52. data/lib/sass/source/map.rb +23 -9
  53. data/lib/sass/stack.rb +0 -6
  54. data/lib/sass/supports.rb +1 -1
  55. data/lib/sass/tree/at_root_node.rb +1 -0
  56. data/lib/sass/tree/directive_node.rb +7 -1
  57. data/lib/sass/tree/error_node.rb +18 -0
  58. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  59. data/lib/sass/tree/prop_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -6
  61. data/lib/sass/tree/visitors/check_nesting.rb +3 -4
  62. data/lib/sass/tree/visitors/convert.rb +8 -17
  63. data/lib/sass/tree/visitors/cssize.rb +12 -24
  64. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  65. data/lib/sass/tree/visitors/perform.rb +43 -28
  66. data/lib/sass/tree/visitors/set_options.rb +5 -0
  67. data/lib/sass/tree/visitors/to_css.rb +14 -13
  68. data/lib/sass/util.rb +94 -90
  69. data/test/sass/cache_test.rb +1 -1
  70. data/test/sass/callbacks_test.rb +1 -1
  71. data/test/sass/compiler_test.rb +5 -14
  72. data/test/sass/conversion_test.rb +47 -1
  73. data/test/sass/css2sass_test.rb +3 -3
  74. data/test/sass/encoding_test.rb +219 -0
  75. data/test/sass/engine_test.rb +128 -191
  76. data/test/sass/exec_test.rb +2 -2
  77. data/test/sass/extend_test.rb +234 -17
  78. data/test/sass/functions_test.rb +268 -213
  79. data/test/sass/importer_test.rb +31 -21
  80. data/test/sass/logger_test.rb +1 -1
  81. data/test/sass/more_results/more_import.css +1 -1
  82. data/test/sass/plugin_test.rb +12 -11
  83. data/test/sass/results/compact.css +1 -1
  84. data/test/sass/results/complex.css +4 -4
  85. data/test/sass/results/expanded.css +1 -1
  86. data/test/sass/results/import.css +1 -1
  87. data/test/sass/results/import_charset_ibm866.css +2 -2
  88. data/test/sass/results/mixins.css +17 -17
  89. data/test/sass/results/nested.css +1 -1
  90. data/test/sass/results/parent_ref.css +2 -2
  91. data/test/sass/results/script.css +3 -3
  92. data/test/sass/results/scss_import.css +1 -1
  93. data/test/sass/script_conversion_test.rb +7 -4
  94. data/test/sass/script_test.rb +202 -79
  95. data/test/sass/scss/css_test.rb +95 -25
  96. data/test/sass/scss/rx_test.rb +4 -4
  97. data/test/sass/scss/scss_test.rb +363 -19
  98. data/test/sass/source_map_test.rb +48 -41
  99. data/test/sass/superselector_test.rb +191 -0
  100. data/test/sass/templates/scss_import.scss +2 -1
  101. data/test/sass/test_helper.rb +1 -1
  102. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  103. data/test/sass/util/normalized_map_test.rb +1 -1
  104. data/test/sass/util/subset_map_test.rb +2 -2
  105. data/test/sass/util_test.rb +1 -1
  106. data/test/sass/value_helpers_test.rb +3 -3
  107. data/test/test_helper.rb +2 -2
  108. metadata +30 -7
  109. data/lib/sass/importers/deprecated_path.rb +0 -51
  110. data/lib/sass/script/value/deprecated_false.rb +0 -55
@@ -4,7 +4,7 @@ require File.dirname(__FILE__) + '/test_helper'
4
4
  require 'mock_importer'
5
5
  require 'sass/plugin'
6
6
 
7
- class ImporterTest < Test::Unit::TestCase
7
+ class ImporterTest < MiniTest::Test
8
8
 
9
9
  class FruitImporter < Sass::Importers::Base
10
10
  def find(name, context = nil)
@@ -225,11 +225,11 @@ SCSS
225
225
  JSON
226
226
  end
227
227
 
228
- def test_source_map_with_only_css_uri_can_have_no_public_url_without_warning
228
+ def test_source_map_with_only_css_uri_can_have_no_public_url
229
229
  ephemeral_importer = NoPublicUrlImporter.new
230
230
  mock_importer = MockImporter.new
231
231
  def mock_importer.public_url(name, sourcemap_directory = nil)
232
- "css_uri"
232
+ "source_uri"
233
233
  end
234
234
 
235
235
  options = {
@@ -248,28 +248,26 @@ JSON
248
248
  }
249
249
  SCSS
250
250
 
251
- assert_warning("") do
252
- css_output, sourcemap = engine.render_with_sourcemap('sourcemap_uri')
253
- assert_equal <<CSS.strip, css_output.strip
251
+ css_output, sourcemap = engine.render_with_sourcemap('sourcemap_uri')
252
+ assert_equal <<CSS.strip, css_output.strip
254
253
  .orange {
255
254
  color: orange; }
256
255
 
257
256
  /*# sourceMappingURL=sourcemap_uri */
258
257
  CSS
259
- map = sourcemap.to_json(:css_uri => 'css_uri')
260
- assert_equal <<JSON.strip, map
258
+ map = sourcemap.to_json(:css_uri => 'css_uri')
259
+ assert_equal <<JSON.strip, map
261
260
  {
262
261
  "version": 3,
263
262
  "mappings": "AACA,OAAQ",
264
- "sources": ["css_uri"],
263
+ "sources": ["source_uri"],
265
264
  "names": [],
266
265
  "file": "css_uri"
267
266
  }
268
267
  JSON
269
- end
270
268
  end
271
269
 
272
- def test_source_map_with_only_css_uri_doesnt_support_filesystem_importer
270
+ def test_source_map_with_only_css_uri_falls_back_to_file_uris
273
271
  file_system_importer = Sass::Importers::Filesystem.new('.')
274
272
  options = {
275
273
  :filename => filename_for_test(:scss),
@@ -284,13 +282,19 @@ SCSS
284
282
 
285
283
  _, sourcemap = engine.render_with_sourcemap('http://1.example.com/style.map')
286
284
 
287
- assert_warning(<<WARNING) {sourcemap.to_json(:css_uri => 'css_uri')}
288
- WARNING: Couldn't determine public URL for "#{filename_for_test(:scss)}" while generating sourcemap.
289
- Without a public URL, there's nothing for the source map to link to.
290
- WARNING
285
+ uri = Sass::Util.file_uri_from_path(Sass::Util.absolute_path(filename_for_test(:scss)))
286
+ assert_equal <<JSON.strip, sourcemap.to_json(:css_uri => 'css_uri')
287
+ {
288
+ "version": 3,
289
+ "mappings": "AAAA,IAAK;EAAC,CAAC,EAAE,CAAC",
290
+ "sources": ["#{uri}"],
291
+ "names": [],
292
+ "file": "css_uri"
293
+ }
294
+ JSON
291
295
  end
292
296
 
293
- def test_source_map_with_css_uri_and_css_path_doesnt_support_filesystem_importer
297
+ def test_source_map_with_css_uri_and_css_path_falls_back_to_file_uris
294
298
  file_system_importer = Sass::Importers::Filesystem.new('.')
295
299
  options = {
296
300
  :filename => filename_for_test(:scss),
@@ -305,10 +309,16 @@ SCSS
305
309
 
306
310
  _, sourcemap = engine.render_with_sourcemap('http://1.example.com/style.map')
307
311
 
308
- assert_warning(<<WARNING) {sourcemap.to_json(:css_uri => 'css_uri', :css_path => 'css_path')}
309
- WARNING: Couldn't determine public URL for "#{filename_for_test(:scss)}" while generating sourcemap.
310
- Without a public URL, there's nothing for the source map to link to.
311
- WARNING
312
+ uri = Sass::Util.file_uri_from_path(Sass::Util.absolute_path(filename_for_test(:scss)))
313
+ assert_equal <<JSON.strip, sourcemap.to_json(:css_uri => 'css_uri', :css_path => 'css_path')
314
+ {
315
+ "version": 3,
316
+ "mappings": "AAAA,IAAK;EAAC,CAAC,EAAE,CAAC",
317
+ "sources": ["#{uri}"],
318
+ "names": [],
319
+ "file": "css_uri"
320
+ }
321
+ JSON
312
322
  end
313
323
 
314
324
  def test_source_map_with_css_uri_and_sourcemap_path_supports_filesystem_importer
@@ -397,6 +407,6 @@ MESSAGE
397
407
 
398
408
  def test_absolute_files_across_template_locations
399
409
  importer = Sass::Importers::Filesystem.new(absolutize 'templates')
400
- assert_not_nil importer.mtime(absolutize('more_templates/more1.sass'), {})
410
+ refute_nil importer.mtime(absolutize('more_templates/more1.sass'), {})
401
411
  end
402
412
  end
@@ -2,7 +2,7 @@
2
2
  require File.dirname(__FILE__) + '/../test_helper'
3
3
  require 'pathname'
4
4
 
5
- class LoggerTest < Test::Unit::TestCase
5
+ class LoggerTest < MiniTest::Test
6
6
 
7
7
  class InterceptedLogger < Sass::Logger::Base
8
8
 
@@ -24,6 +24,6 @@ body { font: Arial; background: blue; }
24
24
  #content.user.show #container.top #column.right { width: 600px; }
25
25
  #content.user.show #container.bottom { background: brown; }
26
26
 
27
- #foo { background-color: #bbaaff; }
27
+ #foo { background-color: #baf; }
28
28
 
29
29
  nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
@@ -17,7 +17,7 @@ module Sass::Script::Functions
17
17
  end
18
18
  end
19
19
 
20
- class SassPluginTest < Test::Unit::TestCase
20
+ class SassPluginTest < MiniTest::Test
21
21
  @@templates = %w{
22
22
  complex script parent_ref import scss_import alt
23
23
  subdir/subdir subdir/nested_subdir/nested_subdir
@@ -113,7 +113,7 @@ class SassPluginTest < Test::Unit::TestCase
113
113
  File.open(tempfile_loc('bork1')) do |file|
114
114
  assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
115
115
  /*
116
- Syntax error: Undefined variable: "$bork".
116
+ Error: Undefined variable: "$bork".
117
117
  on line 2 of #{template_loc('bork1')}
118
118
 
119
119
  1: bork
@@ -129,7 +129,7 @@ CSS
129
129
  File.open(tempfile_loc('bork5')) do |file|
130
130
  assert_equal(<<CSS.strip, file.read.split("\n")[0...7].join("\n"))
131
131
  /*
132
- Syntax error: Undefined variable: "$bork".
132
+ Error: Undefined variable: "$bork".
133
133
  on line 3 of #{template_loc('bork5')}
134
134
 
135
135
  1: bork
@@ -146,7 +146,7 @@ CSS
146
146
  File.open(tempfile_loc('single_import_loop')) do |file|
147
147
  assert_equal(<<CSS.strip, file.read.split("\n")[0...2].join("\n"))
148
148
  /*
149
- Syntax error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
149
+ Error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
150
150
  CSS
151
151
  end
152
152
  end
@@ -157,9 +157,9 @@ CSS
157
157
  File.open(tempfile_loc('double_import_loop1')) do |file|
158
158
  assert_equal(<<CSS.strip, file.read.split("\n")[0...4].join("\n"))
159
159
  /*
160
- Syntax error: An @import loop has been found:
161
- #{template_loc('double_import_loop1')} imports #{template_loc('_double_import_loop2')}
162
- #{template_loc('_double_import_loop2')} imports #{template_loc('double_import_loop1')}
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
163
  CSS
164
164
  end
165
165
  end
@@ -170,8 +170,8 @@ CSS
170
170
  File.open(tempfile_loc('subdir/import_up1')) do |file|
171
171
  assert_equal(<<CSS.strip, file.read.split("\n")[0...5].join("\n"))
172
172
  /*
173
- Syntax error: File to import not found or unreadable: ../subdir/import_up3.scss.
174
- Load path: #{template_loc}
173
+ Error: File to import not found or unreadable: ../subdir/import_up3.scss.
174
+ Load path: #{template_loc}
175
175
  on line 1 of #{template_loc 'subdir/import_up2'}
176
176
  from line 1 of #{template_loc 'subdir/import_up1'}
177
177
  CSS
@@ -183,7 +183,7 @@ CSS
183
183
  Sass::Plugin.options[:full_exception] = false
184
184
 
185
185
  File.delete(tempfile_loc('bork1'))
186
- assert_raise(Sass::SyntaxError) {check_for_updates!}
186
+ assert_raises(Sass::SyntaxError) {check_for_updates!}
187
187
  ensure
188
188
  Sass::Plugin.options[:full_exception] = old_full_exception
189
189
  end
@@ -537,7 +537,8 @@ WARNING
537
537
  :always_update => true,
538
538
  :never_update => false,
539
539
  :full_exception => true,
540
- :cache_store => @@cache_store
540
+ :cache_store => @@cache_store,
541
+ :sourcemap => :none
541
542
  )
542
543
  Sass::Plugin.options.merge!(overrides)
543
544
  end
@@ -1,4 +1,4 @@
1
- #main { width: 15em; color: blue; }
1
+ #main { width: 15em; color: #0000ff; }
2
2
  #main p { border-style: dotted; /* Nested comment More nested stuff */ border-width: 2px; }
3
3
  #main .cool { width: 100px; }
4
4
 
@@ -1,4 +1,4 @@
1
- body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-serif; color: white; background: url(/images/global_bg.gif); }
1
+ body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-serif; color: #fff; background: url(/images/global_bg.gif); }
2
2
 
3
3
  #page { width: 900px; margin: 0 auto; background: #440008; border-top-width: 5px; border-top-style: solid; border-top-color: #ff8500; }
4
4
 
@@ -16,8 +16,8 @@ body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-se
16
16
 
17
17
  #menu { clear: both; text-align: right; height: 20px; border-bottom: 5px solid #006b95; background: #00a4e4; }
18
18
  #menu .contests ul { margin: 0 5px 0 0; padding: 0; }
19
- #menu .contests ul li { list-style-type: none; margin: 0 5px; padding: 5px 5px 0 5px; display: inline; font-size: 1.1em; color: white; background: #00a4e4; }
20
- #menu .contests a:link, #menu .contests a:visited { color: white; text-decoration: none; font-weight: bold; }
19
+ #menu .contests ul li { list-style-type: none; margin: 0 5px; padding: 5px 5px 0 5px; display: inline; font-size: 1.1em; color: #fff; background: #00a4e4; }
20
+ #menu .contests a:link, #menu .contests a:visited { color: #fff; text-decoration: none; font-weight: bold; }
21
21
  #menu .contests a:hover { text-decoration: underline; }
22
22
 
23
23
  #content { clear: both; }
@@ -81,6 +81,6 @@ body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-se
81
81
 
82
82
  img { border: none; }
83
83
 
84
- button.short { width: 60px; height: 22px; padding: 0 0 2px 0; color: white; border: none; background: url(/images/btn_short.gif) no-repeat; }
84
+ button.short { width: 60px; height: 22px; padding: 0 0 2px 0; color: #fff; border: none; background: url(/images/btn_short.gif) no-repeat; }
85
85
 
86
86
  table { border-collapse: collapse; }
@@ -1,6 +1,6 @@
1
1
  #main {
2
2
  width: 15em;
3
- color: blue;
3
+ color: #0000ff;
4
4
  }
5
5
  #main p {
6
6
  border-style: dotted;
@@ -26,6 +26,6 @@ body { font: Arial; background: blue; }
26
26
  #content.user.show #container.top #column.right { width: 600px; }
27
27
  #content.user.show #container.bottom { background: brown; }
28
28
 
29
- #foo { background-color: #bbaaff; }
29
+ #foo { background-color: #baf; }
30
30
 
31
31
  nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
@@ -1,5 +1,5 @@
1
- @charset "IBM866";
1
+ @charset "UTF-8";
2
2
  @import url(foo.css);
3
3
  .foo { a: b; }
4
4
 
5
- .bar { a: �; }
5
+ .bar { a: щ; }
@@ -1,12 +1,12 @@
1
1
  #main {
2
2
  width: 15em;
3
- color: blue;
3
+ color: #0000ff;
4
4
  }
5
5
  #main p {
6
6
  border-top-width: 2px;
7
- border-top-color: #ffcc00;
7
+ border-top-color: #fc0;
8
8
  border-left-width: 1px;
9
- border-left-color: black;
9
+ border-left-color: #000;
10
10
  -moz-border-radius: 10px;
11
11
  border-style: dotted;
12
12
  border-width: 2px;
@@ -17,9 +17,9 @@
17
17
 
18
18
  #left {
19
19
  border-top-width: 2px;
20
- border-top-color: #ffcc00;
20
+ border-top-color: #fc0;
21
21
  border-left-width: 1px;
22
- border-left-color: black;
22
+ border-left-color: #000;
23
23
  -moz-border-radius: 10px;
24
24
  font-size: 2em;
25
25
  font-weight: bold;
@@ -28,25 +28,25 @@
28
28
 
29
29
  #right {
30
30
  border-top-width: 2px;
31
- border-top-color: #ffcc00;
31
+ border-top-color: #fc0;
32
32
  border-left-width: 1px;
33
- border-left-color: black;
33
+ border-left-color: #000;
34
34
  -moz-border-radius: 10px;
35
- color: red;
35
+ color: #f00;
36
36
  font-size: 20px;
37
37
  float: right;
38
38
  }
39
39
 
40
40
  .bordered {
41
41
  border-top-width: 2px;
42
- border-top-color: #ffcc00;
42
+ border-top-color: #fc0;
43
43
  border-left-width: 1px;
44
- border-left-color: black;
44
+ border-left-color: #000;
45
45
  -moz-border-radius: 10px;
46
46
  }
47
47
 
48
48
  .complex {
49
- color: red;
49
+ color: #f00;
50
50
  font-size: 20px;
51
51
  text-decoration: none;
52
52
  }
@@ -59,12 +59,12 @@
59
59
  }
60
60
  * html .complex {
61
61
  height: 1px;
62
- color: red;
62
+ color: #f00;
63
63
  font-size: 20px;
64
64
  }
65
65
 
66
66
  .more-complex {
67
- color: red;
67
+ color: #f00;
68
68
  font-size: 20px;
69
69
  text-decoration: none;
70
70
  display: inline;
@@ -80,16 +80,16 @@
80
80
  }
81
81
  * html .more-complex {
82
82
  height: 1px;
83
- color: red;
83
+ color: #f00;
84
84
  font-size: 20px;
85
85
  }
86
86
  .more-complex a:hover {
87
87
  text-decoration: underline;
88
- color: red;
88
+ color: #f00;
89
89
  font-size: 20px;
90
90
  border-top-width: 2px;
91
- border-top-color: #ffcc00;
91
+ border-top-color: #fc0;
92
92
  border-left-width: 1px;
93
- border-left-color: black;
93
+ border-left-color: #000;
94
94
  -moz-border-radius: 10px;
95
95
  }
@@ -1,6 +1,6 @@
1
1
  #main {
2
2
  width: 15em;
3
- color: blue; }
3
+ color: #0000ff; }
4
4
  #main p {
5
5
  border-style: dotted;
6
6
  /* Nested comment
@@ -1,5 +1,5 @@
1
- a { color: black; }
2
- a:hover { color: red; }
1
+ a { color: #000; }
2
+ a:hover { color: #f00; }
3
3
 
4
4
  p, div { width: 100em; }
5
5
  p foo, div foo { width: 10em; }
@@ -1,7 +1,7 @@
1
- #main { content: Hello\!; qstr: 'Quo"ted"!'; hstr: Hyph-en\!; width: 30em; background-color: black; color: #ffffaa; short-color: #112233; named-color: olive; con: "foo" bar 9 hi there "boom"; con2: "noquo" quo; }
2
- #main #sidebar { background-color: #00ff98; num-normal: 10; num-dec: 10.2; num-dec0: 99; num-neg: -10; esc: 10 \+12; many: 6; order: 7; complex: #4c9db1hi16; }
1
+ #main { content: Hello\!; qstr: 'Quo"ted"!'; hstr: Hyph-en\!; width: 30em; background-color: #000; color: #ffa; short-color: #123; named-color: olive; con: "foo" bar 9 hi there "boom"; con2: "noquo" quo; }
2
+ #main #sidebar { background-color: #00ff98; num-normal: 10; num-dec: 10.2; num-dec0: 99; num-neg: -10; esc: 10\+12; many: 6; order: 7; complex: #4c9db1hi16; }
3
3
 
4
- #plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: #b7b7b7; num-perc: 31%; str-str: "hi\ there"; str-str2: "hi there"; str-col: "14em solid #112233"; str-num: "times: 13"; col-num: #ff7b9d; col-col: #5173ff; }
4
+ #plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: #b7b7b7; num-perc: 31%; str-str: "hi there"; str-str2: "hi there"; str-col: "14em solid #123"; str-num: "times: 13"; col-num: #ff7b9d; col-col: #5173ff; }
5
5
 
6
6
  #minus { num-num: 900; col-num: #f9f9f4; col-col: #000035; unary-num: -1; unary-const: 10; unary-paren: -11; unary-two: 12; unary-many: 12; unary-crazy: -15; }
7
7
 
@@ -26,6 +26,6 @@ body { font: Arial; background: blue; }
26
26
  #content.user.show #container.top #column.right { width: 600px; }
27
27
  #content.user.show #container.bottom { background: brown; }
28
28
 
29
- #foo { background-color: #bbaaff; }
29
+ #foo { background-color: #baf; }
30
30
 
31
31
  nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
@@ -3,7 +3,7 @@
3
3
  require File.dirname(__FILE__) + '/../test_helper'
4
4
  require 'sass/engine'
5
5
 
6
- class SassScriptConversionTest < Test::Unit::TestCase
6
+ class SassScriptConversionTest < MiniTest::Test
7
7
  def test_bool
8
8
  assert_renders "true"
9
9
  assert_renders "false"
@@ -13,9 +13,8 @@ class SassScriptConversionTest < Test::Unit::TestCase
13
13
  assert_renders "#abcdef"
14
14
  assert_renders "blue"
15
15
  assert_renders "rgba(0, 1, 2, 0.2)"
16
-
17
- assert_equal "#aabbcc", render("#abc")
18
- assert_equal "blue", render("#0000ff")
16
+ assert_renders "#abc"
17
+ assert_renders "#0000ff"
19
18
  end
20
19
 
21
20
  def test_number
@@ -109,6 +108,10 @@ class SassScriptConversionTest < Test::Unit::TestCase
109
108
  assert_renders "(foo: (bar, baz), bip: bop)"
110
109
  end
111
110
 
111
+ def test_selector
112
+ assert_renders "&"
113
+ end
114
+
112
115
  def self.test_precedence(outer, inner)
113
116
  op_outer = Sass::Script::Lexer::OPERATORS_REVERSE[outer]
114
117
  op_inner = Sass::Script::Lexer::OPERATORS_REVERSE[inner]
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
2
3
  require File.dirname(__FILE__) + '/../test_helper'
3
4
  require 'sass/engine'
4
5
 
@@ -17,7 +18,7 @@ module Sass::Script::Functions
17
18
  include Sass::Script::Functions::UserFunctions
18
19
  end
19
20
 
20
- class SassScriptTest < Test::Unit::TestCase
21
+ class SassScriptTest < MiniTest::Test
21
22
  include Sass::Script
22
23
 
23
24
  def test_color_checks_input
@@ -33,18 +34,43 @@ class SassScriptTest < Test::Unit::TestCase
33
34
  def test_string_escapes
34
35
  assert_equal "'", resolve("\"'\"")
35
36
  assert_equal '"', resolve("\"\\\"\"")
36
- assert_equal "\\\\", resolve("\"\\\\\"")
37
- assert_equal "\\02fa", resolve("\"\\02fa\"")
38
-
39
- assert_equal "'", resolve("'\\''")
40
- assert_equal '"', resolve("'\"'")
41
- assert_equal "\\\\", resolve("'\\\\'")
42
- assert_equal "\\02fa", resolve("'\\02fa'")
37
+ assert_equal "\\", resolve("\"\\\\\"")
38
+ assert_equal "", resolve("\"\\2603\"")
39
+ assert_equal "☃f", resolve("\"\\2603 f\"")
40
+ assert_equal "☃x", resolve("\"\\2603x\"")
41
+ assert_equal "\\2603", resolve("\"\\\\2603\"")
42
+
43
+ # U+FFFD is the replacement character, "".
44
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\0\"")
45
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\FFFFFF\"")
46
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\D800\"")
47
+ assert_equal [0xD7FF].pack("U"), resolve("\"\\D7FF\"")
48
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\DFFF\"")
49
+ assert_equal [0xE000].pack("U"), resolve("\"\\E000\"")
50
+ end
51
+
52
+ def test_string_escapes_are_resolved_before_operators
53
+ assert_equal "true", resolve('"abc" == "\61\62\63"')
54
+ end
55
+
56
+ def test_string_quote
57
+ assert_equal '"foo"', resolve_quoted('"foo"')
58
+ assert_equal "'f\"oo'", resolve_quoted('"f\"oo"')
59
+ assert_equal "\"f'oo\"", resolve_quoted("'f\\'oo'")
60
+ assert_equal "\"f'o\\\"o\"", resolve_quoted("'f\\'o\"o'")
61
+ assert_equal '"foo bar"', resolve_quoted('"foo\20 bar"')
62
+ assert_equal '"foo\a bar"', resolve_quoted('"foo\a bar"')
63
+ assert_equal '"x\ay"', resolve_quoted('"x\a y"')
64
+ assert_equal '"\a "', resolve_quoted('"\a\20"')
65
+ assert_equal '"\a abcdef"', resolve_quoted('"\a abcdef"')
66
+ assert_equal '"☃abcdef"', resolve_quoted('"\2603 abcdef"')
67
+ assert_equal '"\\\\"', resolve_quoted('"\\\\"')
68
+ assert_equal '"foobar"', resolve_quoted("\"foo\\\nbar\"")
43
69
  end
44
70
 
45
71
  def test_color_names
46
72
  assert_equal "white", resolve("white")
47
- assert_equal "white", resolve("#ffffff")
73
+ assert_equal "#ffffff", resolve("#ffffff")
48
74
  assert_equal "#fffffe", resolve("white - #000001")
49
75
  assert_equal "transparent", resolve("transparent")
50
76
  assert_equal "transparent", resolve("rgba(0, 0, 0, 0)")
@@ -93,7 +119,7 @@ class SassScriptTest < Test::Unit::TestCase
93
119
  assert_equal "#123", resolve("#112233", :style => :compressed)
94
120
  assert_equal "#000", resolve("black", :style => :compressed)
95
121
  assert_equal "red", resolve("#f00", :style => :compressed)
96
- assert_equal "blue", resolve("#00f", :style => :compressed)
122
+ assert_equal "blue", resolve("blue", :style => :compressed)
97
123
  assert_equal "navy", resolve("#000080", :style => :compressed)
98
124
  assert_equal "navy #fff", resolve("#000080 white", :style => :compressed)
99
125
  assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed)
@@ -255,8 +281,8 @@ SASS
255
281
  assert_equal eval('1 2 3.0'), eval('1 2 3')
256
282
  assert_equal eval('1, 2, 3.0'), eval('1, 2, 3')
257
283
  assert_equal eval('(1 2), (3, 4), (5 6)'), eval('(1 2), (3, 4), (5 6)')
258
- assert_not_equal eval('1, 2, 3'), eval('1 2 3')
259
- assert_not_equal eval('1'), eval('"1"')
284
+ refute_equal eval('1, 2, 3'), eval('1 2 3')
285
+ refute_equal eval('1'), eval('"1"')
260
286
  end
261
287
 
262
288
  def test_booleans
@@ -430,6 +456,36 @@ SASS
430
456
  assert_equal "true", resolve("1.1cm == 11mm")
431
457
  end
432
458
 
459
+ def test_length_units
460
+ assert_equal "2.54", resolve("(1in/1cm)")
461
+ assert_equal "2.3622", resolve("(1cm/1pc)")
462
+ assert_equal "4.23333", resolve("(1pc/1mm)")
463
+ assert_equal "2.83465", resolve("(1mm/1pt)")
464
+ assert_equal "1.33333", resolve("(1pt/1px)")
465
+ assert_equal "0.01042", resolve("(1px/1in)")
466
+ end
467
+
468
+ def test_angle_units
469
+ assert_equal "1.11111", resolve("(1deg/1grad)")
470
+ assert_equal "0.01571", resolve("(1grad/1rad)")
471
+ assert_equal "0.15915", resolve("(1rad/1turn)")
472
+ assert_equal "360", resolve("(1turn/1deg)")
473
+ end
474
+
475
+ def test_time_units
476
+ assert_equal "1000", resolve("(1s/1ms)")
477
+ end
478
+
479
+ def test_frequency_units
480
+ assert_equal "0.001", resolve("(1Hz/1kHz)")
481
+ end
482
+
483
+ def test_resolution_units
484
+ assert_equal "2.54", resolve("(1dpi/1dpcm)")
485
+ assert_equal "37.79528", resolve("(1dpcm/1dppx)")
486
+ assert_equal "0.01042", resolve("(1dppx/1dpi)")
487
+ end
488
+
433
489
  def test_operations_have_options
434
490
  assert_equal "Options defined!", resolve("assert_options(1 + 1)")
435
491
  assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')")
@@ -462,22 +518,22 @@ SASS
462
518
  assert_equal "0.5", resolve("$var", {}, env("var" => eval("1px/2px")))
463
519
  end
464
520
 
465
- def test_colors_with_wrong_number_of_digits
466
- assert_raise_message(Sass::SyntaxError,
467
- "Colors must have either three or six digits: '#0'") {eval("#0")}
521
+ def test_non_ident_colors_with_wrong_number_of_digits
468
522
  assert_raise_message(Sass::SyntaxError,
469
- "Colors must have either three or six digits: '#12'") {eval("#12")}
523
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1"') {eval("#1")}
470
524
  assert_raise_message(Sass::SyntaxError,
471
- "Colors must have either three or six digits: '#abcd'") {eval("#abcd")}
525
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12"') {eval("#12")}
472
526
  assert_raise_message(Sass::SyntaxError,
473
- "Colors must have either three or six digits: '#abcdE'") {eval("#abcdE")}
527
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1234"') {eval("#1234")}
474
528
  assert_raise_message(Sass::SyntaxError,
475
- "Colors must have either three or six digits: '#abcdEFA'") {eval("#abcdEFA")}
529
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12345"') {eval("#12345")}
530
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "": expected expression (e.g. ' \
531
+ '1px, bold), was "#1234567"') {eval("#1234567")}
476
532
  end
477
533
 
478
534
  def test_case_insensitive_color_names
479
- assert_equal "blue", resolve("BLUE")
480
- assert_equal "red", resolve("rEd")
535
+ assert_equal "BLUE", resolve("BLUE")
536
+ assert_equal "rEd", resolve("rEd")
481
537
  assert_equal "#7f4000", resolve("mix(GrEeN, ReD)")
482
538
  end
483
539
 
@@ -523,7 +579,7 @@ SASS
523
579
  assert_raise_message(Sass::SyntaxError, 'Duplicate key 2px in map (2px: bar, 1px + 1px: baz).') do
524
580
  eval("(2px: bar, 1px + 1px: baz)")
525
581
  end
526
- assert_raise_message(Sass::SyntaxError, 'Duplicate key #0000ff in map (blue: bar, blue: baz).') do
582
+ assert_raise_message(Sass::SyntaxError, 'Duplicate key #0000ff in map (blue: bar, #00f: baz).') do
527
583
  eval("(blue: bar, #00f: baz)")
528
584
  end
529
585
  end
@@ -558,7 +614,7 @@ SASS
558
614
  return if RUBY_PLATFORM =~ /java/
559
615
 
560
616
  # Don't validate the message; it's different on Rubinius.
561
- assert_raise(ArgumentError) {resolve("arg-error()")}
617
+ assert_raises(ArgumentError) {resolve("arg-error()")}
562
618
  end
563
619
 
564
620
  def test_shallow_argument_error_unwrapped
@@ -570,49 +626,25 @@ SASS
570
626
  assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Value::Bool.new(true)))
571
627
  end
572
628
 
573
- def test_setting_global_variable_locally_warns
574
- assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
575
- DEPRECATION WARNING on line 4 of test_setting_global_variable_locally_warns_inline.scss:
576
- Assigning to global variable "$var" by default is deprecated.
577
- In future versions of Sass, this will create a new local variable.
578
- If you want to assign to the global variable, use "$var: x !global" instead.
579
- Note that this will be incompatible with Sass 3.2.
580
- WARNING
581
- .foo {
582
- a: x; }
583
-
584
- .bar {
585
- b: x; }
586
- CSS
587
- $var: 1;
588
-
589
- .foo {
590
- $var: x;
591
- a: $var;
592
- }
593
-
594
- .bar {
595
- b: $var;
596
- }
597
- SCSS
598
- end
629
+ def test_selector
630
+ env = Sass::Environment.new
631
+ assert_equal "true", resolve("& == null", {}, env)
599
632
 
600
- def test_setting_global_variable_locally_warns_only_once
601
- assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
602
- DEPRECATION WARNING on line 3 of test_setting_global_variable_locally_warns_only_once_inline.scss:
603
- Assigning to global variable "$var" by default is deprecated.
604
- In future versions of Sass, this will create a new local variable.
605
- If you want to assign to the global variable, use "$var: x !global" instead.
606
- Note that this will be incompatible with Sass 3.2.
607
- WARNING
608
- CSS
609
- $var: 1;
633
+ env.selector = selector('.foo.bar .baz.bang, .bip.bop')
634
+ assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
635
+ assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
636
+ assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
637
+ assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
638
+ assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
639
+ assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
640
+ assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
610
641
 
611
- @mixin foo {$var: x}
612
- @include foo;
613
- @include foo;
614
- @include foo;
615
- SCSS
642
+ env.selector = selector('.foo > .bar')
643
+ assert_equal ".foo > .bar", resolve("&", {}, env)
644
+ assert_equal ".foo > .bar", resolve("nth(&, 1)", {}, env)
645
+ assert_equal ".foo", resolve("nth(nth(&, 1), 1)", {}, env)
646
+ assert_equal ">", resolve("nth(nth(&, 1), 2)", {}, env)
647
+ assert_equal ".bar", resolve("nth(nth(&, 1), 3)", {}, env)
616
648
  end
617
649
 
618
650
  def test_setting_global_variable_globally
@@ -637,7 +669,7 @@ $var: 2;
637
669
  SCSS
638
670
  end
639
671
 
640
- def test_setting_global_variable_with_flag
672
+ def test_setting_global_variable_locally
641
673
  assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
642
674
  .bar {
643
675
  a: x;
@@ -663,7 +695,7 @@ $var3: 3;
663
695
  SCSS
664
696
  end
665
697
 
666
- def test_setting_global_variable_with_flag_and_default
698
+ def test_setting_global_variable_locally_with_default
667
699
  assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
668
700
  .bar {
669
701
  a: 1;
@@ -688,21 +720,104 @@ $var1: 1;
688
720
  SCSS
689
721
  end
690
722
 
691
- def test_unclosed_special_fun
692
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(foo()": expected ")", was ""') do
693
- resolve("calc(foo()")
694
- end
695
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{\')\'}": expected ")", was ""') do
696
- resolve("calc(\#{')'}")
697
- end
698
- assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{foo": expected "}", was ""') do
699
- resolve("calc(\#{foo")
700
- end
723
+ def test_setting_local_variable
724
+ assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
725
+ .a {
726
+ value: inside; }
727
+
728
+ .b {
729
+ value: outside; }
730
+ CSS
731
+ $var: outside;
732
+
733
+ .a {
734
+ $var: inside;
735
+ value: $var;
736
+ }
737
+
738
+ .b {
739
+ value: $var;
740
+ }
741
+ SCSS
742
+ end
743
+
744
+ def test_setting_local_variable_from_inner_scope
745
+ assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
746
+ .a .b {
747
+ value: inside; }
748
+ .a .c {
749
+ value: inside; }
750
+ CSS
751
+ .a {
752
+ $var: outside;
753
+
754
+ .b {
755
+ $var: inside;
756
+ value: $var;
757
+ }
758
+
759
+ .c {
760
+ value: $var;
761
+ }
762
+ }
763
+ SCSS
764
+ end
765
+
766
+ def test_color_format_is_preserved_by_default
767
+ assert_equal "blue", resolve("blue")
768
+ assert_equal "bLuE", resolve("bLuE")
769
+ assert_equal "#00f", resolve("#00f")
770
+ assert_equal "blue #00F", resolve("blue #00F")
771
+ assert_equal "blue", resolve("nth(blue #00F, 1)")
772
+ assert_equal "#00F", resolve("nth(blue #00F, 2)")
701
773
  end
702
774
 
703
- def test_special_fun_with_interpolation
704
- assert_equal "calc())", resolve("calc(\#{')'})")
705
- assert_equal "calc(# {foo})", resolve("calc(# {foo})")
775
+ def test_color_format_isnt_always_preserved_in_compressed_style
776
+ assert_equal "red", resolve("red", :style => :compressed)
777
+ assert_equal "red", resolve("#f00", :style => :compressed)
778
+ assert_equal "red red", resolve("red #f00", :style => :compressed)
779
+ assert_equal "red", resolve("nth(red #f00, 2)", :style => :compressed)
780
+ end
781
+
782
+ def test_color_format_is_sometimes_preserved_in_compressed_style
783
+ assert_equal "ReD", resolve("ReD", :style => :compressed)
784
+ assert_equal "blue", resolve("blue", :style => :compressed)
785
+ assert_equal "#00f", resolve("#00f", :style => :compressed)
786
+ end
787
+
788
+ def test_color_format_isnt_preserved_when_modified
789
+ assert_equal "magenta", resolve("#f00 + #00f")
790
+ end
791
+
792
+ def test_ids
793
+ assert_equal "#foo", resolve("#foo")
794
+ assert_equal "#abcd", resolve("#abcd")
795
+ assert_equal "#abc-def", resolve("#abc-def")
796
+ assert_equal "#abc_def", resolve("#abc_def")
797
+ assert_equal "#uvw-xyz", resolve("#uvw-xyz")
798
+ assert_equal "#uvw_xyz", resolve("#uvw_xyz")
799
+ assert_equal "#uvwxyz", resolve("#uvw + xyz")
800
+ end
801
+
802
+ def test_scientific_notation
803
+ assert_equal "2000", resolve("2e3")
804
+ assert_equal "2000", resolve("2E3")
805
+ assert_equal "2000", resolve("2e+3")
806
+ assert_equal "2000em", resolve("2e3em")
807
+ assert_equal "25000000000", resolve("2.5e10")
808
+ assert_equal "0.1234", resolve("1234e-4")
809
+ assert_equal "12.34", resolve("1.234e1")
810
+ end
811
+
812
+ def test_identifier_units
813
+ assert_equal "5-foo", resolve("2-foo + 3-foo")
814
+ assert_equal "5-foo-", resolve("2-foo- + 3-foo-")
815
+ assert_equal "5-\\u2603", resolve("2-\\u2603 + 3-\\u2603")
816
+ end
817
+
818
+ def test_backslash_newline_in_string
819
+ assert_equal 'foobar', resolve("\"foo\\\nbar\"")
820
+ assert_equal 'foobar', resolve("'foo\\\nbar'")
706
821
  end
707
822
 
708
823
  # Regression Tests
@@ -714,6 +829,7 @@ SCSS
714
829
 
715
830
  def test_minus_without_whitespace
716
831
  assert_equal "5px", resolve("15px-10px")
832
+ assert_equal "5px-", resolve("15px--10px-")
717
833
  end
718
834
 
719
835
  def test_minus_preceded_by_comment
@@ -833,6 +949,13 @@ SASS
833
949
  val.is_a?(Sass::Script::Value::String) ? val.value : val.to_s
834
950
  end
835
951
 
952
+ def resolve_quoted(str, opts = {}, environment = env)
953
+ munge_filename opts
954
+ val = eval(str, opts, environment)
955
+ assert_kind_of Sass::Script::Value::Base, val
956
+ val.to_s
957
+ end
958
+
836
959
  def assert_unquoted(str, opts = {}, environment = env)
837
960
  munge_filename opts
838
961
  val = eval(str, opts, environment)