sass 3.4.0 → 3.4.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +3 -1
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +148 -0
- data/MIT-LICENSE +1 -1
- data/README.md +26 -20
- data/Rakefile +103 -20
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/extra/sass-spec-ref.sh +32 -0
- data/extra/update_watch.rb +1 -1
- data/lib/sass/cache_stores/filesystem.rb +7 -7
- data/lib/sass/cache_stores/memory.rb +4 -5
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +11 -10
- data/lib/sass/deprecation.rb +55 -0
- data/lib/sass/engine.rb +83 -38
- data/lib/sass/environment.rb +26 -2
- data/lib/sass/error.rb +12 -12
- data/lib/sass/exec/base.rb +15 -3
- data/lib/sass/exec/sass_convert.rb +34 -15
- data/lib/sass/exec/sass_scss.rb +23 -7
- data/lib/sass/features.rb +2 -2
- data/lib/sass/importers/base.rb +1 -1
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +24 -16
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +8 -2
- data/lib/sass/logger/delayed.rb +50 -0
- data/lib/sass/logger.rb +8 -3
- data/lib/sass/plugin/compiler.rb +42 -25
- data/lib/sass/plugin/configuration.rb +38 -22
- data/lib/sass/plugin/merb.rb +2 -2
- data/lib/sass/plugin/rack.rb +3 -3
- data/lib/sass/plugin/rails.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +3 -3
- data/lib/sass/plugin.rb +3 -2
- data/lib/sass/script/css_parser.rb +2 -3
- data/lib/sass/script/css_variable_warning.rb +52 -0
- data/lib/sass/script/functions.rb +140 -73
- data/lib/sass/script/lexer.rb +37 -22
- data/lib/sass/script/parser.rb +235 -40
- data/lib/sass/script/tree/funcall.rb +12 -5
- data/lib/sass/script/tree/interpolation.rb +109 -4
- data/lib/sass/script/tree/list_literal.rb +31 -4
- data/lib/sass/script/tree/literal.rb +4 -0
- data/lib/sass/script/tree/node.rb +21 -3
- data/lib/sass/script/tree/operation.rb +54 -1
- data/lib/sass/script/tree/string_interpolation.rb +58 -37
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/value/base.rb +10 -9
- data/lib/sass/script/value/color.rb +42 -24
- data/lib/sass/script/value/helpers.rb +16 -6
- data/lib/sass/script/value/map.rb +1 -1
- data/lib/sass/script/value/number.rb +52 -19
- data/lib/sass/script/value/string.rb +46 -5
- data/lib/sass/script.rb +3 -3
- data/lib/sass/scss/css_parser.rb +16 -2
- data/lib/sass/scss/parser.rb +120 -75
- data/lib/sass/scss/rx.rb +9 -10
- data/lib/sass/scss/static_parser.rb +19 -14
- data/lib/sass/scss.rb +0 -2
- data/lib/sass/selector/abstract_sequence.rb +8 -6
- data/lib/sass/selector/comma_sequence.rb +25 -9
- data/lib/sass/selector/pseudo.rb +45 -35
- data/lib/sass/selector/sequence.rb +54 -18
- data/lib/sass/selector/simple.rb +11 -11
- data/lib/sass/selector/simple_sequence.rb +34 -15
- data/lib/sass/selector.rb +7 -10
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/source/map.rb +7 -4
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +2 -2
- data/lib/sass/supports.rb +8 -10
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/css_import_node.rb +9 -1
- data/lib/sass/tree/function_node.rb +8 -3
- data/lib/sass/tree/import_node.rb +6 -5
- data/lib/sass/tree/node.rb +5 -3
- data/lib/sass/tree/prop_node.rb +5 -6
- data/lib/sass/tree/rule_node.rb +14 -4
- data/lib/sass/tree/visitors/check_nesting.rb +18 -22
- data/lib/sass/tree/visitors/convert.rb +43 -26
- data/lib/sass/tree/visitors/cssize.rb +5 -1
- data/lib/sass/tree/visitors/deep_copy.rb +1 -1
- data/lib/sass/tree/visitors/extend.rb +15 -13
- data/lib/sass/tree/visitors/perform.rb +42 -17
- data/lib/sass/tree/visitors/set_options.rb +1 -1
- data/lib/sass/tree/visitors/to_css.rb +58 -30
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/normalized_map.rb +0 -1
- data/lib/sass/util/subset_map.rb +1 -2
- data/lib/sass/util.rb +125 -68
- data/lib/sass/version.rb +2 -2
- data/lib/sass.rb +10 -3
- data/test/sass/compiler_test.rb +6 -2
- data/test/sass/conversion_test.rb +187 -53
- data/test/sass/css2sass_test.rb +50 -1
- data/test/sass/css_variable_test.rb +132 -0
- data/test/sass/engine_test.rb +207 -61
- data/test/sass/exec_test.rb +10 -0
- data/test/sass/extend_test.rb +101 -29
- data/test/sass/functions_test.rb +60 -9
- data/test/sass/importer_test.rb +9 -0
- data/test/sass/more_templates/more1.sass +10 -10
- data/test/sass/more_templates/more_import.sass +2 -2
- data/test/sass/plugin_test.rb +10 -8
- data/test/sass/results/script.css +3 -3
- data/test/sass/script_conversion_test.rb +58 -29
- data/test/sass/script_test.rb +430 -53
- data/test/sass/scss/css_test.rb +73 -7
- data/test/sass/scss/rx_test.rb +4 -0
- data/test/sass/scss/scss_test.rb +309 -4
- data/test/sass/source_map_test.rb +152 -74
- data/test/sass/superselector_test.rb +19 -0
- data/test/sass/templates/_partial.sass +1 -1
- data/test/sass/templates/basic.sass +10 -10
- data/test/sass/templates/bork1.sass +1 -1
- data/test/sass/templates/bork5.sass +1 -1
- data/test/sass/templates/compact.sass +10 -10
- data/test/sass/templates/complex.sass +187 -187
- data/test/sass/templates/compressed.sass +10 -10
- data/test/sass/templates/expanded.sass +10 -10
- data/test/sass/templates/import.sass +2 -2
- data/test/sass/templates/importee.sass +3 -3
- data/test/sass/templates/mixins.sass +22 -22
- data/test/sass/templates/multiline.sass +4 -4
- data/test/sass/templates/nested.sass +13 -13
- data/test/sass/templates/parent_ref.sass +12 -12
- data/test/sass/templates/script.sass +70 -70
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
- data/test/sass/templates/subdir/subdir.sass +3 -3
- data/test/sass/templates/units.sass +10 -10
- data/test/sass/util/multibyte_string_scanner_test.rb +10 -2
- data/test/sass/util_test.rb +15 -44
- data/test/sass-spec.yml +3 -0
- data/test/test_helper.rb +5 -4
- metadata +302 -295
- data/CONTRIBUTING +0 -3
- data/lib/sass/scss/script_lexer.rb +0 -15
- data/lib/sass/scss/script_parser.rb +0 -25
data/lib/sass/selector/pseudo.rb
CHANGED
@@ -9,7 +9,7 @@ module Sass
|
|
9
9
|
# selectors.
|
10
10
|
#
|
11
11
|
# @return [Set<String>]
|
12
|
-
ACTUALLY_ELEMENTS = %w
|
12
|
+
ACTUALLY_ELEMENTS = %w(after before first-line first-letter).to_set
|
13
13
|
|
14
14
|
# Like \{#type}, but returns the type of selector this looks like, rather
|
15
15
|
# than the type it is semantically. This only differs from type for
|
@@ -51,40 +51,50 @@ module Sass
|
|
51
51
|
# Returns a copy of this with \{#selector} set to \{#new\_selector}.
|
52
52
|
#
|
53
53
|
# @param new_selector [CommaSequence]
|
54
|
-
# @return [
|
54
|
+
# @return [Array<Simple>]
|
55
55
|
def with_selector(new_selector)
|
56
|
-
Pseudo.new(syntactic_type, name, arg,
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
result = Pseudo.new(syntactic_type, name, arg,
|
57
|
+
CommaSequence.new(new_selector.members.map do |seq|
|
58
|
+
next seq unless seq.members.length == 1
|
59
|
+
sseq = seq.members.first
|
60
|
+
next seq unless sseq.is_a?(SimpleSequence) && sseq.members.length == 1
|
61
|
+
sel = sseq.members.first
|
62
|
+
next seq unless sel.is_a?(Pseudo) && sel.selector
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
64
|
+
case normalized_name
|
65
|
+
when 'not'
|
66
|
+
# In theory, if there's a nested :not its contents should be
|
67
|
+
# unified with the return value. For example, if :not(.foo)
|
68
|
+
# extends .bar, :not(.bar) should become .foo:not(.bar). However,
|
69
|
+
# this is a narrow edge case and supporting it properly would make
|
70
|
+
# this code and the code calling it a lot more complicated, so
|
71
|
+
# it's not supported for now.
|
72
|
+
next [] unless sel.normalized_name == 'matches'
|
73
|
+
sel.selector.members
|
74
|
+
when 'matches', 'any', 'current', 'nth-child', 'nth-last-child'
|
75
|
+
# As above, we could theoretically support :not within :matches, but
|
76
|
+
# doing so would require this method and its callers to handle much
|
77
|
+
# more complex cases that likely aren't worth the pain.
|
78
|
+
next [] unless sel.name == name && sel.arg == arg
|
79
|
+
sel.selector.members
|
80
|
+
when 'has', 'host', 'host-context'
|
81
|
+
# We can't expand nested selectors here, because each layer adds an
|
82
|
+
# additional layer of semantics. For example, `:has(:has(img))`
|
83
|
+
# doesn't match `<div><img></div>` but `:has(img)` does.
|
84
|
+
sel
|
85
|
+
else
|
86
|
+
[]
|
87
|
+
end
|
88
|
+
end.flatten))
|
89
|
+
|
90
|
+
# Older browsers support :not but only with a single complex selector.
|
91
|
+
# In order to support those browsers, we break up the contents of a :not
|
92
|
+
# unless it originally contained a selector list.
|
93
|
+
return [result] unless normalized_name == 'not'
|
94
|
+
return [result] if selector.members.length > 1
|
95
|
+
result.selector.members.map do |seq|
|
96
|
+
Pseudo.new(syntactic_type, name, arg, CommaSequence.new([seq]))
|
97
|
+
end
|
88
98
|
end
|
89
99
|
|
90
100
|
# The type of the selector. `:class` if this is a pseudoclass selector,
|
@@ -103,13 +113,13 @@ module Sass
|
|
103
113
|
end
|
104
114
|
|
105
115
|
# @see Selector#to_s
|
106
|
-
def to_s
|
116
|
+
def to_s(opts = {})
|
107
117
|
res = (syntactic_type == :class ? ":" : "::") + @name
|
108
118
|
if @arg || @selector
|
109
119
|
res << "("
|
110
120
|
res << @arg.strip if @arg
|
111
121
|
res << " " if @arg && @selector
|
112
|
-
res << @selector.to_s if @selector
|
122
|
+
res << @selector.to_s(opts) if @selector
|
113
123
|
res << ")"
|
114
124
|
end
|
115
125
|
res
|
@@ -6,11 +6,11 @@ module Sass
|
|
6
6
|
# Sets the line of the Sass template on which this selector was declared.
|
7
7
|
# This also sets the line for all child selectors.
|
8
8
|
#
|
9
|
-
# @param line [
|
10
|
-
# @return [
|
9
|
+
# @param line [Integer]
|
10
|
+
# @return [Integer]
|
11
11
|
def line=(line)
|
12
12
|
members.each {|m| m.line = line if m.is_a?(SimpleSequence)}
|
13
|
-
line
|
13
|
+
@line = line
|
14
14
|
end
|
15
15
|
|
16
16
|
# Sets the name of the file in which this selector was declared,
|
@@ -52,9 +52,7 @@ module Sass
|
|
52
52
|
def resolve_parent_refs(super_cseq, implicit_parent)
|
53
53
|
members = @members.dup
|
54
54
|
nl = (members.first == "\n" && members.shift)
|
55
|
-
contains_parent_ref =
|
56
|
-
seq_or_op.is_a?(SimpleSequence) && seq_or_op.members.first.is_a?(Parent)
|
57
|
-
end
|
55
|
+
contains_parent_ref = contains_parent_ref?
|
58
56
|
return CommaSequence.new([self]) if !implicit_parent && !contains_parent_ref
|
59
57
|
|
60
58
|
unless contains_parent_ref
|
@@ -75,6 +73,19 @@ module Sass
|
|
75
73
|
end)
|
76
74
|
end
|
77
75
|
|
76
|
+
# Returns whether there's a {Parent} selector anywhere in this sequence.
|
77
|
+
#
|
78
|
+
# @return [Boolean]
|
79
|
+
def contains_parent_ref?
|
80
|
+
members.any? do |sseq_or_op|
|
81
|
+
next false unless sseq_or_op.is_a?(SimpleSequence)
|
82
|
+
next true if sseq_or_op.members.first.is_a?(Parent)
|
83
|
+
sseq_or_op.members.any? do |sel|
|
84
|
+
sel.is_a?(Pseudo) && sel.selector && sel.selector.contains_parent_ref?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
78
89
|
# Non-destructively extends this selector with the extensions specified in a hash
|
79
90
|
# (which should come from {Sass::Tree::Visitors::Cssize}).
|
80
91
|
#
|
@@ -146,8 +157,8 @@ module Sass
|
|
146
157
|
end
|
147
158
|
|
148
159
|
# @see AbstractSequence#to_s
|
149
|
-
def to_s
|
150
|
-
@members.join(" ").gsub(/ ?\n ?/, "\n")
|
160
|
+
def to_s(opts = {})
|
161
|
+
@members.map {|m| m.is_a?(String) ? m : m.to_s(opts)}.join(" ").gsub(/ ?\n ?/, "\n")
|
151
162
|
end
|
152
163
|
|
153
164
|
# Returns a string representation of the sequence.
|
@@ -217,11 +228,11 @@ module Sass
|
|
217
228
|
next if current.empty?
|
218
229
|
current = current.dup
|
219
230
|
last_current = [current.pop]
|
220
|
-
prefixes =
|
231
|
+
prefixes = prefixes.map do |prefix|
|
221
232
|
sub = subweave(prefix, current)
|
222
233
|
next [] unless sub
|
223
234
|
sub.map {|seqs| seqs + last_current}
|
224
|
-
end
|
235
|
+
end.flatten(1)
|
225
236
|
end
|
226
237
|
prefixes
|
227
238
|
end
|
@@ -249,10 +260,22 @@ module Sass
|
|
249
260
|
return [seq1] if seq2.empty?
|
250
261
|
|
251
262
|
seq1, seq2 = seq1.dup, seq2.dup
|
252
|
-
init = merge_initial_ops(seq1, seq2)
|
253
|
-
return unless
|
254
|
-
|
255
|
-
|
263
|
+
return unless (init = merge_initial_ops(seq1, seq2))
|
264
|
+
return unless (fin = merge_final_ops(seq1, seq2))
|
265
|
+
|
266
|
+
# Make sure there's only one root selector in the output.
|
267
|
+
root1 = has_root?(seq1.first) && seq1.shift
|
268
|
+
root2 = has_root?(seq2.first) && seq2.shift
|
269
|
+
if root1 && root2
|
270
|
+
return unless (root = root1.unify(root2))
|
271
|
+
seq1.unshift root
|
272
|
+
seq2.unshift root
|
273
|
+
elsif root1
|
274
|
+
seq2.unshift root1
|
275
|
+
elsif root2
|
276
|
+
seq1.unshift root2
|
277
|
+
end
|
278
|
+
|
256
279
|
seq1 = group_selectors(seq1)
|
257
280
|
seq2 = group_selectors(seq2)
|
258
281
|
lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
|
@@ -263,6 +286,7 @@ module Sass
|
|
263
286
|
end
|
264
287
|
|
265
288
|
diff = [[init]]
|
289
|
+
|
266
290
|
until lcs.empty?
|
267
291
|
diff << chunks(seq1, seq2) {|s| parent_superselector?(s.first, lcs.first)} << [lcs.shift]
|
268
292
|
seq1.shift
|
@@ -371,10 +395,10 @@ module Sass
|
|
371
395
|
([merged, '+'] if merged)
|
372
396
|
].compact
|
373
397
|
end
|
374
|
-
elsif op1 == '>' && %w
|
398
|
+
elsif op1 == '>' && %w(~ +).include?(op2)
|
375
399
|
res.unshift sel2, op2
|
376
400
|
seq1.push sel1, op1
|
377
|
-
elsif op2 == '>' && %w
|
401
|
+
elsif op2 == '>' && %w(~ +).include?(op1)
|
378
402
|
res.unshift sel1, op1
|
379
403
|
seq2.push sel2, op2
|
380
404
|
elsif op1 == op2
|
@@ -479,8 +503,15 @@ module Sass
|
|
479
503
|
|
480
504
|
if seq1[1].is_a?(String)
|
481
505
|
return unless seq2[si + 1].is_a?(String)
|
506
|
+
|
482
507
|
# .foo ~ .bar is a superselector of .foo + .bar
|
483
508
|
return unless seq1[1] == "~" ? seq2[si + 1] != ">" : seq1[1] == seq2[si + 1]
|
509
|
+
|
510
|
+
# .foo > .baz is not a superselector of .foo > .bar > .baz or .foo >
|
511
|
+
# .bar .baz, despite the fact that .baz is a superselector of .bar >
|
512
|
+
# .baz and .bar .baz. Same goes for + and ~.
|
513
|
+
return if seq1.length == 3 && seq2.length > 3
|
514
|
+
|
484
515
|
return _superselector?(seq1[2..-1], seq2[si + 2..-1])
|
485
516
|
elsif seq2[si + 1].is_a?(String)
|
486
517
|
return unless seq2[si + 1] == ">"
|
@@ -520,7 +551,7 @@ module Sass
|
|
520
551
|
def trim(seqses)
|
521
552
|
# Avoid truly horrific quadratic behavior. TODO: I think there
|
522
553
|
# may be a way to get perfect trimming without going quadratic.
|
523
|
-
return
|
554
|
+
return seqses.flatten(1) if seqses.size > 100
|
524
555
|
|
525
556
|
# Keep the results in a separate array so we can be sure we aren't
|
526
557
|
# comparing against an already-trimmed selector. This ensures that two
|
@@ -555,7 +586,7 @@ module Sass
|
|
555
586
|
end
|
556
587
|
end
|
557
588
|
end
|
558
|
-
|
589
|
+
result.flatten(1)
|
559
590
|
end
|
560
591
|
|
561
592
|
def _hash
|
@@ -595,6 +626,11 @@ module Sass
|
|
595
626
|
"(#{choices.join ', '})"
|
596
627
|
end.join ' '
|
597
628
|
end
|
629
|
+
|
630
|
+
def has_root?(sseq)
|
631
|
+
sseq.is_a?(SimpleSequence) &&
|
632
|
+
sseq.members.any? {|sel| sel.is_a?(Pseudo) && sel.normalized_name == "root"}
|
633
|
+
end
|
598
634
|
end
|
599
635
|
end
|
600
636
|
end
|
data/lib/sass/selector/simple.rb
CHANGED
@@ -5,7 +5,7 @@ module Sass
|
|
5
5
|
class Simple
|
6
6
|
# The line of the Sass template on which this selector was declared.
|
7
7
|
#
|
8
|
-
# @return [
|
8
|
+
# @return [Integer]
|
9
9
|
attr_accessor :line
|
10
10
|
|
11
11
|
# The name of the file in which this selector was declared,
|
@@ -23,8 +23,10 @@ module Sass
|
|
23
23
|
|
24
24
|
# Returns the selector string.
|
25
25
|
#
|
26
|
+
# @param opts [Hash] rendering options.
|
27
|
+
# @option opts [Symbol] :style The css rendering style.
|
26
28
|
# @return [String]
|
27
|
-
def to_s
|
29
|
+
def to_s(opts = {})
|
28
30
|
Sass::Util.abstract(self)
|
29
31
|
end
|
30
32
|
|
@@ -34,7 +36,7 @@ module Sass
|
|
34
36
|
# so if that contains information irrelevant to the identity of the selector,
|
35
37
|
# this should be overridden.
|
36
38
|
#
|
37
|
-
# @return [
|
39
|
+
# @return [Integer]
|
38
40
|
def hash
|
39
41
|
@_hash ||= equality_key.hash
|
40
42
|
end
|
@@ -70,14 +72,12 @@ module Sass
|
|
70
72
|
# by the time extension and unification happen,
|
71
73
|
# this exception will only ever be raised as a result of programmer error
|
72
74
|
def unify(sels)
|
75
|
+
return sels.first.unify([self]) if sels.length == 1 && sels.first.is_a?(Universal)
|
73
76
|
return sels if sels.any? {|sel2| eql?(sel2)}
|
74
77
|
sels_with_ix = Sass::Util.enum_with_index(sels)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
else
|
79
|
-
sels_with_ix.find {|sel, _| sel.is_a?(Pseudo)}
|
80
|
-
end
|
78
|
+
if !is_a?(Pseudo) || (sels.last.is_a?(Pseudo) && sels.last.type == :element)
|
79
|
+
_, i = sels_with_ix.find {|sel, _| sel.is_a?(Pseudo)}
|
80
|
+
end
|
81
81
|
return sels + [self] unless i
|
82
82
|
sels[0...i] + [self] + sels[i..-1]
|
83
83
|
end
|
@@ -107,10 +107,10 @@ module Sass
|
|
107
107
|
# could be found at all.
|
108
108
|
# If the second value is `false`, the first should be ignored.
|
109
109
|
def unify_namespaces(ns1, ns2)
|
110
|
-
return nil, false unless ns1 == ns2 || ns1.nil? || ns1 == '*' || ns2.nil? || ns2 == '*'
|
111
110
|
return ns2, true if ns1 == '*'
|
112
111
|
return ns1, true if ns2 == '*'
|
113
|
-
|
112
|
+
return nil, false unless ns1 == ns2
|
113
|
+
[ns1, true]
|
114
114
|
end
|
115
115
|
end
|
116
116
|
end
|
@@ -86,9 +86,14 @@ module Sass
|
|
86
86
|
# @return [CommaSequence] This selector, with parent references resolved
|
87
87
|
# @raise [Sass::SyntaxError] If a parent selector is invalid
|
88
88
|
def resolve_parent_refs(super_cseq)
|
89
|
+
resolved_members = @members.map do |sel|
|
90
|
+
next sel unless sel.is_a?(Pseudo) && sel.selector
|
91
|
+
sel.with_selector(sel.selector.resolve_parent_refs(super_cseq, false))
|
92
|
+
end.flatten
|
93
|
+
|
89
94
|
# Parent selector only appears as the first selector in the sequence
|
90
|
-
unless (parent =
|
91
|
-
return CommaSequence.new([Sequence.new([
|
95
|
+
unless (parent = resolved_members.first).is_a?(Parent)
|
96
|
+
return CommaSequence.new([Sequence.new([SimpleSequence.new(resolved_members, subject?)])])
|
92
97
|
end
|
93
98
|
|
94
99
|
return super_cseq if @members.size == 1 && parent.suffix.nil?
|
@@ -128,9 +133,9 @@ module Sass
|
|
128
133
|
end
|
129
134
|
|
130
135
|
Sequence.new(members[0...-1] +
|
131
|
-
[SimpleSequence.new(parent_sub +
|
136
|
+
[SimpleSequence.new(parent_sub + resolved_members[1..-1], subject?)] +
|
132
137
|
[newline].compact)
|
133
|
-
|
138
|
+
end)
|
134
139
|
end
|
135
140
|
|
136
141
|
# Non-destructively extends this selector with the extensions specified in a hash
|
@@ -153,17 +158,31 @@ module Sass
|
|
153
158
|
seen_with_pseudo_selectors = seen.dup
|
154
159
|
|
155
160
|
modified_original = false
|
156
|
-
members =
|
161
|
+
members = self.members.map do |sel|
|
157
162
|
next sel unless sel.is_a?(Pseudo) && sel.selector
|
158
163
|
next sel if seen.include?([sel])
|
159
|
-
extended = sel.selector.do_extend(extends, parent_directives, replace, seen,
|
164
|
+
extended = sel.selector.do_extend(extends, parent_directives, replace, seen, false)
|
160
165
|
next sel if extended == sel.selector
|
161
166
|
extended.members.reject! {|seq| seq.has_placeholder?}
|
167
|
+
|
168
|
+
# For `:not()`, we usually want to get rid of any complex
|
169
|
+
# selectors because that will cause the selector to fail to
|
170
|
+
# parse on all browsers at time of writing. We can keep them
|
171
|
+
# if either the original selector had a complex selector, or
|
172
|
+
# the result of extending has only complex selectors,
|
173
|
+
# because either way we aren't breaking anything that isn't
|
174
|
+
# already broken.
|
175
|
+
if sel.normalized_name == 'not' &&
|
176
|
+
(sel.selector.members.none? {|seq| seq.members.length > 1} &&
|
177
|
+
extended.members.any? {|seq| seq.members.length == 1})
|
178
|
+
extended.members.reject! {|seq| seq.members.length > 1}
|
179
|
+
end
|
180
|
+
|
162
181
|
modified_original = true
|
163
182
|
result = sel.with_selector(extended)
|
164
|
-
seen_with_pseudo_selectors << [
|
183
|
+
result.each {|new_sel| seen_with_pseudo_selectors << [new_sel]}
|
165
184
|
result
|
166
|
-
end
|
185
|
+
end.flatten
|
167
186
|
|
168
187
|
groups = Sass::Util.group_by_to_a(extends[members.to_set]) {|ex| ex.extender}
|
169
188
|
groups.map! do |seq, group|
|
@@ -185,7 +204,7 @@ module Sass
|
|
185
204
|
groups.map! do |sels, seq|
|
186
205
|
next [] if seen.include?(sels)
|
187
206
|
seq.do_extend(
|
188
|
-
extends, parent_directives,
|
207
|
+
extends, parent_directives, false, seen_with_pseudo_selectors + [sels], false)
|
189
208
|
end
|
190
209
|
groups.flatten!
|
191
210
|
|
@@ -241,7 +260,7 @@ module Sass
|
|
241
260
|
|
242
261
|
# Some psuedo-selectors can be subselectors of non-pseudo selectors.
|
243
262
|
# Pull those out here so we can efficiently check against them below.
|
244
|
-
their_subselector_pseudos = %w
|
263
|
+
their_subselector_pseudos = %w(matches any nth-child nth-last-child).
|
245
264
|
map {|name| their_spcs[name] || []}.flatten
|
246
265
|
|
247
266
|
# If `self`'s non-pseudo simple selectors aren't a subset of `their_sseq`'s,
|
@@ -260,14 +279,14 @@ module Sass
|
|
260
279
|
end
|
261
280
|
end
|
262
281
|
|
263
|
-
our_spcs.all? do |
|
282
|
+
our_spcs.all? do |_name, pseudos|
|
264
283
|
pseudos.all? {|pseudo| pseudo.superselector?(their_sseq, parents)}
|
265
284
|
end
|
266
285
|
end
|
267
286
|
|
268
287
|
# @see Simple#to_s
|
269
|
-
def to_s
|
270
|
-
res = @members.join
|
288
|
+
def to_s(opts = {})
|
289
|
+
res = @members.map {|m| m.to_s(opts)}.join
|
271
290
|
res << '!' if subject?
|
272
291
|
res
|
273
292
|
end
|
@@ -313,12 +332,12 @@ MESSAGE
|
|
313
332
|
end
|
314
333
|
|
315
334
|
def _hash
|
316
|
-
[base,
|
335
|
+
[base, rest.hash].hash
|
317
336
|
end
|
318
337
|
|
319
338
|
def _eql?(other)
|
320
339
|
other.base.eql?(base) && other.pseudo_elements == pseudo_elements &&
|
321
|
-
|
340
|
+
other.rest.eql?(rest) && other.subject? == subject?
|
322
341
|
end
|
323
342
|
end
|
324
343
|
end
|
data/lib/sass/selector.rb
CHANGED
@@ -39,7 +39,7 @@ module Sass
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# @see Selector#to_s
|
42
|
-
def to_s
|
42
|
+
def to_s(opts = {})
|
43
43
|
"&" + (@suffix || '')
|
44
44
|
end
|
45
45
|
|
@@ -65,7 +65,7 @@ module Sass
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# @see Selector#to_s
|
68
|
-
def to_s
|
68
|
+
def to_s(opts = {})
|
69
69
|
"." + @name
|
70
70
|
end
|
71
71
|
|
@@ -88,7 +88,7 @@ module Sass
|
|
88
88
|
end
|
89
89
|
|
90
90
|
# @see Selector#to_s
|
91
|
-
def to_s
|
91
|
+
def to_s(opts = {})
|
92
92
|
"#" + @name
|
93
93
|
end
|
94
94
|
|
@@ -123,7 +123,7 @@ module Sass
|
|
123
123
|
end
|
124
124
|
|
125
125
|
# @see Selector#to_s
|
126
|
-
def to_s
|
126
|
+
def to_s(opts = {})
|
127
127
|
"%" + @name
|
128
128
|
end
|
129
129
|
|
@@ -147,7 +147,7 @@ module Sass
|
|
147
147
|
end
|
148
148
|
|
149
149
|
# @see Selector#to_s
|
150
|
-
def to_s
|
150
|
+
def to_s(opts = {})
|
151
151
|
@namespace ? "#{@namespace}|*" : "*"
|
152
152
|
end
|
153
153
|
|
@@ -219,7 +219,7 @@ module Sass
|
|
219
219
|
end
|
220
220
|
|
221
221
|
# @see Selector#to_s
|
222
|
-
def to_s
|
222
|
+
def to_s(opts = {})
|
223
223
|
@namespace ? "#{@namespace}|#{@name}" : @name
|
224
224
|
end
|
225
225
|
|
@@ -296,10 +296,7 @@ module Sass
|
|
296
296
|
# @param operator [String] The matching operator, e.g. `"="` or `"^="`
|
297
297
|
# @param value [String] See \{#value}
|
298
298
|
# @param flags [String] See \{#flags}
|
299
|
-
# @comment
|
300
|
-
# rubocop:disable ParameterLists
|
301
299
|
def initialize(name, namespace, operator, value, flags)
|
302
|
-
# rubocop:enable ParameterLists
|
303
300
|
@name = name
|
304
301
|
@namespace = namespace
|
305
302
|
@operator = operator
|
@@ -308,7 +305,7 @@ module Sass
|
|
308
305
|
end
|
309
306
|
|
310
307
|
# @see Selector#to_s
|
311
|
-
def to_s
|
308
|
+
def to_s(opts = {})
|
312
309
|
res = "["
|
313
310
|
res << @namespace << "|" if @namespace
|
314
311
|
res << @name
|
data/lib/sass/shared.rb
CHANGED
@@ -31,7 +31,7 @@ module Sass
|
|
31
31
|
# A `Fixnum` in 1.8, a `String` in 1.9
|
32
32
|
# @param finish [Character] The character closing the balanced pair.
|
33
33
|
# A `Fixnum` in 1.8, a `String` in 1.9
|
34
|
-
# @param count [
|
34
|
+
# @param count [Integer] The number of opening characters matched
|
35
35
|
# before calling this method
|
36
36
|
# @return [(String, String)] The string matched within the balanced pair
|
37
37
|
# and the rest of the string.
|
data/lib/sass/source/map.rb
CHANGED
@@ -37,7 +37,7 @@ module Sass::Source
|
|
37
37
|
|
38
38
|
# Shifts all output source ranges forward one or more lines.
|
39
39
|
#
|
40
|
-
# @param delta [
|
40
|
+
# @param delta [Integer] The number of lines to shift the ranges forward.
|
41
41
|
def shift_output_lines(delta)
|
42
42
|
return if delta == 0
|
43
43
|
@data.each do |m|
|
@@ -49,7 +49,7 @@ module Sass::Source
|
|
49
49
|
# Shifts any output source ranges that lie on the first line forward one or
|
50
50
|
# more characters on that line.
|
51
51
|
#
|
52
|
-
# @param delta [
|
52
|
+
# @param delta [Integer] The number of characters to shift the ranges
|
53
53
|
# forward.
|
54
54
|
def shift_output_offsets(delta)
|
55
55
|
return if delta == 0
|
@@ -95,7 +95,8 @@ module Sass::Source
|
|
95
95
|
end
|
96
96
|
css_path &&= Sass::Util.pathname(Sass::Util.absolute_path(css_path))
|
97
97
|
sourcemap_path &&= Sass::Util.pathname(Sass::Util.absolute_path(sourcemap_path))
|
98
|
-
css_uri ||= Sass::Util.file_uri_from_path(
|
98
|
+
css_uri ||= Sass::Util.file_uri_from_path(
|
99
|
+
Sass::Util.relative_path_from(css_path, sourcemap_path.dirname))
|
99
100
|
|
100
101
|
result = "{\n"
|
101
102
|
write_json_field(result, "version", 3, true)
|
@@ -117,12 +118,14 @@ module Sass::Source
|
|
117
118
|
@data.each do |m|
|
118
119
|
file, importer = m.input.file, m.input.importer
|
119
120
|
|
121
|
+
next unless importer
|
122
|
+
|
120
123
|
if options[:type] == :inline
|
121
124
|
source_uri = file
|
122
125
|
else
|
123
126
|
sourcemap_dir = sourcemap_path && sourcemap_path.dirname.to_s
|
124
127
|
sourcemap_dir = nil if options[:type] == :file
|
125
|
-
source_uri = importer
|
128
|
+
source_uri = importer.public_url(file, sourcemap_dir)
|
126
129
|
next unless source_uri
|
127
130
|
end
|
128
131
|
|
data/lib/sass/source/position.rb
CHANGED
@@ -2,17 +2,17 @@ module Sass::Source
|
|
2
2
|
class Position
|
3
3
|
# The one-based line of the document associated with the position.
|
4
4
|
#
|
5
|
-
# @return [
|
5
|
+
# @return [Integer]
|
6
6
|
attr_accessor :line
|
7
7
|
|
8
8
|
# The one-based offset in the line of the document associated with the
|
9
9
|
# position.
|
10
10
|
#
|
11
|
-
# @return [
|
11
|
+
# @return [Integer]
|
12
12
|
attr_accessor :offset
|
13
13
|
|
14
|
-
# @param line [
|
15
|
-
# @param offset [
|
14
|
+
# @param line [Integer] The source line
|
15
|
+
# @param offset [Integer] The source offset
|
16
16
|
def initialize(line, offset)
|
17
17
|
@line = line
|
18
18
|
@offset = offset
|
data/lib/sass/stack.rb
CHANGED
@@ -101,8 +101,8 @@ module Sass
|
|
101
101
|
def to_s
|
102
102
|
Sass::Util.enum_with_index(Sass::Util.enum_cons(frames.reverse + [nil], 2)).
|
103
103
|
map do |(frame, caller), i|
|
104
|
-
"#{i == 0 ?
|
105
|
-
" of #{frame.filename ||
|
104
|
+
"#{i == 0 ? 'on' : 'from'} line #{frame.line}" +
|
105
|
+
" of #{frame.filename || 'an unknown file'}" +
|
106
106
|
(caller && caller.name ? ", in `#{caller.name}'" : "")
|
107
107
|
end.join("\n")
|
108
108
|
end
|
data/lib/sass/supports.rb
CHANGED
@@ -58,11 +58,11 @@ module Sass::Supports
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def to_css
|
61
|
-
"#{
|
61
|
+
"#{parens @left, @left.to_css} #{op} #{parens @right, @right.to_css}"
|
62
62
|
end
|
63
63
|
|
64
64
|
def to_src(options)
|
65
|
-
"#{
|
65
|
+
"#{parens @left, @left.to_src(options)} #{op} #{parens @right, @right.to_src(options)}"
|
66
66
|
end
|
67
67
|
|
68
68
|
def deep_copy
|
@@ -79,14 +79,12 @@ module Sass::Supports
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
return "(#{str})" if @right.is_a?(Negation) || @right.is_a?(Operator)
|
89
|
-
str
|
82
|
+
def parens(condition, str)
|
83
|
+
if condition.is_a?(Negation) || (condition.is_a?(Operator) && condition.op != op)
|
84
|
+
return "(#{str})"
|
85
|
+
else
|
86
|
+
return str
|
87
|
+
end
|
90
88
|
end
|
91
89
|
end
|
92
90
|
|