sass 3.1.0.alpha.22 → 3.1.0.alpha.23

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.
@@ -1 +1 @@
1
- 3.1.0.alpha.22
1
+ 3.1.0.alpha.23
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.0.alpha.22
1
+ 3.1.0.alpha.23
@@ -17,6 +17,7 @@ require 'sass/tree/for_node'
17
17
  require 'sass/tree/debug_node'
18
18
  require 'sass/tree/warn_node'
19
19
  require 'sass/tree/import_node'
20
+ require 'sass/tree/charset_node'
20
21
  require 'sass/selector'
21
22
  require 'sass/environment'
22
23
  require 'sass/script'
@@ -264,7 +265,14 @@ module Sass
264
265
  def _render
265
266
  rendered = _to_tree.render
266
267
  return rendered if ruby1_8?
267
- return rendered.encode(source_encoding)
268
+ begin
269
+ # Try to convert the result to the original encoding,
270
+ # but if that doesn't work fall back on UTF-8
271
+ rendered = rendered.encode(source_encoding)
272
+ rescue EncodingError
273
+ end
274
+ rendered.gsub(Regexp.new('\A@charset "(.*?)"'.encode(source_encoding)),
275
+ "@charset \"#{source_encoding.name}\"".encode(source_encoding))
268
276
  end
269
277
 
270
278
  def _to_tree
@@ -628,6 +636,12 @@ WARNING
628
636
  :line => @line + 1) unless line.children.empty?
629
637
  offset = line.offset + line.text.index(value).to_i
630
638
  Tree::WarnNode.new(parse_script(value, :offset => offset))
639
+ elsif directive == "charset"
640
+ name = value && value[/\A(["'])(.*)\1\Z/, 2] #"
641
+ raise SyntaxError.new("Invalid charset directive '@charset': expected string.") unless name
642
+ raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath charset directives.",
643
+ :line => @line + 1) unless line.children.empty?
644
+ Tree::CharsetNode.new(name)
631
645
  else
632
646
  Tree::DirectiveNode.new(line.text)
633
647
  end
@@ -318,7 +318,10 @@ module Sass::Plugin
318
318
  # Finally, write the file
319
319
  flag = 'w'
320
320
  flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
321
- File.open(css, flag) {|file| file.print(result)}
321
+ File.open(css, flag) do |file|
322
+ file.set_encoding(result.encoding) unless Sass::Util.ruby1_8?
323
+ file.print(result)
324
+ end
322
325
  end
323
326
 
324
327
  def try_delete_css(css)
@@ -24,11 +24,6 @@ module Sass
24
24
  def interp_ident(ident = IDENT); tok(ident); end
25
25
  def use_css_import?; true; end
26
26
 
27
- def special_directive(name)
28
- return unless name == 'media' || name == 'import'
29
- super
30
- end
31
-
32
27
  def block_child(context)
33
28
  case context
34
29
  when :ruleset
@@ -98,7 +98,8 @@ module Sass
98
98
  node << comment
99
99
  end
100
100
 
101
- DIRECTIVES = Set[:mixin, :include, :debug, :warn, :for, :while, :if, :extend, :import, :media]
101
+ DIRECTIVES = Set[:mixin, :include, :debug, :warn, :for, :while, :if, :extend, :import,
102
+ :media, :charset]
102
103
 
103
104
  def directive
104
105
  return unless tok(/@/)
@@ -289,6 +290,13 @@ module Sass
289
290
  true
290
291
  end
291
292
 
293
+ def charset_directive
294
+ tok! STRING
295
+ name = @scanner[1] || @scanner[2]
296
+ ss
297
+ node(Sass::Tree::CharsetNode.new(name))
298
+ end
299
+
292
300
  def variable
293
301
  return unless tok(/\$/)
294
302
  name = tok!(IDENT)
@@ -32,7 +32,7 @@ module Sass
32
32
  def use_css_import?; true; end
33
33
 
34
34
  def special_directive(name)
35
- return unless name == 'media' || name == 'import'
35
+ return unless %w[media import charset].include?(name)
36
36
  super
37
37
  end
38
38
  end
@@ -0,0 +1,37 @@
1
+ module Sass::Tree
2
+ # A static node representing an unproccessed Sass `@charset` directive.
3
+ #
4
+ # @see Sass::Tree
5
+ class CharsetNode < Node
6
+ # The name of the charset.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :name
10
+
11
+ # @param name [String] see \{#name}
12
+ def initialize(name)
13
+ @name = name
14
+ super()
15
+ end
16
+
17
+ # @see Node#invisible?
18
+ def invisible?
19
+ !Sass::Util.ruby1_8?
20
+ end
21
+
22
+ protected
23
+
24
+ # @see Node#to_src
25
+ def to_src(tabs, opts, fmt)
26
+ "#{' ' * tabs}@charset \"#{name}\"#{semi fmt}\n"
27
+ end
28
+
29
+ # Computes the CSS for the directive.
30
+ #
31
+ # @param tabs [Fixnum] The level of indentation for the CSS
32
+ # @return [String] The resulting CSS
33
+ def _to_s(tabs)
34
+ "@charset \"#{name}\";"
35
+ end
36
+ end
37
+ end
@@ -4,8 +4,8 @@ module Sass::Tree
4
4
  # are handled by their own nodes;
5
5
  # only CSS directives like `@media` and `@font-face` become {DirectiveNode}s.
6
6
  #
7
- # `@import` is a bit of a weird case;
8
- # it becomes an {ImportNode}.
7
+ # `@import` and `@charset` are special cases;
8
+ # they become {ImportNode}s and {CharsetNode}s, respectively.
9
9
  #
10
10
  # @see Sass::Tree
11
11
  class DirectiveNode < Node
@@ -47,7 +47,7 @@ module Sass
47
47
  # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
48
48
  # *and* the extensions defined for this tree
49
49
  def cssize(extends = Sass::Util::SubsetMap.new, parent = nil)
50
- return super(extends), extends
50
+ return super(extends, parent), extends
51
51
  rescue Sass::SyntaxError => e
52
52
  e.sass_template = @template
53
53
  raise e
@@ -106,7 +106,39 @@ module Sass
106
106
  end
107
107
  result.rstrip!
108
108
  return "" if result.empty?
109
- return result + "\n"
109
+ result << "\n"
110
+ unless Sass::Util.ruby1_8? || result.ascii_only?
111
+ if children.first.is_a?(CharsetNode)
112
+ begin
113
+ encoding = children.first.name
114
+ # Default to big-endian encoding, because we have to decide somehow
115
+ encoding << 'BE' if encoding =~ /\Autf-(16|32)\Z/i
116
+ result = result.encode(Encoding.find(encoding))
117
+ rescue EncodingError
118
+ end
119
+ end
120
+
121
+ result = "@charset \"#{result.encoding.name}\";#{
122
+ style == :compressed ? '' : "\n"
123
+ }".encode(result.encoding) + result
124
+ end
125
+ result
126
+ end
127
+
128
+ # In Ruby 1.8, ensures that there's only one @charset directive
129
+ # and that it's at the top of the document.
130
+ #
131
+ # @see Node#cssize
132
+ def cssize!(extends, parent)
133
+ super
134
+
135
+ # In Ruby 1.9 we can make all @charset nodes invisible
136
+ # and infer the final @charset from the encoding of the final string.
137
+ if Sass::Util.ruby1_8? && parent.nil?
138
+ charset = self.children.find {|c| c.is_a?(CharsetNode)}
139
+ self.children.reject! {|c| c.is_a?(CharsetNode)}
140
+ self.children.unshift charset if charset
141
+ end
110
142
  end
111
143
 
112
144
  # Returns an error message if the given child node is invalid,
@@ -607,6 +607,14 @@ foo {
607
607
  SCSS
608
608
  end
609
609
 
610
+ def test_charset
611
+ assert_renders <<SASS, <<SCSS
612
+ @charset "utf-8"
613
+ SASS
614
+ @charset "utf-8";
615
+ SCSS
616
+ end
617
+
610
618
  def test_for
611
619
  assert_renders <<SASS, <<SCSS
612
620
  foo
@@ -2241,7 +2241,7 @@ SASS
2241
2241
 
2242
2242
  def test_same_charset_as_encoding
2243
2243
  assert_renders_encoded(<<CSS, <<SASS)
2244
- @charset "utf-8";
2244
+ @charset "UTF-8";
2245
2245
  fóó {
2246
2246
  a: b; }
2247
2247
  CSS
@@ -2253,7 +2253,7 @@ SASS
2253
2253
 
2254
2254
  def test_different_charset_than_encoding
2255
2255
  assert_renders_encoded(<<CSS.force_encoding("IBM866"), <<SASS)
2256
- @charset "ibm866";
2256
+ @charset "IBM866";
2257
2257
  fóó {
2258
2258
  a: b; }
2259
2259
  CSS
@@ -2265,6 +2265,7 @@ SASS
2265
2265
 
2266
2266
  def test_different_encoding_than_system
2267
2267
  assert_renders_encoded(<<CSS.encode("IBM866"), <<SASS.encode("IBM866"))
2268
+ @charset "IBM866";
2268
2269
  тАЬ {
2269
2270
  a: b; }
2270
2271
  CSS
@@ -2274,20 +2275,20 @@ SASS
2274
2275
  end
2275
2276
 
2276
2277
  def test_multibyte_charset
2277
- assert_renders_encoded(<<CSS.encode("UTF-16BE"), <<SASS.encode("UTF-16BE").force_encoding("UTF-8"))
2278
- @charset "utf-16be";
2278
+ assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("UTF-8"))
2279
+ @charset "UTF-16LE";
2279
2280
  fóó {
2280
2281
  a: b; }
2281
2282
  CSS
2282
- @charset "utf-16be"
2283
+ @charset "utf-16le"
2283
2284
  fóó
2284
2285
  a: b
2285
2286
  SASS
2286
2287
  end
2287
2288
 
2288
2289
  def test_multibyte_charset_without_endian_specifier
2289
- assert_renders_encoded(<<CSS.encode("UTF-32LE"), <<SASS.encode("UTF-32LE").force_encoding("UTF-8"))
2290
- @charset "utf-32";
2290
+ assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("UTF-8"))
2291
+ @charset "UTF-32BE";
2291
2292
  fóó {
2292
2293
  a: b; }
2293
2294
  CSS
@@ -2299,6 +2300,7 @@ SASS
2299
2300
 
2300
2301
  def test_utf8_bom
2301
2302
  assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
2303
+ @charset "UTF-8";
2302
2304
  fóó {
2303
2305
  a: b; }
2304
2306
  CSS
@@ -2309,6 +2311,7 @@ SASS
2309
2311
 
2310
2312
  def test_utf16le_bom
2311
2313
  assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("BINARY"))
2314
+ @charset "UTF-16LE";
2312
2315
  fóó {
2313
2316
  a: b; }
2314
2317
  CSS
@@ -2319,6 +2322,7 @@ SASS
2319
2322
 
2320
2323
  def test_utf32be_bom
2321
2324
  assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("BINARY"))
2325
+ @charset "UTF-32BE";
2322
2326
  fóó {
2323
2327
  a: b; }
2324
2328
  CSS
@@ -10,6 +10,8 @@ class SassPluginTest < Test::Unit::TestCase
10
10
  subdir/subdir subdir/nested_subdir/nested_subdir
11
11
  options
12
12
  }
13
+ @@templates += %w[import_charset import_charset_ibm866] unless Sass::Util.ruby1_8?
14
+ @@templates << 'import_charset_1_8' if Sass::Util.ruby1_8?
13
15
 
14
16
  @@cache_store = Sass::InMemoryCacheStore.new
15
17
 
@@ -279,11 +281,18 @@ CSS
279
281
  prefix = options[:prefix]
280
282
  result_name = arguments.shift
281
283
  tempfile_name = arguments.shift || result_name
282
- expected_lines = File.read(result_loc(result_name, prefix)).split("\n")
283
- actual_lines = File.read(tempfile_loc(tempfile_name, prefix)).split("\n")
284
+
285
+ expected_str = File.read(result_loc(result_name, prefix))
286
+ actual_str = File.read(tempfile_loc(tempfile_name, prefix))
287
+ unless Sass::Util.ruby1_8?
288
+ expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
289
+ actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
290
+ end
291
+ expected_lines = expected_str.split("\n")
292
+ actual_lines = actual_str.split("\n")
284
293
 
285
294
  if actual_lines.first == "/*" && expected_lines.first != "/*"
286
- assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n"))
295
+ assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n"))
287
296
  end
288
297
 
289
298
  expected_lines.zip(actual_lines).each_with_index do |pair, line|
@@ -0,0 +1,4 @@
1
+ @charset "UTF-8";
2
+ .foo { a: b; }
3
+
4
+ .bar { a: щ; }
@@ -0,0 +1,4 @@
1
+ @charset "IBM866";
2
+ .foo { a: b; }
3
+
4
+ .bar { a: �; }
@@ -0,0 +1,4 @@
1
+ @charset "IBM866";
2
+ .foo { a: b; }
3
+
4
+ .bar { a: �; }
@@ -49,11 +49,34 @@ baz {bar: baz}
49
49
  SCSS
50
50
  end
51
51
 
52
- def test_unicode
53
- assert_parses <<SCSS
52
+ if Sass::Util.ruby1_8?
53
+ def test_unicode
54
+ assert_parses <<SCSS
55
+ @charset "UTF-8";
56
+ foo {
57
+ bar: föö bâr; }
58
+ SCSS
59
+ assert_parses <<SCSS
54
60
  foo {
55
61
  bar: föö bâr; }
56
62
  SCSS
63
+ end
64
+ else
65
+ def test_unicode
66
+ assert_parses <<SCSS
67
+ @charset "UTF-8";
68
+ foo {
69
+ bar: föö bâr; }
70
+ SCSS
71
+ assert_equal <<CSS, render(<<SCSS)
72
+ @charset "UTF-8";
73
+ foo {
74
+ bar: föö bâr; }
75
+ CSS
76
+ foo {
77
+ bar: föö bâr; }
78
+ SCSS
79
+ end
57
80
  end
58
81
 
59
82
  def test_invisible_comments
@@ -429,10 +452,6 @@ SCSS
429
452
 
430
453
  ## Directives
431
454
 
432
- def test_charset_directive
433
- assert_parses '@charset "utf-8";'
434
- end
435
-
436
455
  def test_namespace_directive
437
456
  assert_parses '@namespace "http://www.w3.org/Profiles/xhtml1-strict";'
438
457
  assert_parses '@namespace url(http://www.w3.org/Profiles/xhtml1-strict);'
@@ -508,11 +527,11 @@ SCSS
508
527
  end
509
528
 
510
529
  def test_blockless_directive_without_semicolon
511
- assert_equal "@charset \"utf-8\";\n", render('@charset "utf-8"')
530
+ assert_equal "@foo \"bar\";\n", render('@foo "bar"')
512
531
  end
513
532
 
514
533
  def test_directive_with_lots_of_whitespace
515
- assert_equal "@charset \"utf-16\";\n", render('@charset "utf-16" ;')
534
+ assert_equal "@foo \"bar\";\n", render('@foo "bar" ;')
516
535
  end
517
536
 
518
537
  def test_empty_blockless_directive
@@ -0,0 +1,4 @@
1
+ @charset "IBM866"
2
+
3
+ .bar
4
+ a: �
@@ -0,0 +1,4 @@
1
+ @charset "UTF-8"
2
+
3
+ .bar
4
+ a: щ
@@ -0,0 +1,7 @@
1
+ .foo
2
+ a: b
3
+
4
+ // Even though the imported file is in IBM866,
5
+ // since the root file is in UTF-8/ASCII
6
+ // the output will end up being UTF-8.
7
+ @import "imported_charset_ibm866"
@@ -0,0 +1,4 @@
1
+ .foo
2
+ a: b
3
+
4
+ @import "imported_charset_ibm866"
@@ -0,0 +1,9 @@
1
+ @charset "IBM866"
2
+
3
+ .foo
4
+ a: b
5
+
6
+ // Even though the imported file is in UTF-8,
7
+ // since the root file is in IBM866
8
+ // the output will end up being IBM866.
9
+ @import "imported_charset_utf8"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sass
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0.alpha.22
4
+ version: 3.1.0.alpha.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2010-10-27 00:00:00 -04:00
14
+ date: 2010-10-31 00:00:00 -04:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -118,6 +118,7 @@ files:
118
118
  - lib/sass/tree/variable_node.rb
119
119
  - lib/sass/tree/warn_node.rb
120
120
  - lib/sass/tree/while_node.rb
121
+ - lib/sass/tree/charset_node.rb
121
122
  - lib/sass/util.rb
122
123
  - lib/sass/util/subset_map.rb
123
124
  - lib/sass/version.rb
@@ -193,6 +194,9 @@ files:
193
194
  - test/sass/results/units.css
194
195
  - test/sass/results/warn.css
195
196
  - test/sass/results/warn_imported.css
197
+ - test/sass/results/import_charset.css
198
+ - test/sass/results/import_charset_1_8.css
199
+ - test/sass/results/import_charset_ibm866.css
196
200
  - test/sass/script_conversion_test.rb
197
201
  - test/sass/script_test.rb
198
202
  - test/sass/scss/css_test.rb
@@ -234,6 +238,11 @@ files:
234
238
  - test/sass/templates/units.sass
235
239
  - test/sass/templates/warn.sass
236
240
  - test/sass/templates/warn_imported.sass
241
+ - test/sass/templates/_imported_charset_ibm866.sass
242
+ - test/sass/templates/_imported_charset_utf8.sass
243
+ - test/sass/templates/import_charset.sass
244
+ - test/sass/templates/import_charset_1_8.sass
245
+ - test/sass/templates/import_charset_ibm866.sass
237
246
  - test/sass/test_helper.rb
238
247
  - test/sass/util/subset_map_test.rb
239
248
  - test/sass/util_test.rb