sass 3.3.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +58 -50
- data/Rakefile +1 -4
- 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/lib/sass/cache_stores/filesystem.rb +6 -2
- data/lib/sass/css.rb +1 -3
- data/lib/sass/engine.rb +37 -46
- data/lib/sass/environment.rb +13 -17
- data/lib/sass/error.rb +6 -9
- data/lib/sass/exec/base.rb +187 -0
- data/lib/sass/exec/sass_convert.rb +264 -0
- data/lib/sass/exec/sass_scss.rb +424 -0
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/features.rb +7 -0
- data/lib/sass/importers/base.rb +7 -2
- data/lib/sass/importers/filesystem.rb +9 -25
- data/lib/sass/importers.rb +0 -1
- data/lib/sass/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +200 -83
- data/lib/sass/plugin/staleness_checker.rb +1 -1
- data/lib/sass/plugin.rb +3 -3
- data/lib/sass/script/css_lexer.rb +1 -1
- data/lib/sass/script/functions.rb +622 -268
- data/lib/sass/script/lexer.rb +99 -34
- data/lib/sass/script/parser.rb +24 -23
- data/lib/sass/script/tree/funcall.rb +1 -1
- data/lib/sass/script/tree/interpolation.rb +20 -2
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +1 -1
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/value/base.rb +7 -5
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +39 -21
- data/lib/sass/script/value/helpers.rb +107 -0
- data/lib/sass/script/value/list.rb +0 -15
- data/lib/sass/script/value/null.rb +0 -5
- data/lib/sass/script/value/number.rb +62 -14
- data/lib/sass/script/value/string.rb +59 -11
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/scss/css_parser.rb +8 -2
- data/lib/sass/scss/parser.rb +190 -328
- data/lib/sass/scss/rx.rb +15 -6
- data/lib/sass/scss/static_parser.rb +298 -1
- data/lib/sass/selector/abstract_sequence.rb +28 -13
- data/lib/sass/selector/comma_sequence.rb +92 -13
- data/lib/sass/selector/pseudo.rb +256 -0
- data/lib/sass/selector/sequence.rb +94 -24
- data/lib/sass/selector/simple.rb +14 -25
- data/lib/sass/selector/simple_sequence.rb +97 -33
- data/lib/sass/selector.rb +57 -194
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/source/map.rb +26 -12
- data/lib/sass/stack.rb +0 -6
- data/lib/sass/supports.rb +2 -3
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/charset_node.rb +1 -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 +4 -0
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/prop_node.rb +1 -1
- data/lib/sass/tree/rule_node.rb +12 -7
- data/lib/sass/tree/visitors/check_nesting.rb +38 -10
- data/lib/sass/tree/visitors/convert.rb +16 -18
- data/lib/sass/tree/visitors/cssize.rb +29 -29
- data/lib/sass/tree/visitors/deep_copy.rb +5 -0
- data/lib/sass/tree/visitors/perform.rb +45 -33
- data/lib/sass/tree/visitors/set_options.rb +14 -0
- data/lib/sass/tree/visitors/to_css.rb +15 -14
- data/lib/sass/util/subset_map.rb +1 -1
- data/lib/sass/util.rb +222 -99
- data/lib/sass/version.rb +5 -5
- data/lib/sass.rb +0 -5
- data/test/sass/cache_test.rb +62 -20
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +19 -10
- data/test/sass/conversion_test.rb +58 -1
- data/test/sass/css2sass_test.rb +23 -4
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +136 -199
- data/test/sass/exec_test.rb +2 -2
- data/test/sass/extend_test.rb +236 -19
- data/test/sass/functions_test.rb +295 -253
- data/test/sass/importer_test.rb +31 -21
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/plugin_test.rb +14 -13
- 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 +3 -3
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +10 -7
- data/test/sass/script_test.rb +288 -74
- data/test/sass/scss/css_test.rb +141 -24
- data/test/sass/scss/rx_test.rb +4 -4
- data/test/sass/scss/scss_test.rb +457 -18
- data/test/sass/source_map_test.rb +115 -25
- data/test/sass/superselector_test.rb +191 -0
- data/test/sass/templates/scss_import.scss +2 -1
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
- 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 +31 -1
- data/test/sass/value_helpers_test.rb +5 -7
- data/test/test_helper.rb +2 -2
- 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 +25 -22
- data/ext/mkrf_conf.rb +0 -27
- data/lib/sass/importers/deprecated_path.rb +0 -51
- data/lib/sass/script/value/deprecated_false.rb +0 -55
- 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/script/lexer.rb
CHANGED
@@ -82,6 +82,8 @@ module Sass
|
|
82
82
|
# with identifier names.
|
83
83
|
IDENT_OP_NAMES = OP_NAMES.select {|k, v| k =~ /^\w+/}
|
84
84
|
|
85
|
+
PARSEABLE_NUMBER = /(?:(\d*\.\d+)|(\d+))(?:[eE]([+-]?\d+))?(#{UNIT})?/
|
86
|
+
|
85
87
|
# A hash of regular expressions that are used for tokenizing.
|
86
88
|
REGULAR_EXPRESSIONS = {
|
87
89
|
:whitespace => /\s+/,
|
@@ -89,9 +91,11 @@ module Sass
|
|
89
91
|
:single_line_comment => SINGLE_LINE_COMMENT,
|
90
92
|
:variable => /(\$)(#{IDENT})/,
|
91
93
|
:ident => /(#{IDENT})(\()?/,
|
92
|
-
:number =>
|
93
|
-
:unary_minus_number =>
|
94
|
+
:number => PARSEABLE_NUMBER,
|
95
|
+
:unary_minus_number => /-#{PARSEABLE_NUMBER}/,
|
94
96
|
:color => HEXCOLOR,
|
97
|
+
:id => /##{IDENT}/,
|
98
|
+
:selector => /&/,
|
95
99
|
:ident_op => /(#{Regexp.union(*IDENT_OP_NAMES.map do |s|
|
96
100
|
Regexp.new(Regexp.escape(s) + "(?!#{NMCHAR}|\Z)")
|
97
101
|
end)})/,
|
@@ -102,7 +106,7 @@ module Sass
|
|
102
106
|
private
|
103
107
|
|
104
108
|
def string_re(open, close)
|
105
|
-
/#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/
|
109
|
+
/#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/m
|
106
110
|
end
|
107
111
|
end
|
108
112
|
|
@@ -246,13 +250,19 @@ module Sass
|
|
246
250
|
end
|
247
251
|
|
248
252
|
def token
|
249
|
-
if after_interpolation? && (
|
250
|
-
|
253
|
+
if after_interpolation? && (interp = @interpolation_stack.pop)
|
254
|
+
interp_type, interp_value = interp
|
255
|
+
if interp_type == :special_fun
|
256
|
+
return special_fun_body(interp_value)
|
257
|
+
else
|
258
|
+
raise "[BUG]: Unknown interp_type #{interp_type}" unless interp_type == :string
|
259
|
+
return string(interp_value, true)
|
260
|
+
end
|
251
261
|
end
|
252
262
|
|
253
|
-
variable || string(:double, false) || string(:single, false) || number || color ||
|
254
|
-
string(:uri, false) || raw(UNICODERANGE) || special_fun || special_val ||
|
255
|
-
ident || op
|
263
|
+
variable || string(:double, false) || string(:single, false) || number || id || color ||
|
264
|
+
selector || string(:uri, false) || raw(UNICODERANGE) || special_fun || special_val ||
|
265
|
+
ident_op || ident || op
|
256
266
|
end
|
257
267
|
|
258
268
|
def variable
|
@@ -271,18 +281,28 @@ module Sass
|
|
271
281
|
end
|
272
282
|
|
273
283
|
def string(re, open)
|
284
|
+
line, offset = @line, @offset
|
274
285
|
return unless scan(STRING_REGULAR_EXPRESSIONS[re][open])
|
286
|
+
if @scanner[0] =~ /([^\\]|^)\n/
|
287
|
+
filename = @options[:filename]
|
288
|
+
Sass::Util.sass_warn <<MESSAGE
|
289
|
+
DEPRECATION WARNING on line #{line}, column #{offset}#{" of #{filename}" if filename}:
|
290
|
+
Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
|
291
|
+
To include a newline in a string, use "\\a" or "\\a " as in CSS.
|
292
|
+
MESSAGE
|
293
|
+
end
|
294
|
+
|
275
295
|
if @scanner[2] == '#{' # '
|
276
296
|
@scanner.pos -= 2 # Don't actually consume the #{
|
277
297
|
@offset -= 2
|
278
|
-
@interpolation_stack << re
|
298
|
+
@interpolation_stack << [:string, re]
|
279
299
|
end
|
280
300
|
str =
|
281
301
|
if re == :uri
|
282
302
|
url = "#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}"
|
283
303
|
Script::Value::String.new(url)
|
284
304
|
else
|
285
|
-
Script::Value::String.new(@scanner[1]
|
305
|
+
Script::Value::String.new(Sass::Script::Value::String.value(@scanner[1]), :string)
|
286
306
|
end
|
287
307
|
[:string, str]
|
288
308
|
end
|
@@ -296,10 +316,12 @@ module Sass
|
|
296
316
|
# minus logic in the parser instead.
|
297
317
|
if @scanner.peek(1) == '-'
|
298
318
|
return if @scanner.pos == 0
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
319
|
+
unary_minus_allowed =
|
320
|
+
case @scanner.string[@scanner.pos - 1, 1]
|
321
|
+
when /\s/; true
|
322
|
+
when '/'; @scanner.pos != 1 && @scanner.string[@scanner.pos - 2, 1] == '*'
|
323
|
+
else; false
|
324
|
+
end
|
303
325
|
|
304
326
|
return unless unary_minus_allowed
|
305
327
|
return unless scan(REGULAR_EXPRESSIONS[:unary_minus_number])
|
@@ -310,33 +332,76 @@ module Sass
|
|
310
332
|
end
|
311
333
|
|
312
334
|
value = (@scanner[1] ? @scanner[1].to_f : @scanner[2].to_i) * (minus ? -1 : 1)
|
313
|
-
|
335
|
+
value *= 10**@scanner[3].to_i if @scanner[3]
|
336
|
+
script_number = Script::Value::Number.new(value, Array(@scanner[4]))
|
314
337
|
[:number, script_number]
|
315
338
|
end
|
316
339
|
|
340
|
+
def id
|
341
|
+
# Colors and ids are tough to tell apart, because they overlap but
|
342
|
+
# neither is a superset of the other. "#xyz" is an id but not a color,
|
343
|
+
# "#000" is a color but not an id, "#abc" is both, and "#0" is neither.
|
344
|
+
# We need to handle all these cases correctly.
|
345
|
+
#
|
346
|
+
# To do so, we first try to parse something as an id. If this works and
|
347
|
+
# the id is also a valid color, we return the color. Otherwise, we
|
348
|
+
# return the id. If it didn't parse as an id, we then try to parse it as
|
349
|
+
# a color. If *this* works, we return the color, and if it doesn't we
|
350
|
+
# give up and throw an error.
|
351
|
+
#
|
352
|
+
# IDs in properties are used in the Basic User Interface Module
|
353
|
+
# (http://www.w3.org/TR/css3-ui/).
|
354
|
+
return unless scan(REGULAR_EXPRESSIONS[:id])
|
355
|
+
if @scanner[0] =~ /^\#[0-9a-fA-F]+$/ && (@scanner[0].length == 4 || @scanner[0].length == 7)
|
356
|
+
return [:color, Script::Value::Color.from_hex(@scanner[0])]
|
357
|
+
end
|
358
|
+
[:ident, @scanner[0]]
|
359
|
+
end
|
360
|
+
|
317
361
|
def color
|
318
|
-
|
319
|
-
return unless
|
320
|
-
|
321
|
-
Colors must have either three or six digits: '#{s}'
|
322
|
-
MESSAGE
|
323
|
-
script_color = Script::Value::Color.from_hex(s)
|
362
|
+
return unless @scanner.match?(REGULAR_EXPRESSIONS[:color])
|
363
|
+
return unless @scanner[0].length == 4 || @scanner[0].length == 7
|
364
|
+
script_color = Script::Value::Color.from_hex(scan(REGULAR_EXPRESSIONS[:color]))
|
324
365
|
[:color, script_color]
|
325
366
|
end
|
326
367
|
|
368
|
+
def selector
|
369
|
+
start_pos = source_position
|
370
|
+
return unless scan(REGULAR_EXPRESSIONS[:selector])
|
371
|
+
script_selector = Script::Tree::Selector.new
|
372
|
+
script_selector.source_range = range(start_pos)
|
373
|
+
[:selector, script_selector]
|
374
|
+
end
|
375
|
+
|
327
376
|
def special_fun
|
328
|
-
|
329
|
-
return unless
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
377
|
+
prefix = scan(/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
|
378
|
+
return unless prefix
|
379
|
+
special_fun_body(1, prefix)
|
380
|
+
end
|
381
|
+
|
382
|
+
def special_fun_body(parens, prefix = nil)
|
383
|
+
str = prefix || ''
|
384
|
+
while (scanned = scan(/.*?([()]|\#\{)/m))
|
385
|
+
str << scanned
|
386
|
+
if scanned[-1] == ?(
|
387
|
+
parens += 1
|
388
|
+
next
|
389
|
+
elsif scanned[-1] == ?)
|
390
|
+
parens -= 1
|
391
|
+
next unless parens == 0
|
392
|
+
else
|
393
|
+
raise "[BUG] Unreachable" unless @scanner[1] == '#{' # '
|
394
|
+
str.slice!(-2..-1)
|
395
|
+
@scanner.pos -= 2 # Don't actually consume the #{
|
396
|
+
@offset -= 2
|
397
|
+
@interpolation_stack << [:special_fun, parens]
|
398
|
+
end
|
399
|
+
|
400
|
+
return [:special_fun, Sass::Script::Value::String.new(str)]
|
401
|
+
end
|
402
|
+
|
403
|
+
scan(/.*/)
|
404
|
+
expected!('")"')
|
340
405
|
end
|
341
406
|
|
342
407
|
def special_val
|
@@ -368,7 +433,7 @@ MESSAGE
|
|
368
433
|
return unless str
|
369
434
|
c = str.count("\n")
|
370
435
|
@line += c
|
371
|
-
@offset = (c == 0 ? @offset + str.size : str.size - str.rindex("\n")
|
436
|
+
@offset = (c == 0 ? @offset + str.size : str.size - str.rindex("\n"))
|
372
437
|
str
|
373
438
|
end
|
374
439
|
|
data/lib/sass/script/parser.rb
CHANGED
@@ -36,13 +36,19 @@ module Sass
|
|
36
36
|
# which signals the end of an interpolated segment,
|
37
37
|
# it returns rather than throwing an error.
|
38
38
|
#
|
39
|
+
# @param warn_for_color [Boolean] Whether raw color values passed to
|
40
|
+
# interoplation should cause a warning.
|
39
41
|
# @return [Script::Tree::Node] The root node of the parse tree
|
40
42
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
41
|
-
def parse_interpolated
|
43
|
+
def parse_interpolated(warn_for_color = false)
|
44
|
+
# Start two characters back to compensate for #{
|
45
|
+
start_pos = Sass::Source::Position.new(line, offset - 2)
|
42
46
|
expr = assert_expr :expr
|
43
47
|
assert_tok :end_interpolation
|
48
|
+
expr = Sass::Script::Tree::Interpolation.new(
|
49
|
+
nil, expr, nil, !:wb, !:wa, !:originally_text, warn_for_color)
|
44
50
|
expr.options = @options
|
45
|
-
expr
|
51
|
+
node(expr, start_pos)
|
46
52
|
rescue Sass::SyntaxError => e
|
47
53
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
48
54
|
raise e
|
@@ -226,8 +232,8 @@ module Sass
|
|
226
232
|
return other_interp
|
227
233
|
end
|
228
234
|
|
229
|
-
|
230
|
-
|
235
|
+
e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type),
|
236
|
+
e.source_range.start_pos)
|
231
237
|
end
|
232
238
|
e
|
233
239
|
end
|
@@ -340,7 +346,8 @@ RUBY
|
|
340
346
|
e = first
|
341
347
|
while (interp = try_tok(:begin_interpolation))
|
342
348
|
wb = @lexer.whitespace?(interp)
|
343
|
-
mid =
|
349
|
+
mid = assert_expr :expr
|
350
|
+
assert_tok :end_interpolation
|
344
351
|
wa = @lexer.whitespace?
|
345
352
|
e = node(
|
346
353
|
Script::Tree::Interpolation.new(e, mid, space, wb, wa),
|
@@ -382,7 +389,7 @@ RUBY
|
|
382
389
|
|
383
390
|
name = @lexer.next
|
384
391
|
if (color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase])
|
385
|
-
literal_node(Sass::Script::Value::Color.new(color), name.source_range)
|
392
|
+
literal_node(Sass::Script::Value::Color.new(color, name.value), name.source_range)
|
386
393
|
elsif name.value == "true"
|
387
394
|
literal_node(Sass::Script::Value::Bool.new(true), name.source_range)
|
388
395
|
elsif name.value == "false"
|
@@ -487,22 +494,14 @@ RUBY
|
|
487
494
|
end
|
488
495
|
|
489
496
|
def special_fun
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
node(
|
499
|
-
Script::Tree::Interpolation.new(
|
500
|
-
l, i,
|
501
|
-
r && literal_node(Script::Value::String.new(r),
|
502
|
-
i.source_range.end_pos, end_pos),
|
503
|
-
false, false),
|
504
|
-
start_pos, end_pos)
|
505
|
-
end
|
497
|
+
first = try_tok(:special_fun)
|
498
|
+
return paren unless first
|
499
|
+
str = literal_node(first.value, first.source_range)
|
500
|
+
return str unless try_tok(:begin_interpolation)
|
501
|
+
mid = parse_interpolated
|
502
|
+
last = assert_expr(:special_fun)
|
503
|
+
node(Tree::Interpolation.new(str, mid, last, false, false),
|
504
|
+
first.source_range.start_pos)
|
506
505
|
end
|
507
506
|
|
508
507
|
def paren
|
@@ -530,7 +529,8 @@ RUBY
|
|
530
529
|
return number unless first
|
531
530
|
str = literal_node(first.value, first.source_range)
|
532
531
|
return str unless try_tok(:begin_interpolation)
|
533
|
-
mid =
|
532
|
+
mid = assert_expr :expr
|
533
|
+
assert_tok :end_interpolation
|
534
534
|
last = assert_expr(:string)
|
535
535
|
node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
|
536
536
|
end
|
@@ -563,6 +563,7 @@ RUBY
|
|
563
563
|
:mixin_arglist => "mixin argument",
|
564
564
|
:fn_arglist => "function argument",
|
565
565
|
:splat => "...",
|
566
|
+
:special_fun => '")"',
|
566
567
|
}
|
567
568
|
|
568
569
|
def assert_expr(name, expected = nil)
|
@@ -214,7 +214,7 @@ module Sass::Script::Tree
|
|
214
214
|
elsif deprecated_argname && keywords.has_key?(deprecated_argname)
|
215
215
|
deprecated_argname = keywords.denormalize(deprecated_argname)
|
216
216
|
Sass::Util.sass_warn("DEPRECATION WARNING: The `$#{deprecated_argname}' argument for " +
|
217
|
-
"`#{name}()' has been renamed to `$#{argname}'.")
|
217
|
+
"`#{@name}()' has been renamed to `$#{argname}'.")
|
218
218
|
keywords.delete(deprecated_argname)
|
219
219
|
else
|
220
220
|
raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}")
|
@@ -23,6 +23,10 @@ module Sass::Script::Tree
|
|
23
23
|
# SassScript.
|
24
24
|
attr_reader :originally_text
|
25
25
|
|
26
|
+
# @return [Boolean] Whether a color value passed to the interpolation should
|
27
|
+
# generate a warning.
|
28
|
+
attr_reader :warn_for_color
|
29
|
+
|
26
30
|
# Interpolation in a property is of the form `before #{mid} after`.
|
27
31
|
#
|
28
32
|
# @param before [Node] See {Interpolation#before}
|
@@ -31,9 +35,10 @@ module Sass::Script::Tree
|
|
31
35
|
# @param wb [Boolean] See {Interpolation#whitespace_before}
|
32
36
|
# @param wa [Boolean] See {Interpolation#whitespace_after}
|
33
37
|
# @param originally_text [Boolean] See {Interpolation#originally_text}
|
38
|
+
# @param warn_for_color [Boolean] See {Interpolation#warn_for_color}
|
34
39
|
# @comment
|
35
40
|
# rubocop:disable ParameterLists
|
36
|
-
def initialize(before, mid, after, wb, wa, originally_text = false)
|
41
|
+
def initialize(before, mid, after, wb, wa, originally_text = false, warn_for_color = false)
|
37
42
|
# rubocop:enable ParameterLists
|
38
43
|
@before = before
|
39
44
|
@mid = mid
|
@@ -41,6 +46,7 @@ module Sass::Script::Tree
|
|
41
46
|
@whitespace_before = wb
|
42
47
|
@whitespace_after = wa
|
43
48
|
@originally_text = originally_text
|
49
|
+
@warn_for_color = warn_for_color
|
44
50
|
end
|
45
51
|
|
46
52
|
# @return [String] A human-readable s-expression representation of the interpolation
|
@@ -90,8 +96,20 @@ module Sass::Script::Tree
|
|
90
96
|
res = ""
|
91
97
|
res << @before.perform(environment).to_s if @before
|
92
98
|
res << " " if @before && @whitespace_before
|
99
|
+
|
93
100
|
val = @mid.perform(environment)
|
94
|
-
|
101
|
+
if @warn_for_color && val.is_a?(Sass::Script::Value::Color) && val.name
|
102
|
+
alternative = Operation.new(Sass::Script::Value::String.new("", :string), @mid, :plus)
|
103
|
+
Sass::Util.sass_warn <<MESSAGE
|
104
|
+
WARNING on line #{line}, column #{source_range.start_pos.offset}#{" of #{filename}" if filename}:
|
105
|
+
You probably don't mean to use the color value `#{val}' in interpolation here.
|
106
|
+
It may end up represented as #{val.inspect}, which will likely produce invalid CSS.
|
107
|
+
Always quote color names when using them as strings (for example, "#{val}").
|
108
|
+
If you really want to use the color value here, use `#{alternative.to_sass}'.
|
109
|
+
MESSAGE
|
110
|
+
end
|
111
|
+
|
112
|
+
res << val.to_s(:quote => :none)
|
95
113
|
res << " " if @after && @whitespace_after
|
96
114
|
res << @after.perform(environment).to_s if @after
|
97
115
|
opts(Sass::Script::Value::String.new(res))
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Sass::Script::Tree
|
2
|
+
# A SassScript node that will resolve to the current selector.
|
3
|
+
class Selector < Node
|
4
|
+
def initialize; end
|
5
|
+
|
6
|
+
def children
|
7
|
+
[]
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_sass(opts = {})
|
11
|
+
'&'
|
12
|
+
end
|
13
|
+
|
14
|
+
def deep_copy
|
15
|
+
dup
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def _perform(environment)
|
21
|
+
selector = environment.selector
|
22
|
+
return opts(Sass::Script::Value::Null.new) unless selector
|
23
|
+
opts(selector.to_sass_script)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -81,7 +81,7 @@ module Sass::Script::Tree
|
|
81
81
|
before = @before.perform(environment)
|
82
82
|
res << before.value
|
83
83
|
mid = @mid.perform(environment)
|
84
|
-
res << (mid.is_a?(Sass::Script::Value::String) ? mid.value : mid.to_s)
|
84
|
+
res << (mid.is_a?(Sass::Script::Value::String) ? mid.value : mid.to_s(:quote => :none))
|
85
85
|
res << @after.perform(environment).value
|
86
86
|
opts(Sass::Script::Value::String.new(res, before.type))
|
87
87
|
end
|
data/lib/sass/script/tree.rb
CHANGED
@@ -20,7 +20,8 @@ module Sass::Script::Value
|
|
20
20
|
#
|
21
21
|
# @param value [Object] The object for \{#value}
|
22
22
|
def initialize(value = nil)
|
23
|
-
|
23
|
+
value.freeze unless value.nil? || value == true || value == false
|
24
|
+
@value = value
|
24
25
|
end
|
25
26
|
|
26
27
|
# Sets the options hash for this node,
|
@@ -95,10 +96,8 @@ MSG
|
|
95
96
|
# @return [Script::Value::String] A string containing both values
|
96
97
|
# without any separation
|
97
98
|
def plus(other)
|
98
|
-
|
99
|
-
|
100
|
-
end
|
101
|
-
Sass::Script::Value::String.new(to_s + other.to_s)
|
99
|
+
type = other.is_a?(Sass::Script::Value::String) ? other.type : :identifier
|
100
|
+
Sass::Script::Value::String.new(to_s(:quote => :none) + other.to_s(:quote => :none), type)
|
102
101
|
end
|
103
102
|
|
104
103
|
# The SassScript `-` operation.
|
@@ -212,6 +211,9 @@ MSG
|
|
212
211
|
# Returns the string representation of this value
|
213
212
|
# as it would be output to the CSS document.
|
214
213
|
#
|
214
|
+
# @options opts :quote [String]
|
215
|
+
# The preferred quote style for quoted strings. If `:none`, strings are
|
216
|
+
# always emitted unquoted.
|
215
217
|
# @return [String]
|
216
218
|
def to_s(opts = {})
|
217
219
|
Sass::Util.abstract(self)
|
@@ -151,6 +151,7 @@ module Sass::Script::Value
|
|
151
151
|
'powderblue' => 0xB0E0E6FF,
|
152
152
|
'purple' => 0x800080FF,
|
153
153
|
'red' => 0xFF0000FF,
|
154
|
+
'rebeccapurple' => 0x663399FF,
|
154
155
|
'rosybrown' => 0xBC8F8FFF,
|
155
156
|
'royalblue' => 0x4169E1FF,
|
156
157
|
'saddlebrown' => 0x8B4513FF,
|
@@ -187,35 +188,43 @@ module Sass::Script::Value
|
|
187
188
|
# different ruby implementations and versions vary on the ordering of the result of invert.
|
188
189
|
COLOR_NAMES.update(ALTERNATE_COLOR_NAMES).freeze
|
189
190
|
|
191
|
+
# The user's original representation of the color.
|
192
|
+
#
|
193
|
+
# @return [String]
|
194
|
+
attr_reader :representation
|
195
|
+
|
190
196
|
# Constructs an RGB or HSL color object,
|
191
197
|
# optionally with an alpha channel.
|
192
198
|
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
# The alpha value
|
199
|
+
# RGB values are clipped within 0 and 255.
|
200
|
+
# Saturation and lightness values are clipped within 0 and 100.
|
201
|
+
# The alpha value is clipped within 0 and 1.
|
196
202
|
#
|
197
203
|
# @raise [Sass::SyntaxError] if any color value isn't in the specified range
|
198
204
|
#
|
199
205
|
# @overload initialize(attrs)
|
200
|
-
# The attributes are specified as a hash.
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
206
|
+
# The attributes are specified as a hash. This hash must contain either
|
207
|
+
# `:hue`, `:saturation`, and `:value` keys, or `:red`, `:green`, and
|
208
|
+
# `:blue` keys. It cannot contain both HSL and RGB keys. It may also
|
209
|
+
# optionally contain an `:alpha` key, and a `:representation` key
|
210
|
+
# indicating the original representation of the color that the user wrote
|
211
|
+
# in their stylesheet.
|
205
212
|
#
|
206
213
|
# @param attrs [{Symbol => Numeric}] A hash of color attributes to values
|
207
214
|
# @raise [ArgumentError] if not enough attributes are specified,
|
208
215
|
# or both RGB and HSL attributes are specified
|
209
216
|
#
|
210
|
-
# @overload initialize(rgba)
|
217
|
+
# @overload initialize(rgba, [representation])
|
211
218
|
# The attributes are specified as an array.
|
212
219
|
# This overload only supports RGB or RGBA colors.
|
213
220
|
#
|
214
221
|
# @param rgba [Array<Numeric>] A three- or four-element array
|
215
222
|
# of the red, green, blue, and optionally alpha values (respectively)
|
216
223
|
# of the color
|
224
|
+
# @param representation [String] The original representation of the color
|
225
|
+
# that the user wrote in their stylesheet.
|
217
226
|
# @raise [ArgumentError] if not enough attributes are specified
|
218
|
-
def initialize(attrs, allow_both_rgb_and_hsl = false)
|
227
|
+
def initialize(attrs, representation = nil, allow_both_rgb_and_hsl = false)
|
219
228
|
super(nil)
|
220
229
|
|
221
230
|
if attrs.is_a?(Array)
|
@@ -226,6 +235,7 @@ module Sass::Script::Value
|
|
226
235
|
red, green, blue = attrs[0...3].map {|c| c.to_i}
|
227
236
|
@attrs = {:red => red, :green => green, :blue => blue}
|
228
237
|
@attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
|
238
|
+
@representation = representation
|
229
239
|
else
|
230
240
|
attrs = attrs.reject {|k, v| v.nil?}
|
231
241
|
hsl = [:hue, :saturation, :lightness] & attrs.keys
|
@@ -243,21 +253,20 @@ module Sass::Script::Value
|
|
243
253
|
@attrs = attrs
|
244
254
|
@attrs[:hue] %= 360 if @attrs[:hue]
|
245
255
|
@attrs[:alpha] ||= 1
|
256
|
+
@representation = @attrs.delete(:representation)
|
246
257
|
end
|
247
258
|
|
248
259
|
[:red, :green, :blue].each do |k|
|
249
260
|
next if @attrs[k].nil?
|
250
|
-
@attrs[k] = @attrs[k].to_i
|
251
|
-
Sass::Util.check_range("#{k.to_s.capitalize} value", 0..255, @attrs[k])
|
261
|
+
@attrs[k] = Sass::Util.restrict(@attrs[k].to_i, 0..255)
|
252
262
|
end
|
253
263
|
|
254
264
|
[:saturation, :lightness].each do |k|
|
255
265
|
next if @attrs[k].nil?
|
256
|
-
|
257
|
-
@attrs[k] = Sass::Util.check_range("#{k.to_s.capitalize}", 0..100, value, '%')
|
266
|
+
@attrs[k] = Sass::Util.restrict(@attrs[k], 0..100)
|
258
267
|
end
|
259
268
|
|
260
|
-
@attrs[:alpha] = Sass::Util.
|
269
|
+
@attrs[:alpha] = Sass::Util.restrict(@attrs[:alpha], 0..1)
|
261
270
|
end
|
262
271
|
|
263
272
|
# Create a new color from a valid CSS hex string.
|
@@ -273,7 +282,9 @@ module Sass::Script::Value
|
|
273
282
|
red = $1.ljust(2, $1).to_i(16)
|
274
283
|
green = $2.ljust(2, $2).to_i(16)
|
275
284
|
blue = $3.ljust(2, $3).to_i(16)
|
276
|
-
|
285
|
+
|
286
|
+
hex_string = '##{hex_string}' unless hex_string[0] == ?#
|
287
|
+
attrs = {:red => red, :green => green, :blue => blue, :representation => hex_string}
|
277
288
|
attrs[:alpha] = alpha if alpha
|
278
289
|
new(attrs)
|
279
290
|
end
|
@@ -428,7 +439,7 @@ module Sass::Script::Value
|
|
428
439
|
end
|
429
440
|
attrs[:alpha] ||= alpha
|
430
441
|
|
431
|
-
Color.new(attrs, :allow_both_rgb_and_hsl)
|
442
|
+
Color.new(attrs, nil, :allow_both_rgb_and_hsl)
|
432
443
|
end
|
433
444
|
|
434
445
|
# The SassScript `+` operation.
|
@@ -549,7 +560,8 @@ module Sass::Script::Value
|
|
549
560
|
# @return [String] The string representation
|
550
561
|
def to_s(opts = {})
|
551
562
|
return smallest if options[:style] == :compressed
|
552
|
-
return
|
563
|
+
return representation if representation
|
564
|
+
return name if name
|
553
565
|
alpha? ? rgba_str : hex_str
|
554
566
|
end
|
555
567
|
alias_method :to_sass, :to_s
|
@@ -561,13 +573,19 @@ module Sass::Script::Value
|
|
561
573
|
alpha? ? rgba_str : hex_str
|
562
574
|
end
|
563
575
|
|
576
|
+
# Returns the color's name, if it has one.
|
577
|
+
#
|
578
|
+
# @return [String, nil]
|
579
|
+
def name
|
580
|
+
COLOR_NAMES_REVERSE[rgba]
|
581
|
+
end
|
582
|
+
|
564
583
|
private
|
565
584
|
|
566
585
|
def smallest
|
567
586
|
small_explicit_str = alpha? ? rgba_str : hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
|
568
|
-
|
569
|
-
|
570
|
-
color
|
587
|
+
[representation, COLOR_NAMES_REVERSE[rgba], small_explicit_str].
|
588
|
+
compact.min_by {|str| str.size}
|
571
589
|
end
|
572
590
|
|
573
591
|
def rgba_str
|