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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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