sass 3.3.0.rc.1 → 3.3.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/lib/sass.rb +5 -0
  5. data/lib/sass/engine.rb +3 -5
  6. data/lib/sass/plugin.rb +0 -1
  7. data/lib/sass/plugin/compiler.rb +1 -2
  8. data/lib/sass/script/functions.rb +16 -2
  9. data/lib/sass/script/lexer.rb +22 -12
  10. data/lib/sass/script/parser.rb +27 -14
  11. data/lib/sass/script/tree/variable.rb +1 -1
  12. data/lib/sass/script/value/base.rb +1 -1
  13. data/lib/sass/script/value/color.rb +29 -17
  14. data/lib/sass/script/value/list.rb +1 -1
  15. data/lib/sass/script/value/number.rb +8 -1
  16. data/lib/sass/scss/parser.rb +2 -2
  17. data/lib/sass/selector/sequence.rb +18 -19
  18. data/lib/sass/selector/simple_sequence.rb +5 -5
  19. data/lib/sass/source/map.rb +1 -1
  20. data/lib/sass/tree/node.rb +25 -0
  21. data/lib/sass/tree/variable_node.rb +5 -0
  22. data/lib/sass/tree/visitors/base.rb +4 -7
  23. data/lib/sass/tree/visitors/check_nesting.rb +2 -2
  24. data/lib/sass/tree/visitors/perform.rb +12 -7
  25. data/lib/sass/util.rb +95 -50
  26. data/lib/sass/util/normalized_map.rb +63 -14
  27. data/lib/sass/util/ordered_hash.rb +9 -5
  28. data/lib/sass/version.rb +10 -12
  29. data/test/sass/engine_test.rb +37 -0
  30. data/test/sass/functions_test.rb +9 -2
  31. data/test/sass/importer_test.rb +3 -3
  32. data/test/sass/script_test.rb +12 -10
  33. data/test/sass/source_map_test.rb +8 -8
  34. data/test/sass/util/normalized_map_test.rb +22 -1
  35. data/test/sass/util_test.rb +18 -0
  36. data/test/test_helper.rb +16 -0
  37. data/vendor/listen/CHANGELOG.md +228 -0
  38. data/vendor/listen/CONTRIBUTING.md +38 -0
  39. data/vendor/listen/Gemfile +30 -0
  40. data/vendor/listen/Guardfile +8 -0
  41. data/vendor/listen/LICENSE +20 -0
  42. data/vendor/listen/README.md +315 -0
  43. data/vendor/listen/Rakefile +47 -0
  44. data/vendor/listen/Vagrantfile +96 -0
  45. data/vendor/listen/lib/listen.rb +40 -0
  46. data/vendor/listen/lib/listen/adapter.rb +214 -0
  47. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  48. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  49. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  50. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  51. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  52. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  53. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  54. data/vendor/listen/lib/listen/listener.rb +225 -0
  55. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  56. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  57. data/vendor/listen/lib/listen/version.rb +3 -0
  58. data/vendor/listen/listen.gemspec +22 -0
  59. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  60. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  61. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  62. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  63. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  64. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  65. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  66. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  67. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  68. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  69. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  70. data/vendor/listen/spec/listen_spec.rb +73 -0
  71. data/vendor/listen/spec/spec_helper.rb +21 -0
  72. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  73. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  74. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  75. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  76. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  77. metadata +318 -300
  78. data/test/Gemfile.lock +0 -10
@@ -93,7 +93,7 @@ module Sass
93
93
  choices
94
94
  end
95
95
  weaves = Sass::Util.paths(extended_not_expanded).map {|path| weave(path)}
96
- Sass::Util.flatten(trim(weaves), 1).map {|p| Sequence.new(p)}
96
+ trim(weaves).map {|p| Sequence.new(p)}
97
97
  end
98
98
 
99
99
  # Returns whether or not this selector matches all elements
@@ -137,32 +137,31 @@ module Sass
137
137
 
138
138
  private
139
139
 
140
- # Conceptually, this expands "parenthesized selectors".
141
- # That is, if we have `.A .B {@extend .C}` and `.D .C {...}`,
142
- # this conceptually expands into `.D .C, .D (.A .B)`,
143
- # and this function translates `.D (.A .B)` into `.D .A .B, .A.D .B, .D .A .B`.
140
+ # Conceptually, this expands "parenthesized selectors". That is, if we
141
+ # have `.A .B {@extend .C}` and `.D .C {...}`, this conceptually expands
142
+ # into `.D .C, .D (.A .B)`, and this function translates `.D (.A .B)` into
143
+ # `.D .A .B, .A .D .B`. For thoroughness, `.A.D .B` would also be
144
+ # required, but including merged selectors results in exponential output
145
+ # for very little gain.
144
146
  #
145
147
  # @param path [Array<Array<SimpleSequence or String>>]
146
148
  # A list of parenthesized selector groups.
147
149
  # @return [Array<Array<SimpleSequence or String>>] A list of fully-expanded selectors.
148
150
  def weave(path)
149
151
  # This function works by moving through the selector path left-to-right,
150
- # building all possible prefixes simultaneously. These prefixes are
151
- # `befores`, while the remaining parenthesized suffixes is `afters`.
152
- befores = [[]]
153
- afters = path.dup
152
+ # building all possible prefixes simultaneously.
153
+ prefixes = [[]]
154
154
 
155
- until afters.empty?
156
- current = afters.shift.dup
155
+ path.each do |current|
156
+ current = current.dup
157
157
  last_current = [current.pop]
158
- befores.map! do |before|
159
- sub = subweave(before, current)
158
+ prefixes = Sass::Util.flatten(prefixes.map do |prefix|
159
+ sub = subweave(prefix, current)
160
160
  next [] unless sub
161
161
  sub.map {|seqs| seqs + last_current}
162
- end
163
- befores = Sass::Util.flatten(befores, 1)
162
+ end, 1)
164
163
  end
165
- befores
164
+ prefixes
166
165
  end
167
166
 
168
167
  # This interweaves two lists of selectors,
@@ -455,11 +454,11 @@ module Sass
455
454
  # the other. The more specific selector is removed.
456
455
  #
457
456
  # @param seqses [Array<Array<Array<SimpleSequence or String>>>]
458
- # @return [Array<Array<Array<SimpleSequence or String>>>]
457
+ # @return [Array<Array<SimpleSequence or String>>]
459
458
  def trim(seqses)
460
459
  # Avoid truly horrific quadratic behavior. TODO: I think there
461
460
  # may be a way to get perfect trimming without going quadratic.
462
- return seqses if seqses.size > 100
461
+ return Sass::Util.flatten(seqses, 1) if seqses.size > 100
463
462
 
464
463
  # Keep the results in a separate array so we can be sure we aren't
465
464
  # comparing against an already-trimmed selector. This ensures that two
@@ -482,7 +481,7 @@ module Sass
482
481
  end
483
482
  end
484
483
  end
485
- result
484
+ Sass::Util.flatten(result, 1)
486
485
  end
487
486
 
488
487
  def _hash
@@ -107,18 +107,18 @@ module Sass
107
107
  # by extending this selector with `extends`.
108
108
  # @see CommaSequence#do_extend
109
109
  def do_extend(extends, parent_directives, seen = Set.new)
110
- groups = Sass::Util.group_by_to_a(extends.get(members.to_set)) {|ex, _| ex.extender}
110
+ groups = Sass::Util.group_by_to_a(extends[members.to_set]) {|ex| ex.extender}
111
111
  groups.map! do |seq, group|
112
- sels = group.map {|_, s| s}.flatten
112
+ sels = group.map {|e| e.target}.flatten
113
113
  # If A {@extend B} and C {...},
114
114
  # seq is A, sels is B, and self is C
115
115
 
116
116
  self_without_sel = Sass::Util.array_minus(members, sels)
117
- group.each {|e, _| e.result = :failed_to_unify unless e.result == :succeeded}
117
+ group.each {|e| e.result = :failed_to_unify unless e.result == :succeeded}
118
118
  unified = seq.members.last.unify(self_without_sel, subject?)
119
119
  next unless unified
120
- group.each {|e, _| e.result = :succeeded}
121
- group.each {|e, _| check_directives_match!(e, parent_directives)}
120
+ group.each {|e| e.result = :succeeded}
121
+ group.each {|e| check_directives_match!(e, parent_directives)}
122
122
  new_seq = Sequence.new(seq.members[0...-1] + [unified])
123
123
  new_seq.add_sources!(sources + [seq])
124
124
  [sels, new_seq]
@@ -104,7 +104,7 @@ module Sass::Source
104
104
  css_uri ||= css_path.relative_path_from(sourcemap_path.dirname).to_s
105
105
 
106
106
  result = "{\n"
107
- write_json_field(result, "version", "3", true)
107
+ write_json_field(result, "version", 3, true)
108
108
 
109
109
  source_uri_to_id = {}
110
110
  id_to_source_uri = {}
@@ -30,6 +30,31 @@ module Sass
30
30
  class Node
31
31
  include Enumerable
32
32
 
33
+ def self.inherited(base)
34
+ node_name = base.name.gsub(/.*::(.*?)Node$/, '\\1').downcase
35
+ base.instance_eval <<-METHODS
36
+ # @return [Symbol] The name that is used for this node when visiting.
37
+ def node_name
38
+ :#{node_name}
39
+ end
40
+
41
+ # @return [Symbol] The method that is used on the visitor to visit nodes of this type.
42
+ def visit_method
43
+ :visit_#{node_name}
44
+ end
45
+
46
+ # @return [Symbol] The method name that determines if the parent is invalid.
47
+ def invalid_child_method_name
48
+ :"invalid_#{node_name}_child?"
49
+ end
50
+
51
+ # @return [Symbol] The method name that determines if the node is an invalid parent.
52
+ def invalid_parent_method_name
53
+ :"invalid_#{node_name}_parent?"
54
+ end
55
+ METHODS
56
+ end
57
+
33
58
  # The child nodes of this node.
34
59
  #
35
60
  # @return [Array<Tree::Node>]
@@ -20,6 +20,11 @@ module Sass
20
20
  # @return [Boolean]
21
21
  attr_reader :global
22
22
 
23
+ # Whether we've warned about deprecated global variable
24
+ # assignment yet for this node.
25
+ # @return [Boolean]
26
+ attr_accessor :global_warning_given
27
+
23
28
  # @param name [String] The name of the variable
24
29
  # @param expr [Script::Tree::Node] See \{#expr}
25
30
  # @param guarded [Boolean] See \{#guarded}
@@ -32,9 +32,8 @@ module Sass::Tree::Visitors
32
32
  # @param node [Tree::Node] The node to visit.
33
33
  # @return [Object] The return value of the `visit_*` method for this node.
34
34
  def visit(node)
35
- method = "visit_#{self.class.node_name node}"
36
- if respond_to?(method, true)
37
- send(method, node) {visit_children(node)}
35
+ if respond_to?(node.class.visit_method, true)
36
+ send(node.class.visit_method, node) {visit_children(node)}
38
37
  else
39
38
  visit_children(node)
40
39
  end
@@ -53,15 +52,13 @@ module Sass::Tree::Visitors
53
52
  parent.children.map {|c| visit(c)}
54
53
  end
55
54
 
56
- NODE_NAME_RE = /.*::(.*?)Node$/
57
-
58
55
  # Returns the name of a node as used in the `visit_*` method.
59
56
  #
60
57
  # @param [Tree::Node] node The node.
61
58
  # @return [String] The name.
62
59
  def self.node_name(node)
63
- @node_names ||= {}
64
- @node_names[node.class.name] ||= node.class.name.gsub(NODE_NAME_RE, '\\1').downcase
60
+ Sass::Util.deprecated(self, "Call node.class.node_name instead.")
61
+ node.class.node_name
65
62
  end
66
63
 
67
64
  # `yield`s, then runs the visitor on the `@else` clause if the node has one.
@@ -9,8 +9,8 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
9
9
 
10
10
  def visit(node)
11
11
  if (error = @parent && (
12
- try_send("invalid_#{self.class.node_name @parent}_child?", @parent, node) ||
13
- try_send("invalid_#{self.class.node_name node}_parent?", @parent, node)))
12
+ try_send(@parent.class.invalid_child_method_name, @parent, node) ||
13
+ try_send(node.class.invalid_parent_method_name, @parent, node)))
14
14
  raise Sass::SyntaxError.new(error)
15
15
  end
16
16
  super
@@ -99,7 +99,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
99
99
  # @api private
100
100
  # @return [Sass::Script::Value::ArgList]
101
101
  def perform_splat(splat, performed_keywords, kwarg_splat, environment)
102
- args, kwargs, separator = [], Sass::Util.ordered_hash, :comma
102
+ args, kwargs, separator = [], nil, :comma
103
103
 
104
104
  if splat
105
105
  splat = splat.perform(environment)
@@ -113,8 +113,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
113
113
  args = splat.to_a
114
114
  end
115
115
  end
116
-
117
- kwargs = kwargs.merge(performed_keywords)
116
+ kwargs ||= Sass::Util.ordered_hash
117
+ kwargs.update(performed_keywords)
118
118
 
119
119
  if kwarg_splat
120
120
  kwarg_splat = kwarg_splat.perform(environment)
@@ -122,7 +122,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
122
122
  raise Sass::SyntaxError.new("Variable keyword arguments must be a map " +
123
123
  "(was #{kwarg_splat.inspect}).")
124
124
  end
125
- kwargs = kwargs.merge(arg_hash(kwarg_splat))
125
+ kwargs.update(arg_hash(kwarg_splat))
126
126
  end
127
127
 
128
128
  Sass::Script::Value::ArgList.new(args, kwargs, separator)
@@ -195,7 +195,11 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
195
195
  # Prints the expression to STDERR.
196
196
  def visit_debug(node)
197
197
  res = node.expr.perform(@environment)
198
- res = res.value if res.is_a?(Sass::Script::Value::String)
198
+ if res.is_a?(Sass::Script::Value::String)
199
+ res = res.value
200
+ else
201
+ res = res.to_sass
202
+ end
199
203
  if node.filename
200
204
  Sass::Util.sass_warn "#{node.filename}:#{node.line} DEBUG: #{res}"
201
205
  else
@@ -325,7 +329,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
325
329
  end
326
330
 
327
331
  args = node.args.map {|a| a.perform(@environment)}
328
- keywords = Sass::Util.map_hash(node.keywords) {|k, v| [k, v.perform(@environment)]}
332
+ keywords = Sass::Util.map_vals(node.keywords) {|v| v.perform(@environment)}
329
333
  splat = self.class.perform_splat(node.splat, keywords, node.kwarg_splat, @environment)
330
334
 
331
335
  self.class.perform_arguments(mixin, args, splat) do |env|
@@ -419,7 +423,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
419
423
  env = @environment
420
424
  if node.global
421
425
  env = env.global_env
422
- elsif env.parent && env.is_var_global?(node.name)
426
+ elsif env.parent && env.is_var_global?(node.name) && !node.global_warning_given
427
+ node.global_warning_given = true
423
428
  var_expr = "$#{node.name}: #{node.expr.to_sass(env.options)} !global"
424
429
  var_expr << " !default" if node.guarded
425
430
  location = "on line #{node.line}"
@@ -31,36 +31,6 @@ module Sass
31
31
  File.join(Sass::ROOT_DIR, file)
32
32
  end
33
33
 
34
- # Converts a hash or a list of pairs into an order-preserving hash.
35
- #
36
- # On Ruby 1.8.7, this uses the orderedhash gem to simulate an
37
- # order-preserving hash. On Ruby 1.9 and up, it just uses the native Hash
38
- # class, since that preserves the order itself.
39
- #
40
- # @overload ordered_hash(hash)
41
- # @param hash [Hash] a normal hash to convert to an ordered hash
42
- # @return [Hash]
43
- # @overload ordered_hash(*pairs)
44
- # @example
45
- # ordered_hash([:foo, "bar"], [:baz, "bang"])
46
- # #=> {:foo => "bar", :baz => "bang"}
47
- # ordered_hash #=> {}
48
- # @param pairs [Array<(Object, Object)>] the list of key/value pairs for
49
- # the hash.
50
- # @return [Hash]
51
- def ordered_hash(*pairs_or_hash)
52
- require 'sass/util/ordered_hash' if ruby1_8?
53
-
54
- if pairs_or_hash.length == 1 && pairs_or_hash.first.is_a?(Hash)
55
- hash = pairs_or_hash.first
56
- return hash unless ruby1_8?
57
- return OrderedHash.new.merge hash
58
- end
59
-
60
- return Hash[pairs_or_hash] unless ruby1_8?
61
- OrderedHash[*flatten(pairs_or_hash, 1)]
62
- end
63
-
64
34
  # Converts an array of `[key, value]` pairs to a hash.
65
35
  #
66
36
  # @example
@@ -85,7 +55,7 @@ module Sass
85
55
  # @see #map_vals
86
56
  # @see #map_hash
87
57
  def map_keys(hash)
88
- to_hash(hash.map {|k, v| [yield(k), v]})
58
+ map_hash(hash) {|k, v| [yield(k), v]}
89
59
  end
90
60
 
91
61
  # Maps the values in a hash according to a block.
@@ -101,7 +71,13 @@ module Sass
101
71
  # @see #map_keys
102
72
  # @see #map_hash
103
73
  def map_vals(hash)
104
- to_hash(hash.map {|k, v| [k, yield(v)]})
74
+ # We don't delegate to map_hash for performance here
75
+ # because map_hash does more than is necessary.
76
+ rv = hash.class.new
77
+ hash.each do |k, v|
78
+ rv[k] = yield(v)
79
+ end
80
+ rv
105
81
  end
106
82
 
107
83
  # Maps the key-value pairs of a hash according to a block.
@@ -118,8 +94,15 @@ module Sass
118
94
  # @see #map_keys
119
95
  # @see #map_vals
120
96
  def map_hash(hash)
121
- # Using &block here completely hoses performance on 1.8.
122
- to_hash(hash.map {|k, v| yield k, v})
97
+ # Copy and modify is more performant than mapping to an array and using
98
+ # to_hash on the result.
99
+ rv = hash.class.new
100
+ hash.each do |k, v|
101
+ new_key, new_value = yield(k, v)
102
+ rv.delete(k)
103
+ rv[new_key] = new_value
104
+ end
105
+ rv
123
106
  end
124
107
 
125
108
  # Computes the powerset of the given array.
@@ -272,12 +255,12 @@ module Sass
272
255
  #
273
256
  # @param enum [Enumerable]
274
257
  # @return [Array<[Object, Array]>] An array of pairs.
275
- def group_by_to_a(enum, &block)
276
- return enum.group_by(&block).to_a unless ruby1_8?
258
+ def group_by_to_a(enum)
259
+ return enum.group_by {|e| yield(e)}.to_a unless ruby1_8?
277
260
  order = {}
278
261
  arr = []
279
262
  groups = enum.group_by do |e|
280
- res = block[e]
263
+ res = yield(e)
281
264
  unless order.include?(res)
282
265
  order[res] = order.size
283
266
  end
@@ -415,6 +398,17 @@ module Sass
415
398
  raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
416
399
  end
417
400
 
401
+ # Prints a deprecation warning for the caller method.
402
+ #
403
+ # @param obj [Object] `self`
404
+ # @param message [String] A message describing what to do instead.
405
+ def deprecated(obj, message = nil)
406
+ obj_class = obj.is_a?(Class) ? "#{obj}." : "#{obj.class}#"
407
+ full_message = "DEPRECATION WARNING: #{obj_class}#{caller_info[2]} " +
408
+ "will be removed in a future version of Sass.#{("\n" + message) if message}"
409
+ Sass::Util.sass_warn full_message
410
+ end
411
+
418
412
  # Silence all output to STDERR within a block.
419
413
  #
420
414
  # @yield A block in which no output will be printed to STDERR
@@ -507,33 +501,40 @@ module Sass
507
501
  end
508
502
 
509
503
  ## Cross-OS Compatibility
504
+ #
505
+ # These methods are cached because some of them are called quite frequently
506
+ # and even basic checks like String#== are too costly to be called repeatedly.
510
507
 
511
508
  # Whether or not this is running on Windows.
512
509
  #
513
510
  # @return [Boolean]
514
511
  def windows?
515
- RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
512
+ return @windows if defined?(@windows)
513
+ @windows = (RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i)
516
514
  end
517
515
 
518
516
  # Whether or not this is running on IronRuby.
519
517
  #
520
518
  # @return [Boolean]
521
519
  def ironruby?
522
- RUBY_ENGINE == "ironruby"
520
+ return @ironruby if defined?(@ironruby)
521
+ @ironruby = RUBY_ENGINE == "ironruby"
523
522
  end
524
523
 
525
524
  # Whether or not this is running on Rubinius.
526
525
  #
527
526
  # @return [Boolean]
528
527
  def rbx?
529
- RUBY_ENGINE == "rbx"
528
+ return @rbx if defined?(@rbx)
529
+ @rbx = RUBY_ENGINE == "rbx"
530
530
  end
531
531
 
532
532
  # Whether or not this is running on JRuby.
533
533
  #
534
534
  # @return [Boolean]
535
535
  def jruby?
536
- RUBY_PLATFORM =~ /java/
536
+ return @jruby if defined?(@jruby)
537
+ @jruby = RUBY_PLATFORM =~ /java/
537
538
  end
538
539
 
539
540
  # @see #jruby_version-class_method
@@ -551,9 +552,13 @@ module Sass
551
552
  # Like `Dir.glob`, but works with backslash-separated paths on Windows.
552
553
  #
553
554
  # @param path [String]
554
- def glob(path, &block)
555
+ def glob(path)
555
556
  path = path.gsub('\\', '/') if windows?
556
- Dir.glob(path, &block)
557
+ if block_given?
558
+ Dir.glob(path) {|f| yield(f)}
559
+ else
560
+ Dir.glob(path)
561
+ end
557
562
  end
558
563
 
559
564
  # Prepare a value for a destructuring assignment (e.g. `a, b =
@@ -575,7 +580,8 @@ module Sass
575
580
  #
576
581
  # @return [Boolean]
577
582
  def ruby1?
578
- Sass::Util::RUBY_VERSION[0] <= 1
583
+ return @ruby1 if defined?(@ruby1)
584
+ @ruby1 = Sass::Util::RUBY_VERSION[0] <= 1
579
585
  end
580
586
 
581
587
  # Whether or not this is running under Ruby 1.8 or lower.
@@ -587,7 +593,9 @@ module Sass
587
593
  def ruby1_8?
588
594
  # IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
589
595
  # We have to fall back to 1.8 behavior.
590
- ironruby? || (Sass::Util::RUBY_VERSION[0] == 1 && Sass::Util::RUBY_VERSION[1] < 9)
596
+ return @ruby1_8 if defined?(@ruby1_8)
597
+ @ruby1_8 = ironruby? ||
598
+ (Sass::Util::RUBY_VERSION[0] == 1 && Sass::Util::RUBY_VERSION[1] < 9)
591
599
  end
592
600
 
593
601
  # Whether or not this is running under Ruby 1.8.6 or lower.
@@ -595,21 +603,55 @@ module Sass
595
603
  #
596
604
  # @return [Boolean]
597
605
  def ruby1_8_6?
598
- ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
606
+ return @ruby1_8_6 if defined?(@ruby1_8_6)
607
+ @ruby1_8_6 = ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
599
608
  end
600
609
 
601
610
  # Wehter or not this is running under JRuby 1.6 or lower.
602
611
  def jruby1_6?
603
- jruby? && jruby_version[0] == 1 && jruby_version[1] < 7
612
+ return @jruby1_6 if defined?(@jruby1_6)
613
+ @jruby1_6 = jruby? && jruby_version[0] == 1 && jruby_version[1] < 7
604
614
  end
605
615
 
606
616
  # Whether or not this is running under MacRuby.
607
617
  #
608
618
  # @return [Boolean]
609
619
  def macruby?
610
- RUBY_ENGINE == 'macruby'
620
+ return @macruby if defined?(@macruby)
621
+ @macruby = RUBY_ENGINE == 'macruby'
611
622
  end
612
623
 
624
+ require 'sass/util/ordered_hash' if ruby1_8?
625
+
626
+ # Converts a hash or a list of pairs into an order-preserving hash.
627
+ #
628
+ # On Ruby 1.8.7, this uses the orderedhash gem to simulate an
629
+ # order-preserving hash. On Ruby 1.9 and up, it just uses the native Hash
630
+ # class, since that preserves the order itself.
631
+ #
632
+ # @overload ordered_hash(hash)
633
+ # @param hash [Hash] a normal hash to convert to an ordered hash
634
+ # @return [Hash]
635
+ # @overload ordered_hash(*pairs)
636
+ # @example
637
+ # ordered_hash([:foo, "bar"], [:baz, "bang"])
638
+ # #=> {:foo => "bar", :baz => "bang"}
639
+ # ordered_hash #=> {}
640
+ # @param pairs [Array<(Object, Object)>] the list of key/value pairs for
641
+ # the hash.
642
+ # @return [Hash]
643
+ def ordered_hash(*pairs_or_hash)
644
+ if pairs_or_hash.length == 1 && pairs_or_hash.first.is_a?(Hash)
645
+ hash = pairs_or_hash.first
646
+ return hash unless ruby1_8?
647
+ return OrderedHash.new.merge hash
648
+ end
649
+
650
+ return Hash[pairs_or_hash] unless ruby1_8?
651
+ (pairs_or_hash.is_a?(NormalizedMap) ? NormalizedMap : OrderedHash)[*flatten(pairs_or_hash, 1)]
652
+ end
653
+
654
+
613
655
  # Checks that the encoding of a string is valid in Ruby 1.9
614
656
  # and cleans up potential encoding gotchas like the UTF-8 BOM.
615
657
  # If it's not, yields an error string describing the invalid character
@@ -1011,8 +1053,8 @@ MSG
1011
1053
  #
1012
1054
  # @param name [Symbol] The name of the variable
1013
1055
  # @return [Boolean]
1014
- def method_missing(name, *args, &block)
1015
- super unless args.empty? && block.nil?
1056
+ def method_missing(name, *args)
1057
+ super unless args.empty? && !block_given?
1016
1058
  @set.include?(name)
1017
1059
  end
1018
1060
  end
@@ -1053,6 +1095,7 @@ MSG
1053
1095
  # Calculates the memoization table for the Least Common Subsequence algorithm.
1054
1096
  # Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
1055
1097
  def lcs_table(x, y)
1098
+ # This method does not take a block as an explicit parameter for performance reasons.
1056
1099
  # rubocop:enable LineLength
1057
1100
  c = Array.new(x.size) {[]}
1058
1101
  x.size.times {|i| c[i][0] = 0}
@@ -1085,6 +1128,8 @@ MSG
1085
1128
  return lcs_backtrace(c, x, y, i, j - 1, &block) if c[i][j - 1] > c[i - 1][j]
1086
1129
  lcs_backtrace(c, x, y, i - 1, j, &block)
1087
1130
  end
1131
+
1132
+ (Sass::Util.methods - Module.methods).each {|method| module_function method}
1088
1133
  end
1089
1134
  end
1090
1135