haml 3.0.6 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.6
1
+ 3.0.7
@@ -85,8 +85,15 @@ module Haml
85
85
  :format => :xhtml,
86
86
  :escape_html => false,
87
87
  }
88
+
89
+
90
+ template = check_haml_encoding(template) do |msg, line|
91
+ raise Haml::Error.new(msg, line)
92
+ end
93
+
88
94
  unless ruby1_8?
89
- @options[:encoding] = Encoding.default_internal || "utf-8"
95
+ @options[:encoding] = Encoding.default_internal || template.encoding
96
+ @options[:encoding] = "utf-8" if @options[:encoding].name == "US-ASCII"
90
97
  end
91
98
  @options.merge! options.reject {|k, v| v.nil?}
92
99
  @index = 0
@@ -99,8 +106,6 @@ module Haml
99
106
  @options[:encoding] = @options[:encoding].name
100
107
  end
101
108
 
102
- template = check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
103
-
104
109
  # :eod is a special end-of-document marker
105
110
  @template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
106
111
  @template_index = 0
@@ -323,6 +323,12 @@ END
323
323
  opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
324
324
  @options[:for_engine][:cache] = false
325
325
  end
326
+
327
+ unless ::Haml::Util.ruby1_8?
328
+ opts.on('-E encoding', 'Specify the default encoding for Sass files.') do |encoding|
329
+ Encoding.default_external = encoding
330
+ end
331
+ end
326
332
  end
327
333
 
328
334
  # Processes the options set by the command-line arguments,
@@ -474,6 +480,14 @@ MSG
474
480
  @options[:load_paths] << path
475
481
  end
476
482
 
483
+ unless ::Haml::Util.ruby1_8?
484
+ opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
485
+ external, internal = encoding.split(':')
486
+ Encoding.default_external = external if external && !external.empty?
487
+ Encoding.default_internal = internal if internal && !internal.empty?
488
+ end
489
+ end
490
+
477
491
  opts.on('--debug', "Print out the precompiled Ruby source.") do
478
492
  @options[:debug] = true
479
493
  end
@@ -656,6 +670,12 @@ END
656
670
  @options[:for_engine][:read_cache] = false
657
671
  end
658
672
 
673
+ unless ::Haml::Util.ruby1_8?
674
+ opts.on('-E encoding', 'Specify the default encoding for Sass and CSS files.') do |encoding|
675
+ Encoding.default_external = encoding
676
+ end
677
+ end
678
+
659
679
  super
660
680
  end
661
681
 
@@ -285,7 +285,7 @@ module Haml
285
285
  self.previous.content =~ /\A\s*\Z/ && self.previous.previous.nil?)
286
286
  nuke_outer_whitespace = true
287
287
  else
288
- output << "- succeed #{self.next.content.slice!(/\A[^\s]+/).dump} do\n"
288
+ output << "= succeed #{self.next.content.slice!(/\A[^\s]+/).dump} do\n"
289
289
  tabs += 1
290
290
  output << tabulate(tabs)
291
291
  end
@@ -43,7 +43,11 @@ module Haml
43
43
  end
44
44
 
45
45
  unless Haml::Util.rails_env == "development"
46
- Haml::Template.options[:ugly] = true
46
+ Haml::Template.options[:ugly] ||= true
47
+ end
48
+
49
+ if ActionPack::VERSION::MAJOR >= 3
50
+ Haml::Template.options[:format] ||= :html5
47
51
  end
48
52
 
49
53
  # Decide how we want to load Haml into Rails.
@@ -11,6 +11,8 @@ module Haml
11
11
  include Haml::Util.av_template_class(:Handlers)::Compilable
12
12
  end
13
13
 
14
+ def handles_encoding?; true; end
15
+
14
16
  def compile(template)
15
17
  options = Haml::Template.options.dup
16
18
 
@@ -2,6 +2,7 @@ require 'erb'
2
2
  require 'set'
3
3
  require 'enumerator'
4
4
  require 'stringio'
5
+ require 'strscan'
5
6
  require 'haml/root'
6
7
  require 'haml/util/subset_map'
7
8
 
@@ -127,9 +128,13 @@ module Haml
127
128
  # @param enum [Enumerable]
128
129
  # @return [Array] The enumerable with strings merged
129
130
  def merge_adjacent_strings(enum)
130
- e = enum.inject([]) do |a, e|
131
- if e.is_a?(String) && a.last.is_a?(String)
132
- a.last << e
131
+ enum.inject([]) do |a, e|
132
+ if e.is_a?(String)
133
+ if a.last.is_a?(String)
134
+ a.last << e
135
+ else
136
+ a << e.dup
137
+ end
133
138
  else
134
139
  a << e
135
140
  end
@@ -434,6 +439,109 @@ MSG
434
439
  return str
435
440
  end
436
441
 
442
+ # Like {\#check\_encoding}, but also checks for a Ruby-style `-# coding:` comment
443
+ # at the beginning of the template and uses that encoding if it exists.
444
+ #
445
+ # The Sass encoding rules are simple.
446
+ # If a `-# coding:` comment exists,
447
+ # we assume that that's the original encoding of the document.
448
+ # Otherwise, we use whatever encoding Ruby has.
449
+ #
450
+ # Haml uses the same rules for parsing coding comments as Ruby.
451
+ # This means that it can understand Emacs-style comments
452
+ # (e.g. `-*- encoding: "utf-8" -*-`),
453
+ # and also that it cannot understand non-ASCII-compatible encodings
454
+ # such as `UTF-16` and `UTF-32`.
455
+ #
456
+ # @param str [String] The Haml template of which to check the encoding
457
+ # @yield [msg] A block in which an encoding error can be raised.
458
+ # Only yields if there is an encoding error
459
+ # @yieldparam msg [String] The error message to be raised
460
+ # @return [String] The original string encoded properly
461
+ # @raise [ArgumentError] if the document declares an unknown encoding
462
+ def check_haml_encoding(str, &block)
463
+ return check_encoding(str, &block) if ruby1_8?
464
+
465
+ bom, encoding = parse_haml_magic_comment(str)
466
+ if encoding; str.force_encoding(encoding)
467
+ elsif bom; str.force_encoding("UTF-8")
468
+ end
469
+
470
+ return check_encoding(str, &block)
471
+ end
472
+
473
+ # Like {\#check\_encoding}, but also checks for a `@charset` declaration
474
+ # at the beginning of the file and uses that encoding if it exists.
475
+ #
476
+ # The Sass encoding rules are simple.
477
+ # If a `@charset` declaration exists,
478
+ # we assume that that's the original encoding of the document.
479
+ # Otherwise, we use whatever encoding Ruby has.
480
+ # Then we convert that to UTF-8 to process internally.
481
+ # The UTF-8 end result is what's returned by this method.
482
+ #
483
+ # @param str [String] The string of which to check the encoding
484
+ # @yield [msg] A block in which an encoding error can be raised.
485
+ # Only yields if there is an encoding error
486
+ # @yieldparam msg [String] The error message to be raised
487
+ # @return [(String, Encoding)] The original string encoded as UTF-8,
488
+ # and the source encoding of the string (or `nil` under Ruby 1.8)
489
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
490
+ # cannot be converted to UTF-8
491
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
492
+ def check_sass_encoding(str, &block)
493
+ return check_encoding(str, &block), nil if ruby1_8?
494
+ # We allow any printable ASCII characters but double quotes in the charset decl
495
+ bin = str.dup.force_encoding("BINARY")
496
+ encoding = Haml::Util::ENCODINGS_TO_CHECK.find do |enc|
497
+ bin =~ Haml::Util::CHARSET_REGEXPS[enc]
498
+ end
499
+ charset, bom = $1, $2
500
+ if charset
501
+ charset = charset.force_encoding(encoding).encode("UTF-8")
502
+ if endianness = encoding[/[BL]E$/]
503
+ begin
504
+ Encoding.find(charset + endianness)
505
+ charset << endianness
506
+ rescue ArgumentError # Encoding charset + endianness doesn't exist
507
+ end
508
+ end
509
+ str.force_encoding(charset)
510
+ elsif bom
511
+ str.force_encoding(encoding)
512
+ end
513
+
514
+ str = check_encoding(str, &block)
515
+ return str.encode("UTF-8"), str.encoding
516
+ end
517
+
518
+ unless ruby1_8?
519
+ # @private
520
+ def _enc(string, encoding)
521
+ string.encode(encoding).force_encoding("BINARY")
522
+ end
523
+
524
+ # We could automatically add in any non-ASCII-compatible encodings here,
525
+ # but there's not really a good way to do that
526
+ # without manually checking that each encoding
527
+ # encodes all ASCII characters properly,
528
+ # which takes long enough to affect the startup time of the CLI.
529
+ ENCODINGS_TO_CHECK = %w[UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE]
530
+
531
+ CHARSET_REGEXPS = Hash.new do |h, e|
532
+ h[e] =
533
+ begin
534
+ # /\A(?:\uFEFF)?@charset "(.*?)"|\A(\uFEFF)/
535
+ Regexp.new(/\A(?:#{_enc("\uFEFF", e)})?#{
536
+ _enc('@charset "', e)}(.*?)#{_enc('"', e)}|\A(#{
537
+ _enc("\uFEFF", e)})/)
538
+ rescue
539
+ # /\A@charset "(.*?)"/
540
+ Regexp.new(/\A#{_enc('@charset "', e)}(.*?)#{_enc('"', e)}/)
541
+ end
542
+ end
543
+ end
544
+
437
545
  # Checks to see if a class has a given method.
438
546
  # For example:
439
547
  #
@@ -623,5 +731,36 @@ METHOD
623
731
  return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
624
732
  return lcs_backtrace(c, x, y, i-1, j, &block)
625
733
  end
734
+
735
+ # Parses a magic comment at the beginning of a Haml file.
736
+ # The parsing rules are basically the same as Ruby's.
737
+ #
738
+ # @return [(Boolean, String or nil)]
739
+ # Whether the document begins with a UTF-8 BOM,
740
+ # and the declared encoding of the document (or nil if none is declared)
741
+ def parse_haml_magic_comment(str)
742
+ scanner = StringScanner.new(str.dup.force_encoding("BINARY"))
743
+ bom = scanner.scan(/\xEF\xBB\xBF/n)
744
+ return bom unless scanner.scan(/-\s*#\s*/n)
745
+ if coding = try_parse_haml_emacs_magic_comment(scanner)
746
+ return bom, coding
747
+ end
748
+
749
+ return bom unless scanner.scan(/.*?coding[=:]\s*([\w-]+)/in)
750
+ return bom, scanner[1]
751
+ end
752
+
753
+ def try_parse_haml_emacs_magic_comment(scanner)
754
+ pos = scanner.pos
755
+ return unless scanner.scan(/.*?-\*-\s*/n)
756
+ # From Ruby's parse.y
757
+ return unless scanner.scan(/([^\s'":;]+)\s*:\s*("(?:\\.|[^"])*"|[^"\s;]+?)[\s;]*-\*-/n)
758
+ name, val = scanner[1], scanner[2]
759
+ return unless name =~ /(en)?coding/in
760
+ val = $1 if val =~ /^"(.*)"$/n
761
+ return val
762
+ ensure
763
+ scanner.pos = pos
764
+ end
626
765
  end
627
766
  end
@@ -14,7 +14,12 @@ module Sass
14
14
  # Sass::CSS.new("p { color: blue }").render(:sass) #=> "p\n color: blue"
15
15
  # Sass::CSS.new("p { color: blue }").render(:scss) #=> "p {\n color: blue; }"
16
16
  class CSS
17
- # @param template [String] The CSS code
17
+ # @param template [String] The CSS stylesheet.
18
+ # This stylesheet can be encoded using any encoding
19
+ # that can be converted to Unicode.
20
+ # If the stylesheet contains an `@charset` declaration,
21
+ # that overrides the Ruby encoding
22
+ # (see {file:SASS_REFERENCE.md#encodings the encoding documentation})
18
23
  # @option options :old [Boolean] (false)
19
24
  # Whether or not to output old property syntax
20
25
  # (`:color blue` as opposed to `color: blue`).
@@ -37,18 +42,35 @@ module Sass
37
42
  # @return [String] The resulting Sass or SCSS code
38
43
  # @raise [Sass::SyntaxError] if there's an error parsing the CSS template
39
44
  def render(fmt = :sass)
40
- Haml::Util.check_encoding(@template) do |msg, line|
41
- raise Sass::SyntaxError.new(msg, :line => line)
42
- end
43
-
45
+ check_encoding!
44
46
  build_tree.send("to_#{fmt}", @options).strip + "\n"
45
47
  rescue Sass::SyntaxError => err
46
48
  err.modify_backtrace(:filename => @options[:filename] || '(css)')
47
49
  raise err
48
50
  end
49
51
 
52
+ # Returns the original encoding of the document,
53
+ # or `nil` under Ruby 1.8.
54
+ #
55
+ # @return [Encoding, nil]
56
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
57
+ # cannot be converted to UTF-8
58
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
59
+ def source_encoding
60
+ check_encoding!
61
+ @original_encoding
62
+ end
63
+
50
64
  private
51
65
 
66
+ def check_encoding!
67
+ return if @checked_encoding
68
+ @checked_encoding = true
69
+ @template, @original_encoding = Haml::Util.check_sass_encoding(@template) do |msg, line|
70
+ raise Sass::SyntaxError.new(msg, :line => line)
71
+ end
72
+ end
73
+
52
74
  # Parses the CSS template and applies various transformations
53
75
  #
54
76
  # @return [Tree::Node] The root node of the parsed tree
@@ -133,6 +133,11 @@ module Sass
133
133
  }.freeze
134
134
 
135
135
  # @param template [String] The Sass template.
136
+ # This template can be encoded using any encoding
137
+ # that can be converted to Unicode.
138
+ # If the template contains an `@charset` declaration,
139
+ # that overrides the Ruby encoding
140
+ # (see {file:SASS_REFERENCE.md#encodings the encoding documentation})
136
141
  # @param options [{Symbol => Object}] An options hash;
137
142
  # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
138
143
  def initialize(template, options={})
@@ -155,9 +160,12 @@ module Sass
155
160
  #
156
161
  # @return [String] The CSS
157
162
  # @raise [Sass::SyntaxError] if there's an error in the document
163
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
164
+ # cannot be converted to UTF-8
165
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
158
166
  def render
159
- return _to_tree.render unless @options[:quiet]
160
- Haml::Util.silence_haml_warnings {_to_tree.render}
167
+ return _render unless @options[:quiet]
168
+ Haml::Util.silence_haml_warnings {_render}
161
169
  end
162
170
  alias_method :to_css, :render
163
171
 
@@ -170,10 +178,28 @@ module Sass
170
178
  Haml::Util.silence_haml_warnings {_to_tree}
171
179
  end
172
180
 
181
+ # Returns the original encoding of the document,
182
+ # or `nil` under Ruby 1.8.
183
+ #
184
+ # @return [Encoding, nil]
185
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
186
+ # cannot be converted to UTF-8
187
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
188
+ def source_encoding
189
+ check_encoding!
190
+ @original_encoding
191
+ end
192
+
173
193
  private
174
194
 
195
+ def _render
196
+ rendered = _to_tree.render
197
+ return rendered if ruby1_8?
198
+ return rendered.encode(source_encoding)
199
+ end
200
+
175
201
  def _to_tree
176
- @template = check_encoding(@template) {|msg, line| raise Sass::SyntaxError.new(msg, :line => line)}
202
+ check_encoding!
177
203
 
178
204
  if @options[:syntax] == :scss
179
205
  root = Sass::SCSS::Parser.new(@template).parse
@@ -190,6 +216,14 @@ module Sass
190
216
  raise e
191
217
  end
192
218
 
219
+ def check_encoding!
220
+ return if @checked_encoding
221
+ @checked_encoding = true
222
+ @template, @original_encoding = check_sass_encoding(@template) do |msg, line|
223
+ raise Sass::SyntaxError.new(msg, :line => line)
224
+ end
225
+ end
226
+
193
227
  def tabulate(string)
194
228
  tab_str = nil
195
229
  comment_tab_str = nil
@@ -603,8 +637,7 @@ WARNING
603
637
  end
604
638
 
605
639
  return silent ? "//" : "/* */" if content.empty?
606
- content.each {|l| l.gsub!(/^\* /, '')}
607
- content.map! {|l| (l.empty? ? "" : " ") + l}
640
+ content.map! {|l| l.gsub!(/^\*( ?)/, '\1') || (l.empty? ? "" : " ") + l}
608
641
  content.first.gsub!(/^ /, '') unless removed_first
609
642
  content.last.gsub!(%r{ ?\*/ *$}, '')
610
643
  if silent
@@ -17,7 +17,9 @@ module Sass
17
17
  # @raise [Sass::SyntaxError] if there's an error in the document.
18
18
  # The caller has responsibility for setting backtrace information, if necessary
19
19
  def tree_for(filename, options)
20
- options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
20
+ default_options = Sass::Engine::DEFAULT_OPTIONS.dup
21
+ default_options.delete(:syntax)
22
+ options = default_options.merge!(options)
21
23
  text = File.read(filename)
22
24
 
23
25
  if options[:cache] || options[:read_cache]
@@ -32,9 +34,9 @@ module Sass
32
34
 
33
35
  options = options.merge(:filename => filename)
34
36
  if filename =~ /\.scss$/
35
- options = options.merge(:syntax => :scss)
37
+ options = {:syntax => :scss}.merge(options)
36
38
  elsif filename =~ /\.sass$/
37
- options = options.merge(:syntax => :sass)
39
+ options = {:syntax => :sass}.merge(options)
38
40
  end
39
41
 
40
42
  engine = Sass::Engine.new(text, options)
@@ -186,7 +186,7 @@ RUBY
186
186
  production :equals, :interpolation, :single_eq
187
187
 
188
188
  def try_op_before_interp(op, prev = nil)
189
- return unless @lexer.peek.type == :begin_interpolation
189
+ return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
190
190
  wb = @lexer.whitespace?(op)
191
191
  str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
192
192
  str.line = @lexer.line
@@ -6,7 +6,9 @@ module Sass
6
6
  # The parser for SCSS.
7
7
  # It parses a string of code into a tree of {Sass::Tree::Node}s.
8
8
  class Parser
9
- # @param str [String, StringScanner] The source document to parse
9
+ # @param str [String, StringScanner] The source document to parse.
10
+ # Note that `Parser` *won't* raise a nice error message if this isn't properly parsed;
11
+ # for that, you should use the higher-level {Sass::Engine} or {Sass::CSS}.
10
12
  # @param line [Fixnum] The line on which the source string appeared,
11
13
  # if it's part of another document
12
14
  def initialize(str, line = 1)
@@ -46,10 +48,7 @@ module Sass
46
48
  if @template.is_a?(StringScanner)
47
49
  @template
48
50
  else
49
- StringScanner.new(
50
- Haml::Util.check_encoding(@template) do |msg, line|
51
- raise Sass::SyntaxError.new(msg, :line => line)
52
- end.gsub("\r", ""))
51
+ StringScanner.new(@template.gsub("\r", ""))
53
52
  end
54
53
  end
55
54
 
@@ -70,7 +70,9 @@ module Sass
70
70
  # variable and mixin values
71
71
  def perform!(environment)
72
72
  environment.push_frame(:filename => @filename, :line => @line)
73
- root = Sass::Files.tree_for(full_filename, @options)
73
+ options = @options.dup
74
+ options.delete(:syntax)
75
+ root = Sass::Files.tree_for(full_filename, options)
74
76
  @template = root.template
75
77
  self.children = root.children
76
78
  self.children = perform_children(environment)
@@ -53,8 +53,11 @@ module Sass::Tree
53
53
  # @param rule [Array<String, Sass::Script::Node>]
54
54
  # The CSS rule. See \{#rule}
55
55
  def initialize(rule)
56
- @rule = Haml::Util.strip_string_array(
57
- Haml::Util.merge_adjacent_strings(rule))
56
+ #p rule
57
+ merged = Haml::Util.merge_adjacent_strings(rule)
58
+ #p merged
59
+ @rule = Haml::Util.strip_string_array(merged)
60
+ #p @rule
58
61
  @tabs = 0
59
62
  super()
60
63
  end
@@ -1546,7 +1546,6 @@ HAML
1546
1546
  unless Haml::Util.ruby1_8?
1547
1547
  def test_default_encoding
1548
1548
  assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
1549
- HTML
1550
1549
  %p bar
1551
1550
  %p foo
1552
1551
  HAML
@@ -1605,6 +1604,202 @@ HAML
1605
1604
  assert_equal(3, e.line)
1606
1605
  assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
1607
1606
  end
1607
+
1608
+ def test_same_coding_comment_as_encoding
1609
+ assert_renders_encoded(<<HTML, <<HAML)
1610
+ <p>bâr</p>
1611
+ <p>föö</p>
1612
+ HTML
1613
+ -# coding: utf-8
1614
+ %p bâr
1615
+ %p föö
1616
+ HAML
1617
+ end
1618
+
1619
+ def test_different_coding_comment_than_encoding
1620
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1621
+ <p>bâr</p>
1622
+ <p>föö</p>
1623
+ HTML
1624
+ -# coding: ibm866
1625
+ %p bâr
1626
+ %p föö
1627
+ HAML
1628
+ end
1629
+
1630
+ def test_different_coding_than_system
1631
+ assert_renders_encoded(<<HTML.encode("IBM866"), <<HAML.encode("IBM866"))
1632
+ <p>тАЬ</p>
1633
+ HTML
1634
+ %p тАЬ
1635
+ HAML
1636
+ end
1637
+
1638
+ def test_case_insensitive_coding_comment
1639
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1640
+ <p>bâr</p>
1641
+ <p>föö</p>
1642
+ HTML
1643
+ -# CodINg: IbM866
1644
+ %p bâr
1645
+ %p föö
1646
+ HAML
1647
+ end
1648
+
1649
+ def test_whitespace_insensitive_coding_comment
1650
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1651
+ <p>bâr</p>
1652
+ <p>föö</p>
1653
+ HTML
1654
+ -#coding:ibm866
1655
+ %p bâr
1656
+ %p föö
1657
+ HAML
1658
+ end
1659
+
1660
+ def test_equals_coding_comment
1661
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1662
+ <p>bâr</p>
1663
+ <p>föö</p>
1664
+ HTML
1665
+ -# CodINg= ibm866
1666
+ %p bâr
1667
+ %p föö
1668
+ HAML
1669
+ end
1670
+
1671
+ def test_prefixed_coding_comment
1672
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1673
+ <p>bâr</p>
1674
+ <p>föö</p>
1675
+ HTML
1676
+ -# foo BAR FAOJcoding: ibm866
1677
+ %p bâr
1678
+ %p föö
1679
+ HAML
1680
+ end
1681
+
1682
+ def test_suffixed_coding_comment
1683
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1684
+ <p>bâr</p>
1685
+ <p>föö</p>
1686
+ HTML
1687
+ -# coding: ibm866 ASFJ (&(&#!$
1688
+ %p bâr
1689
+ %p föö
1690
+ HAML
1691
+ end
1692
+
1693
+ def test_emacs_prefixed_coding_comment
1694
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1695
+ <p>bâr</p>
1696
+ <p>föö</p>
1697
+ HTML
1698
+ -# -*- coding: ibm866
1699
+ %p bâr
1700
+ %p föö
1701
+ HAML
1702
+ end
1703
+
1704
+ def test_emacs_suffixed_coding_comment
1705
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1706
+ <p>bâr</p>
1707
+ <p>föö</p>
1708
+ HTML
1709
+ -# coding: ibm866 -*- coding: blah
1710
+ %p bâr
1711
+ %p föö
1712
+ HAML
1713
+ end
1714
+
1715
+ def test_emacs_coding_comment
1716
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1717
+ <p>bâr</p>
1718
+ <p>föö</p>
1719
+ HTML
1720
+ -# -*- coding: ibm866 -*-
1721
+ %p bâr
1722
+ %p föö
1723
+ HAML
1724
+ end
1725
+
1726
+ def test_emacs_encoding_comment
1727
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1728
+ <p>bâr</p>
1729
+ <p>föö</p>
1730
+ HTML
1731
+ -# -*- encoding: ibm866 -*-
1732
+ %p bâr
1733
+ %p föö
1734
+ HAML
1735
+ end
1736
+
1737
+ def test_quoted_emacs_coding_comment
1738
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1739
+ <p>bâr</p>
1740
+ <p>föö</p>
1741
+ HTML
1742
+ -# -*- coding: "ibm866" -*-
1743
+ %p bâr
1744
+ %p föö
1745
+ HAML
1746
+ end
1747
+
1748
+ def test_whitespace_insensitive_emacs_coding_comment
1749
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1750
+ <p>bâr</p>
1751
+ <p>föö</p>
1752
+ HTML
1753
+ -#-*-coding:ibm866-*-
1754
+ %p bâr
1755
+ %p föö
1756
+ HAML
1757
+ end
1758
+
1759
+ def test_whitespace_insensitive_emacs_coding_comment
1760
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1761
+ <p>bâr</p>
1762
+ <p>föö</p>
1763
+ HTML
1764
+ -#-*-coding:ibm866-*-
1765
+ %p bâr
1766
+ %p föö
1767
+ HAML
1768
+ end
1769
+
1770
+ def test_one_of_several_emacs_comments
1771
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1772
+ <p>bâr</p>
1773
+ <p>föö</p>
1774
+ HTML
1775
+ -# -*- foo: bar; coding: ibm866; baz: bang -*-
1776
+ %p bâr
1777
+ %p föö
1778
+ HAML
1779
+ end
1780
+
1781
+ def test_prefixed_emacs_coding_comment
1782
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1783
+ <p>bâr</p>
1784
+ <p>föö</p>
1785
+ HTML
1786
+ -# foo bar coding: baz -*- coding: ibm866 -*-
1787
+ %p bâr
1788
+ %p föö
1789
+ HAML
1790
+ end
1791
+
1792
+ def test_suffixed_emacs_coding_comment
1793
+ assert_renders_encoded(<<HTML.force_encoding("IBM866"), <<HAML)
1794
+ <p>bâr</p>
1795
+ <p>föö</p>
1796
+ HTML
1797
+ -# -*- coding: ibm866 -*- foo bar coding: baz
1798
+ %p bâr
1799
+ %p föö
1800
+ HAML
1801
+ end
1802
+
1608
1803
  end
1609
1804
 
1610
1805
  private
@@ -1619,4 +1814,10 @@ HAML
1619
1814
  <p>föö</p>
1620
1815
  HTML
1621
1816
  end
1817
+
1818
+ def assert_renders_encoded(html, haml)
1819
+ result = render(haml)
1820
+ assert_equal html.encoding, result.encoding
1821
+ assert_equal html, result
1822
+ end
1622
1823
  end
@@ -268,7 +268,7 @@ HTML
268
268
  assert_equal(<<HAML.rstrip, render(<<HTML))
269
269
  #foo
270
270
  Batch
271
- - succeed "," do
271
+ = succeed "," do
272
272
  %span Foo
273
273
  %span Bar
274
274
  HAML
@@ -64,6 +64,9 @@ class UtilTest < Test::Unit::TestCase
64
64
  def test_merge_adjacent_strings
65
65
  assert_equal(["foo bar baz", :bang, "biz bop", 12],
66
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]))
67
70
  end
68
71
 
69
72
  def test_intersperse
@@ -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
  require 'stringio'
@@ -1422,6 +1423,18 @@ CSS
1422
1423
  SASS
1423
1424
  end
1424
1425
 
1426
+ def test_loud_comments_with_no_space_after_starred_lines
1427
+ assert_equal(<<CSS, render(<<SASS))
1428
+ /*bip bop
1429
+ *beep boop
1430
+ *bap blimp */
1431
+ CSS
1432
+ /*bip bop
1433
+ *beep boop
1434
+ *bap blimp
1435
+ SASS
1436
+ end
1437
+
1425
1438
  def test_comment_indentation_at_beginning_of_doc
1426
1439
  assert_equal <<CSS, render(<<SASS)
1427
1440
  /* foo
@@ -2038,6 +2051,94 @@ SASS
2038
2051
  assert_equal(3, e.sass_line)
2039
2052
  assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
2040
2053
  end
2054
+
2055
+ def test_same_charset_as_encoding
2056
+ assert_renders_encoded(<<CSS, <<SASS)
2057
+ @charset "utf-8";
2058
+ fóó {
2059
+ a: b; }
2060
+ CSS
2061
+ @charset "utf-8"
2062
+ fóó
2063
+ a: b
2064
+ SASS
2065
+ end
2066
+
2067
+ def test_different_charset_than_encoding
2068
+ assert_renders_encoded(<<CSS.force_encoding("IBM866"), <<SASS)
2069
+ @charset "ibm866";
2070
+ fóó {
2071
+ a: b; }
2072
+ CSS
2073
+ @charset "ibm866"
2074
+ fóó
2075
+ a: b
2076
+ SASS
2077
+ end
2078
+
2079
+ def test_different_encoding_than_system
2080
+ assert_renders_encoded(<<CSS.encode("IBM866"), <<SASS.encode("IBM866"))
2081
+ тАЬ {
2082
+ a: b; }
2083
+ CSS
2084
+ тАЬ
2085
+ a: b
2086
+ SASS
2087
+ end
2088
+
2089
+ def test_multibyte_charset
2090
+ assert_renders_encoded(<<CSS.encode("UTF-16BE"), <<SASS.encode("UTF-16BE").force_encoding("UTF-8"))
2091
+ @charset "utf-16be";
2092
+ fóó {
2093
+ a: b; }
2094
+ CSS
2095
+ @charset "utf-16be"
2096
+ fóó
2097
+ a: b
2098
+ SASS
2099
+ end
2100
+
2101
+ def test_multibyte_charset_without_endian_specifier
2102
+ assert_renders_encoded(<<CSS.encode("UTF-32LE"), <<SASS.encode("UTF-32LE").force_encoding("UTF-8"))
2103
+ @charset "utf-32";
2104
+ fóó {
2105
+ a: b; }
2106
+ CSS
2107
+ @charset "utf-32"
2108
+ fóó
2109
+ a: b
2110
+ SASS
2111
+ end
2112
+
2113
+ def test_utf8_bom
2114
+ assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
2115
+ fóó {
2116
+ a: b; }
2117
+ CSS
2118
+ \uFEFFfóó
2119
+ a: b
2120
+ SASS
2121
+ end
2122
+
2123
+ def test_utf16le_bom
2124
+ assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("BINARY"))
2125
+ fóó {
2126
+ a: b; }
2127
+ CSS
2128
+ \uFEFFfóó
2129
+ a: b
2130
+ SASS
2131
+ end
2132
+
2133
+ def test_utf32be_bom
2134
+ assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("BINARY"))
2135
+ fóó {
2136
+ a: b; }
2137
+ CSS
2138
+ \uFEFFfóó
2139
+ a: b
2140
+ SASS
2141
+ end
2041
2142
  end
2042
2143
 
2043
2144
  private
@@ -2046,6 +2147,12 @@ SASS
2046
2147
  expected.each {|k, v| assert_equal(v, hash[k])}
2047
2148
  end
2048
2149
 
2150
+ def assert_renders_encoded(css, sass)
2151
+ result = render(sass)
2152
+ assert_equal css.encoding, result.encoding
2153
+ assert_equal css, result
2154
+ end
2155
+
2049
2156
  def render(sass, options = {})
2050
2157
  munge_filename options
2051
2158
  Sass::Engine.new(sass, options).render
@@ -979,6 +979,16 @@ foo {
979
979
  SCSS
980
980
  end
981
981
 
982
+ def test_interpolation_with_bracket_on_next_line
983
+ assert_equal <<CSS, render(<<SCSS)
984
+ a.foo b {
985
+ color: red; }
986
+ CSS
987
+ a.\#{"foo"} b
988
+ {color: red}
989
+ SCSS
990
+ end
991
+
982
992
  def test_extra_comma_in_mixin_arglist_error
983
993
  assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
984
994
  Invalid CSS after "@include foo(bar, ": expected mixin argument, was ")"
@@ -9,6 +9,7 @@ require 'sass'
9
9
 
10
10
  require 'haml/template'
11
11
  Haml::Template.options[:ugly] = false
12
+ Haml::Template.options[:format] = :xhtml
12
13
 
13
14
  Sass::RAILS_LOADED = true unless defined?(Sass::RAILS_LOADED)
14
15
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 3
7
7
  - 0
8
- - 6
9
- version: 3.0.6
8
+ - 7
9
+ version: 3.0.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nathan Weizenbaum
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-05-24 00:00:00 -07:00
19
+ date: 2010-06-01 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency