sass 3.3.0.rc.2 → 3.3.0.rc.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|