sass 3.3.0.alpha.218 → 3.3.0.alpha.222

Sign up to get free protection for your applications and to get access to all the features.
data/REVISION CHANGED
@@ -1 +1 @@
1
- 85f7ca624f2fb7d19320e107d518d3376952bf16
1
+ 0ef77dc0e3cff821aadca09aca98cac46354093d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.3.0.alpha.218
1
+ 3.3.0.alpha.222
data/VERSION_DATE CHANGED
@@ -1 +1 @@
1
- 27 July 2013 01:12:19 GMT
1
+ 30 July 2013 17:39:38 GMT
@@ -88,7 +88,7 @@ module Sass
88
88
  def parse_mixin_include_arglist
89
89
  args, keywords = [], {}
90
90
  if try_tok(:lparen)
91
- args, keywords, splat = mixin_arglist || [[], {}]
91
+ args, keywords, splat = mixin_arglist
92
92
  assert_tok(:rparen)
93
93
  end
94
94
  assert_done
@@ -343,7 +343,7 @@ RUBY
343
343
 
344
344
  def funcall
345
345
  return raw unless tok = try_tok(:funcall)
346
- args, keywords, splat = fn_arglist || [[], {}]
346
+ args, keywords, splat = fn_arglist
347
347
  assert_tok(:rparen)
348
348
  node(Script::Tree::Funcall.new(tok.value, args, keywords, splat),
349
349
  tok.source_range.start_pos, source_position)
@@ -388,10 +388,11 @@ RUBY
388
388
  end
389
389
 
390
390
  def arglist(subexpr, description)
391
- return unless e = send(subexpr)
392
-
393
391
  args = []
394
- keywords = {}
392
+ keywords = Sass::Util::NormalizedMap.new
393
+
394
+ return [args, keywords] unless e = send(subexpr)
395
+
395
396
  loop do
396
397
  if @lexer.peek && @lexer.peek.type == :colon
397
398
  name = e
@@ -399,11 +400,11 @@ RUBY
399
400
  assert_tok(:colon)
400
401
  value = assert_expr(subexpr, description)
401
402
 
402
- if keywords[name.underscored_name]
403
+ if keywords[name.name]
403
404
  raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
404
405
  end
405
406
 
406
- keywords[name.underscored_name] = value
407
+ keywords[name.name] = value
407
408
  else
408
409
  if !keywords.empty?
409
410
  raise SyntaxError.new("Positional arguments must come before keyword arguments.")
@@ -419,7 +420,6 @@ RUBY
419
420
  end
420
421
 
421
422
  def raw
422
- start_pos = source_position
423
423
  return special_fun unless tok = try_tok(:raw)
424
424
  literal_node(Script::Value::String.new(tok.value), tok.source_range)
425
425
  end
@@ -1,4 +1,5 @@
1
1
  require 'sass/script/functions'
2
+ require 'sass/util/normalized_map'
2
3
 
3
4
  module Sass::Script::Tree
4
5
  # A SassScript parse node representing a function call.
@@ -29,8 +30,8 @@ module Sass::Script::Tree
29
30
 
30
31
  # @param name [String] See \{#name}
31
32
  # @param args [Array<Node>] See \{#args}
33
+ # @param keywords [Sass::Util::NormalizedMap<Node>] See \{#keywords}
32
34
  # @param splat [Node] See \{#splat}
33
- # @param keywords [{String => Node}] See \{#keywords}
34
35
  def initialize(name, args, keywords, splat)
35
36
  @name = name
36
37
  @args = args
@@ -42,7 +43,7 @@ module Sass::Script::Tree
42
43
  # @return [String] A string representation of the function call
43
44
  def inspect
44
45
  args = @args.map {|a| a.inspect}.join(', ')
45
- keywords = Sass::Util.hash_to_a(@keywords).
46
+ keywords = Sass::Util.hash_to_a(@keywords.as_stored).
46
47
  map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
47
48
  if self.splat
48
49
  splat = (args.empty? && keywords.empty?) ? "" : ", "
@@ -60,7 +61,7 @@ module Sass::Script::Tree
60
61
  end
61
62
 
62
63
  args = @args.map(&arg_to_sass).join(', ')
63
- keywords = Sass::Util.hash_to_a(@keywords).
64
+ keywords = Sass::Util.hash_to_a(@keywords.as_stored).
64
65
  map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}.join(', ')
65
66
  if self.splat
66
67
  splat = (args.empty? && keywords.empty?) ? "" : ", "
@@ -83,7 +84,9 @@ module Sass::Script::Tree
83
84
  def deep_copy
84
85
  node = dup
85
86
  node.instance_variable_set('@args', args.map {|a| a.deep_copy})
86
- node.instance_variable_set('@keywords', Hash[keywords.map {|k, v| [k, v.deep_copy]}])
87
+ copied_keywords = Sass::Util::NormalizedMap.new
88
+ @keywords.as_stored.each {|k,v| copied_keywords[k] = v.deep_copy}
89
+ node.instance_variable_set('@keywords', copied_keywords)
87
90
  node
88
91
  end
89
92
 
data/lib/sass/util.rb CHANGED
@@ -30,6 +30,36 @@ module Sass
30
30
  File.join(Sass::ROOT_DIR, file)
31
31
  end
32
32
 
33
+ # Converts a hash or a list of pairs into an order-preserving hash.
34
+ #
35
+ # On Ruby 1.8.7, this uses the orderedhash gem to simulate an
36
+ # order-preserving hash. On Ruby 1.9 and up, it just uses the native Hash
37
+ # class, since that preserves the order itself.
38
+ #
39
+ # @overload ordered_hash(hash)
40
+ # @param hash [Hash] a normal hash to convert to an ordered hash
41
+ # @return [Hash]
42
+ # @overload ordered_hash(*pairs)
43
+ # @example
44
+ # ordered_hash([:foo, "bar"], [:baz, "bang"])
45
+ # #=> {:foo => "bar", :baz => "bang"}
46
+ # ordered_hash #=> {}
47
+ # @param pairs [Array<(Object, Object)>] the list of key/value pairs for
48
+ # the hash.
49
+ # @return [Hash]
50
+ def ordered_hash(*pairs_or_hash)
51
+ require 'sass/util/ordered_hash' if ruby1_8?
52
+
53
+ if pairs_or_hash.length == 1 && pairs_or_hash.first.is_a?(Hash)
54
+ hash = pairs_or_hash.first
55
+ return hash unless ruby1_8?
56
+ return OrderedHash.new.merge hash
57
+ end
58
+
59
+ return Hash[pairs_or_hash] unless ruby1_8?
60
+ return OrderedHash[*flatten(pairs_or_hash, 1)]
61
+ end
62
+
33
63
  # Converts an array of `[key, value]` pairs to a hash.
34
64
  #
35
65
  # @example
@@ -38,7 +68,7 @@ module Sass
38
68
  # @param arr [Array<(Object, Object)>] An array of pairs
39
69
  # @return [Hash] A hash
40
70
  def to_hash(arr)
41
- Hash[arr.compact]
71
+ ordered_hash(*arr.compact)
42
72
  end
43
73
 
44
74
  # Maps the keys in a hash according to a block.
@@ -1008,3 +1038,4 @@ MSG
1008
1038
  end
1009
1039
 
1010
1040
  require 'sass/util/multibyte_string_scanner'
1041
+ require 'sass/util/normalized_map'
@@ -0,0 +1,65 @@
1
+ require 'delegate'
2
+ require 'sass/util'
3
+
4
+ module Sass
5
+ module Util
6
+ # A hash that normalizes its string keys while still allowing you to get back
7
+ # to the original keys that were stored. If several different values normalize
8
+ # to the same value, whichever is stored last wins.
9
+ require 'sass/util/ordered_hash' if ruby1_8?
10
+ class NormalizedMap < DelegateClass(ruby1_8? ? OrderedHash : Hash)
11
+ # Create a normalized map
12
+ def initialize
13
+ @key_strings = {}
14
+ @map = Util.ruby1_8? ? OrderedHash.new : {}
15
+
16
+ # We delegate all hash methods that are not overridden here to @map.
17
+ super(@map)
18
+ end
19
+
20
+ # Specifies how to transform the key.
21
+ #
22
+ # This can be overridden to create other normalization behaviors.
23
+ def normalize(key)
24
+ key.tr("-", "_")
25
+ end
26
+
27
+ # @private
28
+ def []=(k, v)
29
+ normalized = normalize(k)
30
+ super(normalized, v)
31
+ @key_strings[normalized] = k
32
+ end
33
+
34
+ # @private
35
+ def [](k)
36
+ super(normalize(k))
37
+ end
38
+
39
+ # @private
40
+ def has_key?(k)
41
+ super(normalize(k))
42
+ end
43
+
44
+ # @private
45
+ def delete(k)
46
+ normalized = normalize(k)
47
+ @key_strings.delete(normalized)
48
+ super(normalized)
49
+ end
50
+
51
+ # @return [Hash] Hash with the keys as they were stored (before normalization).
52
+ def as_stored
53
+ Sass::Util.map_keys(@map) {|k| @key_strings[k]}
54
+ end
55
+
56
+ # this is magically invoked by ruby, not sure why DelegateClass doesn't take care of it.
57
+ # @private
58
+ def initialize_dup(other)
59
+ super
60
+ @map = other.instance_variable_get("@map").dup
61
+ __setobj__(@map)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,186 @@
1
+ # Copyright (c) 2005-2013 David Heinemeier Hansson
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # This class was copied from an old version of ActiveSupport.
23
+ class OrderedHash < ::Hash
24
+ # In MRI the Hash class is core and written in C. In particular, methods are
25
+ # programmed with explicit C function calls and polymorphism is not honored.
26
+ #
27
+ # For example, []= is crucial in this implementation to maintain the @keys
28
+ # array but hash.c invokes rb_hash_aset() originally. This prevents method
29
+ # reuse through inheritance and forces us to reimplement stuff.
30
+ #
31
+ # For instance, we cannot use the inherited #merge! because albeit the algorithm
32
+ # itself would work, our []= is not being called at all by the C code.
33
+
34
+ def initialize(*args, &block)
35
+ super
36
+ @keys = []
37
+ end
38
+
39
+ def self.[](*args)
40
+ ordered_hash = new
41
+
42
+ if (args.length == 1 && args.first.is_a?(Array))
43
+ args.first.each do |key_value_pair|
44
+ next unless (key_value_pair.is_a?(Array))
45
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
46
+ end
47
+
48
+ return ordered_hash
49
+ end
50
+
51
+ unless (args.size % 2 == 0)
52
+ raise ArgumentError.new("odd number of arguments for Hash")
53
+ end
54
+
55
+ args.each_with_index do |val, ind|
56
+ next if (ind % 2 != 0)
57
+ ordered_hash[val] = args[ind + 1]
58
+ end
59
+
60
+ ordered_hash
61
+ end
62
+
63
+ def initialize_copy(other)
64
+ super
65
+ # make a deep copy of keys
66
+ @keys = other.keys
67
+ end
68
+
69
+ def []=(key, value)
70
+ @keys << key unless has_key?(key)
71
+ super
72
+ end
73
+
74
+ def delete(key)
75
+ if has_key? key
76
+ index = @keys.index(key)
77
+ @keys.delete_at index
78
+ end
79
+ super
80
+ end
81
+
82
+ def delete_if
83
+ super
84
+ sync_keys!
85
+ self
86
+ end
87
+
88
+ def reject!
89
+ super
90
+ sync_keys!
91
+ self
92
+ end
93
+
94
+ def reject(&block)
95
+ dup.reject!(&block)
96
+ end
97
+
98
+ def keys
99
+ @keys.dup
100
+ end
101
+
102
+ def values
103
+ @keys.collect { |key| self[key] }
104
+ end
105
+
106
+ def to_hash
107
+ self
108
+ end
109
+
110
+ def to_a
111
+ @keys.map { |key| [ key, self[key] ] }
112
+ end
113
+
114
+ def each_key
115
+ return to_enum(:each_key) unless block_given?
116
+ @keys.each { |key| yield key }
117
+ self
118
+ end
119
+
120
+ def each_value
121
+ return to_enum(:each_value) unless block_given?
122
+ @keys.each { |key| yield self[key]}
123
+ self
124
+ end
125
+
126
+ def each
127
+ return to_enum(:each) unless block_given?
128
+ @keys.each {|key| yield [key, self[key]]}
129
+ self
130
+ end
131
+
132
+ def each_pair
133
+ return to_enum(:each_pair) unless block_given?
134
+ @keys.each {|key| yield key, self[key]}
135
+ self
136
+ end
137
+
138
+ alias_method :select, :find_all
139
+
140
+ def clear
141
+ super
142
+ @keys.clear
143
+ self
144
+ end
145
+
146
+ def shift
147
+ k = @keys.first
148
+ v = delete(k)
149
+ [k, v]
150
+ end
151
+
152
+ def merge!(other_hash)
153
+ if block_given?
154
+ other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
155
+ else
156
+ other_hash.each { |k, v| self[k] = v }
157
+ end
158
+ self
159
+ end
160
+
161
+ alias_method :update, :merge!
162
+
163
+ def merge(other_hash, &block)
164
+ dup.merge!(other_hash, &block)
165
+ end
166
+
167
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
168
+ def replace(other)
169
+ super
170
+ @keys = other.keys
171
+ self
172
+ end
173
+
174
+ def invert
175
+ OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
176
+ end
177
+
178
+ def inspect
179
+ "#<OrderedHash #{super}>"
180
+ end
181
+
182
+ private
183
+ def sync_keys!
184
+ @keys.delete_if {|k| !has_key?(k)}
185
+ end
186
+ end
@@ -1714,6 +1714,34 @@ foo {
1714
1714
  SCSS
1715
1715
  end
1716
1716
 
1717
+ def test_keyword_arguments
1718
+ assert_renders(<<SASS, <<SCSS, :dasherize => true)
1719
+ $foo: foo($dash-ed: 2px)
1720
+ SASS
1721
+ $foo: foo($dash-ed: 2px);
1722
+ SCSS
1723
+ assert_scss_to_sass(<<SASS, <<SCSS, :dasherize => true)
1724
+ $foo: foo($dash-ed: 2px)
1725
+ SASS
1726
+ $foo: foo($dash_ed: 2px);
1727
+ SCSS
1728
+ assert_sass_to_scss(<<SCSS, <<SASS, :dasherize => true)
1729
+ $foo: foo($dash-ed: 2px);
1730
+ SCSS
1731
+ $foo: foo($dash_ed: 2px)
1732
+ SASS
1733
+ assert_renders(<<SASS, <<SCSS)
1734
+ $foo: foo($under_scored: 1px)
1735
+ SASS
1736
+ $foo: foo($under_scored: 1px);
1737
+ SCSS
1738
+ assert_renders(<<SASS, <<SCSS)
1739
+ $foo: foo($dash-ed: 2px, $under_scored: 1px)
1740
+ SASS
1741
+ $foo: foo($dash-ed: 2px, $under_scored: 1px);
1742
+ SCSS
1743
+ end
1744
+
1717
1745
  private
1718
1746
 
1719
1747
  def assert_sass_to_sass(sass, options = {})
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../test_helper'
3
+ require 'sass/util/normalized_map'
4
+
5
+ class NormalizedMapTest < Test::Unit::TestCase
6
+ def test_basic_lifecycle
7
+ m = Sass::Util::NormalizedMap.new
8
+ m["a-b"] = 1
9
+ assert_equal ["a_b"], m.keys
10
+ assert_equal 1, m["a_b"]
11
+ assert_equal 1, m["a-b"]
12
+ assert m.has_key?("a_b")
13
+ assert m.has_key?("a-b")
14
+ assert_equal({"a-b" => 1}, m.as_stored)
15
+ assert_equal 1, m.delete("a-b")
16
+ assert !m.has_key?("a-b")
17
+ m["a_b"] = 2
18
+ assert_equal({"a_b" => 2}, m.as_stored)
19
+ end
20
+
21
+ def test_dup
22
+ m = Sass::Util::NormalizedMap.new
23
+ m["a-b"] = 1
24
+ m2 = m.dup
25
+ m.delete("a-b")
26
+ assert !m.has_key?("a-b")
27
+ assert m2.has_key?("a-b")
28
+ end
29
+
30
+ 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: 592302777
4
+ hash: 592302769
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 3
9
9
  - 0
10
10
  - alpha
11
- - 218
12
- version: 3.3.0.alpha.218
11
+ - 222
12
+ version: 3.3.0.alpha.222
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: 2013-07-26 00:00:00 -04:00
22
+ date: 2013-07-30 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
@@ -195,6 +195,8 @@ files:
195
195
  - lib/sass/util/multibyte_string_scanner.rb
196
196
  - lib/sass/util/subset_map.rb
197
197
  - lib/sass/util/test.rb
198
+ - lib/sass/util/normalized_map.rb
199
+ - lib/sass/util/ordered_hash.rb
198
200
  - lib/sass/version.rb
199
201
  - lib/sass/features.rb
200
202
  - bin/sass
@@ -317,6 +319,7 @@ files:
317
319
  - test/sass/test_helper.rb
318
320
  - test/sass/util/multibyte_string_scanner_test.rb
319
321
  - test/sass/util/subset_map_test.rb
322
+ - test/sass/util/normalized_map_test.rb
320
323
  - test/sass/source_map_test.rb
321
324
  - test/test_helper.rb
322
325
  - extra/update_watch.rb
@@ -389,4 +392,5 @@ test_files:
389
392
  - test/sass/compiler_test.rb
390
393
  - test/sass/util/multibyte_string_scanner_test.rb
391
394
  - test/sass/util/subset_map_test.rb
395
+ - test/sass/util/normalized_map_test.rb
392
396
  - test/sass/source_map_test.rb