sass 3.3.0.alpha.231 → 3.3.0.alpha.243
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/REVISION +1 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass/engine.rb +11 -7
- data/lib/sass/environment.rb +8 -0
- data/lib/sass/script/functions.rb +140 -17
- data/lib/sass/script/parser.rb +28 -5
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/value.rb +1 -0
- data/lib/sass/script/value/base.rb +29 -1
- data/lib/sass/script/value/color.rb +4 -0
- data/lib/sass/script/value/list.rb +27 -1
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/number.rb +12 -0
- data/lib/sass/scss/parser.rb +8 -2
- data/lib/sass/stack.rb +9 -0
- data/lib/sass/tree/each_node.rb +6 -6
- data/lib/sass/tree/rule_node.rb +1 -1
- data/lib/sass/tree/visitors/convert.rb +2 -1
- data/lib/sass/tree/visitors/perform.rb +19 -22
- data/lib/sass/tree/visitors/to_css.rb +1 -1
- data/test/sass/conversion_test.rb +10 -0
- data/test/sass/engine_test.rb +21 -0
- data/test/sass/functions_test.rb +126 -0
- data/test/sass/script_conversion_test.rb +16 -0
- data/test/sass/script_test.rb +41 -0
- data/test/sass/scss/scss_test.rb +25 -0
- metadata +11 -9
data/README.md
CHANGED
@@ -56,7 +56,7 @@ to `config.ru`.
|
|
56
56
|
Then any Sass files in `public/stylesheets/sass`
|
57
57
|
will be compiled into CSS files in `public/stylesheets` on every request.
|
58
58
|
|
59
|
-
To use Sass
|
59
|
+
To use Sass programmatically,
|
60
60
|
check out the [YARD documentation](http://sass-lang.com/docs/yardoc/).
|
61
61
|
|
62
62
|
## Formatting
|
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
01ca24be4a152901b7caffd7d3eeaf717dda29d4
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.0.alpha.
|
1
|
+
3.3.0.alpha.243
|
data/VERSION_DATE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
29 August 2013 23:26:16 GMT
|
data/lib/sass/engine.rb
CHANGED
@@ -874,21 +874,25 @@ WARNING
|
|
874
874
|
end
|
875
875
|
|
876
876
|
def parse_each(line, root, text)
|
877
|
-
|
877
|
+
vars, list_expr = text.scan(/^([^\s]+(?:\s*,\s*[^\s]+)*)\s+in\s+(.+)$/).first
|
878
878
|
|
879
|
-
if
|
879
|
+
if vars.nil? # scan failed, try to figure out why for error message
|
880
880
|
if text !~ /^[^\s]+/
|
881
881
|
expected = "variable name"
|
882
|
-
elsif text !~ /^[^\s]+\s+from\s+.+/
|
882
|
+
elsif text !~ /^[^\s]+(?:\s*,\s*[^\s]+)*[^\s]+\s+from\s+.+/
|
883
883
|
expected = "'in <expr>'"
|
884
884
|
end
|
885
|
-
raise SyntaxError.new("Invalid
|
885
|
+
raise SyntaxError.new("Invalid each directive '@each #{text}': expected #{expected}.")
|
886
|
+
end
|
887
|
+
|
888
|
+
vars = vars.split(',').map do |var|
|
889
|
+
var.strip!
|
890
|
+
raise SyntaxError.new("Invalid variable \"#{var}\".") unless var =~ Script::VALIDATE
|
891
|
+
var[1..-1]
|
886
892
|
end
|
887
|
-
raise SyntaxError.new("Invalid variable \"#{var}\".") unless var =~ Script::VALIDATE
|
888
893
|
|
889
|
-
var = var[1..-1]
|
890
894
|
parsed_list = parse_script(list_expr, :offset => line.offset + line.text.index(list_expr))
|
891
|
-
Tree::EachNode.new(
|
895
|
+
Tree::EachNode.new(vars, parsed_list)
|
892
896
|
end
|
893
897
|
|
894
898
|
def parse_else(parent, line, text)
|
data/lib/sass/environment.rb
CHANGED
@@ -28,6 +28,7 @@ module Sass
|
|
28
28
|
def initialize(parent = nil, options = nil)
|
29
29
|
@parent = parent
|
30
30
|
@options = options || (parent && parent.options) || {}
|
31
|
+
@stack = Sass::Stack.new if @parent.nil?
|
31
32
|
end
|
32
33
|
|
33
34
|
# The environment of the caller of this environment's mixin or function.
|
@@ -47,6 +48,13 @@ module Sass
|
|
47
48
|
@global_env ||= parent.nil? ? self : parent.global_env
|
48
49
|
end
|
49
50
|
|
51
|
+
# The import/mixin stack.
|
52
|
+
#
|
53
|
+
# @return [Sass::Stack]
|
54
|
+
def stack
|
55
|
+
@stack || global_env.stack
|
56
|
+
end
|
57
|
+
|
50
58
|
private
|
51
59
|
|
52
60
|
class << self
|
@@ -40,7 +40,7 @@ module Sass::Script
|
|
40
40
|
#
|
41
41
|
# \{#hsla hsla($hue, $saturation, $lightness, $alpha)}
|
42
42
|
# : Creates a {Sass::Script::Value::Color Color} from hue, saturation,
|
43
|
-
# lightness,
|
43
|
+
# lightness, and alpha values.
|
44
44
|
#
|
45
45
|
# \{#hue hue($color)}
|
46
46
|
# : Gets the hue component of a color.
|
@@ -154,6 +154,8 @@ module Sass::Script
|
|
154
154
|
#
|
155
155
|
# ## List Functions {#list-functions}
|
156
156
|
#
|
157
|
+
# All list functions work for maps as well, treating them as lists of pairs.
|
158
|
+
#
|
157
159
|
# \{#length length($list)}
|
158
160
|
# : Returns the length of a list.
|
159
161
|
#
|
@@ -175,6 +177,23 @@ module Sass::Script
|
|
175
177
|
# \{#list_separator list-separator(#list)}
|
176
178
|
# : Returns the separator of a list.
|
177
179
|
#
|
180
|
+
# ## Map Functions {#map-functions}
|
181
|
+
#
|
182
|
+
# \{#map_get map-get($map, $key)}
|
183
|
+
# : Returns the value in a map associated with a given key.
|
184
|
+
#
|
185
|
+
# \{#map_merge map-merge($map1, $map2)}
|
186
|
+
# : Merges two maps together into a new map.
|
187
|
+
#
|
188
|
+
# \{#map_keys map-keys($map)}
|
189
|
+
# : Returns a list of all keys in a map.
|
190
|
+
#
|
191
|
+
# \{#map_values map-values($map)}
|
192
|
+
# : Returns a list of all values in a map.
|
193
|
+
#
|
194
|
+
# \{#map_has_key map-has-key($key)}
|
195
|
+
# : Returns whether a map has a value associated with a given key.
|
196
|
+
#
|
178
197
|
# ## Introspection Functions
|
179
198
|
#
|
180
199
|
# \{#feature_exists feature-exists($feature)}
|
@@ -348,8 +367,7 @@ module Sass::Script
|
|
348
367
|
class EvaluationContext
|
349
368
|
include Functions
|
350
369
|
|
351
|
-
|
352
|
-
# The environment of the {Sass::Engine}
|
370
|
+
# The global environment.
|
353
371
|
#
|
354
372
|
# @return [Environment]
|
355
373
|
attr_reader :environment
|
@@ -380,7 +398,9 @@ module Sass::Script
|
|
380
398
|
# @param name [String, Symbol, nil] The name of the argument.
|
381
399
|
# @raise [ArgumentError] if value is not of the correct type.
|
382
400
|
def assert_type(value, type, name = nil)
|
383
|
-
|
401
|
+
klass = Sass::Script::Value.const_get(type)
|
402
|
+
return if value.is_a?(klass)
|
403
|
+
return if value.is_a?(Sass::Script::Value::List) && type == :Map && value.is_pseudo_map?
|
384
404
|
err = "#{value.inspect} is not a #{type.to_s.downcase}"
|
385
405
|
err = "$#{name.to_s.gsub('_', '-')}: " + err if name
|
386
406
|
raise ArgumentError.new(err)
|
@@ -552,9 +572,9 @@ module Sass::Script
|
|
552
572
|
end
|
553
573
|
declare :hsl, [:hue, :saturation, :lightness]
|
554
574
|
|
555
|
-
# Creates a {Sass::Script::Value::Color Color} from hue,
|
556
|
-
#
|
557
|
-
# spec][].
|
575
|
+
# Creates a {Sass::Script::Value::Color Color} from hue,
|
576
|
+
# saturation, lightness, and alpha values. Uses the algorithm from
|
577
|
+
# the [CSS3 spec][].
|
558
578
|
#
|
559
579
|
# [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
|
560
580
|
#
|
@@ -1561,9 +1581,12 @@ module Sass::Script
|
|
1561
1581
|
|
1562
1582
|
# Return the length of a list.
|
1563
1583
|
#
|
1584
|
+
# This can return the number of pairs in a map as well.
|
1585
|
+
#
|
1564
1586
|
# @example
|
1565
1587
|
# length(10px) => 1
|
1566
1588
|
# length(10px 20px 30px) => 3
|
1589
|
+
# length((width: 10px, height: 20px)) => 2
|
1567
1590
|
# @overload length($list)
|
1568
1591
|
# @param $list [Sass::Script::Value::Base]
|
1569
1592
|
# @return [Sass::Script::Value::Number]
|
@@ -1577,9 +1600,12 @@ module Sass::Script
|
|
1577
1600
|
# Note that unlike some languages, the first item in a Sass list is number
|
1578
1601
|
# 1, the second number 2, and so forth.
|
1579
1602
|
#
|
1603
|
+
# This can return the nth pair in a map as well.
|
1604
|
+
#
|
1580
1605
|
# @example
|
1581
1606
|
# nth(10px 20px 30px, 1) => 10px
|
1582
1607
|
# nth((Helvetica, Arial, sans-serif), 3) => sans-serif
|
1608
|
+
# nth((width: 10px, length: 20px), 2) => length, 20px
|
1583
1609
|
# @overload nth($list, $n)
|
1584
1610
|
# @param $list [Sass::Script::Value::Base]
|
1585
1611
|
# @param $n [Sass::Script::Value::Number] The index of the item to get.
|
@@ -1627,12 +1653,10 @@ module Sass::Script
|
|
1627
1653
|
unless %w[auto space comma].include?(separator.value)
|
1628
1654
|
raise ArgumentError.new("Separator name must be space, comma, or auto")
|
1629
1655
|
end
|
1630
|
-
sep1 = list1.separator if list1.is_a?(Sass::Script::Value::List) && !list1.value.empty?
|
1631
|
-
sep2 = list2.separator if list2.is_a?(Sass::Script::Value::List) && !list2.value.empty?
|
1632
1656
|
Sass::Script::Value::List.new(
|
1633
1657
|
list1.to_a + list2.to_a,
|
1634
1658
|
if separator.value == 'auto'
|
1635
|
-
|
1659
|
+
list1.separator || list2.separator || :space
|
1636
1660
|
else
|
1637
1661
|
separator.value.to_sym
|
1638
1662
|
end)
|
@@ -1663,11 +1687,10 @@ module Sass::Script
|
|
1663
1687
|
unless %w[auto space comma].include?(separator.value)
|
1664
1688
|
raise ArgumentError.new("Separator name must be space, comma, or auto")
|
1665
1689
|
end
|
1666
|
-
sep = list.separator if list.is_a?(Sass::Script::Value::List)
|
1667
1690
|
Sass::Script::Value::List.new(
|
1668
1691
|
list.to_a + [val],
|
1669
1692
|
if separator.value == 'auto'
|
1670
|
-
|
1693
|
+
list.separator || :space
|
1671
1694
|
else
|
1672
1695
|
separator.value.to_sym
|
1673
1696
|
end)
|
@@ -1711,9 +1734,12 @@ module Sass::Script
|
|
1711
1734
|
# Note that unlike some languages, the first item in a Sass list is number
|
1712
1735
|
# 1, the second number 2, and so forth.
|
1713
1736
|
#
|
1737
|
+
# This can return the position of a pair in a map as well.
|
1738
|
+
#
|
1714
1739
|
# @example
|
1715
1740
|
# index(1px solid red, solid) => 2
|
1716
1741
|
# index(1px solid red, dashed) => false
|
1742
|
+
# index((width: 10px, height: 20px), (height, 20px)) => 2
|
1717
1743
|
# @overload index($list, $value)
|
1718
1744
|
# @param $list [Sass::Script::Value::Base]
|
1719
1745
|
# @param $value [Sass::Script::Value::Base]
|
@@ -1740,14 +1766,99 @@ module Sass::Script
|
|
1740
1766
|
# @param $list [Sass::Script::Value::Base]
|
1741
1767
|
# @return [Sass::Script::Value::String] `comma` or `space`
|
1742
1768
|
def list_separator(list)
|
1743
|
-
|
1744
|
-
Sass::Script::Value::String.new(list.separator.to_s)
|
1745
|
-
else
|
1746
|
-
Sass::Script::Value::String.new('space')
|
1747
|
-
end
|
1769
|
+
Sass::Script::Value::String.new((list.separator || :space).to_s)
|
1748
1770
|
end
|
1749
1771
|
declare :separator, [:list]
|
1750
1772
|
|
1773
|
+
# Returns the value in a map associated with the given key. If the map
|
1774
|
+
# doesn't have such a key, returns `null`.
|
1775
|
+
#
|
1776
|
+
# @example
|
1777
|
+
# map-get(("foo": 1, "bar": 2), "foo") => 1
|
1778
|
+
# map-get(("foo": 1, "bar": 2), "bar") => 2
|
1779
|
+
# map-get(("foo": 1, "bar": 2), "baz") => null
|
1780
|
+
# @overload map_get($map, $key)
|
1781
|
+
# @param $map [Sass::Script::Value::Map]
|
1782
|
+
# @param $key [Sass::Script::Value::Base]
|
1783
|
+
# @return [Sass::Script::Value::Base] The value indexed by `$key`, or `null`
|
1784
|
+
# if the map doesn't contain the given key
|
1785
|
+
# @raise [ArgumentError] if `$map` is not a map
|
1786
|
+
def map_get(map, key)
|
1787
|
+
assert_type map, :Map
|
1788
|
+
to_h(map)[key] || Sass::Script::Value::Null.new
|
1789
|
+
end
|
1790
|
+
declare :map_get, [:map, :key]
|
1791
|
+
|
1792
|
+
# Merges two maps together into a new map. Keys in `$map2` will take
|
1793
|
+
# precedence over keys in `$map1`.
|
1794
|
+
#
|
1795
|
+
# This is the best way to add new values to a map.
|
1796
|
+
#
|
1797
|
+
# All keys in the returned map that also appear in `$map1` will have the
|
1798
|
+
# same order as in `$map1`. New keys from `$map2` will be placed at the end
|
1799
|
+
# of the map.
|
1800
|
+
#
|
1801
|
+
# @example
|
1802
|
+
# map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)
|
1803
|
+
# map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
|
1804
|
+
# @overload map_merge($map1, $map2)
|
1805
|
+
# @param $map1 [Sass::Script::Value::Map]
|
1806
|
+
# @param $map2 [Sass::Script::Value::Map]
|
1807
|
+
# @return [Sass::Script::Value::Map]
|
1808
|
+
# @raise [ArgumentError] if either parameter is not a map
|
1809
|
+
def map_merge(map1, map2)
|
1810
|
+
assert_type map1, :Map
|
1811
|
+
assert_type map2, :Map
|
1812
|
+
Sass::Script::Value::Map.new(to_h(map1).merge(to_h(map2)))
|
1813
|
+
end
|
1814
|
+
declare :map_get, [:map1, :map2]
|
1815
|
+
|
1816
|
+
# Returns a list of all keys in a map.
|
1817
|
+
#
|
1818
|
+
# @example
|
1819
|
+
# map-keys(("foo": 1, "bar": 2)) => "foo", "bar"
|
1820
|
+
# @overload map_keys($map)
|
1821
|
+
# @param $map [Map]
|
1822
|
+
# @return [List] the list of keys, comma-separated
|
1823
|
+
# @raise [ArgumentError] if `$map` is not a map
|
1824
|
+
def map_keys(map)
|
1825
|
+
assert_type map, :Map
|
1826
|
+
Sass::Script::Value::List.new(to_h(map).keys, :comma)
|
1827
|
+
end
|
1828
|
+
declare :map_keys, [:map]
|
1829
|
+
|
1830
|
+
# Returns a list of all values in a map. This list may include duplicate
|
1831
|
+
# values, if multiple keys have the same value.
|
1832
|
+
#
|
1833
|
+
# @example
|
1834
|
+
# map-keys(("foo": 1, "bar": 2)) => 1, 2
|
1835
|
+
# map-keys(("foo": 1, "bar": 2, "baz": 1)) => 1, 2, 1
|
1836
|
+
# @overload map_values($map)
|
1837
|
+
# @param $map [Map]
|
1838
|
+
# @return [List] the list of values, comma-separated
|
1839
|
+
# @raise [ArgumentError] if `$map` is not a map
|
1840
|
+
def map_values(map)
|
1841
|
+
assert_type map, :Map
|
1842
|
+
Sass::Script::Value::List.new(to_h(map).values, :comma)
|
1843
|
+
end
|
1844
|
+
declare :map_values, [:map]
|
1845
|
+
|
1846
|
+
# Returns whether a map has a value associated with a given key.
|
1847
|
+
#
|
1848
|
+
# @example
|
1849
|
+
# map-has-key(("foo": 1, "bar": 2), "foo") => true
|
1850
|
+
# map-has-key(("foo": 1, "bar": 2), "baz") => false
|
1851
|
+
# @overload map_has_key($map, $key)
|
1852
|
+
# @param $map [Sass::Script::Value::Map]
|
1853
|
+
# @param $key [Sass::Script::Value::Base]
|
1854
|
+
# @return [Sass::Script::Value::Bool]
|
1855
|
+
# @raise [ArgumentError] if `$map` is not a map
|
1856
|
+
def map_has_key(map, key)
|
1857
|
+
assert_type map, :Map
|
1858
|
+
Sass::Script::Value::Bool.new(to_h(map).has_key?(key))
|
1859
|
+
end
|
1860
|
+
declare :map_has_key, [:map, :key]
|
1861
|
+
|
1751
1862
|
# Returns one of two values, depending on whether or not `$condition` is
|
1752
1863
|
# true. Just like in `@if`, all values other than `false` and `null` are
|
1753
1864
|
# considered to be true.
|
@@ -1847,5 +1958,17 @@ module Sass::Script
|
|
1847
1958
|
color.with(attr => Sass::Util.restrict(
|
1848
1959
|
color.send(attr).send(op, amount.value), range))
|
1849
1960
|
end
|
1961
|
+
|
1962
|
+
def to_h(obj)
|
1963
|
+
return obj.to_h unless obj.is_a?(Sass::Script::Value::List) && obj.needs_map_warning?
|
1964
|
+
|
1965
|
+
fn_name = Sass::Util.caller_info.last.gsub('_', '-')
|
1966
|
+
Sass::Util.sass_warn <<WARNING + environment.stack.to_s.gsub(/^/, ' ')
|
1967
|
+
DEPRECATION WARNING: Passing lists of pairs to #{fn_name} is deprecated and will
|
1968
|
+
be removed in future versions of Sass. Use Sass maps instead. For details, see
|
1969
|
+
http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
|
1970
|
+
WARNING
|
1971
|
+
return obj.to_h
|
1972
|
+
end
|
1850
1973
|
end
|
1851
1974
|
end
|
data/lib/sass/script/parser.rb
CHANGED
@@ -253,11 +253,34 @@ RUBY
|
|
253
253
|
# @private
|
254
254
|
def lexer_class; Lexer; end
|
255
255
|
|
256
|
+
def map
|
257
|
+
start_pos = source_position
|
258
|
+
return unless e = interpolation
|
259
|
+
return list e, start_pos unless @lexer.peek && @lexer.peek.type == :colon
|
260
|
+
|
261
|
+
key, value = map_pair(e)
|
262
|
+
map = node(Sass::Script::Tree::MapLiteral.new([[key, value]]), start_pos)
|
263
|
+
while tok = try_tok(:comma)
|
264
|
+
key, value = assert_expr(:map_pair)
|
265
|
+
map.pairs << [key, value]
|
266
|
+
end
|
267
|
+
map
|
268
|
+
end
|
269
|
+
|
270
|
+
def map_pair(key=nil)
|
271
|
+
return unless key ||= interpolation
|
272
|
+
assert_tok :colon
|
273
|
+
return key, assert_expr(:interpolation)
|
274
|
+
end
|
275
|
+
|
256
276
|
def expr
|
257
|
-
interp = try_ops_after_interp([:comma], :expr) and return interp
|
258
277
|
start_pos = source_position
|
259
278
|
return unless e = interpolation
|
260
|
-
list
|
279
|
+
list e, start_pos
|
280
|
+
end
|
281
|
+
|
282
|
+
def list(first, start_pos)
|
283
|
+
list = node(Sass::Script::Tree::ListLiteral.new([first], :comma), start_pos)
|
261
284
|
while tok = try_tok(:comma)
|
262
285
|
if interp = try_op_before_interp(tok, list)
|
263
286
|
return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
|
@@ -447,10 +470,10 @@ RUBY
|
|
447
470
|
was_in_parens = @in_parens
|
448
471
|
@in_parens = true
|
449
472
|
start_pos = source_position
|
450
|
-
e =
|
473
|
+
e = map
|
451
474
|
end_pos = source_position
|
452
475
|
assert_tok(:rparen)
|
453
|
-
return e || node(Sass::Script::Tree::ListLiteral.new([],
|
476
|
+
return e || node(Sass::Script::Tree::ListLiteral.new([], nil), start_pos, end_pos)
|
454
477
|
ensure
|
455
478
|
@in_parens = was_in_parens
|
456
479
|
end
|
@@ -502,7 +525,7 @@ RUBY
|
|
502
525
|
end
|
503
526
|
|
504
527
|
def try_tok(*names)
|
505
|
-
peeked =
|
528
|
+
peeked = @lexer.peek
|
506
529
|
peeked && names.include?(peeked.type) && @lexer.next
|
507
530
|
end
|
508
531
|
|
data/lib/sass/script/tree.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Sass::Script::Tree
|
2
|
+
# A class representing a map literal. When resolved, this returns a
|
3
|
+
# {Sass::Script::Node::Map}.
|
4
|
+
class MapLiteral < Node
|
5
|
+
# The key/value pairs that make up this map node. This isn't a Hash so that
|
6
|
+
# we can detect key collisions once all the keys have been performed.
|
7
|
+
#
|
8
|
+
# @return [Array<(Node, Node)>]
|
9
|
+
attr_reader :pairs
|
10
|
+
|
11
|
+
# Creates a new map literal.
|
12
|
+
#
|
13
|
+
# @param pairs [Array<(Node, Node)>] See \{#pairs}
|
14
|
+
def initialize(pairs)
|
15
|
+
@pairs = pairs
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see Node#children
|
19
|
+
def children
|
20
|
+
@pairs.flatten
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see Node#to_sass
|
24
|
+
def to_sass(opts = {})
|
25
|
+
return "()" if pairs.empty?
|
26
|
+
|
27
|
+
to_sass = lambda do |value|
|
28
|
+
if value.is_a?(ListLiteral) && value.separator == :comma
|
29
|
+
"(#{value.to_sass(opts)})"
|
30
|
+
else
|
31
|
+
value.to_sass(opts)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
"(" + pairs.map {|(k, v)| "#{to_sass[k]}: #{to_sass[v]}"}.join(', ') + ")"
|
36
|
+
end
|
37
|
+
alias_method :inspect, :to_sass
|
38
|
+
|
39
|
+
# @see Node#deep_copy
|
40
|
+
def deep_copy
|
41
|
+
node = dup
|
42
|
+
node.instance_variable_set('@pairs',
|
43
|
+
pairs.map {|(k, v)| [k.deep_copy, v.deep_copy]})
|
44
|
+
node
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# @see Node#_perform
|
50
|
+
def _perform(environment)
|
51
|
+
keys = Set.new
|
52
|
+
map = Sass::Script::Value::Map.new(Sass::Util.to_hash(pairs.map do |(k, v)|
|
53
|
+
k, v = k.perform(environment), v.perform(environment)
|
54
|
+
if keys.include?(k)
|
55
|
+
raise Sass::SyntaxError.new("Duplicate key #{k.inspect} in map #{to_sass}.")
|
56
|
+
end
|
57
|
+
keys << k
|
58
|
+
[k, v]
|
59
|
+
end))
|
60
|
+
map.options = self.options
|
61
|
+
map
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|