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.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass.rb +5 -0
- data/lib/sass/engine.rb +3 -5
- data/lib/sass/plugin.rb +0 -1
- data/lib/sass/plugin/compiler.rb +1 -2
- data/lib/sass/script/functions.rb +16 -2
- data/lib/sass/script/lexer.rb +22 -12
- data/lib/sass/script/parser.rb +27 -14
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/value/base.rb +1 -1
- data/lib/sass/script/value/color.rb +29 -17
- data/lib/sass/script/value/list.rb +1 -1
- data/lib/sass/script/value/number.rb +8 -1
- data/lib/sass/scss/parser.rb +2 -2
- data/lib/sass/selector/sequence.rb +18 -19
- data/lib/sass/selector/simple_sequence.rb +5 -5
- data/lib/sass/source/map.rb +1 -1
- data/lib/sass/tree/node.rb +25 -0
- data/lib/sass/tree/variable_node.rb +5 -0
- data/lib/sass/tree/visitors/base.rb +4 -7
- data/lib/sass/tree/visitors/check_nesting.rb +2 -2
- data/lib/sass/tree/visitors/perform.rb +12 -7
- data/lib/sass/util.rb +95 -50
- data/lib/sass/util/normalized_map.rb +63 -14
- data/lib/sass/util/ordered_hash.rb +9 -5
- data/lib/sass/version.rb +10 -12
- data/test/sass/engine_test.rb +37 -0
- data/test/sass/functions_test.rb +9 -2
- data/test/sass/importer_test.rb +3 -3
- data/test/sass/script_test.rb +12 -10
- data/test/sass/source_map_test.rb +8 -8
- data/test/sass/util/normalized_map_test.rb +22 -1
- data/test/sass/util_test.rb +18 -0
- data/test/test_helper.rb +16 -0
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/listen/LICENSE +20 -0
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +318 -300
- 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
|
-
|
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
|
-
#
|
142
|
-
#
|
143
|
-
#
|
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.
|
151
|
-
|
152
|
-
befores = [[]]
|
153
|
-
afters = path.dup
|
152
|
+
# building all possible prefixes simultaneously.
|
153
|
+
prefixes = [[]]
|
154
154
|
|
155
|
-
|
156
|
-
current =
|
155
|
+
path.each do |current|
|
156
|
+
current = current.dup
|
157
157
|
last_current = [current.pop]
|
158
|
-
|
159
|
-
sub = subweave(
|
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
|
-
|
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<
|
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
|
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 {|
|
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
|
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
|
121
|
-
group.each {|e
|
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]
|
data/lib/sass/source/map.rb
CHANGED
@@ -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",
|
107
|
+
write_json_field(result, "version", 3, true)
|
108
108
|
|
109
109
|
source_uri_to_id = {}
|
110
110
|
id_to_source_uri = {}
|
data/lib/sass/tree/node.rb
CHANGED
@@ -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
|
-
|
36
|
-
|
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
|
-
|
64
|
-
|
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(
|
13
|
-
try_send(
|
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 = [],
|
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
|
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
|
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
|
-
|
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.
|
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}"
|
data/lib/sass/util.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
#
|
122
|
-
to_hash
|
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
|
276
|
-
return enum.group_by(
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
555
|
+
def glob(path)
|
555
556
|
path = path.gsub('\\', '/') if windows?
|
556
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
1015
|
-
super unless args.empty? &&
|
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
|
|