sass 3.3.0.rc.2 → 3.3.0.rc.3
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 +15 -0
- data/CONTRIBUTING +1 -1
- data/README.md +7 -7
- data/Rakefile +4 -2
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/bin/sass +5 -1
- data/bin/sass-convert +5 -1
- data/bin/scss +5 -1
- data/ext/mkrf_conf.rb +23 -0
- data/lib/sass/css.rb +1 -1
- data/lib/sass/engine.rb +19 -9
- data/lib/sass/environment.rb +8 -0
- data/lib/sass/exec.rb +4 -4
- data/lib/sass/features.rb +0 -1
- data/lib/sass/importers/base.rb +13 -6
- data/lib/sass/importers/deprecated_path.rb +8 -2
- data/lib/sass/importers/filesystem.rb +33 -7
- data/lib/sass/logger.rb +1 -4
- data/lib/sass/logger/base.rb +0 -2
- data/lib/sass/logger/log_level.rb +0 -2
- data/lib/sass/plugin.rb +2 -2
- data/lib/sass/plugin/compiler.rb +23 -11
- data/lib/sass/plugin/configuration.rb +0 -1
- data/lib/sass/railtie.rb +1 -0
- data/lib/sass/script/css_lexer.rb +0 -1
- data/lib/sass/script/css_parser.rb +0 -1
- data/lib/sass/script/functions.rb +158 -96
- data/lib/sass/script/lexer.rb +29 -35
- data/lib/sass/script/parser.rb +10 -3
- data/lib/sass/script/tree.rb +0 -1
- data/lib/sass/script/tree/funcall.rb +21 -5
- data/lib/sass/script/tree/list_literal.rb +0 -1
- data/lib/sass/script/value/arg_list.rb +7 -3
- data/lib/sass/script/value/bool.rb +0 -1
- data/lib/sass/script/value/null.rb +0 -1
- data/lib/sass/script/value/number.rb +2 -6
- data/lib/sass/scss/css_parser.rb +0 -1
- data/lib/sass/scss/parser.rb +5 -5
- data/lib/sass/scss/script_lexer.rb +0 -1
- data/lib/sass/scss/script_parser.rb +0 -1
- data/lib/sass/selector.rb +11 -1
- data/lib/sass/selector/comma_sequence.rb +3 -4
- data/lib/sass/selector/sequence.rb +11 -7
- data/lib/sass/selector/simple_sequence.rb +42 -11
- data/lib/sass/source/map.rb +6 -19
- data/lib/sass/tree/at_root_node.rb +1 -1
- data/lib/sass/tree/mixin_node.rb +2 -2
- data/lib/sass/tree/prop_node.rb +0 -1
- data/lib/sass/tree/variable_node.rb +0 -5
- data/lib/sass/tree/visitors/check_nesting.rb +0 -1
- data/lib/sass/tree/visitors/convert.rb +2 -2
- data/lib/sass/tree/visitors/cssize.rb +184 -84
- data/lib/sass/tree/visitors/deep_copy.rb +0 -1
- data/lib/sass/tree/visitors/perform.rb +14 -44
- data/lib/sass/util.rb +59 -12
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/normalized_map.rb +17 -1
- data/test/sass/compiler_test.rb +10 -0
- data/test/sass/conversion_test.rb +36 -0
- data/test/sass/css2sass_test.rb +19 -0
- data/test/sass/engine_test.rb +54 -105
- data/test/sass/functions_test.rb +233 -26
- data/test/sass/importer_test.rb +72 -10
- data/test/sass/plugin_test.rb +14 -0
- data/test/sass/script_conversion_test.rb +4 -4
- data/test/sass/script_test.rb +58 -21
- data/test/sass/scss/css_test.rb +8 -1
- data/test/sass/scss/scss_test.rb +376 -179
- data/test/sass/source_map_test.rb +8 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/util_test.rb +16 -0
- data/test/test_helper.rb +12 -4
- metadata +269 -287
- data/lib/sass/script/tree/selector.rb +0 -30
data/lib/sass/script/lexer.rb
CHANGED
@@ -72,8 +72,7 @@ module Sass
|
|
72
72
|
|
73
73
|
TOKEN_NAMES = Sass::Util.map_hash(OPERATORS_REVERSE) {|k, v| [k, v.inspect]}.merge(
|
74
74
|
:const => "variable (e.g. $foo)",
|
75
|
-
:ident => "identifier (e.g. middle)"
|
76
|
-
:bool => "boolean (e.g. true, false)")
|
75
|
+
:ident => "identifier (e.g. middle)")
|
77
76
|
|
78
77
|
# A list of operator strings ordered with longer names first
|
79
78
|
# so that `>` and `<` don't clobber `>=` and `<=`.
|
@@ -90,11 +89,9 @@ module Sass
|
|
90
89
|
:single_line_comment => SINGLE_LINE_COMMENT,
|
91
90
|
:variable => /(\$)(#{IDENT})/,
|
92
91
|
:ident => /(#{IDENT})(\()?/,
|
93
|
-
:number => /(
|
92
|
+
:number => /(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
|
93
|
+
:unary_minus_number => /-(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
|
94
94
|
:color => HEXCOLOR,
|
95
|
-
:bool => /(true|false)\b/,
|
96
|
-
:null => /null\b/,
|
97
|
-
:selector => /&/,
|
98
95
|
:ident_op => /(#{Regexp.union(*IDENT_OP_NAMES.map do |s|
|
99
96
|
Regexp.new(Regexp.escape(s) + "(?!#{NMCHAR}|\Z)")
|
100
97
|
end)})/,
|
@@ -102,7 +99,6 @@ module Sass
|
|
102
99
|
}
|
103
100
|
|
104
101
|
class << self
|
105
|
-
|
106
102
|
private
|
107
103
|
|
108
104
|
def string_re(open, close)
|
@@ -254,9 +250,9 @@ module Sass
|
|
254
250
|
return string(interp_type, true)
|
255
251
|
end
|
256
252
|
|
257
|
-
variable || string(:double, false) || string(:single, false) || number ||
|
258
|
-
|
259
|
-
|
253
|
+
variable || string(:double, false) || string(:single, false) || number || color ||
|
254
|
+
string(:uri, false) || raw(UNICODERANGE) || special_fun || special_val || ident_op ||
|
255
|
+
ident || op
|
260
256
|
end
|
261
257
|
|
262
258
|
def variable
|
@@ -292,10 +288,29 @@ module Sass
|
|
292
288
|
end
|
293
289
|
|
294
290
|
def number
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
291
|
+
# Handling unary minus is complicated by the fact that whitespace is an
|
292
|
+
# operator in SassScript. We want "1-2" to be parsed as "1 - 2", but we
|
293
|
+
# want "1 -2" to be parsed as "1 (-2)". To accomplish this, we only
|
294
|
+
# parse a unary minus as part of a number literal if there's whitespace
|
295
|
+
# before and not after it. Cases like "(-2)" are handled by the unary
|
296
|
+
# minus logic in the parser instead.
|
297
|
+
if @scanner.peek(1) == '-'
|
298
|
+
return if @scanner.pos == 0
|
299
|
+
@scanner.pos -= 1
|
300
|
+
# Don't use @scanner.scan so we don't mess up the match data.
|
301
|
+
unary_minus_allowed = @scanner.peek(1) =~ /\s/
|
302
|
+
@scanner.pos += 1
|
303
|
+
|
304
|
+
return unless unary_minus_allowed
|
305
|
+
return unless scan(REGULAR_EXPRESSIONS[:unary_minus_number])
|
306
|
+
minus = true
|
307
|
+
else
|
308
|
+
return unless scan(REGULAR_EXPRESSIONS[:number])
|
309
|
+
minus = false
|
310
|
+
end
|
311
|
+
|
312
|
+
value = (@scanner[1] ? @scanner[1].to_f : @scanner[2].to_i) * (minus ? -1 : 1)
|
313
|
+
script_number = Script::Value::Number.new(value, Array(@scanner[3]))
|
299
314
|
[:number, script_number]
|
300
315
|
end
|
301
316
|
|
@@ -309,27 +324,6 @@ MESSAGE
|
|
309
324
|
[:color, script_color]
|
310
325
|
end
|
311
326
|
|
312
|
-
def bool
|
313
|
-
s = scan(REGULAR_EXPRESSIONS[:bool])
|
314
|
-
return unless s
|
315
|
-
script_bool = Script::Value::Bool.new(s == 'true')
|
316
|
-
[:bool, script_bool]
|
317
|
-
end
|
318
|
-
|
319
|
-
def null
|
320
|
-
return unless scan(REGULAR_EXPRESSIONS[:null])
|
321
|
-
script_null = Script::Value::Null.new
|
322
|
-
[:null, script_null]
|
323
|
-
end
|
324
|
-
|
325
|
-
def selector
|
326
|
-
start_pos = source_position
|
327
|
-
return unless scan(REGULAR_EXPRESSIONS[:selector])
|
328
|
-
script_selector = Script::Tree::Selector.new
|
329
|
-
script_selector.source_range = range(start_pos)
|
330
|
-
[:selector, script_selector]
|
331
|
-
end
|
332
|
-
|
333
327
|
def special_fun
|
334
328
|
str1 = scan(/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
|
335
329
|
return unless str1
|
data/lib/sass/script/parser.rb
CHANGED
@@ -382,9 +382,16 @@ RUBY
|
|
382
382
|
|
383
383
|
name = @lexer.next
|
384
384
|
if (color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase])
|
385
|
-
|
385
|
+
literal_node(Sass::Script::Value::Color.new(color), name.source_range)
|
386
|
+
elsif name.value == "true"
|
387
|
+
literal_node(Sass::Script::Value::Bool.new(true), name.source_range)
|
388
|
+
elsif name.value == "false"
|
389
|
+
literal_node(Sass::Script::Value::Bool.new(false), name.source_range)
|
390
|
+
elsif name.value == "null"
|
391
|
+
literal_node(Sass::Script::Value::Null.new, name.source_range)
|
392
|
+
else
|
393
|
+
literal_node(Sass::Script::Value::String.new(name.value, :identifier), name.source_range)
|
386
394
|
end
|
387
|
-
literal_node(Script::Value::String.new(name.value, :identifier), name.source_range)
|
388
395
|
end
|
389
396
|
|
390
397
|
def funcall
|
@@ -543,7 +550,7 @@ RUBY
|
|
543
550
|
end
|
544
551
|
|
545
552
|
def literal
|
546
|
-
t =
|
553
|
+
t = try_tok(:color)
|
547
554
|
return literal_node(t.value, t.source_range) if t
|
548
555
|
end
|
549
556
|
|
data/lib/sass/script/tree.rb
CHANGED
@@ -20,7 +20,7 @@ module Sass::Script::Tree
|
|
20
20
|
|
21
21
|
# The keyword arguments to the function.
|
22
22
|
#
|
23
|
-
# @return [
|
23
|
+
# @return [Sass::Util::NormalizedMap<Node>]
|
24
24
|
attr_reader :keywords
|
25
25
|
|
26
26
|
# The first splat argument for this function, if one exists.
|
@@ -128,7 +128,7 @@ module Sass::Script::Tree
|
|
128
128
|
splat = Sass::Tree::Visitors::Perform.perform_splat(
|
129
129
|
@splat, keywords, @kwarg_splat, environment)
|
130
130
|
if (fn = environment.function(@name))
|
131
|
-
return perform_sass_fn(fn, args, splat, environment)
|
131
|
+
return without_original(perform_sass_fn(fn, args, splat, environment))
|
132
132
|
end
|
133
133
|
|
134
134
|
args = construct_ruby_args(ruby_name, args, splat, environment)
|
@@ -136,8 +136,9 @@ module Sass::Script::Tree
|
|
136
136
|
if Sass::Script::Functions.callable?(ruby_name)
|
137
137
|
local_environment = Sass::Environment.new(environment.global_env, environment.options)
|
138
138
|
local_environment.caller = Sass::ReadOnlyEnvironment.new(environment, environment.options)
|
139
|
-
opts(Sass::Script::Functions::EvaluationContext.new(
|
139
|
+
result = opts(Sass::Script::Functions::EvaluationContext.new(
|
140
140
|
local_environment).send(ruby_name, *args))
|
141
|
+
without_original(result)
|
141
142
|
else
|
142
143
|
opts(to_literal(args))
|
143
144
|
end
|
@@ -173,6 +174,13 @@ module Sass::Script::Tree
|
|
173
174
|
@signature ||= Sass::Script::Functions.signature(name.to_sym, @args.size, @keywords.size)
|
174
175
|
end
|
175
176
|
|
177
|
+
def without_original(value)
|
178
|
+
return value unless value.is_a?(Sass::Script::Value::Number)
|
179
|
+
value = value.dup
|
180
|
+
value.original = nil
|
181
|
+
value
|
182
|
+
end
|
183
|
+
|
176
184
|
def construct_ruby_args(name, args, splat, environment)
|
177
185
|
args += splat.to_a if splat
|
178
186
|
|
@@ -198,9 +206,16 @@ module Sass::Script::Tree
|
|
198
206
|
return args
|
199
207
|
end
|
200
208
|
|
201
|
-
|
209
|
+
argnames = signature.args[args.size..-1] || []
|
210
|
+
deprecated_argnames = (signature.deprecated && signature.deprecated[args.size..-1]) || []
|
211
|
+
args = args + argnames.zip(deprecated_argnames).map do |(argname, deprecated_argname)|
|
202
212
|
if keywords.has_key?(argname)
|
203
213
|
keywords.delete(argname)
|
214
|
+
elsif deprecated_argname && keywords.has_key?(deprecated_argname)
|
215
|
+
deprecated_argname = keywords.denormalize(deprecated_argname)
|
216
|
+
Sass::Util.sass_warn("DEPRECATION WARNING: The `$#{deprecated_argname}' argument for " +
|
217
|
+
"`#{name}()' has been renamed to `$#{argname}'.")
|
218
|
+
keywords.delete(deprecated_argname)
|
204
219
|
else
|
205
220
|
raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}")
|
206
221
|
end
|
@@ -208,7 +223,8 @@ module Sass::Script::Tree
|
|
208
223
|
|
209
224
|
if keywords.size > 0
|
210
225
|
if signature.var_kwargs
|
211
|
-
|
226
|
+
# Don't pass a NormalizedMap to a Ruby function.
|
227
|
+
args << keywords.to_hash
|
212
228
|
else
|
213
229
|
argname = keywords.keys.sort.first
|
214
230
|
if signature.args.include?(argname)
|
@@ -14,16 +14,20 @@ module Sass::Script::Value
|
|
14
14
|
# Creates a new argument list.
|
15
15
|
#
|
16
16
|
# @param value [Array<Value>] See \{List#value}.
|
17
|
-
# @param keywords [Hash<String, Value>] See \{#keywords}
|
17
|
+
# @param keywords [Hash<String, Value>, NormalizedMap<Value>] See \{#keywords}
|
18
18
|
# @param separator [String] See \{List#separator}.
|
19
19
|
def initialize(value, keywords, separator)
|
20
20
|
super(value, separator)
|
21
|
-
|
21
|
+
if keywords.is_a?(Sass::Util::NormalizedMap)
|
22
|
+
@keywords = keywords
|
23
|
+
else
|
24
|
+
@keywords = Sass::Util::NormalizedMap.new(keywords)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
# The keyword arguments attached to this list.
|
25
29
|
#
|
26
|
-
# @return [
|
30
|
+
# @return [NormalizedMap<Value>]
|
27
31
|
def keywords
|
28
32
|
@keywords_accessed = true
|
29
33
|
@keywords
|
@@ -175,13 +175,9 @@ module Sass::Script::Value
|
|
175
175
|
# @param other [Number] The right-hand side of the operator
|
176
176
|
# @return [Number] This number modulo the other
|
177
177
|
# @raise [NoMethodError] if `other` is an invalid type
|
178
|
-
# @raise [Sass::UnitConversionError] if `other` has
|
178
|
+
# @raise [Sass::UnitConversionError] if `other` has incompatible units
|
179
179
|
def mod(other)
|
180
180
|
if other.is_a?(Number)
|
181
|
-
unless other.unitless?
|
182
|
-
raise Sass::UnitConversionError.new(
|
183
|
-
"Cannot modulo by a number with units: #{other.inspect}.")
|
184
|
-
end
|
185
181
|
operate(other, :%)
|
186
182
|
else
|
187
183
|
raise NoMethodError.new(nil, :mod)
|
@@ -388,7 +384,7 @@ module Sass::Script::Value
|
|
388
384
|
end
|
389
385
|
end
|
390
386
|
|
391
|
-
OPERATIONS = [:+, :-, :<=, :<, :>,
|
387
|
+
OPERATIONS = [:+, :-, :<=, :<, :>, :>=, :%]
|
392
388
|
|
393
389
|
def operate(other, operation)
|
394
390
|
this = self
|
data/lib/sass/scss/css_parser.rb
CHANGED
data/lib/sass/scss/parser.rb
CHANGED
@@ -5,7 +5,6 @@ module Sass
|
|
5
5
|
# The parser for SCSS.
|
6
6
|
# It parses a string of code into a tree of {Sass::Tree::Node}s.
|
7
7
|
class Parser
|
8
|
-
|
9
8
|
# Expose for the SASS parser.
|
10
9
|
attr_accessor :offset
|
11
10
|
|
@@ -147,12 +146,12 @@ module Sass
|
|
147
146
|
end
|
148
147
|
|
149
148
|
def process_comment(text, node)
|
150
|
-
silent = text =~ %r{
|
151
|
-
loud = !silent && text =~ %r{
|
149
|
+
silent = text =~ %r{\A//}
|
150
|
+
loud = !silent && text =~ %r{\A/[/*]!}
|
152
151
|
line = @line - text.count("\n")
|
153
152
|
|
154
153
|
if silent
|
155
|
-
value = [text.sub(%r{
|
154
|
+
value = [text.sub(%r{\A\s*//}, '/*').gsub(%r{^\s*//}, ' *') + ' */']
|
156
155
|
else
|
157
156
|
value = Sass::Engine.parse_interp(
|
158
157
|
text, line, @scanner.pos - text.size, :filename => @filename)
|
@@ -375,6 +374,7 @@ module Sass
|
|
375
374
|
return unless (str = tok(STRING)) || (uri = tok?(/url\(/i))
|
376
375
|
if uri
|
377
376
|
str = sass_script(:parse_string)
|
377
|
+
ss
|
378
378
|
media = media_query_list
|
379
379
|
ss
|
380
380
|
return node(Tree::CssImportNode.new(str, media.to_a), start_pos)
|
@@ -812,7 +812,7 @@ module Sass
|
|
812
812
|
|
813
813
|
def parent_selector
|
814
814
|
return unless tok(/&/)
|
815
|
-
Selector::Parent.new
|
815
|
+
Selector::Parent.new(interp_ident(NAME) || [])
|
816
816
|
end
|
817
817
|
|
818
818
|
def class_selector
|
data/lib/sass/selector.rb
CHANGED
@@ -27,9 +27,19 @@ module Sass
|
|
27
27
|
# The function of this is to be replaced by the parent selector
|
28
28
|
# in the nested hierarchy.
|
29
29
|
class Parent < Simple
|
30
|
+
# The identifier following the `&`. Often empty.
|
31
|
+
#
|
32
|
+
# @return [Array<String, Sass::Script::Tree::Node>]
|
33
|
+
attr_reader :suffix
|
34
|
+
|
35
|
+
# @param name [Array<String, Sass::Script::Tree::Node>] See \{#suffix}
|
36
|
+
def initialize(suffix = [])
|
37
|
+
@suffix = suffix
|
38
|
+
end
|
39
|
+
|
30
40
|
# @see Selector#to_a
|
31
41
|
def to_a
|
32
|
-
["&"]
|
42
|
+
["&", *@suffix]
|
33
43
|
end
|
34
44
|
|
35
45
|
# Always raises an exception.
|
@@ -37,10 +37,9 @@ module Sass
|
|
37
37
|
return self
|
38
38
|
end
|
39
39
|
|
40
|
-
CommaSequence.new(
|
41
|
-
super_cseq.members
|
42
|
-
|
43
|
-
end.flatten)
|
40
|
+
CommaSequence.new(Sass::Util.flatten_vertically(@members.map do |seq|
|
41
|
+
seq.resolve_parent_refs(super_cseq, implicit_parent).members
|
42
|
+
end))
|
44
43
|
end
|
45
44
|
|
46
45
|
# Non-destrucively extends this selector with the extensions specified in a hash
|
@@ -43,13 +43,13 @@ module Sass
|
|
43
43
|
# by replacing them with the given parent selector,
|
44
44
|
# handling commas appropriately.
|
45
45
|
#
|
46
|
-
# @param
|
46
|
+
# @param super_cseq [CommaSequence] The parent selector
|
47
47
|
# @param implicit_parent [Boolean] Whether the the parent
|
48
48
|
# selector should automatically be prepended to the resolved
|
49
49
|
# selector if it contains no parent refs.
|
50
|
-
# @return [
|
50
|
+
# @return [CommaSequence] This selector, with parent references resolved
|
51
51
|
# @raise [Sass::SyntaxError] If a parent selector is invalid
|
52
|
-
def resolve_parent_refs(
|
52
|
+
def resolve_parent_refs(super_cseq, implicit_parent)
|
53
53
|
members = @members.dup
|
54
54
|
nl = (members.first == "\n" && members.shift)
|
55
55
|
contains_parent_ref = members.any? do |seq_or_op|
|
@@ -64,11 +64,15 @@ module Sass
|
|
64
64
|
members += old_members
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
CommaSequence.new(Sass::Util.paths(members.map do |sseq_or_op|
|
68
|
+
next [sseq_or_op] unless sseq_or_op.is_a?(SimpleSequence)
|
69
|
+
sseq_or_op.resolve_parent_refs(super_cseq).members
|
70
|
+
end).map do |path|
|
71
|
+
Sequence.new(path.map do |seq_or_op|
|
72
|
+
next seq_or_op unless seq_or_op.is_a?(Sequence)
|
73
|
+
seq_or_op.members
|
71
74
|
end.flatten)
|
75
|
+
end)
|
72
76
|
end
|
73
77
|
|
74
78
|
# Non-destructively extends this selector with the extensions specified in a hash
|
@@ -77,21 +77,52 @@ module Sass
|
|
77
77
|
# by replacing them with the given parent selector,
|
78
78
|
# handling commas appropriately.
|
79
79
|
#
|
80
|
-
# @param
|
81
|
-
# @return [
|
82
|
-
# This is an array because the parent selector is itself a {Sequence}
|
80
|
+
# @param super_cseq [CommaSequence] The parent selector
|
81
|
+
# @return [CommaSequence] This selector, with parent references resolved
|
83
82
|
# @raise [Sass::SyntaxError] If a parent selector is invalid
|
84
|
-
def resolve_parent_refs(
|
83
|
+
def resolve_parent_refs(super_cseq)
|
85
84
|
# Parent selector only appears as the first selector in the sequence
|
86
|
-
|
87
|
-
|
88
|
-
return super_seq.members if @members.size == 1
|
89
|
-
unless super_seq.members.last.is_a?(SimpleSequence)
|
90
|
-
raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join)
|
85
|
+
unless (parent = @members.first).is_a?(Parent)
|
86
|
+
return CommaSequence.new([Sequence.new([self])])
|
91
87
|
end
|
92
88
|
|
93
|
-
|
94
|
-
|
89
|
+
return super_cseq if @members.size == 1 && parent.suffix.empty?
|
90
|
+
|
91
|
+
CommaSequence.new(super_cseq.members.map do |super_seq|
|
92
|
+
unless super_seq.members.last.is_a?(SimpleSequence)
|
93
|
+
raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
|
94
|
+
super_seq.to_a.join + '"')
|
95
|
+
end
|
96
|
+
|
97
|
+
parent_sub = super_seq.members.last.members
|
98
|
+
unless parent.suffix.empty?
|
99
|
+
parent_sub = parent_sub.dup
|
100
|
+
parent_sub[-1] = parent_sub.last.dup
|
101
|
+
case parent_sub.last
|
102
|
+
when Sass::Selector::Class, Sass::Selector::Id, Sass::Selector::Placeholder
|
103
|
+
parent_sub[-1] = parent_sub.last.class.new(parent_sub.last.name + parent.suffix)
|
104
|
+
when Sass::Selector::Element
|
105
|
+
parent_sub[-1] = parent_sub.last.class.new(
|
106
|
+
parent_sub.last.name + parent.suffix,
|
107
|
+
parent_sub.last.namespace)
|
108
|
+
when Sass::Selector::Pseudo
|
109
|
+
if parent_sub.last.arg
|
110
|
+
raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
|
111
|
+
super_seq.to_a.join + '"')
|
112
|
+
end
|
113
|
+
parent_sub[-1] = parent_sub.last.class.new(
|
114
|
+
parent_sub.last.type,
|
115
|
+
parent_sub.last.name + parent.suffix,
|
116
|
+
nil)
|
117
|
+
else
|
118
|
+
raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
|
119
|
+
super_seq.to_a.join + '"')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
Sequence.new(super_seq.members[0...-1] +
|
124
|
+
[SimpleSequence.new(parent_sub + @members[1..-1], subject?)])
|
125
|
+
end)
|
95
126
|
end
|
96
127
|
|
97
128
|
# Non-destrucively extends this selector with the extensions specified in a hash
|