sass 3.4.0 → 3.4.25
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 +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
|
|