sass 3.3.14 → 3.4.0.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +5 -5
- 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.rb +0 -5
- data/lib/sass/css.rb +1 -3
- data/lib/sass/engine.rb +28 -39
- data/lib/sass/environment.rb +13 -17
- data/lib/sass/error.rb +6 -9
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/exec/base.rb +187 -0
- data/lib/sass/exec/sass_convert.rb +264 -0
- data/lib/sass/exec/sass_scss.rb +419 -0
- data/lib/sass/features.rb +6 -0
- data/lib/sass/importers.rb +0 -1
- data/lib/sass/importers/base.rb +5 -1
- data/lib/sass/importers/filesystem.rb +4 -21
- data/lib/sass/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +32 -136
- data/lib/sass/script/css_lexer.rb +1 -1
- data/lib/sass/script/functions.rb +363 -39
- data/lib/sass/script/lexer.rb +68 -50
- data/lib/sass/script/parser.rb +29 -14
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/tree/funcall.rb +1 -1
- data/lib/sass/script/tree/interpolation.rb +19 -1
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +32 -12
- 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 +60 -14
- data/lib/sass/script/value/string.rb +53 -9
- data/lib/sass/scss/css_parser.rb +8 -2
- data/lib/sass/scss/parser.rb +175 -319
- data/lib/sass/scss/rx.rb +14 -5
- data/lib/sass/scss/static_parser.rb +298 -1
- data/lib/sass/selector.rb +56 -193
- data/lib/sass/selector/abstract_sequence.rb +28 -13
- data/lib/sass/selector/comma_sequence.rb +91 -12
- data/lib/sass/selector/pseudo.rb +256 -0
- data/lib/sass/selector/sequence.rb +99 -31
- data/lib/sass/selector/simple.rb +14 -25
- data/lib/sass/selector/simple_sequence.rb +101 -37
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/source/map.rb +23 -9
- data/lib/sass/stack.rb +0 -6
- data/lib/sass/supports.rb +1 -1
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/directive_node.rb +7 -1
- data/lib/sass/tree/error_node.rb +18 -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 +11 -6
- data/lib/sass/tree/visitors/check_nesting.rb +3 -4
- data/lib/sass/tree/visitors/convert.rb +8 -17
- data/lib/sass/tree/visitors/cssize.rb +12 -24
- data/lib/sass/tree/visitors/deep_copy.rb +5 -0
- data/lib/sass/tree/visitors/perform.rb +43 -28
- data/lib/sass/tree/visitors/set_options.rb +5 -0
- data/lib/sass/tree/visitors/to_css.rb +14 -13
- data/lib/sass/util.rb +94 -90
- data/test/sass/cache_test.rb +1 -1
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +5 -14
- data/test/sass/conversion_test.rb +47 -1
- data/test/sass/css2sass_test.rb +3 -3
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +128 -191
- data/test/sass/exec_test.rb +2 -2
- data/test/sass/extend_test.rb +234 -17
- data/test/sass/functions_test.rb +268 -213
- 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 +12 -11
- 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 +7 -4
- data/test/sass/script_test.rb +202 -79
- data/test/sass/scss/css_test.rb +95 -25
- data/test/sass/scss/rx_test.rb +4 -4
- data/test/sass/scss/scss_test.rb +363 -19
- data/test/sass/source_map_test.rb +48 -41
- 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 +1 -1
- data/test/sass/value_helpers_test.rb +3 -3
- data/test/test_helper.rb +2 -2
- metadata +30 -7
- data/lib/sass/importers/deprecated_path.rb +0 -51
- data/lib/sass/script/value/deprecated_false.rb +0 -55
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,19 +250,13 @@ module Sass
|
|
246
250
|
end
|
247
251
|
|
248
252
|
def token
|
249
|
-
if after_interpolation? && (
|
250
|
-
interp_type,
|
251
|
-
if interp_type == :special_fun
|
252
|
-
return special_fun_body(interp_value)
|
253
|
-
else
|
254
|
-
raise "[BUG]: Unknown interp_type #{interp_type}" unless interp_type == :string
|
255
|
-
return string(interp_value, true)
|
256
|
-
end
|
253
|
+
if after_interpolation? && (interp_type = @interpolation_stack.pop)
|
254
|
+
return string(interp_type, true)
|
257
255
|
end
|
258
256
|
|
259
|
-
variable || string(:double, false) || string(:single, false) || number || color ||
|
260
|
-
string(:uri, false) || raw(UNICODERANGE) || special_fun || special_val ||
|
261
|
-
ident || op
|
257
|
+
variable || string(:double, false) || string(:single, false) || number || id || color ||
|
258
|
+
selector || string(:uri, false) || raw(UNICODERANGE) || special_fun || special_val ||
|
259
|
+
ident_op || ident || op
|
262
260
|
end
|
263
261
|
|
264
262
|
def variable
|
@@ -277,18 +275,27 @@ module Sass
|
|
277
275
|
end
|
278
276
|
|
279
277
|
def string(re, open)
|
278
|
+
line, offset = @line, @offset
|
280
279
|
return unless scan(STRING_REGULAR_EXPRESSIONS[re][open])
|
280
|
+
if @scanner[0] =~ /([^\\]|^)\n/
|
281
|
+
Sass::Util.sass_warn <<MESSAGE
|
282
|
+
DEPRECATION WARNING on line #{line}, column #{offset}#{" of #{@filename}" if @filename}:
|
283
|
+
Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
|
284
|
+
To include a newline in a string, use "\\a" or "\\a " as in CSS.
|
285
|
+
MESSAGE
|
286
|
+
end
|
287
|
+
|
281
288
|
if @scanner[2] == '#{' # '
|
282
289
|
@scanner.pos -= 2 # Don't actually consume the #{
|
283
290
|
@offset -= 2
|
284
|
-
@interpolation_stack <<
|
291
|
+
@interpolation_stack << re
|
285
292
|
end
|
286
293
|
str =
|
287
294
|
if re == :uri
|
288
295
|
url = "#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}"
|
289
296
|
Script::Value::String.new(url)
|
290
297
|
else
|
291
|
-
Script::Value::String.new(@scanner[1]
|
298
|
+
Script::Value::String.new(Sass::Script::Value::String.value(@scanner[1]), :string)
|
292
299
|
end
|
293
300
|
[:string, str]
|
294
301
|
end
|
@@ -318,49 +325,60 @@ module Sass
|
|
318
325
|
end
|
319
326
|
|
320
327
|
value = (@scanner[1] ? @scanner[1].to_f : @scanner[2].to_i) * (minus ? -1 : 1)
|
321
|
-
|
328
|
+
value *= 10**@scanner[3].to_i if @scanner[3]
|
329
|
+
script_number = Script::Value::Number.new(value, Array(@scanner[4]))
|
322
330
|
[:number, script_number]
|
323
331
|
end
|
324
332
|
|
333
|
+
def id
|
334
|
+
# Colors and ids are tough to tell apart, because they overlap but
|
335
|
+
# neither is a superset of the other. "#xyz" is an id but not a color,
|
336
|
+
# "#000" is a color but not an id, "#abc" is both, and "#0" is neither.
|
337
|
+
# We need to handle all these cases correctly.
|
338
|
+
#
|
339
|
+
# To do so, we first try to parse something as an id. If this works and
|
340
|
+
# the id is also a valid color, we return the color. Otherwise, we
|
341
|
+
# return the id. If it didn't parse as an id, we then try to parse it as
|
342
|
+
# a color. If *this* works, we return the color, and if it doesn't we
|
343
|
+
# give up and throw an error.
|
344
|
+
#
|
345
|
+
# IDs in properties are used in the Basic User Interface Module
|
346
|
+
# (http://www.w3.org/TR/css3-ui/).
|
347
|
+
return unless scan(REGULAR_EXPRESSIONS[:id])
|
348
|
+
if @scanner[0] =~ /^\#[0-9a-fA-F]+$/ && (@scanner[0].length == 4 || @scanner[0].length == 7)
|
349
|
+
return [:color, Script::Value::Color.from_hex(@scanner[0])]
|
350
|
+
end
|
351
|
+
[:ident, @scanner[0]]
|
352
|
+
end
|
353
|
+
|
325
354
|
def color
|
326
|
-
|
327
|
-
return unless
|
328
|
-
|
329
|
-
Colors must have either three or six digits: '#{s}'
|
330
|
-
MESSAGE
|
331
|
-
script_color = Script::Value::Color.from_hex(s)
|
355
|
+
return unless @scanner.match?(REGULAR_EXPRESSIONS[:color])
|
356
|
+
return unless @scanner[0].length == 4 || @scanner[0].length == 7
|
357
|
+
script_color = Script::Value::Color.from_hex(scan(REGULAR_EXPRESSIONS[:color]))
|
332
358
|
[:color, script_color]
|
333
359
|
end
|
334
360
|
|
335
|
-
def
|
336
|
-
|
337
|
-
return unless
|
338
|
-
|
361
|
+
def selector
|
362
|
+
start_pos = source_position
|
363
|
+
return unless scan(REGULAR_EXPRESSIONS[:selector])
|
364
|
+
script_selector = Script::Tree::Selector.new
|
365
|
+
script_selector.source_range = range(start_pos)
|
366
|
+
[:selector, script_selector]
|
339
367
|
end
|
340
368
|
|
341
|
-
def
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
@scanner.pos -= 2 # Don't actually consume the #{
|
355
|
-
@offset -= 2
|
356
|
-
@interpolation_stack << [:special_fun, parens]
|
357
|
-
end
|
358
|
-
|
359
|
-
return [:special_fun, Sass::Script::Value::String.new(str)]
|
360
|
-
end
|
361
|
-
|
362
|
-
scan(/.*/)
|
363
|
-
expected!('")"')
|
369
|
+
def special_fun
|
370
|
+
str1 = scan(/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
|
371
|
+
return unless str1
|
372
|
+
str2, _ = Sass::Shared.balance(@scanner, ?(, ?), 1)
|
373
|
+
c = str2.count("\n")
|
374
|
+
old_line = @line
|
375
|
+
old_offset = @offset
|
376
|
+
@line += c
|
377
|
+
@offset = c == 0 ? @offset + str2.size : str2[/\n([^\n]*)/, 1].size + 1
|
378
|
+
[:special_fun,
|
379
|
+
Sass::Util.merge_adjacent_strings(
|
380
|
+
[str1] + Sass::Engine.parse_interp(str2, old_line, old_offset, @options)),
|
381
|
+
str1.size + str2.size]
|
364
382
|
end
|
365
383
|
|
366
384
|
def special_val
|
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
|
@@ -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,14 +494,22 @@ RUBY
|
|
487
494
|
end
|
488
495
|
|
489
496
|
def special_fun
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
497
|
+
start_pos = source_position
|
498
|
+
tok = try_tok(:special_fun)
|
499
|
+
return paren unless tok
|
500
|
+
first = literal_node(Script::Value::String.new(tok.value.first),
|
501
|
+
start_pos, start_pos.after(tok.value.first))
|
502
|
+
Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
|
503
|
+
end_pos = i.source_range.end_pos
|
504
|
+
end_pos = end_pos.after(r) if r
|
505
|
+
node(
|
506
|
+
Script::Tree::Interpolation.new(
|
507
|
+
l, i,
|
508
|
+
r && literal_node(Script::Value::String.new(r),
|
509
|
+
i.source_range.end_pos, end_pos),
|
510
|
+
false, false),
|
511
|
+
start_pos, end_pos)
|
512
|
+
end
|
498
513
|
end
|
499
514
|
|
500
515
|
def paren
|
@@ -522,7 +537,8 @@ RUBY
|
|
522
537
|
return number unless first
|
523
538
|
str = literal_node(first.value, first.source_range)
|
524
539
|
return str unless try_tok(:begin_interpolation)
|
525
|
-
mid =
|
540
|
+
mid = assert_expr :expr
|
541
|
+
assert_tok :end_interpolation
|
526
542
|
last = assert_expr(:string)
|
527
543
|
node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
|
528
544
|
end
|
@@ -555,7 +571,6 @@ RUBY
|
|
555
571
|
:mixin_arglist => "mixin argument",
|
556
572
|
:fn_arglist => "function argument",
|
557
573
|
:splat => "...",
|
558
|
-
:special_fun => '")"',
|
559
574
|
}
|
560
575
|
|
561
576
|
def assert_expr(name, expected = nil)
|
data/lib/sass/script/tree.rb
CHANGED
@@ -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,7 +96,19 @@ 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)
|
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
|
+
|
94
112
|
res << (val.is_a?(Sass::Script::Value::String) ? val.value : val.to_s)
|
95
113
|
res << " " if @after && @whitespace_after
|
96
114
|
res << @after.perform(environment).to_s if @after
|
@@ -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
|
data/lib/sass/script/value.rb
CHANGED
@@ -5,7 +5,6 @@ require 'sass/script/value/string'
|
|
5
5
|
require 'sass/script/value/number'
|
6
6
|
require 'sass/script/value/color'
|
7
7
|
require 'sass/script/value/bool'
|
8
|
-
require 'sass/script/value/deprecated_false'
|
9
8
|
require 'sass/script/value/null'
|
10
9
|
require 'sass/script/value/list'
|
11
10
|
require 'sass/script/value/arg_list'
|
@@ -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,6 +188,11 @@ 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
|
#
|
@@ -197,25 +203,28 @@ module Sass::Script::Value
|
|
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,6 +253,7 @@ 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|
|
@@ -273,7 +284,9 @@ module Sass::Script::Value
|
|
273
284
|
red = $1.ljust(2, $1).to_i(16)
|
274
285
|
green = $2.ljust(2, $2).to_i(16)
|
275
286
|
blue = $3.ljust(2, $3).to_i(16)
|
276
|
-
|
287
|
+
|
288
|
+
hex_string = '##{hex_string}' unless hex_string[0] == ?#
|
289
|
+
attrs = {:red => red, :green => green, :blue => blue, :representation => hex_string}
|
277
290
|
attrs[:alpha] = alpha if alpha
|
278
291
|
new(attrs)
|
279
292
|
end
|
@@ -549,7 +562,8 @@ module Sass::Script::Value
|
|
549
562
|
# @return [String] The string representation
|
550
563
|
def to_s(opts = {})
|
551
564
|
return smallest if options[:style] == :compressed
|
552
|
-
return
|
565
|
+
return representation if representation
|
566
|
+
return name if name
|
553
567
|
alpha? ? rgba_str : hex_str
|
554
568
|
end
|
555
569
|
alias_method :to_sass, :to_s
|
@@ -561,13 +575,19 @@ module Sass::Script::Value
|
|
561
575
|
alpha? ? rgba_str : hex_str
|
562
576
|
end
|
563
577
|
|
578
|
+
# Returns the color's name, if it has one.
|
579
|
+
#
|
580
|
+
# @return [String, nil]
|
581
|
+
def name
|
582
|
+
COLOR_NAMES_REVERSE[rgba]
|
583
|
+
end
|
584
|
+
|
564
585
|
private
|
565
586
|
|
566
587
|
def smallest
|
567
588
|
small_explicit_str = alpha? ? rgba_str : hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
|
568
|
-
|
569
|
-
|
570
|
-
color
|
589
|
+
[representation, COLOR_NAMES_REVERSE[rgba], small_explicit_str].
|
590
|
+
compact.min_by {|str| str.size}
|
571
591
|
end
|
572
592
|
|
573
593
|
def rgba_str
|