sass 3.3.14 → 3.4.0.rc.1
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 +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
|