sass 3.7.4 → 4.0.0.alpha.1
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 +13 -5
- data/.yardopts +1 -1
- data/CODE_OF_CONDUCT.md +1 -1
- data/CONTRIBUTING.md +1 -146
- data/MIT-LICENSE +1 -1
- data/README.md +25 -39
- data/Rakefile +274 -0
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass.rb +3 -3
- data/lib/sass/cache_stores/filesystem.rb +2 -2
- data/lib/sass/cache_stores/memory.rb +5 -4
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +12 -12
- data/lib/sass/engine.rb +44 -62
- data/lib/sass/environment.rb +7 -35
- data/lib/sass/error.rb +14 -14
- data/lib/sass/exec/base.rb +14 -3
- data/lib/sass/exec/sass_convert.rb +6 -20
- data/lib/sass/exec/sass_scss.rb +29 -5
- data/lib/sass/features.rb +2 -3
- data/lib/sass/importers/filesystem.rb +6 -11
- data/lib/sass/logger.rb +3 -8
- data/lib/sass/logger/base.rb +2 -19
- data/lib/sass/plugin.rb +2 -3
- data/lib/sass/plugin/compiler.rb +67 -48
- data/lib/sass/plugin/configuration.rb +3 -3
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/rack.rb +3 -3
- data/lib/sass/plugin/staleness_checker.rb +3 -3
- data/lib/sass/railtie.rb +1 -1
- data/lib/sass/script.rb +3 -3
- data/lib/sass/script/css_parser.rb +15 -5
- data/lib/sass/script/functions.rb +121 -337
- data/lib/sass/script/lexer.rb +36 -102
- data/lib/sass/script/parser.rb +153 -529
- data/lib/sass/script/tree/funcall.rb +34 -42
- data/lib/sass/script/tree/interpolation.rb +26 -171
- data/lib/sass/script/tree/list_literal.rb +8 -23
- data/lib/sass/script/tree/map_literal.rb +2 -2
- data/lib/sass/script/tree/node.rb +3 -3
- data/lib/sass/script/tree/operation.rb +16 -43
- data/lib/sass/script/tree/string_interpolation.rb +43 -64
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/value.rb +0 -2
- data/lib/sass/script/value/arg_list.rb +1 -1
- data/lib/sass/script/value/base.rb +9 -27
- data/lib/sass/script/value/color.rb +18 -26
- data/lib/sass/script/value/helpers.rb +18 -44
- data/lib/sass/script/value/list.rb +14 -35
- data/lib/sass/script/value/map.rb +2 -2
- data/lib/sass/script/value/number.rb +16 -26
- data/lib/sass/script/value/string.rb +1 -30
- data/lib/sass/scss.rb +2 -0
- data/lib/sass/scss/css_parser.rb +3 -7
- data/lib/sass/scss/parser.rb +78 -196
- data/lib/sass/scss/rx.rb +14 -7
- data/lib/sass/scss/script_lexer.rb +15 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/scss/static_parser.rb +55 -38
- data/lib/sass/selector.rb +10 -7
- data/lib/sass/selector/abstract_sequence.rb +12 -15
- data/lib/sass/selector/comma_sequence.rb +6 -24
- data/lib/sass/selector/pseudo.rb +6 -19
- data/lib/sass/selector/sequence.rb +16 -14
- data/lib/sass/selector/simple.rb +7 -9
- data/lib/sass/selector/simple_sequence.rb +12 -16
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/source/map.rb +9 -7
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +3 -23
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/function_node.rb +3 -2
- data/lib/sass/tree/node.rb +3 -5
- data/lib/sass/tree/prop_node.rb +58 -49
- data/lib/sass/tree/rule_node.rb +8 -15
- data/lib/sass/tree/visitors/check_nesting.rb +23 -19
- data/lib/sass/tree/visitors/convert.rb +13 -15
- data/lib/sass/tree/visitors/cssize.rb +15 -4
- data/lib/sass/tree/visitors/deep_copy.rb +2 -2
- data/lib/sass/tree/visitors/extend.rb +14 -10
- data/lib/sass/tree/visitors/perform.rb +18 -29
- data/lib/sass/tree/visitors/set_options.rb +2 -2
- data/lib/sass/tree/visitors/to_css.rb +47 -77
- data/lib/sass/util.rb +311 -98
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +133 -127
- data/lib/sass/util/normalized_map.rb +8 -1
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/version.rb +6 -2
- data/test/sass/cache_test.rb +131 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/compiler_test.rb +236 -0
- data/test/sass/conversion_test.rb +2171 -0
- data/test/sass/css2sass_test.rb +526 -0
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +3400 -0
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +1719 -0
- 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 +1984 -0
- data/test/sass/importer_test.rb +421 -0
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/mock_importer.rb +49 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +556 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +86 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/if.css +3 -0
- data/test/sass/results/import.css +31 -0
- data/test/sass/results/import_charset.css +5 -0
- data/test/sass/results/import_charset_1_8.css +5 -0
- data/test/sass/results/import_charset_ibm866.css +5 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/options.css +1 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/scss_import.css +31 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +306 -0
- data/test/sass/script_test.rb +1206 -0
- data/test/sass/scss/css_test.rb +1281 -0
- data/test/sass/scss/rx_test.rb +160 -0
- data/test/sass/scss/scss_test.rb +4147 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/source_map_test.rb +1055 -0
- data/test/sass/superselector_test.rb +210 -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_charset_ibm866.sass +4 -0
- data/test/sass/templates/_imported_charset_utf8.sass +4 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork1.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/bork4.sass +2 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +305 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/if.sass +11 -0
- data/test/sass/templates/import.sass +12 -0
- data/test/sass/templates/import_charset.sass +9 -0
- data/test/sass/templates/import_charset_1_8.sass +6 -0
- data/test/sass/templates/import_charset_ibm866.sass +11 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/importee.less +2 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixin_bork.sass +5 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -0
- data/test/sass/templates/nested_bork4.sass +2 -0
- data/test/sass/templates/nested_import.sass +2 -0
- data/test/sass/templates/nested_mixin_bork.sass +6 -0
- data/test/sass/templates/options.sass +2 -0
- data/test/sass/templates/parent_ref.sass +25 -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/script.sass +101 -0
- data/test/sass/templates/scss_import.scss +12 -0
- data/test/sass/templates/scss_importee.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/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/sass/templates/warn.sass +3 -0
- data/test/sass/templates/warn_imported.sass +4 -0
- data/test/sass/test_helper.rb +8 -0
- 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/subset_map_test.rb +91 -0
- data/test/sass/util_test.rb +438 -0
- data/test/sass/value_helpers_test.rb +179 -0
- data/test/test_helper.rb +110 -0
- data/vendor/listen/CHANGELOG.md +1 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +20 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/listen/LICENSE +20 -0
- data/vendor/listen/README.md +349 -0
- data/vendor/listen/Rakefile +5 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen.rb +54 -0
- data/vendor/listen/lib/listen/adapter.rb +327 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +75 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +48 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +81 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +58 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +91 -0
- data/vendor/listen/lib/listen/directory_record.rb +406 -0
- data/vendor/listen/lib/listen/listener.rb +323 -0
- data/vendor/listen/lib/listen/turnstile.rb +32 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/listen.gemspec +28 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +149 -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/directory_record_spec.rb +1250 -0
- data/vendor/listen/spec/listen/listener_spec.rb +258 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +67 -0
- data/vendor/listen/spec/spec_helper.rb +25 -0
- data/vendor/listen/spec/support/adapter_helper.rb +666 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +57 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +179 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +217 -76
- data/extra/sass-spec-ref.sh +0 -40
- data/lib/sass/deprecation.rb +0 -55
- data/lib/sass/logger/delayed.rb +0 -50
- data/lib/sass/script/value/callable.rb +0 -25
- data/lib/sass/script/value/function.rb +0 -19
data/lib/sass/util.rb
CHANGED
@@ -33,6 +33,17 @@ module Sass
|
|
33
33
|
File.join(Sass::ROOT_DIR, file)
|
34
34
|
end
|
35
35
|
|
36
|
+
# Converts an array of `[key, value]` pairs to a hash.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# to_hash([[:foo, "bar"], [:baz, "bang"]])
|
40
|
+
# #=> {:foo => "bar", :baz => "bang"}
|
41
|
+
# @param arr [Array<(Object, Object)>] An array of pairs
|
42
|
+
# @return [Hash] A hash
|
43
|
+
def to_hash(arr)
|
44
|
+
ordered_hash(*arr.compact)
|
45
|
+
end
|
46
|
+
|
36
47
|
# Maps the keys in a hash according to a block.
|
37
48
|
#
|
38
49
|
# @example
|
@@ -135,13 +146,8 @@ module Sass
|
|
135
146
|
def round(value)
|
136
147
|
# If the number is within epsilon of X.5, round up (or down for negative
|
137
148
|
# numbers).
|
138
|
-
|
139
|
-
|
140
|
-
if value > 0
|
141
|
-
!mod_is_half && mod < 0.5 ? value.floor : value.ceil
|
142
|
-
else
|
143
|
-
mod_is_half || mod < 0.5 ? value.floor : value.ceil
|
144
|
-
end
|
149
|
+
return value.round if (value % 1) - 0.5 <= -1 * Script::Value::Number.epsilon
|
150
|
+
value > 0 ? value.ceil : value.floor
|
145
151
|
end
|
146
152
|
|
147
153
|
# Concatenates all strings that are adjacent in an array,
|
@@ -246,67 +252,18 @@ module Sass
|
|
246
252
|
res
|
247
253
|
end
|
248
254
|
|
249
|
-
# Destructively strips whitespace from the beginning and end
|
250
|
-
# and last elements, respectively,
|
251
|
-
#
|
255
|
+
# Destructively strips whitespace from the beginning and end
|
256
|
+
# of the first and last elements, respectively,
|
257
|
+
# in the array (if those elements are strings).
|
252
258
|
#
|
253
259
|
# @param arr [Array]
|
254
260
|
# @return [Array] `arr`
|
255
261
|
def strip_string_array(arr)
|
256
262
|
arr.first.lstrip! if arr.first.is_a?(String)
|
257
|
-
arr
|
263
|
+
arr.last.rstrip! if arr.last.is_a?(String)
|
258
264
|
arr
|
259
265
|
end
|
260
266
|
|
261
|
-
# Normalizes identifier escapes.
|
262
|
-
#
|
263
|
-
# See https://github.com/sass/language/blob/master/accepted/identifier-escapes.md.
|
264
|
-
#
|
265
|
-
# @param ident [String]
|
266
|
-
# @return [String]
|
267
|
-
def normalize_ident_escapes(ident, start: true)
|
268
|
-
ident.gsub(/(^)?(#{Sass::SCSS::RX::ESCAPE})/) do |s|
|
269
|
-
at_start = start && $1
|
270
|
-
char = escaped_char(s)
|
271
|
-
next char if char =~ (at_start ? Sass::SCSS::RX::NMSTART : Sass::SCSS::RX::NMCHAR)
|
272
|
-
if char =~ (at_start ? /[\x0-\x1F\x7F0-9]/ : /[\x0-\x1F\x7F]/)
|
273
|
-
"\\#{char.ord.to_s(16)} "
|
274
|
-
else
|
275
|
-
"\\#{char}"
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
# Returns the character encoded by the given escape sequence.
|
281
|
-
#
|
282
|
-
# @param escape [String]
|
283
|
-
# @return [String]
|
284
|
-
def escaped_char(escape)
|
285
|
-
if escape =~ /^\\([0-9a-fA-F]{1,6})[ \t\r\n\f]?/
|
286
|
-
$1.to_i(16).chr(Encoding::UTF_8)
|
287
|
-
else
|
288
|
-
escape[1]
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
# Like [String#strip], but preserves escaped whitespace at the end of the
|
293
|
-
# string.
|
294
|
-
#
|
295
|
-
# @param string [String]
|
296
|
-
# @return [String]
|
297
|
-
def strip_except_escapes(string)
|
298
|
-
rstrip_except_escapes(string.lstrip)
|
299
|
-
end
|
300
|
-
|
301
|
-
# Like [String#rstrip], but preserves escaped whitespace at the end of the
|
302
|
-
# string.
|
303
|
-
#
|
304
|
-
# @param string [String]
|
305
|
-
# @return [String]
|
306
|
-
def rstrip_except_escapes(string)
|
307
|
-
string.sub(/(?<!\\)\s+$/, '')
|
308
|
-
end
|
309
|
-
|
310
267
|
# Return an array of all possible paths through the given arrays.
|
311
268
|
#
|
312
269
|
# @param arrs [Array<Array>]
|
@@ -342,16 +299,42 @@ module Sass
|
|
342
299
|
lcs_backtrace(lcs_table(x, y, &block), x, y, x.size - 1, y.size - 1, &block)
|
343
300
|
end
|
344
301
|
|
345
|
-
#
|
346
|
-
|
347
|
-
|
348
|
-
|
302
|
+
# Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
|
303
|
+
# with the following exceptions:
|
304
|
+
#
|
305
|
+
# * In Ruby 1.8, `Hash#to_a` is not deterministically ordered, but this is.
|
306
|
+
# * In Ruby 1.9 when running tests, this is ordered in the same way it would
|
307
|
+
# be under Ruby 1.8 (sorted key order rather than insertion order).
|
308
|
+
#
|
309
|
+
# @param hash [Hash]
|
310
|
+
# @return [Array]
|
311
|
+
def hash_to_a(hash)
|
312
|
+
return hash.to_a unless ruby1_8? || defined?(Test::Unit)
|
313
|
+
hash.sort_by {|k, v| k}
|
349
314
|
end
|
350
315
|
|
351
|
-
#
|
352
|
-
|
353
|
-
|
354
|
-
|
316
|
+
# Performs the equivalent of `enum.group_by.to_a`, but with a guaranteed
|
317
|
+
# order. Unlike {Util#hash_to_a}, the resulting order isn't sorted key order;
|
318
|
+
# instead, it's the same order as `#group_by` has under Ruby 1.9 (key
|
319
|
+
# appearance order).
|
320
|
+
#
|
321
|
+
# @param enum [Enumerable]
|
322
|
+
# @return [Array<[Object, Array]>] An array of pairs.
|
323
|
+
def group_by_to_a(enum)
|
324
|
+
return enum.group_by {|e| yield(e)}.to_a unless ruby1_8?
|
325
|
+
order = {}
|
326
|
+
arr = []
|
327
|
+
groups = enum.group_by do |e|
|
328
|
+
res = yield(e)
|
329
|
+
unless order.include?(res)
|
330
|
+
order[res] = order.size
|
331
|
+
end
|
332
|
+
res
|
333
|
+
end
|
334
|
+
groups.each do |key, vals|
|
335
|
+
arr[order[key]] = [key, vals]
|
336
|
+
end
|
337
|
+
arr
|
355
338
|
end
|
356
339
|
|
357
340
|
# Returns a sub-array of `minuend` containing only elements that are also in
|
@@ -433,7 +416,7 @@ module Sass
|
|
433
416
|
# Returns information about the caller of the previous method.
|
434
417
|
#
|
435
418
|
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
436
|
-
# @return [[String,
|
419
|
+
# @return [[String, Fixnum, (String, nil)]]
|
437
420
|
# An array containing the filename, line, and method name of the caller.
|
438
421
|
# The method name may be nil
|
439
422
|
def caller_info(entry = nil)
|
@@ -503,6 +486,16 @@ module Sass
|
|
503
486
|
Sass::Util.sass_warn full_message
|
504
487
|
end
|
505
488
|
|
489
|
+
# Silence all output to STDERR within a block.
|
490
|
+
#
|
491
|
+
# @yield A block in which no output will be printed to STDERR
|
492
|
+
def silence_warnings
|
493
|
+
the_real_stderr, $stderr = $stderr, StringIO.new
|
494
|
+
yield
|
495
|
+
ensure
|
496
|
+
$stderr = the_real_stderr
|
497
|
+
end
|
498
|
+
|
506
499
|
# Silences all Sass warnings within a block.
|
507
500
|
#
|
508
501
|
# @yield A block in which no Sass warnings will be printed
|
@@ -517,7 +510,8 @@ module Sass
|
|
517
510
|
#
|
518
511
|
# @param msg [String]
|
519
512
|
def sass_warn(msg)
|
520
|
-
|
513
|
+
msg = msg + "\n" unless ruby1?
|
514
|
+
Sass.logger.warn(msg)
|
521
515
|
end
|
522
516
|
|
523
517
|
## Cross Rails Version Compatibility
|
@@ -570,6 +564,24 @@ module Sass
|
|
570
564
|
version_geq(ActionPack::VERSION::STRING, version)
|
571
565
|
end
|
572
566
|
|
567
|
+
# Returns whether this environment is using Listen
|
568
|
+
# version 2.0.0 or greater.
|
569
|
+
#
|
570
|
+
# @return [Boolean]
|
571
|
+
def listen_geq_2?
|
572
|
+
return @listen_geq_2 unless @listen_geq_2.nil?
|
573
|
+
@listen_geq_2 =
|
574
|
+
begin
|
575
|
+
# Make sure we're loading listen/version from the same place that
|
576
|
+
# we're loading listen itself.
|
577
|
+
load_listen!
|
578
|
+
require 'listen/version'
|
579
|
+
version_geq(::Listen::VERSION, '2.0.0')
|
580
|
+
rescue LoadError
|
581
|
+
false
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
573
585
|
# Returns an ActionView::Template* class.
|
574
586
|
# In pre-3.0 versions of Rails, most of these classes
|
575
587
|
# were of the form `ActionView::TemplateFoo`,
|
@@ -622,7 +634,7 @@ module Sass
|
|
622
634
|
|
623
635
|
# Returns an array of ints representing the JRuby version number.
|
624
636
|
#
|
625
|
-
# @return [Array<
|
637
|
+
# @return [Array<Fixnum>]
|
626
638
|
def jruby_version
|
627
639
|
@jruby_version ||= ::JRUBY_VERSION.split(".").map {|s| s.to_i}
|
628
640
|
end
|
@@ -631,7 +643,7 @@ module Sass
|
|
631
643
|
#
|
632
644
|
# @param path [String]
|
633
645
|
def glob(path)
|
634
|
-
path = path.
|
646
|
+
path = path.gsub('\\', '/') if windows?
|
635
647
|
if block_given?
|
636
648
|
Dir.glob(path) {|f| yield(f)}
|
637
649
|
else
|
@@ -713,10 +725,10 @@ module Sass
|
|
713
725
|
def file_uri_from_path(path)
|
714
726
|
path = path.to_s if path.is_a?(Pathname)
|
715
727
|
path = path.tr('\\', '/') if windows?
|
716
|
-
path =
|
728
|
+
path = Sass::Util.escape_uri(path)
|
717
729
|
return path.start_with?('/') ? "file://" + path : path unless windows?
|
718
|
-
return "file:///" + path.tr("\\", "/") if path =~
|
719
|
-
return "file:" + path.tr("\\", "/") if path =~
|
730
|
+
return "file:///" + path.tr("\\", "/") if path =~ /^[a-zA-Z]:[\/\\]/
|
731
|
+
return "file:" + path.tr("\\", "/") if path =~ /\\\\[^\\]+\\[^\\\/]+/
|
720
732
|
path.tr("\\", "/")
|
721
733
|
end
|
722
734
|
|
@@ -748,25 +760,87 @@ module Sass
|
|
748
760
|
val || []
|
749
761
|
end
|
750
762
|
|
751
|
-
CHARSET_REGEXP = /\A@charset "([^"]+)"/
|
752
|
-
bom = "\uFEFF"
|
753
|
-
UTF_8_BOM = bom.encode("UTF-8").force_encoding('BINARY')
|
754
|
-
UTF_16BE_BOM = bom.encode("UTF-16BE").force_encoding('BINARY')
|
755
|
-
UTF_16LE_BOM = bom.encode("UTF-16LE").force_encoding('BINARY')
|
756
|
-
|
757
763
|
## Cross-Ruby-Version Compatibility
|
758
764
|
|
759
|
-
# Whether or not this is running under Ruby
|
765
|
+
# Whether or not this is running under a Ruby version under 2.0.
|
760
766
|
#
|
761
767
|
# @return [Boolean]
|
762
|
-
def
|
763
|
-
return @
|
764
|
-
@
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
768
|
+
def ruby1?
|
769
|
+
return @ruby1 if defined?(@ruby1)
|
770
|
+
@ruby1 = RUBY_VERSION_COMPONENTS[0] <= 1
|
771
|
+
end
|
772
|
+
|
773
|
+
# Whether or not this is running under Ruby 1.8 or lower.
|
774
|
+
#
|
775
|
+
# Note that IronRuby counts as Ruby 1.8,
|
776
|
+
# because it doesn't support the Ruby 1.9 encoding API.
|
777
|
+
#
|
778
|
+
# @return [Boolean]
|
779
|
+
def ruby1_8?
|
780
|
+
# IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
|
781
|
+
# We have to fall back to 1.8 behavior.
|
782
|
+
return @ruby1_8 if defined?(@ruby1_8)
|
783
|
+
@ruby1_8 = ironruby? ||
|
784
|
+
(RUBY_VERSION_COMPONENTS[0] == 1 && RUBY_VERSION_COMPONENTS[1] < 9)
|
785
|
+
end
|
786
|
+
|
787
|
+
# Whether or not this is running under Ruby 1.9.2 exactly.
|
788
|
+
#
|
789
|
+
# @return [Boolean]
|
790
|
+
def ruby1_9_2?
|
791
|
+
return @ruby1_9_2 if defined?(@ruby1_9_2)
|
792
|
+
@ruby1_9_2 = RUBY_VERSION_COMPONENTS == [1, 9, 2]
|
793
|
+
end
|
794
|
+
|
795
|
+
# Wehter or not this is running under JRuby 1.6 or lower.
|
796
|
+
def jruby1_6?
|
797
|
+
return @jruby1_6 if defined?(@jruby1_6)
|
798
|
+
@jruby1_6 = jruby? && jruby_version[0] == 1 && jruby_version[1] < 7
|
799
|
+
end
|
800
|
+
|
801
|
+
# Whether or not this is running under MacRuby.
|
802
|
+
#
|
803
|
+
# @return [Boolean]
|
804
|
+
def macruby?
|
805
|
+
return @macruby if defined?(@macruby)
|
806
|
+
@macruby = RUBY_ENGINE == 'macruby'
|
807
|
+
end
|
808
|
+
|
809
|
+
require 'sass/util/ordered_hash' if ruby1_8?
|
810
|
+
|
811
|
+
# Converts a hash or a list of pairs into an order-preserving hash.
|
812
|
+
#
|
813
|
+
# On Ruby 1.8.7, this uses the orderedhash gem to simulate an
|
814
|
+
# order-preserving hash. On Ruby 1.9 and up, it just uses the native Hash
|
815
|
+
# class, since that preserves the order itself.
|
816
|
+
#
|
817
|
+
# @overload ordered_hash(hash)
|
818
|
+
# @param hash [Hash] a normal hash to convert to an ordered hash
|
819
|
+
# @return [Hash]
|
820
|
+
# @overload ordered_hash(*pairs)
|
821
|
+
# @example
|
822
|
+
# ordered_hash([:foo, "bar"], [:baz, "bang"])
|
823
|
+
# #=> {:foo => "bar", :baz => "bang"}
|
824
|
+
# ordered_hash #=> {}
|
825
|
+
# @param pairs [Array<(Object, Object)>] the list of key/value pairs for
|
826
|
+
# the hash.
|
827
|
+
# @return [Hash]
|
828
|
+
def ordered_hash(*pairs_or_hash)
|
829
|
+
if pairs_or_hash.length == 1 && pairs_or_hash.first.is_a?(Hash)
|
830
|
+
hash = pairs_or_hash.first
|
831
|
+
return hash unless ruby1_8?
|
832
|
+
return OrderedHash.new.merge hash
|
833
|
+
end
|
834
|
+
|
835
|
+
return Hash[pairs_or_hash] unless ruby1_8?
|
836
|
+
(pairs_or_hash.is_a?(NormalizedMap) ? NormalizedMap : OrderedHash)[*pairs_or_hash.flatten(1)]
|
837
|
+
end
|
838
|
+
|
839
|
+
unless ruby1_8?
|
840
|
+
CHARSET_REGEXP = /\A@charset "([^"]+)"/
|
841
|
+
UTF_8_BOM = "\xEF\xBB\xBF".force_encoding('BINARY')
|
842
|
+
UTF_16BE_BOM = "\xFE\xFF".force_encoding('BINARY')
|
843
|
+
UTF_16LE_BOM = "\xFF\xFE".force_encoding('BINARY')
|
770
844
|
end
|
771
845
|
|
772
846
|
# Like {\#check\_encoding}, but also checks for a `@charset` declaration
|
@@ -776,7 +850,7 @@ module Sass
|
|
776
850
|
#
|
777
851
|
# @param str [String] The string of which to check the encoding
|
778
852
|
# @return [(String, Encoding)] The original string encoded as UTF-8,
|
779
|
-
# and the source encoding of the string
|
853
|
+
# and the source encoding of the string (or `nil` under Ruby 1.8)
|
780
854
|
# @raise [Encoding::UndefinedConversionError] if the source encoding
|
781
855
|
# cannot be converted to UTF-8
|
782
856
|
# @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
|
@@ -784,6 +858,15 @@ module Sass
|
|
784
858
|
# doesn't match its contents, or it doesn't declare an encoding and its
|
785
859
|
# contents are invalid in the native encoding.
|
786
860
|
def check_sass_encoding(str)
|
861
|
+
# On Ruby 1.8 we can't do anything complicated with encodings.
|
862
|
+
# Instead, we just strip out a UTF-8 BOM if it exists and
|
863
|
+
# sanitize according to Section 3.3 of CSS Syntax Level 3. We
|
864
|
+
# don't sanitize null characters since they might be components
|
865
|
+
# of other characters.
|
866
|
+
if ruby1_8?
|
867
|
+
return str.gsub(/\A\xEF\xBB\xBF/, '').gsub(/\r\n?|\f/, "\n"), nil
|
868
|
+
end
|
869
|
+
|
787
870
|
# Determine the fallback encoding following section 3.2 of CSS Syntax Level 3 and Encodings:
|
788
871
|
# http://www.w3.org/TR/2013/WD-css-syntax-3-20130919/#determine-the-fallback-encoding
|
789
872
|
# http://encoding.spec.whatwg.org/#decode
|
@@ -799,9 +882,14 @@ module Sass
|
|
799
882
|
str = binary.force_encoding('UTF-16LE')
|
800
883
|
elsif binary =~ CHARSET_REGEXP
|
801
884
|
charset = $1.force_encoding('US-ASCII')
|
802
|
-
encoding
|
803
|
-
if
|
885
|
+
# Ruby 1.9.2 doesn't recognize a UTF-16 encoding without an endian marker.
|
886
|
+
if ruby1_9_2? && charset.downcase == 'utf-16'
|
804
887
|
encoding = Encoding.find('UTF-8')
|
888
|
+
else
|
889
|
+
encoding = Encoding.find(charset)
|
890
|
+
if encoding.name == 'UTF-16' || encoding.name == 'UTF-16BE'
|
891
|
+
encoding = Encoding.find('UTF-8')
|
892
|
+
end
|
805
893
|
end
|
806
894
|
str = binary.force_encoding(encoding)
|
807
895
|
elsif str.encoding.name == "ASCII-8BIT"
|
@@ -821,6 +909,50 @@ module Sass
|
|
821
909
|
end
|
822
910
|
end
|
823
911
|
|
912
|
+
# Checks to see if a class has a given method.
|
913
|
+
# For example:
|
914
|
+
#
|
915
|
+
# Sass::Util.has?(:public_instance_method, String, :gsub) #=> true
|
916
|
+
#
|
917
|
+
# Method collections like `Class#instance_methods`
|
918
|
+
# return strings in Ruby 1.8 and symbols in Ruby 1.9 and on,
|
919
|
+
# so this handles checking for them in a compatible way.
|
920
|
+
#
|
921
|
+
# @param attr [#to_s] The (singular) name of the method-collection method
|
922
|
+
# (e.g. `:instance_methods`, `:private_methods`)
|
923
|
+
# @param klass [Module] The class to check the methods of which to check
|
924
|
+
# @param method [String, Symbol] The name of the method do check for
|
925
|
+
# @return [Boolean] Whether or not the given collection has the given method
|
926
|
+
def has?(attr, klass, method)
|
927
|
+
klass.send("#{attr}s").include?(ruby1_8? ? method.to_s : method.to_sym)
|
928
|
+
end
|
929
|
+
|
930
|
+
# A version of `Enumerable#enum_with_index` that works in Ruby 1.8 and 1.9.
|
931
|
+
#
|
932
|
+
# @param enum [Enumerable] The enumerable to get the enumerator for
|
933
|
+
# @return [Enumerator] The with-index enumerator
|
934
|
+
def enum_with_index(enum)
|
935
|
+
ruby1_8? ? enum.enum_with_index : enum.each_with_index
|
936
|
+
end
|
937
|
+
|
938
|
+
# A version of `Enumerable#enum_cons` that works in Ruby 1.8 and 1.9.
|
939
|
+
#
|
940
|
+
# @param enum [Enumerable] The enumerable to get the enumerator for
|
941
|
+
# @param n [Fixnum] The size of each cons
|
942
|
+
# @return [Enumerator] The consed enumerator
|
943
|
+
def enum_cons(enum, n)
|
944
|
+
ruby1_8? ? enum.enum_cons(n) : enum.each_cons(n)
|
945
|
+
end
|
946
|
+
|
947
|
+
# A version of `Enumerable#enum_slice` that works in Ruby 1.8 and 1.9.
|
948
|
+
#
|
949
|
+
# @param enum [Enumerable] The enumerable to get the enumerator for
|
950
|
+
# @param n [Fixnum] The size of each slice
|
951
|
+
# @return [Enumerator] The consed enumerator
|
952
|
+
def enum_slice(enum, n)
|
953
|
+
ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
|
954
|
+
end
|
955
|
+
|
824
956
|
# Destructively removes all elements from an array that match a block, and
|
825
957
|
# returns the removed elements.
|
826
958
|
#
|
@@ -839,6 +971,14 @@ module Sass
|
|
839
971
|
out
|
840
972
|
end
|
841
973
|
|
974
|
+
# Returns the ASCII code of the given character.
|
975
|
+
#
|
976
|
+
# @param c [String] All characters but the first are ignored.
|
977
|
+
# @return [Fixnum] The ASCII code of `c`.
|
978
|
+
def ord(c)
|
979
|
+
ruby1_8? ? c[0] : c.ord
|
980
|
+
end
|
981
|
+
|
842
982
|
# Flattens the first level of nested arrays in `arrs`. Unlike
|
843
983
|
# `Array#flatten`, this orders the result by taking the first
|
844
984
|
# values from each array in order, then the second, and so on.
|
@@ -959,11 +1099,11 @@ module Sass
|
|
959
1099
|
|
960
1100
|
# Converts the argument into a valid JSON value.
|
961
1101
|
#
|
962
|
-
# @param v [
|
1102
|
+
# @param v [Fixnum, String, Array, Boolean, nil]
|
963
1103
|
# @return [String]
|
964
1104
|
def json_value_of(v)
|
965
1105
|
case v
|
966
|
-
when
|
1106
|
+
when Fixnum
|
967
1107
|
v.to_s
|
968
1108
|
when String
|
969
1109
|
"\"" + json_escape_string(v) + "\""
|
@@ -985,10 +1125,10 @@ module Sass
|
|
985
1125
|
VLQ_BASE_MASK = VLQ_BASE - 1
|
986
1126
|
VLQ_CONTINUATION_BIT = VLQ_BASE
|
987
1127
|
|
988
|
-
BASE64_DIGITS = ('A'..'Z').to_a
|
1128
|
+
BASE64_DIGITS = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + ['+', '/']
|
989
1129
|
BASE64_DIGIT_MAP = begin
|
990
1130
|
map = {}
|
991
|
-
BASE64_DIGITS.
|
1131
|
+
Sass::Util.enum_with_index(BASE64_DIGITS).map do |digit, i|
|
992
1132
|
map[digit] = i
|
993
1133
|
end
|
994
1134
|
map
|
@@ -996,7 +1136,7 @@ module Sass
|
|
996
1136
|
|
997
1137
|
# Encodes `value` as VLQ (http://en.wikipedia.org/wiki/VLQ).
|
998
1138
|
#
|
999
|
-
# @param value [
|
1139
|
+
# @param value [Fixnum]
|
1000
1140
|
# @return [String] The encoded value
|
1001
1141
|
def encode_vlq(value)
|
1002
1142
|
if value < 0
|
@@ -1017,6 +1157,35 @@ module Sass
|
|
1017
1157
|
result
|
1018
1158
|
end
|
1019
1159
|
|
1160
|
+
# This is a hack around the fact that you can't instantiate a URI parser on
|
1161
|
+
# 1.8, so we have to have this hacky stuff to work around it. When 1.8
|
1162
|
+
# support is dropped, we can remove this method.
|
1163
|
+
#
|
1164
|
+
# @private
|
1165
|
+
URI_ESCAPE = URI.const_defined?("DEFAULT_PARSER") ? URI::DEFAULT_PARSER : URI
|
1166
|
+
|
1167
|
+
# URI-escape `string`.
|
1168
|
+
#
|
1169
|
+
# @param string [String]
|
1170
|
+
# @return [String]
|
1171
|
+
def escape_uri(string)
|
1172
|
+
URI_ESCAPE.escape string
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
# A cross-platform implementation of `File.absolute_path`.
|
1176
|
+
#
|
1177
|
+
# @param path [String]
|
1178
|
+
# @param dir_string [String] The directory to consider [path] relative to.
|
1179
|
+
# @return [String] The absolute version of `path`.
|
1180
|
+
def absolute_path(path, dir_string = nil)
|
1181
|
+
# Ruby 1.8 doesn't support File.absolute_path.
|
1182
|
+
return File.absolute_path(path, dir_string) unless ruby1_8?
|
1183
|
+
|
1184
|
+
# File.expand_path expands "~", which we don't want.
|
1185
|
+
return File.expand_path(path, dir_string) unless path[0] == ?~
|
1186
|
+
File.expand_path(File.join(".", path), dir_string)
|
1187
|
+
end
|
1188
|
+
|
1020
1189
|
## Static Method Stuff
|
1021
1190
|
|
1022
1191
|
# The context in which the ERB for \{#def\_static\_method} will be run.
|
@@ -1074,6 +1243,44 @@ module Sass
|
|
1074
1243
|
tmpfile.unlink if tmpfile
|
1075
1244
|
end
|
1076
1245
|
|
1246
|
+
def load_listen!
|
1247
|
+
if defined?(gem)
|
1248
|
+
begin
|
1249
|
+
gem 'listen', '>= 1.1.0', '< 3.0.0'
|
1250
|
+
require 'listen'
|
1251
|
+
rescue Gem::LoadError
|
1252
|
+
dir = scope("vendor/listen/lib")
|
1253
|
+
$LOAD_PATH.unshift dir
|
1254
|
+
begin
|
1255
|
+
require 'listen'
|
1256
|
+
rescue LoadError => e
|
1257
|
+
if version_geq(RUBY_VERSION, "1.9.3")
|
1258
|
+
version_constraint = "~> 3.0"
|
1259
|
+
else
|
1260
|
+
version_constraint = "~> 1.1"
|
1261
|
+
end
|
1262
|
+
e.message << "\n" <<
|
1263
|
+
"Run \"gem install listen --version '#{version_constraint}'\" to get it."
|
1264
|
+
raise e
|
1265
|
+
end
|
1266
|
+
end
|
1267
|
+
else
|
1268
|
+
begin
|
1269
|
+
require 'listen'
|
1270
|
+
rescue LoadError => e
|
1271
|
+
dir = scope("vendor/listen/lib")
|
1272
|
+
if $LOAD_PATH.include?(dir)
|
1273
|
+
raise e unless File.exist?(scope(".git"))
|
1274
|
+
e.message << "\n" <<
|
1275
|
+
'Run "git submodule update --init" to get the bundled version.'
|
1276
|
+
else
|
1277
|
+
$LOAD_PATH.unshift dir
|
1278
|
+
retry
|
1279
|
+
end
|
1280
|
+
end
|
1281
|
+
end
|
1282
|
+
end
|
1283
|
+
|
1077
1284
|
private
|
1078
1285
|
|
1079
1286
|
def find_encoding_error(str)
|
@@ -1097,10 +1304,13 @@ module Sass
|
|
1097
1304
|
return str, str.encoding
|
1098
1305
|
end
|
1099
1306
|
|
1307
|
+
# rubocop:disable LineLength
|
1308
|
+
|
1100
1309
|
# Calculates the memoization table for the Least Common Subsequence algorithm.
|
1101
1310
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
|
1102
1311
|
def lcs_table(x, y)
|
1103
1312
|
# This method does not take a block as an explicit parameter for performance reasons.
|
1313
|
+
# rubocop:enable LineLength
|
1104
1314
|
c = Array.new(x.size) {[]}
|
1105
1315
|
x.size.times {|i| c[i][0] = 0}
|
1106
1316
|
y.size.times {|j| c[0][j] = 0}
|
@@ -1116,10 +1326,12 @@ module Sass
|
|
1116
1326
|
end
|
1117
1327
|
c
|
1118
1328
|
end
|
1329
|
+
# rubocop:disable ParameterLists, LineLength
|
1119
1330
|
|
1120
1331
|
# Computes a single longest common subsequence for arrays x and y.
|
1121
1332
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
|
1122
1333
|
def lcs_backtrace(c, x, y, i, j, &block)
|
1334
|
+
# rubocop:enable ParameterList, LineLengths
|
1123
1335
|
return [] if i == 0 || j == 0
|
1124
1336
|
if (v = yield(x[i], y[j]))
|
1125
1337
|
return lcs_backtrace(c, x, y, i - 1, j - 1, &block) << v
|
@@ -1135,3 +1347,4 @@ end
|
|
1135
1347
|
|
1136
1348
|
require 'sass/util/multibyte_string_scanner'
|
1137
1349
|
require 'sass/util/normalized_map'
|
1350
|
+
require 'sass/util/cross_platform_random'
|