sass 3.3.0.alpha.256 → 3.3.0.alpha.353
Sign up to get free protection for your applications and to get access to all the features.
- data/REVISION +1 -1
- data/Rakefile +21 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass.rb +6 -3
- data/lib/sass/cache_stores/base.rb +1 -1
- data/lib/sass/cache_stores/chain.rb +2 -1
- data/lib/sass/cache_stores/filesystem.rb +2 -6
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +1 -0
- data/lib/sass/css.rb +6 -6
- data/lib/sass/engine.rb +60 -34
- data/lib/sass/environment.rb +3 -1
- data/lib/sass/error.rb +5 -5
- data/lib/sass/exec.rb +52 -25
- data/lib/sass/features.rb +0 -2
- data/lib/sass/importers/deprecated_path.rb +1 -1
- data/lib/sass/importers/filesystem.rb +8 -6
- data/lib/sass/logger/base.rb +3 -3
- data/lib/sass/logger/log_level.rb +4 -6
- data/lib/sass/media.rb +2 -2
- data/lib/sass/plugin.rb +4 -2
- data/lib/sass/plugin/compiler.rb +28 -15
- data/lib/sass/plugin/configuration.rb +15 -7
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +24 -8
- data/lib/sass/repl.rb +3 -3
- data/lib/sass/script.rb +2 -1
- data/lib/sass/script/css_lexer.rb +8 -3
- data/lib/sass/script/css_parser.rb +6 -2
- data/lib/sass/script/functions.rb +164 -109
- data/lib/sass/script/lexer.rb +30 -20
- data/lib/sass/script/parser.rb +66 -37
- data/lib/sass/script/tree/funcall.rb +23 -14
- data/lib/sass/script/tree/interpolation.rb +5 -1
- data/lib/sass/script/tree/list_literal.rb +5 -4
- data/lib/sass/script/tree/map_literal.rb +1 -1
- data/lib/sass/script/tree/node.rb +2 -2
- data/lib/sass/script/tree/operation.rb +2 -1
- data/lib/sass/script/tree/selector.rb +3 -2
- data/lib/sass/script/tree/string_interpolation.rb +2 -1
- data/lib/sass/script/tree/variable.rb +4 -3
- data/lib/sass/script/value/base.rb +12 -14
- data/lib/sass/script/value/color.rb +35 -16
- data/lib/sass/script/value/helpers.rb +146 -0
- data/lib/sass/script/value/list.rb +24 -5
- data/lib/sass/script/value/map.rb +1 -1
- data/lib/sass/script/value/null.rb +13 -3
- data/lib/sass/script/value/number.rb +44 -35
- data/lib/sass/script/value/string.rb +2 -2
- data/lib/sass/scss/css_parser.rb +2 -1
- data/lib/sass/scss/parser.rb +143 -93
- data/lib/sass/scss/rx.rb +4 -4
- data/lib/sass/scss/script_lexer.rb +1 -0
- data/lib/sass/scss/script_parser.rb +1 -0
- data/lib/sass/scss/static_parser.rb +5 -5
- data/lib/sass/selector.rb +5 -2
- data/lib/sass/selector/abstract_sequence.rb +1 -1
- data/lib/sass/selector/comma_sequence.rb +16 -14
- data/lib/sass/selector/sequence.rb +38 -24
- data/lib/sass/selector/simple.rb +4 -4
- data/lib/sass/selector/simple_sequence.rb +21 -11
- data/lib/sass/source/map.rb +7 -2
- data/lib/sass/source/range.rb +1 -1
- data/lib/sass/supports.rb +3 -3
- data/lib/sass/tree/debug_node.rb +1 -1
- data/lib/sass/tree/function_node.rb +2 -1
- data/lib/sass/tree/if_node.rb +1 -1
- data/lib/sass/tree/import_node.rb +3 -4
- data/lib/sass/tree/prop_node.rb +4 -2
- data/lib/sass/tree/rule_node.rb +5 -2
- data/lib/sass/tree/visitors/base.rb +6 -6
- data/lib/sass/tree/visitors/check_nesting.rb +12 -9
- data/lib/sass/tree/visitors/convert.rb +34 -28
- data/lib/sass/tree/visitors/cssize.rb +4 -3
- data/lib/sass/tree/visitors/deep_copy.rb +1 -0
- data/lib/sass/tree/visitors/perform.rb +31 -16
- data/lib/sass/tree/visitors/to_css.rb +34 -16
- data/lib/sass/util.rb +88 -37
- data/lib/sass/util/multibyte_string_scanner.rb +2 -0
- data/lib/sass/util/ordered_hash.rb +20 -18
- data/lib/sass/util/subset_map.rb +3 -2
- data/lib/sass/util/test.rb +0 -1
- data/lib/sass/version.rb +9 -5
- data/test/rubocop_extensions.rb +70 -0
- data/test/sass/functions_test.rb +20 -1
- data/test/sass/importer_test.rb +2 -1
- data/test/sass/script_test.rb +4 -0
- data/test/sass/source_map_test.rb +1 -1
- data/test/sass/util_test.rb +49 -0
- data/test/sass/value_helpers_test.rb +181 -0
- metadata +13 -9
@@ -63,7 +63,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
63
63
|
@offset -= chars
|
64
64
|
end
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
# Avoid allocating lots of new strings for `#output`. This is important
|
68
68
|
# because `#output` is called all the time.
|
69
69
|
NEWLINE = "\n"
|
@@ -157,11 +157,17 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
157
157
|
spaces = (' ' * [@tabs - node.resolved_value[/^ */].size, 0].max)
|
158
158
|
|
159
159
|
content = node.resolved_value.gsub(/^/, spaces)
|
160
|
-
|
161
|
-
|
160
|
+
if node.type == :silent
|
161
|
+
content.gsub!(%r{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"}
|
162
|
+
end
|
163
|
+
if (node.style == :compact || node.style == :compressed) && node.type != :loud
|
164
|
+
content.gsub!(/\n +(\* *(?!\/))?/, ' ')
|
165
|
+
end
|
162
166
|
for_node(node) {output(content)}
|
163
167
|
end
|
164
168
|
|
169
|
+
# @comment
|
170
|
+
# rubocop:disable MethodLength
|
165
171
|
def visit_directive(node)
|
166
172
|
was_in_directive = @in_directive
|
167
173
|
tab_str = ' ' * @tabs
|
@@ -224,6 +230,8 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
224
230
|
ensure
|
225
231
|
@in_directive = was_in_directive
|
226
232
|
end
|
233
|
+
# @comment
|
234
|
+
# rubocop:enable MethodLength
|
227
235
|
|
228
236
|
def visit_media(node)
|
229
237
|
with_tabs(@tabs + node.tabs) {visit_directive(node)}
|
@@ -244,7 +252,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
244
252
|
output(tab_str)
|
245
253
|
for_node(node, :name) {output(node.resolved_name)}
|
246
254
|
if node.style == :compressed
|
247
|
-
output(":")
|
255
|
+
output(":")
|
248
256
|
for_node(node, :value) {output(node.resolved_value)}
|
249
257
|
else
|
250
258
|
output(": ")
|
@@ -253,17 +261,23 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
253
261
|
end
|
254
262
|
end
|
255
263
|
|
264
|
+
# @comment
|
265
|
+
# rubocop:disable MethodLength
|
256
266
|
def visit_rule(node)
|
257
267
|
with_tabs(@tabs + node.tabs) do
|
258
268
|
rule_separator = node.style == :compressed ? ',' : ', '
|
259
269
|
line_separator =
|
260
270
|
case node.style
|
261
|
-
|
262
|
-
|
263
|
-
|
271
|
+
when :nested, :expanded; "\n"
|
272
|
+
when :compressed; ""
|
273
|
+
else; " "
|
264
274
|
end
|
265
275
|
rule_indent = ' ' * @tabs
|
266
|
-
per_rule_indent, total_indent = [:nested, :expanded].include?(node.style)
|
276
|
+
per_rule_indent, total_indent = if [:nested, :expanded].include?(node.style)
|
277
|
+
[rule_indent, '']
|
278
|
+
else
|
279
|
+
['', rule_indent]
|
280
|
+
end
|
267
281
|
|
268
282
|
joined_rules = node.resolved_rules.members.map do |seq|
|
269
283
|
next if seq.has_placeholder?
|
@@ -293,13 +307,13 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
293
307
|
|
294
308
|
if node.filename
|
295
309
|
relative_filename = if node.options[:css_filename]
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
310
|
+
begin
|
311
|
+
Pathname.new(node.filename).relative_path_from(
|
312
|
+
Pathname.new(File.dirname(node.options[:css_filename]))).to_s
|
313
|
+
rescue ArgumentError
|
314
|
+
nil
|
315
|
+
end
|
316
|
+
end
|
303
317
|
relative_filename ||= node.filename
|
304
318
|
output(", #{relative_filename}")
|
305
319
|
end
|
@@ -335,6 +349,8 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
335
349
|
output("}" + trailer)
|
336
350
|
end
|
337
351
|
end
|
352
|
+
# @comment
|
353
|
+
# rubocop:enable MethodLength
|
338
354
|
|
339
355
|
private
|
340
356
|
|
@@ -355,7 +371,9 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
355
371
|
rule << prop
|
356
372
|
node << rule
|
357
373
|
end
|
358
|
-
node.options = options.merge(:debug_info => false,
|
374
|
+
node.options = options.merge(:debug_info => false,
|
375
|
+
:line_comments => false,
|
376
|
+
:style => :compressed)
|
359
377
|
node
|
360
378
|
end
|
361
379
|
end
|
data/lib/sass/util.rb
CHANGED
@@ -4,6 +4,7 @@ require 'enumerator'
|
|
4
4
|
require 'stringio'
|
5
5
|
require 'rbconfig'
|
6
6
|
require 'uri'
|
7
|
+
require 'thread'
|
7
8
|
|
8
9
|
require 'sass/root'
|
9
10
|
require 'sass/util/subset_map'
|
@@ -57,7 +58,7 @@ module Sass
|
|
57
58
|
end
|
58
59
|
|
59
60
|
return Hash[pairs_or_hash] unless ruby1_8?
|
60
|
-
|
61
|
+
OrderedHash[*flatten(pairs_or_hash, 1)]
|
61
62
|
end
|
62
63
|
|
63
64
|
# Converts an array of `[key, value]` pairs to a hash.
|
@@ -195,8 +196,8 @@ module Sass
|
|
195
196
|
res = ary.dup
|
196
197
|
i = 0
|
197
198
|
while i < res.size
|
198
|
-
if res[i...i+from.size] == from
|
199
|
-
res[i...i+from.size] = to
|
199
|
+
if res[i...i + from.size] == from
|
200
|
+
res[i...i + from.size] = to
|
200
201
|
end
|
201
202
|
i += 1
|
202
203
|
end
|
@@ -247,7 +248,7 @@ module Sass
|
|
247
248
|
x = [nil, *x]
|
248
249
|
y = [nil, *y]
|
249
250
|
block ||= proc {|a, b| a == b && a}
|
250
|
-
lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
|
251
|
+
lcs_backtrace(lcs_table(x, y, &block), x, y, x.size - 1, y.size - 1, &block)
|
251
252
|
end
|
252
253
|
|
253
254
|
# Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
|
@@ -261,7 +262,7 @@ module Sass
|
|
261
262
|
# @return [Array]
|
262
263
|
def hash_to_a(hash)
|
263
264
|
return hash.to_a unless ruby1_8? || defined?(Test::Unit)
|
264
|
-
|
265
|
+
hash.sort_by {|k, v| k}
|
265
266
|
end
|
266
267
|
|
267
268
|
# Performs the equivalent of `enum.group_by.to_a`, but with a guaranteed
|
@@ -275,13 +276,14 @@ module Sass
|
|
275
276
|
return enum.group_by(&block).to_a unless ruby1_8?
|
276
277
|
order = {}
|
277
278
|
arr = []
|
278
|
-
enum.group_by do |e|
|
279
|
+
groups = enum.group_by do |e|
|
279
280
|
res = block[e]
|
280
281
|
unless order.include?(res)
|
281
282
|
order[res] = order.size
|
282
283
|
end
|
283
284
|
res
|
284
|
-
end
|
285
|
+
end
|
286
|
+
groups.each do |key, vals|
|
285
287
|
arr[order[key]] = [key, vals]
|
286
288
|
end
|
287
289
|
arr
|
@@ -311,7 +313,7 @@ module Sass
|
|
311
313
|
# JRuby (as of 1.7.2) doesn't have an error_char field on
|
312
314
|
# Encoding::UndefinedConversionError.
|
313
315
|
return e.error_char.dump unless jruby?
|
314
|
-
e.message[/^"[^"]+"/] #"
|
316
|
+
e.message[/^"[^"]+"/] # "
|
315
317
|
end
|
316
318
|
|
317
319
|
# Asserts that `value` falls within `range` (inclusive), leaving
|
@@ -323,7 +325,7 @@ module Sass
|
|
323
325
|
# @param unit [String] The unit of the value. Used in error reporting.
|
324
326
|
# @return [Numeric] `value` adjusted to fall within range, if it
|
325
327
|
# was outside by a floating-point margin.
|
326
|
-
def check_range(name, range, value, unit='')
|
328
|
+
def check_range(name, range, value, unit = '')
|
327
329
|
grace = (-0.00001..0.00001)
|
328
330
|
str = value.to_s
|
329
331
|
value = value.value if value.is_a?(Sass::Script::Value::Number)
|
@@ -354,7 +356,8 @@ module Sass
|
|
354
356
|
# Returns information about the caller of the previous method.
|
355
357
|
#
|
356
358
|
# @param entry [String] An entry in the `#caller` list, or a similarly formatted string
|
357
|
-
# @return [[String, Fixnum, (String, nil)]]
|
359
|
+
# @return [[String, Fixnum, (String, nil)]]
|
360
|
+
# An array containing the filename, line, and method name of the caller.
|
358
361
|
# The method name may be nil
|
359
362
|
def caller_info(entry = nil)
|
360
363
|
# JRuby evaluates `caller` incorrectly when it's in an actual default argument.
|
@@ -422,7 +425,6 @@ module Sass
|
|
422
425
|
$stderr = the_real_stderr
|
423
426
|
end
|
424
427
|
|
425
|
-
@@silence_warnings = false
|
426
428
|
# Silences all Sass warnings within a block.
|
427
429
|
#
|
428
430
|
# @yield A block in which no Sass warnings will be printed
|
@@ -454,7 +456,7 @@ module Sass
|
|
454
456
|
raise "ERROR: Rails.root is nil!"
|
455
457
|
end
|
456
458
|
return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
|
457
|
-
|
459
|
+
nil
|
458
460
|
end
|
459
461
|
|
460
462
|
# Returns the environment of the Rails application,
|
@@ -465,7 +467,7 @@ module Sass
|
|
465
467
|
def rails_env
|
466
468
|
return ::Rails.env.to_s if defined?(::Rails.env)
|
467
469
|
return RAILS_ENV.to_s if defined?(RAILS_ENV)
|
468
|
-
|
470
|
+
nil
|
469
471
|
end
|
470
472
|
|
471
473
|
# Returns whether this environment is using ActionPack
|
@@ -501,7 +503,7 @@ module Sass
|
|
501
503
|
# or `ActionView::Template::Error`.
|
502
504
|
def av_template_class(name)
|
503
505
|
return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
|
504
|
-
|
506
|
+
ActionView::Template.const_get(name.to_s)
|
505
507
|
end
|
506
508
|
|
507
509
|
## Cross-OS Compatibility
|
@@ -534,11 +536,16 @@ module Sass
|
|
534
536
|
RUBY_PLATFORM =~ /java/
|
535
537
|
end
|
536
538
|
|
539
|
+
# @see #jruby_version-class_method
|
540
|
+
def jruby_version
|
541
|
+
Sass::Util.jruby_version
|
542
|
+
end
|
543
|
+
|
537
544
|
# Returns an array of ints representing the JRuby version number.
|
538
545
|
#
|
539
546
|
# @return [Array<Fixnum>]
|
540
|
-
def jruby_version
|
541
|
-
|
547
|
+
def self.jruby_version
|
548
|
+
@jruby_version ||= ::JRUBY_VERSION.split(".").map {|s| s.to_i}
|
542
549
|
end
|
543
550
|
|
544
551
|
# Like `Dir.glob`, but works with backslash-separated paths on Windows.
|
@@ -636,7 +643,7 @@ Invalid #{encoding.name} character #{undefined_conversion_error_char(e)}
|
|
636
643
|
MSG
|
637
644
|
end
|
638
645
|
end
|
639
|
-
|
646
|
+
str
|
640
647
|
end
|
641
648
|
|
642
649
|
# Like {\#check\_encoding}, but also checks for a `@charset` declaration
|
@@ -669,7 +676,7 @@ MSG
|
|
669
676
|
charset, bom = $1, $2
|
670
677
|
if charset
|
671
678
|
charset = charset.force_encoding(encoding).encode("UTF-8")
|
672
|
-
if endianness = encoding[/[BL]E$/]
|
679
|
+
if (endianness = encoding[/[BL]E$/])
|
673
680
|
begin
|
674
681
|
Encoding.find(charset + endianness)
|
675
682
|
charset << endianness
|
@@ -816,8 +823,9 @@ MSG
|
|
816
823
|
set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
|
817
824
|
end
|
818
825
|
|
819
|
-
# Like `Object#inspect`, but preserves non-ASCII characters rather than
|
820
|
-
# This is necessary so that the
|
826
|
+
# Like `Object#inspect`, but preserves non-ASCII characters rather than
|
827
|
+
# escaping them under Ruby 1.9.2. This is necessary so that the
|
828
|
+
# precompiled Haml template can be `#encode`d into `@options[:encoding]`
|
821
829
|
# before being evaluated.
|
822
830
|
#
|
823
831
|
# @param obj {Object}
|
@@ -843,11 +851,12 @@ MSG
|
|
843
851
|
# @return [(String, Array)] The resulting string, and an array of extracted values.
|
844
852
|
def extract_values(arr)
|
845
853
|
values = []
|
846
|
-
|
854
|
+
mapped = arr.map do |e|
|
847
855
|
next e.gsub('{', '{{') if e.is_a?(String)
|
848
856
|
values << e
|
849
857
|
next "{#{values.count - 1}}"
|
850
|
-
end
|
858
|
+
end
|
859
|
+
return mapped.join, values
|
851
860
|
end
|
852
861
|
|
853
862
|
# Undoes \{#extract\_values} by transforming a string with escape sequences
|
@@ -962,7 +971,7 @@ MSG
|
|
962
971
|
value <<= 1
|
963
972
|
end
|
964
973
|
|
965
|
-
result =
|
974
|
+
result = ''
|
966
975
|
begin
|
967
976
|
digit = value & VLQ_BASE_MASK
|
968
977
|
value >>= VLQ_BASE_SHIFT
|
@@ -974,6 +983,21 @@ MSG
|
|
974
983
|
result
|
975
984
|
end
|
976
985
|
|
986
|
+
# This is a hack around the fact that you can't instantiate a URI parser on
|
987
|
+
# 1.8, so we have to have this hacky stuff to work around it. When 1.8
|
988
|
+
# support is dropped, we can remove this method.
|
989
|
+
#
|
990
|
+
# @private
|
991
|
+
URI_ESCAPE = URI.const_defined?("DEFAULT_PARSER") ? URI::DEFAULT_PARSER : URI
|
992
|
+
|
993
|
+
# URI-escape `string`.
|
994
|
+
#
|
995
|
+
# @param string [String]
|
996
|
+
# @return [String]
|
997
|
+
def escape_uri(string)
|
998
|
+
URI_ESCAPE.escape string
|
999
|
+
end
|
1000
|
+
|
977
1001
|
## Static Method Stuff
|
978
1002
|
|
979
1003
|
# The context in which the ERB for \{#def\_static\_method} will be run.
|
@@ -993,20 +1017,43 @@ MSG
|
|
993
1017
|
end
|
994
1018
|
end
|
995
1019
|
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1020
|
+
# @private
|
1021
|
+
ATOMIC_WRITE_MUTEX = Mutex.new
|
1022
|
+
|
1023
|
+
# This creates a temp file and yields it for writing. When the
|
1024
|
+
# write is complete, the file is moved into the desired location.
|
1025
|
+
# The atomicity of this operation is provided by the filesystem's
|
1026
|
+
# rename operation.
|
1027
|
+
#
|
1028
|
+
# @param filename [String] The file to write to.
|
1029
|
+
# @yieldparam tmpfile [Tempfile] The temp file that can be written to.
|
1030
|
+
# @return The value returned by the block.
|
1031
|
+
def atomic_create_and_write_file(filename)
|
1032
|
+
require 'tempfile'
|
1033
|
+
tmpfile = Tempfile.new(File.basename(filename), File.dirname(filename))
|
1034
|
+
tmpfile.binmode if tmpfile.respond_to?(:binmode)
|
1035
|
+
result = yield tmpfile
|
1036
|
+
tmpfile.close
|
1037
|
+
ATOMIC_WRITE_MUTEX.synchronize do
|
1038
|
+
File.rename tmpfile.path, filename
|
1039
|
+
end
|
1040
|
+
result
|
1041
|
+
ensure
|
1042
|
+
# close and remove the tempfile if it still exists,
|
1043
|
+
# presumably due to an error during write
|
1044
|
+
tmpfile.close if tmpfile
|
1045
|
+
tmpfile.unlink if tmpfile
|
1003
1046
|
end
|
1004
1047
|
|
1005
1048
|
private
|
1006
1049
|
|
1050
|
+
# rubocop:disable LineLength
|
1051
|
+
|
1052
|
+
|
1007
1053
|
# Calculates the memoization table for the Least Common Subsequence algorithm.
|
1008
1054
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
|
1009
1055
|
def lcs_table(x, y)
|
1056
|
+
# rubocop:enable LineLength
|
1010
1057
|
c = Array.new(x.size) {[]}
|
1011
1058
|
x.size.times {|i| c[i][0] = 0}
|
1012
1059
|
y.size.times {|j| c[0][j] = 0}
|
@@ -1014,25 +1061,29 @@ MSG
|
|
1014
1061
|
(1...y.size).each do |j|
|
1015
1062
|
c[i][j] =
|
1016
1063
|
if yield x[i], y[j]
|
1017
|
-
c[i-1][j-1] + 1
|
1064
|
+
c[i - 1][j - 1] + 1
|
1018
1065
|
else
|
1019
|
-
[c[i][j-1], c[i-1][j]].max
|
1066
|
+
[c[i][j - 1], c[i - 1][j]].max
|
1020
1067
|
end
|
1021
1068
|
end
|
1022
1069
|
end
|
1023
|
-
|
1070
|
+
c
|
1024
1071
|
end
|
1025
1072
|
|
1073
|
+
# rubocop:disable ParameterLists, LineLength
|
1074
|
+
|
1075
|
+
|
1026
1076
|
# Computes a single longest common subsequence for arrays x and y.
|
1027
1077
|
# Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
|
1028
1078
|
def lcs_backtrace(c, x, y, i, j, &block)
|
1079
|
+
# rubocop:enable ParameterList, LineLengths
|
1029
1080
|
return [] if i == 0 || j == 0
|
1030
|
-
if v = yield(x[i], y[j])
|
1031
|
-
return lcs_backtrace(c, x, y, i-1, j-1, &block) << v
|
1081
|
+
if (v = yield(x[i], y[j]))
|
1082
|
+
return lcs_backtrace(c, x, y, i - 1, j - 1, &block) << v
|
1032
1083
|
end
|
1033
1084
|
|
1034
|
-
return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
|
1035
|
-
|
1085
|
+
return lcs_backtrace(c, x, y, i, j - 1, &block) if c[i][j - 1] > c[i - 1][j]
|
1086
|
+
lcs_backtrace(c, x, y, i - 1, j, &block)
|
1036
1087
|
end
|
1037
1088
|
end
|
1038
1089
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'strscan'
|
2
2
|
|
3
3
|
if Sass::Util.ruby1_8?
|
4
|
+
# rubocop:disable ConstantName
|
4
5
|
Sass::Util::MultibyteStringScanner = StringScanner
|
6
|
+
# rubocop:enable ConstantName
|
5
7
|
else
|
6
8
|
if Sass::Util.rbx?
|
7
9
|
# Rubinius's StringScanner class implements some of its methods in terms of
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (c) 2005-2013 David Heinemeier Hansson
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
5
5
|
# "Software"), to deal in the Software without restriction, including
|
@@ -7,10 +7,10 @@
|
|
7
7
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
8
|
# permit persons to whom the Software is furnished to do so, subject to
|
9
9
|
# the following conditions:
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# The above copyright notice and this permission notice shall be
|
12
12
|
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
15
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
16
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -39,21 +39,21 @@ class OrderedHash < ::Hash
|
|
39
39
|
def self.[](*args)
|
40
40
|
ordered_hash = new
|
41
41
|
|
42
|
-
if
|
42
|
+
if args.length == 1 && args.first.is_a?(Array)
|
43
43
|
args.first.each do |key_value_pair|
|
44
|
-
next unless
|
44
|
+
next unless key_value_pair.is_a?(Array)
|
45
45
|
ordered_hash[key_value_pair[0]] = key_value_pair[1]
|
46
46
|
end
|
47
47
|
|
48
48
|
return ordered_hash
|
49
49
|
end
|
50
50
|
|
51
|
-
unless
|
51
|
+
unless args.size.even?
|
52
52
|
raise ArgumentError.new("odd number of arguments for Hash")
|
53
53
|
end
|
54
54
|
|
55
55
|
args.each_with_index do |val, ind|
|
56
|
-
next if
|
56
|
+
next if ind.odd?
|
57
57
|
ordered_hash[val] = args[ind + 1]
|
58
58
|
end
|
59
59
|
|
@@ -100,7 +100,7 @@ class OrderedHash < ::Hash
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def values
|
103
|
-
@keys.
|
103
|
+
@keys.map {|key| self[key]}
|
104
104
|
end
|
105
105
|
|
106
106
|
def to_hash
|
@@ -108,18 +108,18 @@ class OrderedHash < ::Hash
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def to_a
|
111
|
-
@keys.map {
|
111
|
+
@keys.map {|key| [key, self[key]]}
|
112
112
|
end
|
113
113
|
|
114
114
|
def each_key
|
115
115
|
return to_enum(:each_key) unless block_given?
|
116
|
-
@keys.each {
|
116
|
+
@keys.each {|key| yield key}
|
117
117
|
self
|
118
118
|
end
|
119
119
|
|
120
120
|
def each_value
|
121
121
|
return to_enum(:each_value) unless block_given?
|
122
|
-
@keys.each {
|
122
|
+
@keys.each {|key| yield self[key]}
|
123
123
|
self
|
124
124
|
end
|
125
125
|
|
@@ -151,9 +151,9 @@ class OrderedHash < ::Hash
|
|
151
151
|
|
152
152
|
def merge!(other_hash)
|
153
153
|
if block_given?
|
154
|
-
other_hash.each {
|
154
|
+
other_hash.each {|k, v| self[k] = key?(k) ? yield(k, self[k], v) : v}
|
155
155
|
else
|
156
|
-
other_hash.each {
|
156
|
+
other_hash.each {|k, v| self[k] = v}
|
157
157
|
end
|
158
158
|
self
|
159
159
|
end
|
@@ -164,7 +164,8 @@ class OrderedHash < ::Hash
|
|
164
164
|
dup.merge!(other_hash, &block)
|
165
165
|
end
|
166
166
|
|
167
|
-
# When replacing with another hash, the initial order of our keys must come from the other hash
|
167
|
+
# When replacing with another hash, the initial order of our keys must come from the other hash --
|
168
|
+
# ordered or not.
|
168
169
|
def replace(other)
|
169
170
|
super
|
170
171
|
@keys = other.keys
|
@@ -172,7 +173,7 @@ class OrderedHash < ::Hash
|
|
172
173
|
end
|
173
174
|
|
174
175
|
def invert
|
175
|
-
OrderedHash[
|
176
|
+
OrderedHash[to_a.map! {|key_value_pair| key_value_pair.reverse}]
|
176
177
|
end
|
177
178
|
|
178
179
|
def inspect
|
@@ -180,7 +181,8 @@ class OrderedHash < ::Hash
|
|
180
181
|
end
|
181
182
|
|
182
183
|
private
|
183
|
-
|
184
|
-
|
185
|
-
|
184
|
+
|
185
|
+
def sync_keys!
|
186
|
+
@keys.delete_if {|k| !has_key?(k)}
|
187
|
+
end
|
186
188
|
end
|