sass 3.3.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 +76 -62
- data/Rakefile +104 -24
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/VERSION_NAME +1 -1
- data/bin/sass +1 -1
- data/bin/scss +1 -1
- data/extra/sass-spec-ref.sh +32 -0
- data/extra/update_watch.rb +1 -1
- data/lib/sass/cache_stores/filesystem.rb +9 -5
- data/lib/sass/cache_stores/memory.rb +4 -5
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +12 -13
- data/lib/sass/deprecation.rb +55 -0
- data/lib/sass/engine.rb +106 -70
- data/lib/sass/environment.rb +39 -19
- data/lib/sass/error.rb +17 -20
- data/lib/sass/exec/base.rb +199 -0
- data/lib/sass/exec/sass_convert.rb +283 -0
- data/lib/sass/exec/sass_scss.rb +440 -0
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/features.rb +9 -2
- data/lib/sass/importers/base.rb +8 -3
- data/lib/sass/importers/filesystem.rb +30 -38
- 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/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +224 -90
- 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 +4 -4
- data/lib/sass/plugin.rb +6 -5
- data/lib/sass/script/css_lexer.rb +1 -1
- 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 +739 -318
- data/lib/sass/script/lexer.rb +134 -54
- data/lib/sass/script/parser.rb +252 -56
- data/lib/sass/script/tree/funcall.rb +13 -6
- data/lib/sass/script/tree/interpolation.rb +127 -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/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +59 -38
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/value/base.rb +17 -14
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +78 -42
- data/lib/sass/script/value/helpers.rb +119 -2
- data/lib/sass/script/value/list.rb +0 -15
- data/lib/sass/script/value/map.rb +1 -1
- data/lib/sass/script/value/null.rb +0 -5
- data/lib/sass/script/value/number.rb +112 -31
- data/lib/sass/script/value/string.rb +102 -13
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/script.rb +3 -3
- data/lib/sass/scss/css_parser.rb +24 -4
- data/lib/sass/scss/parser.rb +290 -383
- data/lib/sass/scss/rx.rb +17 -9
- data/lib/sass/scss/static_parser.rb +306 -4
- data/lib/sass/scss.rb +0 -2
- data/lib/sass/selector/abstract_sequence.rb +35 -18
- data/lib/sass/selector/comma_sequence.rb +114 -19
- data/lib/sass/selector/pseudo.rb +266 -0
- data/lib/sass/selector/sequence.rb +146 -40
- data/lib/sass/selector/simple.rb +22 -33
- data/lib/sass/selector/simple_sequence.rb +122 -39
- data/lib/sass/selector.rb +57 -197
- data/lib/sass/shared.rb +2 -2
- data/lib/sass/source/map.rb +31 -14
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +2 -8
- data/lib/sass/supports.rb +10 -13
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/css_import_node.rb +9 -1
- data/lib/sass/tree/directive_node.rb +8 -2
- data/lib/sass/tree/error_node.rb +18 -0
- data/lib/sass/tree/extend_node.rb +1 -1
- data/lib/sass/tree/function_node.rb +9 -0
- data/lib/sass/tree/import_node.rb +6 -5
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/node.rb +5 -3
- data/lib/sass/tree/prop_node.rb +6 -7
- data/lib/sass/tree/rule_node.rb +26 -11
- data/lib/sass/tree/visitors/check_nesting.rb +56 -32
- data/lib/sass/tree/visitors/convert.rb +59 -44
- data/lib/sass/tree/visitors/cssize.rb +34 -30
- data/lib/sass/tree/visitors/deep_copy.rb +6 -1
- data/lib/sass/tree/visitors/extend.rb +15 -13
- data/lib/sass/tree/visitors/perform.rb +87 -50
- data/lib/sass/tree/visitors/set_options.rb +15 -1
- data/lib/sass/tree/visitors/to_css.rb +72 -43
- 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 +2 -3
- data/lib/sass/util.rb +334 -154
- data/lib/sass/version.rb +7 -7
- data/lib/sass.rb +10 -8
- data/test/sass/cache_test.rb +62 -20
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +24 -11
- data/test/sass/conversion_test.rb +241 -50
- data/test/sass/css2sass_test.rb +73 -5
- data/test/sass/css_variable_test.rb +132 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +343 -260
- data/test/sass/exec_test.rb +12 -2
- data/test/sass/extend_test.rb +333 -44
- data/test/sass/functions_test.rb +353 -260
- data/test/sass/importer_test.rb +40 -21
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- 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 +24 -21
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +4 -4
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +1 -1
- data/test/sass/results/import_charset_ibm866.css +2 -2
- data/test/sass/results/mixins.css +17 -17
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +2 -2
- data/test/sass/results/script.css +5 -5
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +71 -39
- data/test/sass/script_test.rb +714 -123
- data/test/sass/scss/css_test.rb +213 -30
- data/test/sass/scss/rx_test.rb +8 -4
- data/test/sass/scss/scss_test.rb +766 -22
- data/test/sass/source_map_test.rb +263 -95
- data/test/sass/superselector_test.rb +210 -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/scss_import.scss +2 -1
- 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/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
- data/test/sass/util/normalized_map_test.rb +1 -1
- data/test/sass/util/subset_map_test.rb +2 -2
- data/test/sass/util_test.rb +46 -45
- data/test/sass/value_helpers_test.rb +5 -7
- data/test/sass-spec.yml +3 -0
- data/test/test_helper.rb +7 -6
- data/vendor/listen/CHANGELOG.md +1 -228
- data/vendor/listen/Gemfile +5 -15
- data/vendor/listen/README.md +111 -77
- data/vendor/listen/Rakefile +0 -42
- data/vendor/listen/lib/listen/adapter.rb +195 -82
- data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
- data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
- data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
- data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
- data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
- data/vendor/listen/lib/listen/directory_record.rb +96 -61
- data/vendor/listen/lib/listen/listener.rb +135 -37
- data/vendor/listen/lib/listen/turnstile.rb +9 -5
- data/vendor/listen/lib/listen/version.rb +1 -1
- data/vendor/listen/lib/listen.rb +33 -19
- data/vendor/listen/listen.gemspec +6 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
- data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
- data/vendor/listen/spec/listen/listener_spec.rb +128 -39
- data/vendor/listen/spec/listen_spec.rb +15 -21
- data/vendor/listen/spec/spec_helper.rb +4 -0
- data/vendor/listen/spec/support/adapter_helper.rb +52 -15
- data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
- data/vendor/listen/spec/support/listeners_helper.rb +30 -7
- metadata +310 -300
- data/CONTRIBUTING +0 -3
- data/ext/mkrf_conf.rb +0 -27
- data/lib/sass/script/value/deprecated_false.rb +0 -55
- data/lib/sass/scss/script_lexer.rb +0 -15
- data/lib/sass/scss/script_parser.rb +0 -25
- data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
- data/vendor/listen/lib/listen/multi_listener.rb +0 -143
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
- data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
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,
|
@@ -14,28 +14,20 @@ module Sass
|
|
14
14
|
# @return [String, nil]
|
15
15
|
attr_accessor :filename
|
16
16
|
|
17
|
-
#
|
18
|
-
# potentially {Sass::Script::Tree::Node}s (if there's interpolation in the
|
19
|
-
# selector). When the interpolation is resolved and the strings are joined
|
20
|
-
# together, this will be the string representation of this node.
|
21
|
-
#
|
22
|
-
# @return [Array<String, Sass::Script::Tree::Node>]
|
23
|
-
def to_a
|
24
|
-
Sass::Util.abstract(self)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns a string representation of the node.
|
28
|
-
# This is basically the selector string.
|
17
|
+
# @see #to_s
|
29
18
|
#
|
30
19
|
# @return [String]
|
31
20
|
def inspect
|
32
|
-
|
21
|
+
to_s
|
33
22
|
end
|
34
23
|
|
35
|
-
#
|
24
|
+
# Returns the selector string.
|
25
|
+
#
|
26
|
+
# @param opts [Hash] rendering options.
|
27
|
+
# @option opts [Symbol] :style The css rendering style.
|
36
28
|
# @return [String]
|
37
|
-
def to_s
|
38
|
-
|
29
|
+
def to_s(opts = {})
|
30
|
+
Sass::Util.abstract(self)
|
39
31
|
end
|
40
32
|
|
41
33
|
# Returns a hash code for this selector object.
|
@@ -44,7 +36,7 @@ module Sass
|
|
44
36
|
# so if that contains information irrelevant to the identity of the selector,
|
45
37
|
# this should be overridden.
|
46
38
|
#
|
47
|
-
# @return [
|
39
|
+
# @return [Integer]
|
48
40
|
def hash
|
49
41
|
@_hash ||= equality_key.hash
|
50
42
|
end
|
@@ -58,7 +50,7 @@ module Sass
|
|
58
50
|
# @param other [Object] The object to test equality against
|
59
51
|
# @return [Boolean] Whether or not this is equal to `other`
|
60
52
|
def eql?(other)
|
61
|
-
other.class == self.class && other.hash == hash && other.equality_key
|
53
|
+
other.class == self.class && other.hash == hash && other.equality_key == equality_key
|
62
54
|
end
|
63
55
|
alias_method :==, :eql?
|
64
56
|
|
@@ -80,14 +72,12 @@ module Sass
|
|
80
72
|
# by the time extension and unification happen,
|
81
73
|
# this exception will only ever be raised as a result of programmer error
|
82
74
|
def unify(sels)
|
75
|
+
return sels.first.unify([self]) if sels.length == 1 && sels.first.is_a?(Universal)
|
83
76
|
return sels if sels.any? {|sel2| eql?(sel2)}
|
84
77
|
sels_with_ix = Sass::Util.enum_with_index(sels)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
else
|
89
|
-
sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)}
|
90
|
-
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
|
91
81
|
return sels + [self] unless i
|
92
82
|
sels[0...i] + [self] + sels[i..-1]
|
93
83
|
end
|
@@ -96,12 +86,11 @@ module Sass
|
|
96
86
|
|
97
87
|
# Returns the key used for testing whether selectors are equal.
|
98
88
|
#
|
99
|
-
# This is
|
100
|
-
# selectors constructed in different ways are considered equivalent.
|
89
|
+
# This is a cached version of \{#to\_s}.
|
101
90
|
#
|
102
|
-
# @return [
|
91
|
+
# @return [String]
|
103
92
|
def equality_key
|
104
|
-
@equality_key ||=
|
93
|
+
@equality_key ||= to_s
|
105
94
|
end
|
106
95
|
|
107
96
|
# Unifies two namespaces,
|
@@ -118,10 +107,10 @@ module Sass
|
|
118
107
|
# could be found at all.
|
119
108
|
# If the second value is `false`, the first should be ignored.
|
120
109
|
def unify_namespaces(ns1, ns2)
|
121
|
-
return
|
122
|
-
return
|
123
|
-
return
|
124
|
-
[ns1
|
110
|
+
return ns2, true if ns1 == '*'
|
111
|
+
return ns1, true if ns2 == '*'
|
112
|
+
return nil, false unless ns1 == ns2
|
113
|
+
[ns1, true]
|
125
114
|
end
|
126
115
|
end
|
127
116
|
end
|
@@ -43,11 +43,16 @@ module Sass
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def pseudo_elements
|
46
|
-
@pseudo_elements ||=
|
47
|
-
select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
|
46
|
+
@pseudo_elements ||= members.select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
|
48
47
|
end
|
49
48
|
|
50
|
-
|
49
|
+
def selector_pseudo_classes
|
50
|
+
@selector_pseudo_classes ||= members.
|
51
|
+
select {|sel| sel.is_a?(Pseudo) && sel.type == :class && sel.selector}.
|
52
|
+
group_by {|sel| sel.normalized_name}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the non-base, non-pseudo-element selectors in this sequence.
|
51
56
|
#
|
52
57
|
# @return [Set<Simple>]
|
53
58
|
def rest
|
@@ -81,23 +86,28 @@ module Sass
|
|
81
86
|
# @return [CommaSequence] This selector, with parent references resolved
|
82
87
|
# @raise [Sass::SyntaxError] If a parent selector is invalid
|
83
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
|
+
|
84
94
|
# Parent selector only appears as the first selector in the sequence
|
85
|
-
unless (parent =
|
86
|
-
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?)])])
|
87
97
|
end
|
88
98
|
|
89
|
-
return super_cseq if @members.size == 1 && parent.suffix.
|
99
|
+
return super_cseq if @members.size == 1 && parent.suffix.nil?
|
90
100
|
|
91
101
|
CommaSequence.new(super_cseq.members.map do |super_seq|
|
92
102
|
members = super_seq.members.dup
|
93
103
|
newline = members.pop if members.last == "\n"
|
94
104
|
unless members.last.is_a?(SimpleSequence)
|
95
105
|
raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
|
96
|
-
super_seq.
|
106
|
+
super_seq.to_s + '"')
|
97
107
|
end
|
98
108
|
|
99
109
|
parent_sub = members.last.members
|
100
|
-
unless parent.suffix.
|
110
|
+
unless parent.suffix.nil?
|
101
111
|
parent_sub = parent_sub.dup
|
102
112
|
parent_sub[-1] = parent_sub.last.dup
|
103
113
|
case parent_sub.last
|
@@ -108,39 +118,72 @@ module Sass
|
|
108
118
|
parent_sub.last.name + parent.suffix,
|
109
119
|
parent_sub.last.namespace)
|
110
120
|
when Sass::Selector::Pseudo
|
111
|
-
if parent_sub.last.arg
|
121
|
+
if parent_sub.last.arg || parent_sub.last.selector
|
112
122
|
raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
|
113
|
-
super_seq.
|
123
|
+
super_seq.to_s + '"')
|
114
124
|
end
|
115
|
-
parent_sub[-1] =
|
125
|
+
parent_sub[-1] = Sass::Selector::Pseudo.new(
|
116
126
|
parent_sub.last.type,
|
117
127
|
parent_sub.last.name + parent.suffix,
|
118
|
-
nil)
|
128
|
+
nil, nil)
|
119
129
|
else
|
120
130
|
raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
|
121
|
-
super_seq.
|
131
|
+
super_seq.to_s + '"')
|
122
132
|
end
|
123
133
|
end
|
124
134
|
|
125
135
|
Sequence.new(members[0...-1] +
|
126
|
-
[SimpleSequence.new(parent_sub +
|
136
|
+
[SimpleSequence.new(parent_sub + resolved_members[1..-1], subject?)] +
|
127
137
|
[newline].compact)
|
128
|
-
|
138
|
+
end)
|
129
139
|
end
|
130
140
|
|
131
|
-
# Non-
|
141
|
+
# Non-destructively extends this selector with the extensions specified in a hash
|
132
142
|
# (which should come from {Sass::Tree::Visitors::Cssize}).
|
133
143
|
#
|
134
|
-
# @overload def do_extend(extends, parent_directives)
|
135
144
|
# @param extends [{Selector::Simple =>
|
136
145
|
# Sass::Tree::Visitors::Cssize::Extend}]
|
137
146
|
# The extensions to perform on this selector
|
138
147
|
# @param parent_directives [Array<Sass::Tree::DirectiveNode>]
|
139
148
|
# The directives containing this selector.
|
149
|
+
# @param seen [Set<Array<Selector::Simple>>]
|
150
|
+
# The set of simple sequences that are currently being replaced.
|
151
|
+
# @param original [Boolean]
|
152
|
+
# Whether this is the original selector being extended, as opposed to
|
153
|
+
# the result of a previous extension that's being re-extended.
|
140
154
|
# @return [Array<Sequence>] A list of selectors generated
|
141
155
|
# by extending this selector with `extends`.
|
142
156
|
# @see CommaSequence#do_extend
|
143
|
-
def do_extend(extends, parent_directives, seen
|
157
|
+
def do_extend(extends, parent_directives, replace, seen)
|
158
|
+
seen_with_pseudo_selectors = seen.dup
|
159
|
+
|
160
|
+
modified_original = false
|
161
|
+
members = self.members.map do |sel|
|
162
|
+
next sel unless sel.is_a?(Pseudo) && sel.selector
|
163
|
+
next sel if seen.include?([sel])
|
164
|
+
extended = sel.selector.do_extend(extends, parent_directives, replace, seen, false)
|
165
|
+
next sel if extended == sel.selector
|
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
|
+
|
181
|
+
modified_original = true
|
182
|
+
result = sel.with_selector(extended)
|
183
|
+
result.each {|new_sel| seen_with_pseudo_selectors << [new_sel]}
|
184
|
+
result
|
185
|
+
end.flatten
|
186
|
+
|
144
187
|
groups = Sass::Util.group_by_to_a(extends[members.to_set]) {|ex| ex.extender}
|
145
188
|
groups.map! do |seq, group|
|
146
189
|
sels = group.map {|e| e.target}.flatten
|
@@ -149,7 +192,7 @@ module Sass
|
|
149
192
|
|
150
193
|
self_without_sel = Sass::Util.array_minus(members, sels)
|
151
194
|
group.each {|e| e.result = :failed_to_unify unless e.result == :succeeded}
|
152
|
-
unified = seq.members.last.unify(self_without_sel, subject?)
|
195
|
+
unified = seq.members.last.unify(SimpleSequence.new(self_without_sel, subject?))
|
153
196
|
next unless unified
|
154
197
|
group.each {|e| e.result = :succeeded}
|
155
198
|
group.each {|e| check_directives_match!(e, parent_directives)}
|
@@ -159,19 +202,30 @@ module Sass
|
|
159
202
|
end
|
160
203
|
groups.compact!
|
161
204
|
groups.map! do |sels, seq|
|
162
|
-
|
205
|
+
next [] if seen.include?(sels)
|
206
|
+
seq.do_extend(
|
207
|
+
extends, parent_directives, false, seen_with_pseudo_selectors + [sels], false)
|
163
208
|
end
|
164
209
|
groups.flatten!
|
210
|
+
|
211
|
+
if modified_original || !replace || groups.empty?
|
212
|
+
# First Law of Extend: the result of extending a selector should
|
213
|
+
# (almost) always contain the base selector.
|
214
|
+
#
|
215
|
+
# See https://github.com/nex3/sass/issues/324.
|
216
|
+
original = Sequence.new([SimpleSequence.new(members, @subject, source_range)])
|
217
|
+
original.add_sources! sources
|
218
|
+
groups.unshift original
|
219
|
+
end
|
165
220
|
groups.uniq!
|
166
221
|
groups
|
167
222
|
end
|
168
223
|
|
169
|
-
# Unifies this selector with another {SimpleSequence}
|
170
|
-
#
|
171
|
-
#
|
224
|
+
# Unifies this selector with another {SimpleSequence}, returning
|
225
|
+
# another `SimpleSequence` that is a subselector of both input
|
226
|
+
# selectors.
|
172
227
|
#
|
173
|
-
# @param
|
174
|
-
# @param other_subject [Boolean] Whether the other {SimpleSequence} being merged is a subject.
|
228
|
+
# @param other [SimpleSequence]
|
175
229
|
# @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector,
|
176
230
|
# or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
|
177
231
|
# @raise [Sass::SyntaxError] If this selector cannot be unified.
|
@@ -180,13 +234,13 @@ module Sass
|
|
180
234
|
# Since these selectors should be resolved
|
181
235
|
# by the time extension and unification happen,
|
182
236
|
# this exception will only ever be raised as a result of programmer error
|
183
|
-
def unify(
|
184
|
-
sseq = members.inject(
|
237
|
+
def unify(other)
|
238
|
+
sseq = members.inject(other.members) do |member, sel|
|
185
239
|
return unless member
|
186
240
|
sel.unify(member)
|
187
241
|
end
|
188
242
|
return unless sseq
|
189
|
-
SimpleSequence.new(sseq,
|
243
|
+
SimpleSequence.new(sseq, other.subject? || subject?)
|
190
244
|
end
|
191
245
|
|
192
246
|
# Returns whether or not this selector matches all elements
|
@@ -195,17 +249,44 @@ module Sass
|
|
195
249
|
# @example
|
196
250
|
# (.foo).superselector?(.foo.bar) #=> true
|
197
251
|
# (.foo).superselector?(.bar) #=> false
|
198
|
-
# @param
|
252
|
+
# @param their_sseq [SimpleSequence]
|
253
|
+
# @param parents [Array<SimpleSequence, String>] The parent selectors of `their_sseq`, if any.
|
199
254
|
# @return [Boolean]
|
200
|
-
def superselector?(
|
201
|
-
|
202
|
-
|
203
|
-
|
255
|
+
def superselector?(their_sseq, parents = [])
|
256
|
+
return false unless base.nil? || base.eql?(their_sseq.base)
|
257
|
+
return false unless pseudo_elements.eql?(their_sseq.pseudo_elements)
|
258
|
+
our_spcs = selector_pseudo_classes
|
259
|
+
their_spcs = their_sseq.selector_pseudo_classes
|
260
|
+
|
261
|
+
# Some psuedo-selectors can be subselectors of non-pseudo selectors.
|
262
|
+
# Pull those out here so we can efficiently check against them below.
|
263
|
+
their_subselector_pseudos = %w(matches any nth-child nth-last-child).
|
264
|
+
map {|name| their_spcs[name] || []}.flatten
|
265
|
+
|
266
|
+
# If `self`'s non-pseudo simple selectors aren't a subset of `their_sseq`'s,
|
267
|
+
# it's definitely not a superselector. This also considers being matched
|
268
|
+
# by `:matches` or `:any`.
|
269
|
+
return false unless rest.all? do |our_sel|
|
270
|
+
next true if our_sel.is_a?(Pseudo) && our_sel.selector
|
271
|
+
next true if their_sseq.rest.include?(our_sel)
|
272
|
+
their_subselector_pseudos.any? do |their_pseudo|
|
273
|
+
their_pseudo.selector.members.all? do |their_seq|
|
274
|
+
next false unless their_seq.members.length == 1
|
275
|
+
their_sseq = their_seq.members.first
|
276
|
+
next false unless their_sseq.is_a?(SimpleSequence)
|
277
|
+
their_sseq.rest.include?(our_sel)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
our_spcs.all? do |_name, pseudos|
|
283
|
+
pseudos.all? {|pseudo| pseudo.superselector?(their_sseq, parents)}
|
284
|
+
end
|
204
285
|
end
|
205
286
|
|
206
|
-
# @see Simple#
|
207
|
-
def
|
208
|
-
res = @members.map {|
|
287
|
+
# @see Simple#to_s
|
288
|
+
def to_s(opts = {})
|
289
|
+
res = @members.map {|m| m.to_s(opts)}.join
|
209
290
|
res << '!' if subject?
|
210
291
|
res
|
211
292
|
end
|
@@ -215,7 +296,9 @@ module Sass
|
|
215
296
|
#
|
216
297
|
# @return [String]
|
217
298
|
def inspect
|
218
|
-
members.map {|m| m.inspect}.join
|
299
|
+
res = members.map {|m| m.inspect}.join
|
300
|
+
res << '!' if subject?
|
301
|
+
res
|
219
302
|
end
|
220
303
|
|
221
304
|
# Return a copy of this simple sequence with `sources` merged into the
|
@@ -249,12 +332,12 @@ MESSAGE
|
|
249
332
|
end
|
250
333
|
|
251
334
|
def _hash
|
252
|
-
[base,
|
335
|
+
[base, rest.hash].hash
|
253
336
|
end
|
254
337
|
|
255
338
|
def _eql?(other)
|
256
339
|
other.base.eql?(base) && other.pseudo_elements == pseudo_elements &&
|
257
|
-
|
340
|
+
other.rest.eql?(rest) && other.subject? == subject?
|
258
341
|
end
|
259
342
|
end
|
260
343
|
end
|