sass 3.3.0.alpha.69 → 3.3.0.alpha.88
Sign up to get free protection for your applications and to get access to all the features.
- data/REVISION +1 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass/engine.rb +29 -8
- data/lib/sass/script/functions.rb +211 -14
- data/lib/sass/script/number.rb +22 -2
- data/lib/sass/scss/parser.rb +12 -8
- data/lib/sass/selector/simple_sequence.rb +9 -3
- data/lib/sass/tree/extend_node.rb +8 -1
- data/lib/sass/tree/rule_node.rb +7 -1
- data/lib/sass/tree/visitors/to_css.rb +3 -3
- data/test/sass/functions_test.rb +96 -2
- data/test/sass/importer_test.rb +3 -3
- data/test/sass/script_test.rb +11 -0
- data/test/sass/source_map_test.rb +254 -254
- metadata +4 -4
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
c8154cc19b995b06961c60fb376d9c4821f8bde1
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.0.alpha.
|
1
|
+
3.3.0.alpha.88
|
data/VERSION_DATE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
18 February 2013 01:09:19 GMT
|
data/lib/sass/engine.rb
CHANGED
@@ -599,7 +599,7 @@ WARNING
|
|
599
599
|
# which begin with ::,
|
600
600
|
# as well as pseudo-classes
|
601
601
|
# if we're using the new property syntax
|
602
|
-
Tree::RuleNode.new(parse_interp(line.text))
|
602
|
+
Tree::RuleNode.new(parse_interp(line.text), full_line_range(line))
|
603
603
|
else
|
604
604
|
name_start_offset = line.offset + 1 # +1 for the leading ':'
|
605
605
|
name, value = line.text.scan(PROPERTY_OLD)[0]
|
@@ -626,12 +626,12 @@ WARNING
|
|
626
626
|
when DIRECTIVE_CHAR
|
627
627
|
parse_directive(parent, line, root)
|
628
628
|
when ESCAPE_CHAR
|
629
|
-
Tree::RuleNode.new(parse_interp(line.text[1..-1]))
|
629
|
+
Tree::RuleNode.new(parse_interp(line.text[1..-1]), full_line_range(line))
|
630
630
|
when MIXIN_DEFINITION_CHAR
|
631
631
|
parse_mixin_definition(line)
|
632
632
|
when MIXIN_INCLUDE_CHAR
|
633
633
|
if line.text[1].nil? || line.text[1] == ?\s
|
634
|
-
Tree::RuleNode.new(parse_interp(line.text))
|
634
|
+
Tree::RuleNode.new(parse_interp(line.text), full_line_range(line))
|
635
635
|
else
|
636
636
|
parse_mixin_include(line, root)
|
637
637
|
end
|
@@ -650,11 +650,12 @@ WARNING
|
|
650
650
|
@line, to_parser_offset(offset))
|
651
651
|
|
652
652
|
unless res = parser.parse_interp_ident
|
653
|
-
|
653
|
+
parsed = parse_interp(line.text, line.offset)
|
654
|
+
return Tree::RuleNode.new(parsed, full_line_range(line))
|
654
655
|
end
|
655
656
|
|
656
657
|
ident_range = Sass::Source::Range.new(
|
657
|
-
Sass::Source::Position.new(@line, to_parser_offset(offset)),
|
658
|
+
Sass::Source::Position.new(@line, to_parser_offset(line.offset)),
|
658
659
|
Sass::Source::Position.new(@line, parser.offset),
|
659
660
|
@options[:filename], @options[:importer])
|
660
661
|
offset = parser.offset - 1
|
@@ -672,7 +673,14 @@ WARNING
|
|
672
673
|
property
|
673
674
|
else
|
674
675
|
res.pop if comment
|
675
|
-
|
676
|
+
scanner_start_pos = scanner.pos
|
677
|
+
interp_parsed = parse_interp(scanner.rest)
|
678
|
+
scanned_size = scanner.pos - scanner_start_pos
|
679
|
+
selector_range = Sass::Source::Range.new(
|
680
|
+
ident_range.start_pos,
|
681
|
+
Sass::Source::Position.new(@line, to_parser_offset(line.offset) + line.text.length),
|
682
|
+
@options[:filename], @options[:importer])
|
683
|
+
Tree::RuleNode.new(res + interp_parsed, selector_range)
|
676
684
|
end
|
677
685
|
end
|
678
686
|
|
@@ -733,7 +741,7 @@ WARNING
|
|
733
741
|
type = if silent then :silent elsif loud then :loud else :normal end
|
734
742
|
Tree::CommentNode.new(value, type)
|
735
743
|
else
|
736
|
-
Tree::RuleNode.new(parse_interp(line.text))
|
744
|
+
Tree::RuleNode.new(parse_interp(line.text), full_line_range(line))
|
737
745
|
end
|
738
746
|
end
|
739
747
|
|
@@ -778,7 +786,13 @@ WARNING
|
|
778
786
|
:line => @line + 1) unless line.children.empty?
|
779
787
|
optional = !!value.gsub!(/\s+#{Sass::SCSS::RX::OPTIONAL}$/, '')
|
780
788
|
offset = line.offset + line.text.index(value).to_i
|
781
|
-
|
789
|
+
interp_parsed = parse_interp(value, offset)
|
790
|
+
selector_range = Sass::Source::Range.new(
|
791
|
+
Sass::Source::Position.new(@line, to_parser_offset(offset)),
|
792
|
+
Sass::Source::Position.new(@line, to_parser_offset(line.offset) + line.text.length),
|
793
|
+
@options[:filename], @options[:importer]
|
794
|
+
)
|
795
|
+
Tree::ExtendNode.new(interp_parsed, optional, selector_range)
|
782
796
|
when 'warn'
|
783
797
|
raise SyntaxError.new("Invalid warn directive '@warn': expected expression.") unless value
|
784
798
|
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath warn directives.",
|
@@ -1030,6 +1044,13 @@ WARNING
|
|
1030
1044
|
offset + 1
|
1031
1045
|
end
|
1032
1046
|
|
1047
|
+
def full_line_range(line)
|
1048
|
+
Sass::Source::Range.new(
|
1049
|
+
Sass::Source::Position.new(@line, to_parser_offset(line.offset)),
|
1050
|
+
Sass::Source::Position.new(@line, to_parser_offset(line.offset) + line.text.length),
|
1051
|
+
@options[:filename], @options[:importer])
|
1052
|
+
end
|
1053
|
+
|
1033
1054
|
# It's important that this have strings (at least)
|
1034
1055
|
# at the beginning, the end, and between each Script::Node.
|
1035
1056
|
#
|
@@ -4,7 +4,7 @@ module Sass::Script
|
|
4
4
|
#
|
5
5
|
# $color = hsl(120deg, 100%, 50%)
|
6
6
|
#
|
7
|
-
# and it will call {
|
7
|
+
# and it will call {Functions#hsl}.
|
8
8
|
#
|
9
9
|
# The following functions are provided:
|
10
10
|
#
|
@@ -110,6 +110,24 @@ module Sass::Script
|
|
110
110
|
# \{#quote quote($string)}
|
111
111
|
# : Adds quotes to a string.
|
112
112
|
#
|
113
|
+
# \{#str_length str-length($string)}
|
114
|
+
# : Returns the number of characters in a string.
|
115
|
+
#
|
116
|
+
# \{#str_insert str-insert($string, $insert, $index)}
|
117
|
+
# : Inserts the second string into the first string at the specified index.
|
118
|
+
#
|
119
|
+
# \{#str_index str-index($string, $substring)}
|
120
|
+
# : Returns the index where a substring is found in another string or 0 if not found.
|
121
|
+
#
|
122
|
+
# \{#str_extract str-slice($string, $start, $end)}
|
123
|
+
# : Extracts a substring of characters from $string
|
124
|
+
#
|
125
|
+
# \{#to_upper_case to-upper-case($string)}
|
126
|
+
# : Converts a string to upper case.
|
127
|
+
#
|
128
|
+
# \{#to_lower_case to-lower-case($string)}
|
129
|
+
# : Converts a string to lower case.
|
130
|
+
#
|
113
131
|
# ## Number Functions
|
114
132
|
#
|
115
133
|
# \{#percentage percentage($value)}
|
@@ -184,14 +202,14 @@ module Sass::Script
|
|
184
202
|
# {declare} can also allow your function to take arbitrary keyword arguments.
|
185
203
|
#
|
186
204
|
# There are a few things to keep in mind when modifying this module.
|
187
|
-
# First of all, the arguments passed are {
|
205
|
+
# First of all, the arguments passed are {Literal} objects.
|
188
206
|
# Literal objects are also expected to be returned.
|
189
207
|
# This means that Ruby values must be unwrapped and wrapped.
|
190
208
|
#
|
191
|
-
# Most Literal objects support the {
|
209
|
+
# Most Literal objects support the {Literal#value value} accessor
|
192
210
|
# for getting their Ruby values.
|
193
|
-
# Color objects, though, must be accessed using {
|
194
|
-
# {
|
211
|
+
# Color objects, though, must be accessed using {Color#rgb rgb},
|
212
|
+
# {Color#red red}, {Color#blue green}, or {Color#blue blue}.
|
195
213
|
#
|
196
214
|
# Second, making Ruby functions accessible from Sass introduces the temptation
|
197
215
|
# to do things like database access within stylesheets.
|
@@ -250,7 +268,7 @@ module Sass::Script
|
|
250
268
|
# Whether the function accepts other keyword arguments
|
251
269
|
# in addition to those in `:args`.
|
252
270
|
# If this is true, the Ruby function will be passed a hash from strings
|
253
|
-
# to {
|
271
|
+
# to {Literal}s as the last argument.
|
254
272
|
# In addition, if this is true and `:var_args` is not,
|
255
273
|
# Sass will ensure that the last argument passed is a hash.
|
256
274
|
#
|
@@ -329,15 +347,63 @@ module Sass::Script
|
|
329
347
|
# @example
|
330
348
|
# assert_type value, :String
|
331
349
|
# assert_type value, :Number
|
332
|
-
# @param value [
|
350
|
+
# @param value [Literal] A SassScript value
|
333
351
|
# @param type [Symbol] The name of the type the value is expected to be
|
334
352
|
# @param name [String, nil] The name of the argument.
|
353
|
+
# @raise [ArgumentError] if value is not of the correct type.
|
335
354
|
def assert_type(value, type, name = nil)
|
336
355
|
return if value.is_a?(Sass::Script.const_get(type))
|
337
356
|
err = "#{value.inspect} is not a #{type.to_s.downcase}"
|
338
357
|
err = "$#{name}: " + err if name
|
339
358
|
raise ArgumentError.new(err)
|
340
359
|
end
|
360
|
+
|
361
|
+
# Asserts that the unit of the number is as expected.
|
362
|
+
#
|
363
|
+
# @example
|
364
|
+
# assert_unit number, "px"
|
365
|
+
# assert_unit number, nil
|
366
|
+
# @param number [Number] The number to be validated.
|
367
|
+
# @param unit [::String]
|
368
|
+
# The unit that the number must have.
|
369
|
+
# If nil, the number must be unitless.
|
370
|
+
# @param name [::String] The name of the parameter being validated.
|
371
|
+
# @raise [ArgumentError] if number is not of the correct unit or is not a number.
|
372
|
+
def assert_unit(number, unit, name = nil)
|
373
|
+
assert_type number, :Number, name
|
374
|
+
return if number.is_unit?(unit)
|
375
|
+
if unit
|
376
|
+
if name
|
377
|
+
raise ArgumentError.new("Expected $#{name} to have a unit of #{unit} but got #{number}")
|
378
|
+
else
|
379
|
+
raise ArgumentError.new("Expected #{number} to have a unit of #{unit}")
|
380
|
+
end
|
381
|
+
else
|
382
|
+
if name
|
383
|
+
raise ArgumentError.new("Expected $#{name} to be unitless but got #{number}")
|
384
|
+
else
|
385
|
+
raise ArgumentError.new("Expected #{number} to be unitless")
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
# Asserts that the value is an integer.
|
391
|
+
#
|
392
|
+
# @example
|
393
|
+
# assert_unit number, "px"
|
394
|
+
# assert_unit number, nil
|
395
|
+
# @param number [Literal] The literal to be validated.
|
396
|
+
# @param name [::String] The name of the parameter being validated.
|
397
|
+
# @raise [ArgumentError] if number is not an integer or is not a number.
|
398
|
+
def assert_integer(number, name = nil)
|
399
|
+
assert_type number, :Number, name
|
400
|
+
return if number.int?
|
401
|
+
if name
|
402
|
+
raise ArgumentError.new("Expected $#{name} to be an integer but got #{number}")
|
403
|
+
else
|
404
|
+
raise ArgumentError.new("Expected #{number} to be an integer")
|
405
|
+
end
|
406
|
+
end
|
341
407
|
end
|
342
408
|
|
343
409
|
class << self
|
@@ -377,11 +443,13 @@ module Sass::Script
|
|
377
443
|
|
378
444
|
Color.new([red, green, blue].map do |c|
|
379
445
|
v = c.value
|
380
|
-
if c.
|
446
|
+
if c.is_unit?("%")
|
381
447
|
v = Sass::Util.check_range("Color value", 0..100, c, '%')
|
382
448
|
v * 255 / 100.0
|
383
|
-
|
449
|
+
elsif c.unitless?
|
384
450
|
Sass::Util.check_range("Color value", 0..255, c)
|
451
|
+
else
|
452
|
+
raise ArgumentError.new("Expected #{c} to be unitless or have a unit of % but got #{c}")
|
385
453
|
end
|
386
454
|
end)
|
387
455
|
end
|
@@ -874,11 +942,8 @@ module Sass::Script
|
|
874
942
|
|
875
943
|
next unless val = kwargs.delete(name)
|
876
944
|
assert_type val, :Number, name
|
877
|
-
|
878
|
-
|
879
|
-
else
|
880
|
-
Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
|
881
|
-
end
|
945
|
+
assert_unit val, '%', name
|
946
|
+
Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
|
882
947
|
|
883
948
|
current = color.send(name)
|
884
949
|
scale = val.value/100.0
|
@@ -1083,6 +1148,138 @@ module Sass::Script
|
|
1083
1148
|
end
|
1084
1149
|
declare :quote, [:string]
|
1085
1150
|
|
1151
|
+
# Returns the number of characters in a string.
|
1152
|
+
#
|
1153
|
+
# @return [Number]
|
1154
|
+
# @raise [ArgumentError] if `string` isn't a string
|
1155
|
+
# @example
|
1156
|
+
# str-length("foo") => 3
|
1157
|
+
def str_length(string)
|
1158
|
+
assert_type string, :String
|
1159
|
+
Sass::Script::Number.new(string.value.size)
|
1160
|
+
end
|
1161
|
+
declare :str_length, [:string]
|
1162
|
+
|
1163
|
+
# Inserts a string into another string.
|
1164
|
+
#
|
1165
|
+
# Inserts the `$insert` string into the `$original` before the character at
|
1166
|
+
# the given `$index`.
|
1167
|
+
#
|
1168
|
+
# @param [String] original The string that will receive the insertion.
|
1169
|
+
# @param [String] insert The string that will be inserted.
|
1170
|
+
# @param [Number] index
|
1171
|
+
# The position where inserted string will start.
|
1172
|
+
# Negative indices count from the end of the original string.
|
1173
|
+
#
|
1174
|
+
# @return [String] A new string
|
1175
|
+
# @raise [ArgumentError] if `$original` isn't a string, `$insert` isn't a string, or `$index` isn't a number.
|
1176
|
+
# @example
|
1177
|
+
# str-insert("abcd", "X", 1) => "Xabcd"
|
1178
|
+
# str-insert("abcd", "X", 4) => "abcXd"
|
1179
|
+
# str-insert("abcd", "X", 100) => "abcdX"
|
1180
|
+
# str-insert("abcd", "X", -100) => "Xabcd"
|
1181
|
+
def str_insert(original, insert, index)
|
1182
|
+
assert_type original, :String, "original"
|
1183
|
+
assert_type insert, :String, "insert"
|
1184
|
+
assert_integer index, "index"
|
1185
|
+
assert_unit index, nil, "index"
|
1186
|
+
insertion_point = index.value > 0 ? [index.value - 1, original.value.size].min : [index.value, -original.value.size - 1].max
|
1187
|
+
Sass::Script::String.new(original.value.dup.insert(insertion_point, insert.value), original.type)
|
1188
|
+
end
|
1189
|
+
declare :str_insert, [:original, :insert, :index]
|
1190
|
+
|
1191
|
+
# Starting at the left, finds the index of the first location
|
1192
|
+
# where `substring` is found in `string`.
|
1193
|
+
#
|
1194
|
+
# @return [Number] The index of the substring, or 0 if not found.
|
1195
|
+
# @raise [ArgumentError] if `original` isn't a string, `insert` isn't a string, or `index` isn't a number.
|
1196
|
+
# @param string The string to search
|
1197
|
+
# @param substring The string to search for
|
1198
|
+
# @example
|
1199
|
+
# str-index(abcd, a) => 1
|
1200
|
+
# str-index(abcd, ab) => 1
|
1201
|
+
# str-index(abcd, X) => 0
|
1202
|
+
# str-index(abcd, c) => 3
|
1203
|
+
def str_index(string, substring)
|
1204
|
+
assert_type string, :String
|
1205
|
+
assert_type substring, :String
|
1206
|
+
index = string.value.index(substring.value) || -1
|
1207
|
+
Sass::Script::Number.new(index + 1)
|
1208
|
+
end
|
1209
|
+
declare :str_index, [:string, :substring]
|
1210
|
+
|
1211
|
+
|
1212
|
+
# Slice a substring from `string` from `start-at` index to `end-at` index.
|
1213
|
+
#
|
1214
|
+
# @return [String] A new string
|
1215
|
+
# @param start_at
|
1216
|
+
# The index (inclusive) of the first character to slice out of the string.
|
1217
|
+
# If negative, counts from the end of the string.
|
1218
|
+
# @param end_at
|
1219
|
+
# The index (inclusive) of the last character to slice out of the string.
|
1220
|
+
# @overload str_slice(string, start_at)
|
1221
|
+
# Slice starting at `start_at` to the end of the string.
|
1222
|
+
# @overload str_slice(string, start_at, end_at)
|
1223
|
+
# Slice starting at `start_at` to `end_at`
|
1224
|
+
# @raise [ArgumentError] if `string` isn't a string or `start_at` and `end_at` aren't unitless numbers
|
1225
|
+
# @example
|
1226
|
+
# str-slice(abcd, 2, 3) => bc
|
1227
|
+
# str-slice(abcd, 2 ) => bcd
|
1228
|
+
# str-slice(abcd, -2 ) => cd
|
1229
|
+
# str-slice(abcd, 2, -2) => bc
|
1230
|
+
# str-slice("abcd", 3, -3) => ""
|
1231
|
+
# str-slice(abcd, 1, 1) => a
|
1232
|
+
# str-slice(abcd, 1, 2) => ab
|
1233
|
+
# str-slice(abcd, 1, 4) => abcd
|
1234
|
+
# str-slice(abcd, -100, 4) => abcd
|
1235
|
+
# str-slice(abcd, 1, 100) => abcd
|
1236
|
+
# str-slice("abcd", 2, 1) => ""
|
1237
|
+
# str-slice("abcd", 2, 3) => "bc"
|
1238
|
+
def str_slice(string, start_at, end_at = nil)
|
1239
|
+
assert_type string, :String
|
1240
|
+
assert_unit start_at, nil, "start-at"
|
1241
|
+
|
1242
|
+
end_at = Sass::Script::Number.new(-1)if end_at.nil?
|
1243
|
+
assert_unit end_at, nil, "end-at"
|
1244
|
+
|
1245
|
+
s = start_at.value > 0 ? start_at.value - 1 : start_at.value
|
1246
|
+
e = end_at.value > 0 ? end_at.value - 1 : end_at.value
|
1247
|
+
s = string.value.length + s if s < 0
|
1248
|
+
s = 0 if s < 0
|
1249
|
+
e = string.value.length + e if e < 0
|
1250
|
+
e = 0 if s < 0
|
1251
|
+
extracted = string.value.slice(s..e)
|
1252
|
+
Sass::Script::String.new(extracted || "", string.type)
|
1253
|
+
end
|
1254
|
+
declare :str_slice, [:string, :start_at]
|
1255
|
+
declare :str_slice, [:string, :start_at, :end_at]
|
1256
|
+
|
1257
|
+
# Convert a string to upper case
|
1258
|
+
#
|
1259
|
+
# @return [String]
|
1260
|
+
# @raise [ArgumentError] if `string` isn't a string
|
1261
|
+
# @example
|
1262
|
+
# to-upper-case(abcd) => ABCD
|
1263
|
+
# to-upper-case("abcd") => "ABCD"
|
1264
|
+
def to_upper_case(string)
|
1265
|
+
assert_type string, :String
|
1266
|
+
Sass::Script::String.new(string.value.upcase, string.type)
|
1267
|
+
end
|
1268
|
+
declare :to_upper_case, [:string]
|
1269
|
+
|
1270
|
+
# Convert a string to lower case
|
1271
|
+
#
|
1272
|
+
# @return [String]
|
1273
|
+
# @raise [ArgumentError] if `string` isn't a string
|
1274
|
+
# @example
|
1275
|
+
# to-lower-case(ABCD) => abcd
|
1276
|
+
# to-lower-case("ABCD") => "abcd"
|
1277
|
+
def to_lower_case(string)
|
1278
|
+
assert_type string, :String
|
1279
|
+
Sass::Script::String.new(string.value.downcase, string.type)
|
1280
|
+
end
|
1281
|
+
declare :to_lower_case, [:string]
|
1282
|
+
|
1086
1283
|
# Inspects the type of the argument, returning it as an unquoted string.
|
1087
1284
|
#
|
1088
1285
|
# @example
|
data/lib/sass/script/number.rb
CHANGED
@@ -57,9 +57,11 @@ module Sass::Script
|
|
57
57
|
NO_UNITS = []
|
58
58
|
|
59
59
|
# @param value [Numeric] The value of the number
|
60
|
-
# @param numerator_units [Array
|
61
|
-
# @param denominator_units [Array
|
60
|
+
# @param numerator_units [::String, Array<::String>] See \{#numerator\_units}
|
61
|
+
# @param denominator_units [::String, Array<::String>] See \{#denominator\_units}
|
62
62
|
def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)
|
63
|
+
numerator_units = [numerator_units] if numerator_units.is_a?(::String)
|
64
|
+
denominator_units = [denominator_units] if denominator_units.is_a?(::String)
|
63
65
|
super(value)
|
64
66
|
@numerator_units = numerator_units
|
65
67
|
@denominator_units = denominator_units
|
@@ -285,6 +287,24 @@ module Sass::Script
|
|
285
287
|
@numerator_units.empty? && @denominator_units.empty?
|
286
288
|
end
|
287
289
|
|
290
|
+
# Checks whether the number has the numerator unit specified.
|
291
|
+
#
|
292
|
+
# @example
|
293
|
+
# number = Sass::Script::Number.new(10, "px")
|
294
|
+
# number.is_unit?("px") => true
|
295
|
+
# number.is_unit?(nil) => false
|
296
|
+
#
|
297
|
+
# @param number [Number] The number to check
|
298
|
+
# @param unit [::String, nil] The unit the number should have or nil if the number should be unitless.
|
299
|
+
# @see Number#unitless? The unitless? method may be more readable.
|
300
|
+
def is_unit?(unit)
|
301
|
+
if unit
|
302
|
+
denominator_units.size == 0 && numerator_units.size == 1 && numerator_units.first == unit
|
303
|
+
else
|
304
|
+
unitless?
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
288
308
|
# @return [Boolean] Whether or not this number has units that can be represented in CSS
|
289
309
|
# (that is, zero or one \{#numerator\_units}).
|
290
310
|
def legal_units?
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -311,10 +311,10 @@ module Sass
|
|
311
311
|
end
|
312
312
|
|
313
313
|
def extend_directive(start_pos)
|
314
|
-
selector = expr!(:selector_sequence)
|
314
|
+
selector, selector_range = expr!(:selector_sequence)
|
315
315
|
optional = tok(OPTIONAL)
|
316
316
|
ss
|
317
|
-
node(Sass::Tree::ExtendNode.new(selector, !!optional), start_pos)
|
317
|
+
node(Sass::Tree::ExtendNode.new(selector, !!optional, selector_range), start_pos)
|
318
318
|
end
|
319
319
|
|
320
320
|
def import_directive(start_pos)
|
@@ -536,8 +536,9 @@ module Sass
|
|
536
536
|
|
537
537
|
def ruleset
|
538
538
|
start_pos = source_position
|
539
|
-
|
540
|
-
|
539
|
+
rules, source_range = selector_sequence
|
540
|
+
return unless rules
|
541
|
+
block(node(Sass::Tree::RuleNode.new(rules.flatten.compact, source_range), start_pos), :ruleset)
|
541
542
|
end
|
542
543
|
|
543
544
|
def block(node, context)
|
@@ -607,8 +608,9 @@ module Sass
|
|
607
608
|
end
|
608
609
|
|
609
610
|
def selector_sequence
|
611
|
+
start_pos = source_position
|
610
612
|
if sel = tok(STATIC_SELECTOR, true)
|
611
|
-
return [sel]
|
613
|
+
return [sel], range(start_pos)
|
612
614
|
end
|
613
615
|
|
614
616
|
rules = []
|
@@ -624,7 +626,7 @@ module Sass
|
|
624
626
|
ws = ''
|
625
627
|
end
|
626
628
|
end
|
627
|
-
rules
|
629
|
+
return rules, range(start_pos)
|
628
630
|
end
|
629
631
|
|
630
632
|
def selector
|
@@ -680,6 +682,8 @@ module Sass
|
|
680
682
|
def simple_selector_sequence
|
681
683
|
# Returning expr by default allows for stuff like
|
682
684
|
# http://www.w3.org/TR/css3-animations/#keyframes-
|
685
|
+
|
686
|
+
start_pos = source_position
|
683
687
|
return expr(!:allow_var) unless e = element_name || id_selector ||
|
684
688
|
class_selector || placeholder_selector || attrib || pseudo ||
|
685
689
|
parent_selector || interpolation_selector
|
@@ -708,7 +712,7 @@ module Sass
|
|
708
712
|
end
|
709
713
|
end
|
710
714
|
|
711
|
-
Selector::SimpleSequence.new(res, tok(/!/))
|
715
|
+
Selector::SimpleSequence.new(res, tok(/!/), range(start_pos))
|
712
716
|
end
|
713
717
|
|
714
718
|
def parent_selector
|
@@ -1038,7 +1042,7 @@ MESSAGE
|
|
1038
1042
|
def self.sass_script_parser; @sass_script_parser; end
|
1039
1043
|
|
1040
1044
|
def sass_script(*args)
|
1041
|
-
parser = self.class.sass_script_parser.new(@scanner, @line, @offset, :filename => @filename)
|
1045
|
+
parser = self.class.sass_script_parser.new(@scanner, @line, @offset, :filename => @filename, :importer => @importer)
|
1042
1046
|
result = parser.send(*args)
|
1043
1047
|
unless @strs.empty?
|
1044
1048
|
# Convert to CSS manually so that comments are ignored.
|