sass 3.2.0.alpha.53 → 3.2.0.alpha.54

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.
data/REVISION CHANGED
@@ -1 +1 @@
1
- d73070e1f6966118f181117faaf9c4cdd6a7d2a0
1
+ 594a6d23b2e7b60d1b522c1c2575c9db8681e9f7
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0.alpha.53
1
+ 3.2.0.alpha.54
@@ -1,7 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/../sass'
2
2
  require 'sass/tree/node'
3
3
  require 'sass/scss/css_parser'
4
- require 'strscan'
5
4
 
6
5
  module Sass
7
6
  # This class converts CSS documents into Sass or SCSS templates.
@@ -1,4 +1,3 @@
1
- require 'strscan'
2
1
  require 'set'
3
2
  require 'digest/sha1'
4
3
  require 'sass/cache_stores'
@@ -570,7 +569,7 @@ WARNING
570
569
  end
571
570
 
572
571
  def parse_property_or_rule(line)
573
- scanner = StringScanner.new(line.text)
572
+ scanner = Sass::Util::MultibyteStringScanner.new(line.text)
574
573
  hack_char = scanner.scan(/[:\*\.]|\#(?!\{)/)
575
574
  parser = Sass::SCSS::SassParser.new(scanner, @options[:filename], @line)
576
575
 
@@ -758,7 +757,7 @@ WARNING
758
757
  raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
759
758
  :line => @line + 1) unless line.children.empty?
760
759
 
761
- scanner = StringScanner.new(value)
760
+ scanner = Sass::Util::MultibyteStringScanner.new(value)
762
761
  values = []
763
762
 
764
763
  loop do
@@ -1,4 +1,3 @@
1
- require 'strscan'
2
1
  require 'sass/script/node'
3
2
  require 'sass/script/variable'
4
3
  require 'sass/script/funcall'
@@ -1,7 +1,5 @@
1
1
  require 'sass/scss/rx'
2
2
 
3
- require 'strscan'
4
-
5
3
  module Sass
6
4
  module Script
7
5
  # The lexical analyzer for SassScript.
@@ -126,7 +124,7 @@ module Sass
126
124
  # @param options [{Symbol => Object}] An options hash;
127
125
  # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
128
126
  def initialize(str, line, offset, options)
129
- @scanner = str.is_a?(StringScanner) ? str : StringScanner.new(str)
127
+ @scanner = str.is_a?(StringScanner) ? str : Sass::Util::MultibyteStringScanner.new(str)
130
128
  @line = line
131
129
  @offset = offset
132
130
  @options = options
@@ -1,4 +1,3 @@
1
- require 'strscan'
2
1
  require 'set'
3
2
 
4
3
  module Sass
@@ -50,7 +49,7 @@ module Sass
50
49
  if @template.is_a?(StringScanner)
51
50
  @template
52
51
  else
53
- StringScanner.new(@template.gsub("\r", ""))
52
+ Sass::Util::MultibyteStringScanner.new(@template.gsub("\r", ""))
54
53
  end
55
54
  end
56
55
 
@@ -915,7 +914,7 @@ MESSAGE
915
914
  if @throw_err
916
915
  throw :_sass_parser_error, err
917
916
  else
918
- @scanner = StringScanner.new(@scanner.string)
917
+ @scanner = Sass::Util::MultibyteStringScanner.new(@scanner.string)
919
918
  @scanner.pos = err[:pos]
920
919
  @line = err[:line]
921
920
  @expected = err[:expected]
@@ -1,5 +1,3 @@
1
- require 'strscan'
2
-
3
1
  module Sass
4
2
  # This module contains functionality that's shared between Haml and Sass.
5
3
  module Shared
@@ -16,7 +14,7 @@ module Sass
16
14
  # @yieldparam scan [StringScanner] The scanner scanning through the string
17
15
  # @return [String] The text remaining in the scanner after all `#{`s have been processed
18
16
  def handle_interpolation(str)
19
- scan = StringScanner.new(str)
17
+ scan = Sass::Util::MultibyteStringScanner.new(str)
20
18
  yield scan while scan.scan(/(.*?)(\\*)\#\{/m)
21
19
  scan.rest
22
20
  end
@@ -40,7 +38,7 @@ module Sass
40
38
  # `["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"]` in the example above.
41
39
  def balance(scanner, start, finish, count = 0)
42
40
  str = ''
43
- scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
41
+ scanner = Sass::Util::MultibyteStringScanner.new(scanner) unless scanner.is_a? StringScanner
44
42
  regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
45
43
  while scanner.scan(regexp)
46
44
  str << scanner.matched
@@ -2,7 +2,6 @@ require 'erb'
2
2
  require 'set'
3
3
  require 'enumerator'
4
4
  require 'stringio'
5
- require 'strscan'
6
5
  require 'rbconfig'
7
6
 
8
7
  require 'sass/root'
@@ -719,3 +718,5 @@ MSG
719
718
  end
720
719
  end
721
720
  end
721
+
722
+ require 'sass/util/multibyte_string_scanner'
@@ -0,0 +1,134 @@
1
+ require 'strscan'
2
+
3
+ if Sass::Util.ruby1_8?
4
+ Sass::Util::MultibyteStringScanner = StringScanner
5
+ else
6
+ # A wrapper of the native StringScanner class that works correctly with
7
+ # multibyte character encodings. The native class deals only in bytes, not
8
+ # characters, for methods like [#pos] and [#matched_size]. This class deals
9
+ # only in characters, instead.
10
+ class Sass::Util::MultibyteStringScanner < StringScanner
11
+ def self.new(str)
12
+ return StringScanner.new(str) if str.ascii_only?
13
+ super
14
+ end
15
+
16
+ def initialize(str)
17
+ super
18
+ @mb_pos = 0
19
+ @mb_matched_size = nil
20
+ @mb_last_pos = nil
21
+ end
22
+
23
+ alias_method :byte_pos, :pos
24
+ alias_method :byte_matched_size, :matched_size
25
+
26
+ def check(pattern); _match super; end
27
+ def check_until(pattern); _matched super; end
28
+ def getch; _forward _match super; end
29
+ def match?(pattern); _size check(pattern); end
30
+ def matched_size; @mb_matched_size; end
31
+ def peek(len); string[@mb_pos, len]; end
32
+ alias_method :peep, :peek
33
+ def pos; @mb_pos; end
34
+ alias_method :pointer, :pos
35
+ def rest_size; rest.size; end
36
+ def scan(pattern); _forward _match super; end
37
+ def scan_until(pattern); _forward _matched super; end
38
+ def skip(pattern); _size scan(pattern); end
39
+ def skip_until(pattern); _matched _size scan_until(pattern); end
40
+
41
+ def get_byte
42
+ raise "MultibyteStringScanner doesn't support #get_byte."
43
+ end
44
+
45
+ def getbyte
46
+ raise "MultibyteStringScanner doesn't support #getbyte."
47
+ end
48
+
49
+ def pos=(n)
50
+ @mb_last_pos = nil
51
+
52
+ # We set position kind of a lot during parsing, so we want it to be as
53
+ # efficient as possible. This is complicated by the fact that UTF-8 is a
54
+ # variable-length encoding, so it's difficult to find the byte length that
55
+ # corresponds to a given character length.
56
+ #
57
+ # Our heuristic here is to try to count the fewest possible characters. So
58
+ # if the new position is close to the current one, just count the
59
+ # characters between the two; if the new position is closer to the
60
+ # beginning of the string, just count the characters from there.
61
+ if @mb_pos - n < @mb_pos / 2
62
+ # New position is close to old position
63
+ byte_delta = @mb_pos > n ? -string[n...@mb_pos].bytesize : string[@mb_pos...n].bytesize
64
+ super(byte_pos + byte_delta)
65
+ else
66
+ # New position is close to BOS
67
+ super(string[0...n].bytesize)
68
+ end
69
+ @mb_pos = n
70
+ end
71
+
72
+ def reset
73
+ @mb_pos = 0
74
+ @mb_matched_size = nil
75
+ @mb_last_pos = nil
76
+ super
77
+ end
78
+
79
+ def scan_full(pattern, advance_pointer_p, return_string_p)
80
+ res = _match super(pattern, advance_pointer_p, true)
81
+ _forward res if advance_pointer_p
82
+ return res if return_string_p
83
+ end
84
+
85
+ def search_full(pattern, advance_pointer_p, return_string_p)
86
+ res = super(pattern, advance_pointer_p, true)
87
+ _forward res if advance_pointer_p
88
+ _matched((res if return_string_p))
89
+ end
90
+
91
+ def string=(str)
92
+ @mb_pos = 0
93
+ @mb_matched_size = nil
94
+ @mb_last_pos = nil
95
+ super
96
+ end
97
+
98
+ def terminate
99
+ @mb_pos = string.size
100
+ @mb_matched_size = nil
101
+ @mb_last_pos = nil
102
+ super
103
+ end
104
+ alias_method :clear, :terminate
105
+
106
+ def unscan
107
+ super
108
+ @mb_pos = @mb_last_pos
109
+ @mb_last_pos = @mb_matched_size = nil
110
+ end
111
+
112
+ private
113
+
114
+ def _size(str)
115
+ str && str.size
116
+ end
117
+
118
+ def _match(str)
119
+ @mb_matched_size = str && str.size
120
+ str
121
+ end
122
+
123
+ def _matched(res)
124
+ _match matched
125
+ res
126
+ end
127
+
128
+ def _forward(str)
129
+ @mb_last_pos = @mb_pos
130
+ @mb_pos += str.size if str
131
+ str
132
+ end
133
+ end
134
+ end
@@ -2545,6 +2545,31 @@ CSS
2545
2545
  a: b
2546
2546
  SASS
2547
2547
  end
2548
+
2549
+ # Encoding Regression Test
2550
+
2551
+ def test_multibyte_prop_name
2552
+ assert_equal(<<CSS, render(<<SASS))
2553
+ @charset "UTF-8";
2554
+ #bar {
2555
+ cölor: blue; }
2556
+ CSS
2557
+ #bar
2558
+ cölor: blue
2559
+ SASS
2560
+ end
2561
+
2562
+ def test_multibyte_and_interpolation
2563
+ assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
2564
+ #bar {
2565
+ background: a 0%; }
2566
+ CSS
2567
+ #bar {
2568
+ // 
2569
+ background: \#{a} 0%;
2570
+ }
2571
+ SCSS
2572
+ end
2548
2573
  end
2549
2574
 
2550
2575
  def test_original_filename_set
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/../../test_helper'
4
+
5
+ class MultibyteStringScannerTest < Test::Unit::TestCase
6
+ def setup
7
+ @scanner = Sass::Util::MultibyteStringScanner.new("cölorfül")
8
+ end
9
+
10
+ def test_initial
11
+ assert_scanner_state 0, 0, nil, nil
12
+ end
13
+
14
+ def test_check
15
+ assert_equal 'cö', @scanner.check(/../)
16
+ assert_scanner_state 0, 0, 2, 3
17
+ assert_equal 0, @scanner.pos
18
+ assert_equal 0, @scanner.pos
19
+ assert_equal 2, @scanner.matched_size
20
+ assert_equal 3, @scanner.byte_matched_size
21
+ end
22
+
23
+ def test_check_until
24
+ assert_equal 'cölorfü', @scanner.check_until(/f./)
25
+ assert_scanner_state 0, 0, 2, 3
26
+ end
27
+
28
+ def test_getch
29
+ assert_equal 'c', @scanner.getch
30
+ assert_equal 'ö', @scanner.getch
31
+ assert_scanner_state 2, 3, 1, 2
32
+ end
33
+
34
+ def test_match?
35
+ assert_equal 2, @scanner.match?(/../)
36
+ assert_scanner_state 0, 0, 2, 3
37
+ end
38
+
39
+ def test_peek
40
+ assert_equal 'cö', @scanner.peek(2)
41
+ assert_scanner_state 0, 0, nil, nil
42
+ end
43
+
44
+ def test_rest_size
45
+ assert_equal 'cö', @scanner.scan(/../)
46
+ assert_equal 6, @scanner.rest_size
47
+ end
48
+
49
+ def test_scan
50
+ assert_equal 'cö', @scanner.scan(/../)
51
+ assert_scanner_state 2, 3, 2, 3
52
+ end
53
+
54
+ def test_scan_until
55
+ assert_equal 'cölorfü', @scanner.scan_until(/f./)
56
+ assert_scanner_state 7, 9, 2, 3
57
+ end
58
+
59
+ def test_skip
60
+ assert_equal 2, @scanner.skip(/../)
61
+ assert_scanner_state 2, 3, 2, 3
62
+ end
63
+
64
+ def test_skip_until
65
+ assert_equal 7, @scanner.skip_until(/f./)
66
+ assert_scanner_state 7, 9, 2, 3
67
+ end
68
+
69
+ def test_set_pos
70
+ @scanner.pos = 7
71
+ assert_scanner_state 7, 9, nil, nil
72
+ @scanner.pos = 6
73
+ assert_scanner_state 6, 7, nil, nil
74
+ @scanner.pos = 1
75
+ assert_scanner_state 1, 1, nil, nil
76
+ end
77
+
78
+ def test_reset
79
+ @scanner.scan(/../)
80
+ @scanner.reset
81
+ assert_scanner_state 0, 0, nil, nil
82
+ end
83
+
84
+ def test_scan_full
85
+ assert_equal 'cö', @scanner.scan_full(/../, true, true)
86
+ assert_scanner_state 2, 3, 2, 3
87
+
88
+ @scanner.reset
89
+ assert_equal 'cö', @scanner.scan_full(/../, false, true)
90
+ assert_scanner_state 0, 0, 2, 3
91
+
92
+ @scanner.reset
93
+ assert_nil @scanner.scan_full(/../, true, false)
94
+ assert_scanner_state 2, 3, 2, 3
95
+
96
+ @scanner.reset
97
+ assert_nil @scanner.scan_full(/../, false, false)
98
+ assert_scanner_state 0, 0, 2, 3
99
+ end
100
+
101
+ def test_search_full
102
+ assert_equal 'cölorfü', @scanner.search_full(/f./, true, true)
103
+ assert_scanner_state 7, 9, 2, 3
104
+
105
+ @scanner.reset
106
+ assert_equal 'cölorfü', @scanner.search_full(/f./, false, true)
107
+ assert_scanner_state 0, 0, 2, 3
108
+
109
+ @scanner.reset
110
+ assert_nil @scanner.search_full(/f./, true, false)
111
+ assert_scanner_state 7, 9, 2, 3
112
+
113
+ @scanner.reset
114
+ assert_nil @scanner.search_full(/f./, false, false)
115
+ assert_scanner_state 0, 0, 2, 3
116
+ end
117
+
118
+ def test_set_string
119
+ @scanner.scan(/../)
120
+ @scanner.string = 'föóbâr'
121
+ assert_scanner_state 0, 0, nil, nil
122
+ end
123
+
124
+ def test_terminate
125
+ @scanner.scan(/../)
126
+ @scanner.terminate
127
+ assert_scanner_state 8, 10, nil, nil
128
+ end
129
+
130
+ def test_unscan
131
+ @scanner.scan(/../)
132
+ @scanner.scan_until(/f./)
133
+ @scanner.unscan
134
+ assert_scanner_state 2, 3, nil, nil
135
+ end
136
+
137
+ private
138
+
139
+ def assert_scanner_state(pos, byte_pos, matched_size, byte_matched_size)
140
+ assert_equal pos, @scanner.pos, 'pos'
141
+ assert_equal byte_pos, @scanner.byte_pos, 'byte_pos'
142
+ assert_equal matched_size, @scanner.matched_size, 'matched_size'
143
+ assert_equal byte_matched_size, @scanner.byte_matched_size, 'byte_matched_size'
144
+ end
145
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sass
3
3
  version: !ruby/object:Gem::Version
4
- hash: 592302967
4
+ hash: 592302961
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 2
9
9
  - 0
10
10
  - alpha
11
- - 53
12
- version: 3.2.0.alpha.53
11
+ - 54
12
+ version: 3.2.0.alpha.54
13
13
  platform: ruby
14
14
  authors:
15
15
  - Nathan Weizenbaum
@@ -19,7 +19,7 @@ autorequire:
19
19
  bindir: bin
20
20
  cert_chain: []
21
21
 
22
- date: 2012-01-04 00:00:00 -05:00
22
+ date: 2012-01-05 00:00:00 -05:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
@@ -164,6 +164,7 @@ files:
164
164
  - lib/sass/tree/while_node.rb
165
165
  - lib/sass/util.rb
166
166
  - lib/sass/util/subset_map.rb
167
+ - lib/sass/util/multibyte_string_scanner.rb
167
168
  - lib/sass/version.rb
168
169
  - vendor/fssm/Gemfile
169
170
  - vendor/fssm/LICENSE
@@ -306,6 +307,7 @@ files:
306
307
  - test/sass/templates/warn_imported.sass
307
308
  - test/sass/test_helper.rb
308
309
  - test/sass/util/subset_map_test.rb
310
+ - test/sass/util/multibyte_string_scanner_test.rb
309
311
  - test/sass/util_test.rb
310
312
  - test/test_helper.rb
311
313
  - extra/update_watch.rb
@@ -374,4 +376,5 @@ test_files:
374
376
  - test/sass/scss/rx_test.rb
375
377
  - test/sass/scss/scss_test.rb
376
378
  - test/sass/util/subset_map_test.rb
379
+ - test/sass/util/multibyte_string_scanner_test.rb
377
380
  - test/sass/util_test.rb