sass 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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'
|