sass 3.1.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- 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/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -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/lib/listen.rb +40 -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 +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +0 -14
data/lib/sass/util.rb
CHANGED
@@ -2,8 +2,10 @@ require 'erb'
|
|
2
2
|
require 'set'
|
3
3
|
require 'enumerator'
|
4
4
|
require 'stringio'
|
5
|
-
require 'strscan'
|
6
5
|
require 'rbconfig'
|
6
|
+
require 'uri'
|
7
|
+
require 'thread'
|
8
|
+
require 'pathname'
|
7
9
|
|
8
10
|
require 'sass/root'
|
9
11
|
require 'sass/util/subset_map'
|
@@ -38,7 +40,7 @@ module Sass
|
|
38
40
|
# @param arr [Array<(Object, Object)>] An array of pairs
|
39
41
|
# @return [Hash] A hash
|
40
42
|
def to_hash(arr)
|
41
|
-
|
43
|
+
ordered_hash(*arr.compact)
|
42
44
|
end
|
43
45
|
|
44
46
|
# Maps the keys in a hash according to a block.
|
@@ -54,7 +56,7 @@ module Sass
|
|
54
56
|
# @see #map_vals
|
55
57
|
# @see #map_hash
|
56
58
|
def map_keys(hash)
|
57
|
-
|
59
|
+
map_hash(hash) {|k, v| [yield(k), v]}
|
58
60
|
end
|
59
61
|
|
60
62
|
# Maps the values in a hash according to a block.
|
@@ -70,7 +72,14 @@ module Sass
|
|
70
72
|
# @see #map_keys
|
71
73
|
# @see #map_hash
|
72
74
|
def map_vals(hash)
|
73
|
-
|
75
|
+
# We don't delegate to map_hash for performance here
|
76
|
+
# because map_hash does more than is necessary.
|
77
|
+
rv = hash.class.new
|
78
|
+
hash = hash.as_stored if hash.is_a?(NormalizedMap)
|
79
|
+
hash.each do |k, v|
|
80
|
+
rv[k] = yield(v)
|
81
|
+
end
|
82
|
+
rv
|
74
83
|
end
|
75
84
|
|
76
85
|
# Maps the key-value pairs of a hash according to a block.
|
@@ -86,8 +95,16 @@ module Sass
|
|
86
95
|
# @return [Hash] The mapped hash
|
87
96
|
# @see #map_keys
|
88
97
|
# @see #map_vals
|
89
|
-
def map_hash(hash
|
90
|
-
|
98
|
+
def map_hash(hash)
|
99
|
+
# Copy and modify is more performant than mapping to an array and using
|
100
|
+
# to_hash on the result.
|
101
|
+
rv = hash.class.new
|
102
|
+
hash.each do |k, v|
|
103
|
+
new_key, new_value = yield(k, v)
|
104
|
+
new_key = hash.denormalize(new_key) if hash.is_a?(NormalizedMap) && new_key == k
|
105
|
+
rv[new_key] = new_value
|
106
|
+
end
|
107
|
+
rv
|
91
108
|
end
|
92
109
|
|
93
110
|
# Computes the powerset of the given array.
|
@@ -155,6 +172,19 @@ module Sass
|
|
155
172
|
enum.inject([]) {|a, e| a << e << val}[0...-1]
|
156
173
|
end
|
157
174
|
|
175
|
+
def slice_by(enum)
|
176
|
+
results = []
|
177
|
+
enum.each do |value|
|
178
|
+
key = yield(value)
|
179
|
+
if !results.empty? && results.last.first == key
|
180
|
+
results.last.last << value
|
181
|
+
else
|
182
|
+
results << [key, [value]]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
results
|
186
|
+
end
|
187
|
+
|
158
188
|
# Substitutes a sub-array of one array with another sub-array.
|
159
189
|
#
|
160
190
|
# @param ary [Array] The array in which to make the substitution
|
@@ -164,8 +194,8 @@ module Sass
|
|
164
194
|
res = ary.dup
|
165
195
|
i = 0
|
166
196
|
while i < res.size
|
167
|
-
if res[i...i+from.size] == from
|
168
|
-
res[i...i+from.size] = to
|
197
|
+
if res[i...i + from.size] == from
|
198
|
+
res[i...i + from.size] = to
|
169
199
|
end
|
170
200
|
i += 1
|
171
201
|
end
|
@@ -216,15 +246,120 @@ module Sass
|
|
216
246
|
x = [nil, *x]
|
217
247
|
y = [nil, *y]
|
218
248
|
block ||= proc {|a, b| a == b && a}
|
219
|
-
lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
|
249
|
+
lcs_backtrace(lcs_table(x, y, &block), x, y, x.size - 1, y.size - 1, &block)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
|
253
|
+
# with the following exceptions:
|
254
|
+
#
|
255
|
+
# * In Ruby 1.8, `Hash#to_a` is not deterministically ordered, but this is.
|
256
|
+
# * In Ruby 1.9 when running tests, this is ordered in the same way it would
|
257
|
+
# be under Ruby 1.8 (sorted key order rather than insertion order).
|
258
|
+
#
|
259
|
+
# @param hash [Hash]
|
260
|
+
# @return [Array]
|
261
|
+
def hash_to_a(hash)
|
262
|
+
return hash.to_a unless ruby1_8? || defined?(Test::Unit)
|
263
|
+
hash.sort_by {|k, v| k}
|
264
|
+
end
|
265
|
+
|
266
|
+
# Performs the equivalent of `enum.group_by.to_a`, but with a guaranteed
|
267
|
+
# order. Unlike {Util#hash_to_a}, the resulting order isn't sorted key order;
|
268
|
+
# instead, it's the same order as `#group_by` has under Ruby 1.9 (key
|
269
|
+
# appearance order).
|
270
|
+
#
|
271
|
+
# @param enum [Enumerable]
|
272
|
+
# @return [Array<[Object, Array]>] An array of pairs.
|
273
|
+
def group_by_to_a(enum)
|
274
|
+
return enum.group_by {|e| yield(e)}.to_a unless ruby1_8?
|
275
|
+
order = {}
|
276
|
+
arr = []
|
277
|
+
groups = enum.group_by do |e|
|
278
|
+
res = yield(e)
|
279
|
+
unless order.include?(res)
|
280
|
+
order[res] = order.size
|
281
|
+
end
|
282
|
+
res
|
283
|
+
end
|
284
|
+
groups.each do |key, vals|
|
285
|
+
arr[order[key]] = [key, vals]
|
286
|
+
end
|
287
|
+
arr
|
288
|
+
end
|
289
|
+
|
290
|
+
# Returns a sub-array of `minuend` containing only elements that are also in
|
291
|
+
# `subtrahend`. Ensures that the return value has the same order as
|
292
|
+
# `minuend`, even on Rubinius where that's not guaranteed by `Array#-`.
|
293
|
+
#
|
294
|
+
# @param minuend [Array]
|
295
|
+
# @param subtrahend [Array]
|
296
|
+
# @return [Array]
|
297
|
+
def array_minus(minuend, subtrahend)
|
298
|
+
return minuend - subtrahend unless rbx?
|
299
|
+
set = Set.new(minuend) - subtrahend
|
300
|
+
minuend.select {|e| set.include?(e)}
|
301
|
+
end
|
302
|
+
|
303
|
+
# Returns a string description of the character that caused an
|
304
|
+
# `Encoding::UndefinedConversionError`.
|
305
|
+
#
|
306
|
+
# @param e [Encoding::UndefinedConversionError]
|
307
|
+
# @return [String]
|
308
|
+
def undefined_conversion_error_char(e)
|
309
|
+
# Rubinius (as of 2.0.0.rc1) pre-quotes the error character.
|
310
|
+
return e.error_char if rbx?
|
311
|
+
# JRuby (as of 1.7.2) doesn't have an error_char field on
|
312
|
+
# Encoding::UndefinedConversionError.
|
313
|
+
return e.error_char.dump unless jruby?
|
314
|
+
e.message[/^"[^"]+"/] # "
|
315
|
+
end
|
316
|
+
|
317
|
+
# Asserts that `value` falls within `range` (inclusive), leaving
|
318
|
+
# room for slight floating-point errors.
|
319
|
+
#
|
320
|
+
# @param name [String] The name of the value. Used in the error message.
|
321
|
+
# @param range [Range] The allowed range of values.
|
322
|
+
# @param value [Numeric, Sass::Script::Value::Number] The value to check.
|
323
|
+
# @param unit [String] The unit of the value. Used in error reporting.
|
324
|
+
# @return [Numeric] `value` adjusted to fall within range, if it
|
325
|
+
# was outside by a floating-point margin.
|
326
|
+
def check_range(name, range, value, unit = '')
|
327
|
+
grace = (-0.00001..0.00001)
|
328
|
+
str = value.to_s
|
329
|
+
value = value.value if value.is_a?(Sass::Script::Value::Number)
|
330
|
+
return value if range.include?(value)
|
331
|
+
return range.first if grace.include?(value - range.first)
|
332
|
+
return range.last if grace.include?(value - range.last)
|
333
|
+
raise ArgumentError.new(
|
334
|
+
"#{name} #{str} must be between #{range.first}#{unit} and #{range.last}#{unit}")
|
335
|
+
end
|
336
|
+
|
337
|
+
# Returns whether or not `seq1` is a subsequence of `seq2`. That is, whether
|
338
|
+
# or not `seq2` contains every element in `seq1` in the same order (and
|
339
|
+
# possibly more elements besides).
|
340
|
+
#
|
341
|
+
# @param seq1 [Array]
|
342
|
+
# @param seq2 [Array]
|
343
|
+
# @return [Boolean]
|
344
|
+
def subsequence?(seq1, seq2)
|
345
|
+
i = j = 0
|
346
|
+
loop do
|
347
|
+
return true if i == seq1.size
|
348
|
+
return false if j == seq2.size
|
349
|
+
i += 1 if seq1[i] == seq2[j]
|
350
|
+
j += 1
|
351
|
+
end
|
220
352
|
end
|
221
353
|
|
222
354
|
# Returns information about the caller of the previous method.
|
223
355
|
#
|
224
356
|
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
225
|
-
# @return [[String, Fixnum, (String, nil)]]
|
357
|
+
# @return [[String, Fixnum, (String, nil)]]
|
358
|
+
# An array containing the filename, line, and method name of the caller.
|
226
359
|
# The method name may be nil
|
227
|
-
def caller_info(entry =
|
360
|
+
def caller_info(entry = nil)
|
361
|
+
# JRuby evaluates `caller` incorrectly when it's in an actual default argument.
|
362
|
+
entry ||= caller[1]
|
228
363
|
info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
|
229
364
|
info[1] = info[1].to_i
|
230
365
|
# This is added by Rubinius to designate a block, but we don't care about it.
|
@@ -278,6 +413,17 @@ module Sass
|
|
278
413
|
raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
|
279
414
|
end
|
280
415
|
|
416
|
+
# Prints a deprecation warning for the caller method.
|
417
|
+
#
|
418
|
+
# @param obj [Object] `self`
|
419
|
+
# @param message [String] A message describing what to do instead.
|
420
|
+
def deprecated(obj, message = nil)
|
421
|
+
obj_class = obj.is_a?(Class) ? "#{obj}." : "#{obj.class}#"
|
422
|
+
full_message = "DEPRECATION WARNING: #{obj_class}#{caller_info[2]} " +
|
423
|
+
"will be removed in a future version of Sass.#{("\n" + message) if message}"
|
424
|
+
Sass::Util.sass_warn full_message
|
425
|
+
end
|
426
|
+
|
281
427
|
# Silence all output to STDERR within a block.
|
282
428
|
#
|
283
429
|
# @yield A block in which no output will be printed to STDERR
|
@@ -288,24 +434,22 @@ module Sass
|
|
288
434
|
$stderr = the_real_stderr
|
289
435
|
end
|
290
436
|
|
291
|
-
@@silence_warnings = false
|
292
437
|
# Silences all Sass warnings within a block.
|
293
438
|
#
|
294
439
|
# @yield A block in which no Sass warnings will be printed
|
295
440
|
def silence_sass_warnings
|
296
|
-
|
297
|
-
@@silence_warnings = true
|
441
|
+
old_level, Sass.logger.log_level = Sass.logger.log_level, :error
|
298
442
|
yield
|
299
443
|
ensure
|
300
|
-
|
444
|
+
Sass.logger.log_level = old_level
|
301
445
|
end
|
302
446
|
|
303
447
|
# The same as `Kernel#warn`, but is silenced by \{#silence\_sass\_warnings}.
|
304
448
|
#
|
305
449
|
# @param msg [String]
|
306
450
|
def sass_warn(msg)
|
307
|
-
|
308
|
-
warn(msg)
|
451
|
+
msg = msg + "\n" unless ruby1?
|
452
|
+
Sass.logger.warn(msg)
|
309
453
|
end
|
310
454
|
|
311
455
|
## Cross Rails Version Compatibility
|
@@ -321,7 +465,7 @@ module Sass
|
|
321
465
|
raise "ERROR: Rails.root is nil!"
|
322
466
|
end
|
323
467
|
return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
|
324
|
-
|
468
|
+
nil
|
325
469
|
end
|
326
470
|
|
327
471
|
# Returns the environment of the Rails application,
|
@@ -332,7 +476,7 @@ module Sass
|
|
332
476
|
def rails_env
|
333
477
|
return ::Rails.env.to_s if defined?(::Rails.env)
|
334
478
|
return RAILS_ENV.to_s if defined?(RAILS_ENV)
|
335
|
-
|
479
|
+
nil
|
336
480
|
end
|
337
481
|
|
338
482
|
# Returns whether this environment is using ActionPack
|
@@ -358,6 +502,15 @@ module Sass
|
|
358
502
|
version_geq(ActionPack::VERSION::STRING, version)
|
359
503
|
end
|
360
504
|
|
505
|
+
# Returns whether this environment is using Listen
|
506
|
+
# version 2.0.0 or greater.
|
507
|
+
#
|
508
|
+
# @return [Boolean]
|
509
|
+
def listen_geq_2?
|
510
|
+
require 'listen/version'
|
511
|
+
version_geq(::Listen::VERSION, '2.0.0')
|
512
|
+
end
|
513
|
+
|
361
514
|
# Returns an ActionView::Template* class.
|
362
515
|
# In pre-3.0 versions of Rails, most of these classes
|
363
516
|
# were of the form `ActionView::TemplateFoo`,
|
@@ -368,27 +521,98 @@ module Sass
|
|
368
521
|
# or `ActionView::Template::Error`.
|
369
522
|
def av_template_class(name)
|
370
523
|
return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
|
371
|
-
|
524
|
+
ActionView::Template.const_get(name.to_s)
|
372
525
|
end
|
373
526
|
|
374
527
|
## Cross-OS Compatibility
|
528
|
+
#
|
529
|
+
# These methods are cached because some of them are called quite frequently
|
530
|
+
# and even basic checks like String#== are too costly to be called repeatedly.
|
375
531
|
|
376
532
|
# Whether or not this is running on Windows.
|
377
533
|
#
|
378
534
|
# @return [Boolean]
|
379
535
|
def windows?
|
380
|
-
|
536
|
+
return @windows if defined?(@windows)
|
537
|
+
@windows = (RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i)
|
381
538
|
end
|
382
539
|
|
383
540
|
# Whether or not this is running on IronRuby.
|
384
541
|
#
|
385
542
|
# @return [Boolean]
|
386
543
|
def ironruby?
|
387
|
-
|
544
|
+
return @ironruby if defined?(@ironruby)
|
545
|
+
@ironruby = RUBY_ENGINE == "ironruby"
|
546
|
+
end
|
547
|
+
|
548
|
+
# Whether or not this is running on Rubinius.
|
549
|
+
#
|
550
|
+
# @return [Boolean]
|
551
|
+
def rbx?
|
552
|
+
return @rbx if defined?(@rbx)
|
553
|
+
@rbx = RUBY_ENGINE == "rbx"
|
554
|
+
end
|
555
|
+
|
556
|
+
# Whether or not this is running on JRuby.
|
557
|
+
#
|
558
|
+
# @return [Boolean]
|
559
|
+
def jruby?
|
560
|
+
return @jruby if defined?(@jruby)
|
561
|
+
@jruby = RUBY_PLATFORM =~ /java/
|
562
|
+
end
|
563
|
+
|
564
|
+
# Returns an array of ints representing the JRuby version number.
|
565
|
+
#
|
566
|
+
# @return [Array<Fixnum>]
|
567
|
+
def jruby_version
|
568
|
+
@jruby_version ||= ::JRUBY_VERSION.split(".").map {|s| s.to_i}
|
569
|
+
end
|
570
|
+
|
571
|
+
# Like `Dir.glob`, but works with backslash-separated paths on Windows.
|
572
|
+
#
|
573
|
+
# @param path [String]
|
574
|
+
def glob(path)
|
575
|
+
path = path.gsub('\\', '/') if windows?
|
576
|
+
if block_given?
|
577
|
+
Dir.glob(path) {|f| yield(f)}
|
578
|
+
else
|
579
|
+
Dir.glob(path)
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
# Like `Pathname.new`, but normalizes Windows paths to always use backslash
|
584
|
+
# separators.
|
585
|
+
#
|
586
|
+
# `Pathname.relative_path_from` can break if the two pathnames aren't
|
587
|
+
# consistent in their slash style.
|
588
|
+
def pathname(path)
|
589
|
+
path = path.tr("/", "\\") if windows?
|
590
|
+
Pathname.new(path)
|
591
|
+
end
|
592
|
+
|
593
|
+
# Prepare a value for a destructuring assignment (e.g. `a, b =
|
594
|
+
# val`). This works around a performance bug when using
|
595
|
+
# ActiveSupport, and only needs to be called when `val` is likely
|
596
|
+
# to be `nil` reasonably often.
|
597
|
+
#
|
598
|
+
# See [this bug report](http://redmine.ruby-lang.org/issues/4917).
|
599
|
+
#
|
600
|
+
# @param val [Object]
|
601
|
+
# @return [Object]
|
602
|
+
def destructure(val)
|
603
|
+
val || []
|
388
604
|
end
|
389
605
|
|
390
606
|
## Cross-Ruby-Version Compatibility
|
391
607
|
|
608
|
+
# Whether or not this is running under a Ruby version under 2.0.
|
609
|
+
#
|
610
|
+
# @return [Boolean]
|
611
|
+
def ruby1?
|
612
|
+
return @ruby1 if defined?(@ruby1)
|
613
|
+
@ruby1 = Sass::Util::RUBY_VERSION[0] <= 1
|
614
|
+
end
|
615
|
+
|
392
616
|
# Whether or not this is running under Ruby 1.8 or lower.
|
393
617
|
#
|
394
618
|
# Note that IronRuby counts as Ruby 1.8,
|
@@ -398,7 +622,9 @@ module Sass
|
|
398
622
|
def ruby1_8?
|
399
623
|
# IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
|
400
624
|
# We have to fall back to 1.8 behavior.
|
401
|
-
|
625
|
+
return @ruby1_8 if defined?(@ruby1_8)
|
626
|
+
@ruby1_8 = ironruby? ||
|
627
|
+
(Sass::Util::RUBY_VERSION[0] == 1 && Sass::Util::RUBY_VERSION[1] < 9)
|
402
628
|
end
|
403
629
|
|
404
630
|
# Whether or not this is running under Ruby 1.8.6 or lower.
|
@@ -406,7 +632,52 @@ module Sass
|
|
406
632
|
#
|
407
633
|
# @return [Boolean]
|
408
634
|
def ruby1_8_6?
|
409
|
-
|
635
|
+
return @ruby1_8_6 if defined?(@ruby1_8_6)
|
636
|
+
@ruby1_8_6 = ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
|
637
|
+
end
|
638
|
+
|
639
|
+
# Wehter or not this is running under JRuby 1.6 or lower.
|
640
|
+
def jruby1_6?
|
641
|
+
return @jruby1_6 if defined?(@jruby1_6)
|
642
|
+
@jruby1_6 = jruby? && jruby_version[0] == 1 && jruby_version[1] < 7
|
643
|
+
end
|
644
|
+
|
645
|
+
# Whether or not this is running under MacRuby.
|
646
|
+
#
|
647
|
+
# @return [Boolean]
|
648
|
+
def macruby?
|
649
|
+
return @macruby if defined?(@macruby)
|
650
|
+
@macruby = RUBY_ENGINE == 'macruby'
|
651
|
+
end
|
652
|
+
|
653
|
+
require 'sass/util/ordered_hash' if ruby1_8?
|
654
|
+
|
655
|
+
# Converts a hash or a list of pairs into an order-preserving hash.
|
656
|
+
#
|
657
|
+
# On Ruby 1.8.7, this uses the orderedhash gem to simulate an
|
658
|
+
# order-preserving hash. On Ruby 1.9 and up, it just uses the native Hash
|
659
|
+
# class, since that preserves the order itself.
|
660
|
+
#
|
661
|
+
# @overload ordered_hash(hash)
|
662
|
+
# @param hash [Hash] a normal hash to convert to an ordered hash
|
663
|
+
# @return [Hash]
|
664
|
+
# @overload ordered_hash(*pairs)
|
665
|
+
# @example
|
666
|
+
# ordered_hash([:foo, "bar"], [:baz, "bang"])
|
667
|
+
# #=> {:foo => "bar", :baz => "bang"}
|
668
|
+
# ordered_hash #=> {}
|
669
|
+
# @param pairs [Array<(Object, Object)>] the list of key/value pairs for
|
670
|
+
# the hash.
|
671
|
+
# @return [Hash]
|
672
|
+
def ordered_hash(*pairs_or_hash)
|
673
|
+
if pairs_or_hash.length == 1 && pairs_or_hash.first.is_a?(Hash)
|
674
|
+
hash = pairs_or_hash.first
|
675
|
+
return hash unless ruby1_8?
|
676
|
+
return OrderedHash.new.merge hash
|
677
|
+
end
|
678
|
+
|
679
|
+
return Hash[pairs_or_hash] unless ruby1_8?
|
680
|
+
(pairs_or_hash.is_a?(NormalizedMap) ? NormalizedMap : OrderedHash)[*flatten(pairs_or_hash, 1)]
|
410
681
|
end
|
411
682
|
|
412
683
|
# Checks that the encoding of a string is valid in Ruby 1.9
|
@@ -438,11 +709,11 @@ module Sass
|
|
438
709
|
line.encode(encoding)
|
439
710
|
rescue Encoding::UndefinedConversionError => e
|
440
711
|
yield <<MSG.rstrip, i + 1
|
441
|
-
Invalid #{encoding.name} character #{e
|
712
|
+
Invalid #{encoding.name} character #{undefined_conversion_error_char(e)}
|
442
713
|
MSG
|
443
714
|
end
|
444
715
|
end
|
445
|
-
|
716
|
+
str
|
446
717
|
end
|
447
718
|
|
448
719
|
# Like {\#check\_encoding}, but also checks for a `@charset` declaration
|
@@ -469,12 +740,13 @@ MSG
|
|
469
740
|
# We allow any printable ASCII characters but double quotes in the charset decl
|
470
741
|
bin = str.dup.force_encoding("BINARY")
|
471
742
|
encoding = Sass::Util::ENCODINGS_TO_CHECK.find do |enc|
|
472
|
-
|
743
|
+
re = Sass::Util::CHARSET_REGEXPS[enc]
|
744
|
+
re && bin =~ re
|
473
745
|
end
|
474
746
|
charset, bom = $1, $2
|
475
747
|
if charset
|
476
748
|
charset = charset.force_encoding(encoding).encode("UTF-8")
|
477
|
-
if endianness = encoding[/[BL]E$/]
|
749
|
+
if (endianness = encoding[/[BL]E$/])
|
478
750
|
begin
|
479
751
|
Encoding.find(charset + endianness)
|
480
752
|
charset << endianness
|
@@ -510,6 +782,8 @@ MSG
|
|
510
782
|
Regexp.new(/\A(?:#{_enc("\uFEFF", e)})?#{
|
511
783
|
_enc('@charset "', e)}(.*?)#{_enc('"', e)}|\A(#{
|
512
784
|
_enc("\uFEFF", e)})/)
|
785
|
+
rescue Encoding::ConverterNotFoundError => _
|
786
|
+
nil # JRuby on Java 5 doesn't support UTF-32
|
513
787
|
rescue
|
514
788
|
# /\A@charset "(.*?)"/
|
515
789
|
Regexp.new(/\A#{_enc('@charset "', e)}(.*?)#{_enc('"', e)}/)
|
@@ -561,6 +835,24 @@ MSG
|
|
561
835
|
ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
|
562
836
|
end
|
563
837
|
|
838
|
+
# Destructively removes all elements from an array that match a block, and
|
839
|
+
# returns the removed elements.
|
840
|
+
#
|
841
|
+
# @param array [Array] The array from which to remove elements.
|
842
|
+
# @yield [el] Called for each element.
|
843
|
+
# @yieldparam el [*] The element to test.
|
844
|
+
# @yieldreturn [Boolean] Whether or not to extract the element.
|
845
|
+
# @return [Array] The extracted elements.
|
846
|
+
def extract!(array)
|
847
|
+
out = []
|
848
|
+
array.reject! do |e|
|
849
|
+
next false unless yield e
|
850
|
+
out << e
|
851
|
+
true
|
852
|
+
end
|
853
|
+
out
|
854
|
+
end
|
855
|
+
|
564
856
|
# Returns the ASCII code of the given character.
|
565
857
|
#
|
566
858
|
# @param c [String] All characters but the first are ignored.
|
@@ -580,6 +872,24 @@ MSG
|
|
580
872
|
arr.inject([]) {|res, e| e.is_a?(Array) ? res.concat(flatten(e, n - 1)) : res << e}
|
581
873
|
end
|
582
874
|
|
875
|
+
# Flattens the first level of nested arrays in `arrs`. Unlike
|
876
|
+
# `Array#flatten`, this orders the result by taking the first
|
877
|
+
# values from each array in order, then the second, and so on.
|
878
|
+
#
|
879
|
+
# @param arrs [Array] The array to flatten.
|
880
|
+
# @return [Array] The flattened array.
|
881
|
+
def flatten_vertically(arrs)
|
882
|
+
result = []
|
883
|
+
arrs = arrs.map {|sub| sub.is_a?(Array) ? sub.dup : Array(sub)}
|
884
|
+
until arrs.empty?
|
885
|
+
arrs.reject! do |arr|
|
886
|
+
result << arr.shift
|
887
|
+
arr.empty?
|
888
|
+
end
|
889
|
+
end
|
890
|
+
result
|
891
|
+
end
|
892
|
+
|
583
893
|
# Returns the hash code for a set in a cross-version manner.
|
584
894
|
# Aggravatingly, this is order-dependent in Ruby 1.8.6.
|
585
895
|
#
|
@@ -601,8 +911,9 @@ MSG
|
|
601
911
|
set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
|
602
912
|
end
|
603
913
|
|
604
|
-
# Like `Object#inspect`, but preserves non-ASCII characters rather than
|
605
|
-
# This is necessary so that the
|
914
|
+
# Like `Object#inspect`, but preserves non-ASCII characters rather than
|
915
|
+
# escaping them under Ruby 1.9.2. This is necessary so that the
|
916
|
+
# precompiled Haml template can be `#encode`d into `@options[:encoding]`
|
606
917
|
# before being evaluated.
|
607
918
|
#
|
608
919
|
# @param obj {Object}
|
@@ -614,6 +925,181 @@ MSG
|
|
614
925
|
'"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
|
615
926
|
end
|
616
927
|
|
928
|
+
# Extracts the non-string vlaues from an array containing both strings and non-strings.
|
929
|
+
# These values are replaced with escape sequences.
|
930
|
+
# This can be undone using \{#inject\_values}.
|
931
|
+
#
|
932
|
+
# This is useful e.g. when we want to do string manipulation
|
933
|
+
# on an interpolated string.
|
934
|
+
#
|
935
|
+
# The precise format of the resulting string is not guaranteed.
|
936
|
+
# However, it is guaranteed that newlines and whitespace won't be affected.
|
937
|
+
#
|
938
|
+
# @param arr [Array] The array from which values are extracted.
|
939
|
+
# @return [(String, Array)] The resulting string, and an array of extracted values.
|
940
|
+
def extract_values(arr)
|
941
|
+
values = []
|
942
|
+
mapped = arr.map do |e|
|
943
|
+
next e.gsub('{', '{{') if e.is_a?(String)
|
944
|
+
values << e
|
945
|
+
next "{#{values.count - 1}}"
|
946
|
+
end
|
947
|
+
return mapped.join, values
|
948
|
+
end
|
949
|
+
|
950
|
+
# Undoes \{#extract\_values} by transforming a string with escape sequences
|
951
|
+
# into an array of strings and non-string values.
|
952
|
+
#
|
953
|
+
# @param str [String] The string with escape sequences.
|
954
|
+
# @param values [Array] The array of values to inject.
|
955
|
+
# @return [Array] The array of strings and values.
|
956
|
+
def inject_values(str, values)
|
957
|
+
return [str.gsub('{{', '{')] if values.empty?
|
958
|
+
# Add an extra { so that we process the tail end of the string
|
959
|
+
result = (str + '{{').scan(/(.*?)(?:(\{\{)|\{(\d+)\})/m).map do |(pre, esc, n)|
|
960
|
+
[pre, esc ? '{' : '', n ? values[n.to_i] : '']
|
961
|
+
end.flatten(1)
|
962
|
+
result[-2] = '' # Get rid of the extra {
|
963
|
+
merge_adjacent_strings(result).reject {|s| s == ''}
|
964
|
+
end
|
965
|
+
|
966
|
+
# Allows modifications to be performed on the string form
|
967
|
+
# of an array containing both strings and non-strings.
|
968
|
+
#
|
969
|
+
# @param arr [Array] The array from which values are extracted.
|
970
|
+
# @yield [str] A block in which string manipulation can be done to the array.
|
971
|
+
# @yieldparam str [String] The string form of `arr`.
|
972
|
+
# @yieldreturn [String] The modified string.
|
973
|
+
# @return [Array] The modified, interpolated array.
|
974
|
+
def with_extracted_values(arr)
|
975
|
+
str, vals = extract_values(arr)
|
976
|
+
str = yield str
|
977
|
+
inject_values(str, vals)
|
978
|
+
end
|
979
|
+
|
980
|
+
# Builds a sourcemap file name given the generated CSS file name.
|
981
|
+
#
|
982
|
+
# @param css [String] The generated CSS file name.
|
983
|
+
# @return [String] The source map file name.
|
984
|
+
def sourcemap_name(css)
|
985
|
+
css + ".map"
|
986
|
+
end
|
987
|
+
|
988
|
+
# Escapes certain characters so that the result can be used
|
989
|
+
# as the JSON string value. Returns the original string if
|
990
|
+
# no escaping is necessary.
|
991
|
+
#
|
992
|
+
# @param s [String] The string to be escaped
|
993
|
+
# @return [String] The escaped string
|
994
|
+
def json_escape_string(s)
|
995
|
+
return s if s !~ /["\\\b\f\n\r\t]/
|
996
|
+
|
997
|
+
result = ""
|
998
|
+
s.split("").each do |c|
|
999
|
+
case c
|
1000
|
+
when '"', "\\"
|
1001
|
+
result << "\\" << c
|
1002
|
+
when "\n" then result << "\\n"
|
1003
|
+
when "\t" then result << "\\t"
|
1004
|
+
when "\r" then result << "\\r"
|
1005
|
+
when "\f" then result << "\\f"
|
1006
|
+
when "\b" then result << "\\b"
|
1007
|
+
else
|
1008
|
+
result << c
|
1009
|
+
end
|
1010
|
+
end
|
1011
|
+
result
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
# Converts the argument into a valid JSON value.
|
1015
|
+
#
|
1016
|
+
# @param v [Fixnum, String, Array, Boolean, nil]
|
1017
|
+
# @return [String]
|
1018
|
+
def json_value_of(v)
|
1019
|
+
case v
|
1020
|
+
when Fixnum
|
1021
|
+
v.to_s
|
1022
|
+
when String
|
1023
|
+
"\"" + json_escape_string(v) + "\""
|
1024
|
+
when Array
|
1025
|
+
"[" + v.map {|x| json_value_of(x)}.join(",") + "]"
|
1026
|
+
when NilClass
|
1027
|
+
"null"
|
1028
|
+
when TrueClass
|
1029
|
+
"true"
|
1030
|
+
when FalseClass
|
1031
|
+
"false"
|
1032
|
+
else
|
1033
|
+
raise ArgumentError.new("Unknown type: #{v.class.name}")
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
VLQ_BASE_SHIFT = 5
|
1038
|
+
VLQ_BASE = 1 << VLQ_BASE_SHIFT
|
1039
|
+
VLQ_BASE_MASK = VLQ_BASE - 1
|
1040
|
+
VLQ_CONTINUATION_BIT = VLQ_BASE
|
1041
|
+
|
1042
|
+
BASE64_DIGITS = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + ['+', '/']
|
1043
|
+
BASE64_DIGIT_MAP = begin
|
1044
|
+
map = {}
|
1045
|
+
Sass::Util.enum_with_index(BASE64_DIGITS).map do |digit, i|
|
1046
|
+
map[digit] = i
|
1047
|
+
end
|
1048
|
+
map
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
# Encodes `value` as VLQ (http://en.wikipedia.org/wiki/VLQ).
|
1052
|
+
#
|
1053
|
+
# @param value [Fixnum]
|
1054
|
+
# @return [String] The encoded value
|
1055
|
+
def encode_vlq(value)
|
1056
|
+
if value < 0
|
1057
|
+
value = ((-value) << 1) | 1
|
1058
|
+
else
|
1059
|
+
value <<= 1
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
result = ''
|
1063
|
+
begin
|
1064
|
+
digit = value & VLQ_BASE_MASK
|
1065
|
+
value >>= VLQ_BASE_SHIFT
|
1066
|
+
if value > 0
|
1067
|
+
digit |= VLQ_CONTINUATION_BIT
|
1068
|
+
end
|
1069
|
+
result << BASE64_DIGITS[digit]
|
1070
|
+
end while value > 0
|
1071
|
+
result
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
# This is a hack around the fact that you can't instantiate a URI parser on
|
1075
|
+
# 1.8, so we have to have this hacky stuff to work around it. When 1.8
|
1076
|
+
# support is dropped, we can remove this method.
|
1077
|
+
#
|
1078
|
+
# @private
|
1079
|
+
URI_ESCAPE = URI.const_defined?("DEFAULT_PARSER") ? URI::DEFAULT_PARSER : URI
|
1080
|
+
|
1081
|
+
# URI-escape `string`.
|
1082
|
+
#
|
1083
|
+
# @param string [String]
|
1084
|
+
# @return [String]
|
1085
|
+
def escape_uri(string)
|
1086
|
+
URI_ESCAPE.escape string
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
# A cross-platform implementation of `File.absolute_path`.
|
1090
|
+
#
|
1091
|
+
# @param path [String]
|
1092
|
+
# @param dir_string [String] The directory to consider [path] relative to.
|
1093
|
+
# @return [String] The absolute version of `path`.
|
1094
|
+
def absolute_path(path, dir_string = nil)
|
1095
|
+
# Ruby 1.8 doesn't support File.absolute_path.
|
1096
|
+
return File.absolute_path(path, dir_string) unless ruby1_8?
|
1097
|
+
|
1098
|
+
# File.expand_path expands "~", which we don't want.
|
1099
|
+
return File.expand_path(path, dir_string) unless path[0] == ?~
|
1100
|
+
File.expand_path(File.join(".", path), dir_string)
|
1101
|
+
end
|
1102
|
+
|
617
1103
|
## Static Method Stuff
|
618
1104
|
|
619
1105
|
# The context in which the ERB for \{#def\_static\_method} will be run.
|
@@ -627,17 +1113,49 @@ MSG
|
|
627
1113
|
#
|
628
1114
|
# @param name [Symbol] The name of the variable
|
629
1115
|
# @return [Boolean]
|
630
|
-
def method_missing(name, *args
|
631
|
-
super unless args.empty? &&
|
1116
|
+
def method_missing(name, *args)
|
1117
|
+
super unless args.empty? && !block_given?
|
632
1118
|
@set.include?(name)
|
633
1119
|
end
|
634
1120
|
end
|
635
1121
|
|
1122
|
+
# @private
|
1123
|
+
ATOMIC_WRITE_MUTEX = Mutex.new
|
1124
|
+
|
1125
|
+
# This creates a temp file and yields it for writing. When the
|
1126
|
+
# write is complete, the file is moved into the desired location.
|
1127
|
+
# The atomicity of this operation is provided by the filesystem's
|
1128
|
+
# rename operation.
|
1129
|
+
#
|
1130
|
+
# @param filename [String] The file to write to.
|
1131
|
+
# @yieldparam tmpfile [Tempfile] The temp file that can be written to.
|
1132
|
+
# @return The value returned by the block.
|
1133
|
+
def atomic_create_and_write_file(filename)
|
1134
|
+
require 'tempfile'
|
1135
|
+
tmpfile = Tempfile.new(File.basename(filename), File.dirname(filename))
|
1136
|
+
tmpfile.binmode if tmpfile.respond_to?(:binmode)
|
1137
|
+
result = yield tmpfile
|
1138
|
+
tmpfile.close
|
1139
|
+
ATOMIC_WRITE_MUTEX.synchronize do
|
1140
|
+
File.rename tmpfile.path, filename
|
1141
|
+
end
|
1142
|
+
result
|
1143
|
+
ensure
|
1144
|
+
# close and remove the tempfile if it still exists,
|
1145
|
+
# presumably due to an error during write
|
1146
|
+
tmpfile.close if tmpfile
|
1147
|
+
tmpfile.unlink if tmpfile
|
1148
|
+
end
|
1149
|
+
|
636
1150
|
private
|
637
1151
|
|
1152
|
+
# rubocop:disable LineLength
|
1153
|
+
|
638
1154
|
# Calculates the memoization table for the Least Common Subsequence algorithm.
|
639
1155
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
|
640
1156
|
def lcs_table(x, y)
|
1157
|
+
# This method does not take a block as an explicit parameter for performance reasons.
|
1158
|
+
# rubocop:enable LineLength
|
641
1159
|
c = Array.new(x.size) {[]}
|
642
1160
|
x.size.times {|i| c[i][0] = 0}
|
643
1161
|
y.size.times {|j| c[0][j] = 0}
|
@@ -645,25 +1163,33 @@ MSG
|
|
645
1163
|
(1...y.size).each do |j|
|
646
1164
|
c[i][j] =
|
647
1165
|
if yield x[i], y[j]
|
648
|
-
c[i-1][j-1] + 1
|
1166
|
+
c[i - 1][j - 1] + 1
|
649
1167
|
else
|
650
|
-
[c[i][j-1], c[i-1][j]].max
|
1168
|
+
[c[i][j - 1], c[i - 1][j]].max
|
651
1169
|
end
|
652
1170
|
end
|
653
1171
|
end
|
654
|
-
|
1172
|
+
c
|
655
1173
|
end
|
1174
|
+
# rubocop:disable ParameterLists, LineLength
|
656
1175
|
|
657
1176
|
# Computes a single longest common subsequence for arrays x and y.
|
658
1177
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
|
659
1178
|
def lcs_backtrace(c, x, y, i, j, &block)
|
1179
|
+
# rubocop:enable ParameterList, LineLengths
|
660
1180
|
return [] if i == 0 || j == 0
|
661
|
-
if v = yield(x[i], y[j])
|
662
|
-
return lcs_backtrace(c, x, y, i-1, j-1, &block) << v
|
1181
|
+
if (v = yield(x[i], y[j]))
|
1182
|
+
return lcs_backtrace(c, x, y, i - 1, j - 1, &block) << v
|
663
1183
|
end
|
664
1184
|
|
665
|
-
return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
|
666
|
-
|
1185
|
+
return lcs_backtrace(c, x, y, i, j - 1, &block) if c[i][j - 1] > c[i - 1][j]
|
1186
|
+
lcs_backtrace(c, x, y, i - 1, j, &block)
|
667
1187
|
end
|
1188
|
+
|
1189
|
+
singleton_methods.each {|method| module_function method}
|
668
1190
|
end
|
669
1191
|
end
|
1192
|
+
|
1193
|
+
require 'sass/util/multibyte_string_scanner'
|
1194
|
+
require 'sass/util/normalized_map'
|
1195
|
+
require 'sass/util/cross_platform_random'
|