sass 3.1.8 → 3.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/sass/engine.rb +26 -10
- data/lib/sass/less.rb +1 -1
- data/lib/sass/scss/parser.rb +28 -8
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/tree/comment_node.rb +24 -11
- data/lib/sass/tree/visitors/convert.rb +10 -5
- data/lib/sass/tree/visitors/perform.rb +36 -8
- data/lib/sass/tree/visitors/to_css.rb +2 -12
- data/lib/sass/util.rb +51 -0
- data/test/sass/conversion_test.rb +2 -6
- data/test/sass/engine_test.rb +38 -5
- data/test/sass/scss/css_test.rb +6 -0
- data/test/sass/util_test.rb +12 -0
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.9
|
data/lib/sass/engine.rb
CHANGED
@@ -90,7 +90,10 @@ module Sass
|
|
90
90
|
#
|
91
91
|
# `children`: `Array<Line>`
|
92
92
|
# : The lines nested below this one.
|
93
|
-
|
93
|
+
#
|
94
|
+
# `comment_tab_str`: `String?`
|
95
|
+
# : The prefix indentation for this comment, if it is a comment.
|
96
|
+
class Line < Struct.new(:text, :tabs, :index, :offset, :filename, :children, :comment_tab_str)
|
94
97
|
def comment?
|
95
98
|
text[0] == COMMENT_CHAR && (text[1] == SASS_COMMENT_CHAR || text[1] == CSS_COMMENT_CHAR)
|
96
99
|
end
|
@@ -107,6 +110,10 @@ module Sass
|
|
107
110
|
# which is not output as a CSS comment.
|
108
111
|
SASS_COMMENT_CHAR = ?/
|
109
112
|
|
113
|
+
# The character that indicates that a comment allows interpolation
|
114
|
+
# and should be preserved even in `:compressed` mode.
|
115
|
+
SASS_LOUD_COMMENT_CHAR = ?!
|
116
|
+
|
110
117
|
# The character that follows the general COMMENT_CHAR and designates a CSS comment,
|
111
118
|
# which is embedded in the CSS document.
|
112
119
|
CSS_COMMENT_CHAR = ?*
|
@@ -420,7 +427,8 @@ but this line was indented by #{Sass::Shared.human_indentation line[/^\s*/]}.
|
|
420
427
|
MSG
|
421
428
|
end
|
422
429
|
|
423
|
-
last.
|
430
|
+
last.comment_tab_str ||= comment_tab_str
|
431
|
+
last.text << "\n" << line
|
424
432
|
true
|
425
433
|
end
|
426
434
|
|
@@ -486,8 +494,8 @@ MSG
|
|
486
494
|
if child.is_a?(Tree::CommentNode) && child.silent
|
487
495
|
if continued_comment &&
|
488
496
|
child.line == continued_comment.line +
|
489
|
-
continued_comment.
|
490
|
-
continued_comment.value
|
497
|
+
continued_comment.lines + 1
|
498
|
+
continued_comment.value += ["\n"] + child.value
|
491
499
|
next
|
492
500
|
end
|
493
501
|
|
@@ -538,7 +546,7 @@ WARNING
|
|
538
546
|
when ?$
|
539
547
|
parse_variable(line)
|
540
548
|
when COMMENT_CHAR
|
541
|
-
parse_comment(line
|
549
|
+
parse_comment(line)
|
542
550
|
when DIRECTIVE_CHAR
|
543
551
|
parse_directive(parent, line, root)
|
544
552
|
when ESCAPE_CHAR
|
@@ -600,11 +608,19 @@ WARNING
|
|
600
608
|
end
|
601
609
|
|
602
610
|
def parse_comment(line)
|
603
|
-
if line[1] == CSS_COMMENT_CHAR || line[1] == SASS_COMMENT_CHAR
|
604
|
-
silent = line[1] == SASS_COMMENT_CHAR
|
605
|
-
|
606
|
-
|
607
|
-
|
611
|
+
if line.text[1] == CSS_COMMENT_CHAR || line.text[1] == SASS_COMMENT_CHAR
|
612
|
+
silent = line.text[1] == SASS_COMMENT_CHAR
|
613
|
+
if loud = line.text[2] == SASS_LOUD_COMMENT_CHAR
|
614
|
+
value = self.class.parse_interp(line.text, line.index, line.offset, :filename => @filename)
|
615
|
+
value[0].slice!(2) # get rid of the "!"
|
616
|
+
else
|
617
|
+
value = [line.text]
|
618
|
+
end
|
619
|
+
value = with_extracted_values(value) do |str|
|
620
|
+
str = str.gsub(/^#{line.comment_tab_str}/m, '')[2..-1] # get rid of // or /*
|
621
|
+
format_comment_text(str, silent)
|
622
|
+
end
|
623
|
+
Tree::CommentNode.new(value, silent, loud)
|
608
624
|
else
|
609
625
|
Tree::RuleNode.new(parse_interp(line))
|
610
626
|
end
|
data/lib/sass/less.rb
CHANGED
@@ -31,7 +31,7 @@ module Less
|
|
31
31
|
WARNING: Sass doesn't support mixing in selector sequences.
|
32
32
|
Replacing "#{sel}" with "@extend #{base}"
|
33
33
|
WARNING
|
34
|
-
env << Node::SassNode.new(Sass::Tree::CommentNode.new("// #{sel};", true))
|
34
|
+
env << Node::SassNode.new(Sass::Tree::CommentNode.new(["// #{sel};"], true, false))
|
35
35
|
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
|
36
36
|
end
|
37
37
|
end
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -89,14 +89,28 @@ module Sass
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def process_comment(text, node)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
92
|
+
silent = text =~ /^\/\//
|
93
|
+
line = @line - text.count("\n")
|
94
|
+
if loud = text =~ %r{^/[/*]!}
|
95
|
+
value = Sass::Engine.parse_interp(text, line, @scanner.pos - text.size, :filename => @filename)
|
96
|
+
value[0].slice!(2) # get rid of the "!"
|
97
|
+
else
|
98
|
+
value = [text]
|
99
|
+
end
|
100
|
+
|
101
|
+
if silent
|
102
|
+
value = Sass::Util.with_extracted_values(value) do |str|
|
103
|
+
str.sub(/^\s*\/\//, '/*').gsub(/^\s*\/\//, ' *') + ' */'
|
104
|
+
end
|
105
|
+
else
|
106
|
+
value.unshift(@scanner.
|
107
|
+
string[0...@scanner.pos].
|
108
|
+
reverse[/.*?\*\/(.*?)($|\Z)/, 1].
|
109
|
+
reverse.gsub(/[^\s]/, ' '))
|
110
|
+
end
|
111
|
+
|
112
|
+
comment = Sass::Tree::CommentNode.new(value, silent, loud)
|
113
|
+
comment.line = line
|
100
114
|
node << comment
|
101
115
|
end
|
102
116
|
|
@@ -777,8 +791,14 @@ MESSAGE
|
|
777
791
|
end
|
778
792
|
|
779
793
|
def str?
|
794
|
+
pos = @scanner.pos
|
795
|
+
line = @line
|
780
796
|
@strs.push ""
|
781
797
|
yield && @strs.last
|
798
|
+
rescue Sass::SyntaxError => e
|
799
|
+
@scanner.pos = pos
|
800
|
+
@line = line
|
801
|
+
nil
|
782
802
|
ensure
|
783
803
|
@strs.pop
|
784
804
|
end
|
data/lib/sass/shared.rb
CHANGED
@@ -17,7 +17,7 @@ module Sass
|
|
17
17
|
# @return [String] The text remaining in the scanner after all `#{`s have been processed
|
18
18
|
def handle_interpolation(str)
|
19
19
|
scan = StringScanner.new(str)
|
20
|
-
yield scan while scan.scan(/(.*?)(\\*)\#\{/)
|
20
|
+
yield scan while scan.scan(/(.*?)(\\*)\#\{/m)
|
21
21
|
scan.rest
|
22
22
|
end
|
23
23
|
|
@@ -6,10 +6,19 @@ module Sass::Tree
|
|
6
6
|
# @see Sass::Tree
|
7
7
|
class CommentNode < Node
|
8
8
|
# The text of the comment, not including `/*` and `*/`.
|
9
|
+
# Interspersed with {Sass::Script::Node}s representing `#{}`-interpolation
|
10
|
+
# if this is a loud comment.
|
9
11
|
#
|
10
|
-
# @return [String]
|
12
|
+
# @return [Array<String, Sass::Script::Node>]
|
11
13
|
attr_accessor :value
|
12
14
|
|
15
|
+
# The text of the comment
|
16
|
+
# after any interpolated SassScript has been resolved.
|
17
|
+
# Only set once \{Tree::Visitors::Perform} has been run.
|
18
|
+
#
|
19
|
+
# @return [String]
|
20
|
+
attr_accessor :resolved_value
|
21
|
+
|
13
22
|
# Whether the comment is loud.
|
14
23
|
#
|
15
24
|
# Loud comments start with ! and force the comment to be generated
|
@@ -23,14 +32,13 @@ module Sass::Tree
|
|
23
32
|
# @return [Boolean]
|
24
33
|
attr_accessor :silent
|
25
34
|
|
26
|
-
# @param value [String] See \{#value}
|
35
|
+
# @param value [Array<String, Sass::Script::Node>] See \{#value}
|
27
36
|
# @param silent [Boolean] See \{#silent}
|
28
|
-
|
29
|
-
|
37
|
+
# @param loud [Boolean] See \{#loud}
|
38
|
+
def initialize(value, silent, loud)
|
39
|
+
@value = Sass::Util.with_extracted_values(value) {|str| normalize_indentation str}
|
30
40
|
@silent = silent
|
31
|
-
@
|
32
|
-
@loud = @value =~ %r{^(/[\/\*])?!}
|
33
|
-
@value.sub!("#{$1}!", $1.to_s) if @loud
|
41
|
+
@loud = loud
|
34
42
|
super()
|
35
43
|
end
|
36
44
|
|
@@ -40,7 +48,7 @@ module Sass::Tree
|
|
40
48
|
# @return [Boolean] Whether or not this node and the other object
|
41
49
|
# are the same
|
42
50
|
def ==(other)
|
43
|
-
self.class == other.class && value == other.value && silent == other.silent
|
51
|
+
self.class == other.class && value == other.value && silent == other.silent && loud == other.loud
|
44
52
|
end
|
45
53
|
|
46
54
|
# Returns `true` if this is a silent comment
|
@@ -57,9 +65,14 @@ module Sass::Tree
|
|
57
65
|
end
|
58
66
|
end
|
59
67
|
|
60
|
-
# Returns
|
61
|
-
|
62
|
-
|
68
|
+
# Returns the number of lines in the comment.
|
69
|
+
#
|
70
|
+
# @return [Fixnum]
|
71
|
+
def lines
|
72
|
+
@value.inject(0) do |s, e|
|
73
|
+
next s + e.count("\n") if e.is_a?(String)
|
74
|
+
next s
|
75
|
+
end
|
63
76
|
end
|
64
77
|
|
65
78
|
private
|
@@ -32,7 +32,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
32
32
|
visit(child) +
|
33
33
|
if nxt &&
|
34
34
|
(child.is_a?(Sass::Tree::CommentNode) &&
|
35
|
-
child.line + child.
|
35
|
+
child.line + child.lines + 1 == nxt.line) ||
|
36
36
|
(child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
|
37
37
|
child.line + 1 == nxt.line) ||
|
38
38
|
(child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
|
@@ -49,8 +49,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def visit_comment(node)
|
52
|
+
value = node.value.map do |r|
|
53
|
+
next r if r.is_a?(String)
|
54
|
+
"\#{#{r.to_sass(@options)}}"
|
55
|
+
end.join
|
56
|
+
|
52
57
|
content = if @format == :sass
|
53
|
-
content =
|
58
|
+
content = value.gsub(/\*\/$/, '').rstrip
|
54
59
|
if content =~ /\A[ \t]/
|
55
60
|
# Re-indent SCSS comments like this:
|
56
61
|
# /* foo
|
@@ -78,11 +83,11 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
78
83
|
content.gsub!(/^/, tab_str)
|
79
84
|
content.rstrip + "\n"
|
80
85
|
else
|
81
|
-
spaces = (' ' * [@tabs -
|
86
|
+
spaces = (' ' * [@tabs - value[/^ */].size, 0].max)
|
82
87
|
content = if node.silent
|
83
|
-
|
88
|
+
value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
|
84
89
|
else
|
85
|
-
|
90
|
+
value
|
86
91
|
end.gsub(/^/, spaces) + "\n"
|
87
92
|
content
|
88
93
|
end
|
@@ -53,12 +53,10 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
53
53
|
# Removes this node from the tree if it's a silent comment.
|
54
54
|
def visit_comment(node)
|
55
55
|
return [] if node.invisible?
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
node.value = run_interp([Sass::Script::String.new(node.value)])
|
61
|
-
end
|
56
|
+
check_for_loud_silent_comment node
|
57
|
+
check_for_comment_interp node
|
58
|
+
node.resolved_value = run_interp_no_strip(node.value)
|
59
|
+
node.resolved_value.gsub!(/\\([\\#])/, '\1')
|
62
60
|
node
|
63
61
|
end
|
64
62
|
|
@@ -278,14 +276,18 @@ END
|
|
278
276
|
|
279
277
|
private
|
280
278
|
|
281
|
-
def
|
279
|
+
def run_interp_no_strip(text)
|
282
280
|
text.map do |r|
|
283
281
|
next r if r.is_a?(String)
|
284
282
|
val = r.perform(@environment)
|
285
283
|
# Interpolated strings should never render with quotes
|
286
284
|
next val.value if val.is_a?(Sass::Script::String)
|
287
285
|
val.to_s
|
288
|
-
end.join
|
286
|
+
end.join
|
287
|
+
end
|
288
|
+
|
289
|
+
def run_interp(text)
|
290
|
+
run_interp_no_strip(text).strip
|
289
291
|
end
|
290
292
|
|
291
293
|
def handle_include_loop!(node)
|
@@ -301,4 +303,30 @@ END
|
|
301
303
|
end.join("\n")
|
302
304
|
raise Sass::SyntaxError.new(msg)
|
303
305
|
end
|
306
|
+
|
307
|
+
def check_for_loud_silent_comment(node)
|
308
|
+
return unless node.loud && node.silent
|
309
|
+
Sass::Util.sass_warn <<MESSAGE
|
310
|
+
WARNING:
|
311
|
+
On line #{node.line}#{" of '#{node.filename}'" if node.filename}
|
312
|
+
`//` comments will no longer be allowed to use the `!` flag in Sass 3.2.
|
313
|
+
Please change to `/*` comments.
|
314
|
+
MESSAGE
|
315
|
+
end
|
316
|
+
|
317
|
+
def check_for_comment_interp(node)
|
318
|
+
return if node.loud
|
319
|
+
node.value.each do |e|
|
320
|
+
next unless e.is_a?(String)
|
321
|
+
e.scan(/(\\*)#\{/) do |esc|
|
322
|
+
Sass::Util.sass_warn <<MESSAGE if esc.first.size.even?
|
323
|
+
WARNING:
|
324
|
+
On line #{node.line}#{" of '#{node.filename}'" if node.filename}
|
325
|
+
Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
|
326
|
+
Please escape the interpolation by adding a backslash before the `#`.
|
327
|
+
MESSAGE
|
328
|
+
return
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
304
332
|
end
|
@@ -57,21 +57,11 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
|
|
57
57
|
|
58
58
|
def visit_comment(node)
|
59
59
|
return if node.invisible?
|
60
|
-
spaces = (' ' * [@tabs - node.
|
60
|
+
spaces = (' ' * [@tabs - node.resolved_value[/^ */].size, 0].max)
|
61
61
|
|
62
|
-
content = node.
|
62
|
+
content = node.resolved_value.gsub(/^/, spaces).gsub(%r{^(\s*)//(.*)$}) do |md|
|
63
63
|
"#{$1}/*#{$2} */"
|
64
64
|
end
|
65
|
-
if content =~ /[^\\]\#\{.*\}/
|
66
|
-
Sass::Util.sass_warn <<MESSAGE
|
67
|
-
WARNING:
|
68
|
-
On line #{node.line}#{" of '#{node.filename}'" if node.filename}
|
69
|
-
Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
|
70
|
-
Please escape the interpolation by adding a backslash before the hash sign.
|
71
|
-
MESSAGE
|
72
|
-
elsif content =~ /\\\#\{.*\}/
|
73
|
-
content.gsub!(/\\(\#\{.*\})/, '\1')
|
74
|
-
end
|
75
65
|
content.gsub!(/\n +(\* *(?!\/))?/, ' ') if (node.style == :compact || node.style == :compressed) && !node.loud
|
76
66
|
content
|
77
67
|
end
|
data/lib/sass/util.rb
CHANGED
@@ -612,6 +612,57 @@ MSG
|
|
612
612
|
'"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
|
613
613
|
end
|
614
614
|
|
615
|
+
# Extracts the non-string vlaues from an array containing both strings and non-strings.
|
616
|
+
# These values are replaced with escape sequences.
|
617
|
+
# This can be undone using \{#inject\_values}.
|
618
|
+
#
|
619
|
+
# This is useful e.g. when we want to do string manipulation
|
620
|
+
# on an interpolated string.
|
621
|
+
#
|
622
|
+
# The precise format of the resulting string is not guaranteed.
|
623
|
+
# However, it is guaranteed that newlines and whitespace won't be affected.
|
624
|
+
#
|
625
|
+
# @param arr [Array] The array from which values are extracted.
|
626
|
+
# @return [(String, Array)] The resulting string, and an array of extracted values.
|
627
|
+
def extract_values(arr)
|
628
|
+
values = []
|
629
|
+
return arr.map do |e|
|
630
|
+
next e.gsub('{', '{{') if e.is_a?(String)
|
631
|
+
values << e
|
632
|
+
next "{#{values.count - 1}}"
|
633
|
+
end.join, values
|
634
|
+
end
|
635
|
+
|
636
|
+
# Undoes \{#extract\_values} by transforming a string with escape sequences
|
637
|
+
# into an array of strings and non-string values.
|
638
|
+
#
|
639
|
+
# @param str [String] The string with escape sequences.
|
640
|
+
# @param values [Array] The array of values to inject.
|
641
|
+
# @return [Array] The array of strings and values.
|
642
|
+
def inject_values(str, values)
|
643
|
+
return [str.gsub('{{', '{')] if values.empty?
|
644
|
+
# Add an extra { so that we process the tail end of the string
|
645
|
+
result = (str + '{{').scan(/(.*?)(?:(\{\{)|\{(\d+)\})/m).map do |(pre, esc, n)|
|
646
|
+
[pre, esc ? '{' : '', n ? values[n.to_i] : '']
|
647
|
+
end.flatten(1)
|
648
|
+
result[-2] = '' # Get rid of the extra {
|
649
|
+
merge_adjacent_strings(result).reject {|s| s == ''}
|
650
|
+
end
|
651
|
+
|
652
|
+
# Allows modifications to be performed on the string form
|
653
|
+
# of an array containing both strings and non-strings.
|
654
|
+
#
|
655
|
+
# @param arr [Array] The array from which values are extracted.
|
656
|
+
# @yield [str] A block in which string manipulation can be done to the array.
|
657
|
+
# @yieldparam str [String] The string form of `arr`.
|
658
|
+
# @yieldreturn [String] The modified string.
|
659
|
+
# @return [Array] The modified, interpolated array.
|
660
|
+
def with_extracted_values(arr)
|
661
|
+
str, vals = extract_values(arr)
|
662
|
+
str = yield str
|
663
|
+
inject_values(str, vals)
|
664
|
+
end
|
665
|
+
|
615
666
|
## Static Method Stuff
|
616
667
|
|
617
668
|
# The context in which the ERB for \{#def\_static\_method} will be run.
|
@@ -1131,17 +1131,13 @@ div
|
|
1131
1131
|
SASS
|
1132
1132
|
end
|
1133
1133
|
|
1134
|
-
|
1134
|
+
def test_loud_comment_conversion
|
1135
1135
|
assert_renders(<<SASS, <<SCSS)
|
1136
1136
|
/*! \#{"interpolated"}
|
1137
|
-
/*!
|
1138
|
-
* \#{"also interpolated"}
|
1139
1137
|
SASS
|
1140
1138
|
/*! \#{"interpolated"} */
|
1141
|
-
/*!
|
1142
|
-
* \#{"also interpolated"} */
|
1143
1139
|
SCSS
|
1144
|
-
assert_renders(<<SASS, <<SCSS)
|
1140
|
+
silence_warnings {assert_renders(<<SASS, <<SCSS)}
|
1145
1141
|
//! \#{"interpolated"}
|
1146
1142
|
//!
|
1147
1143
|
//! \#{"also interpolated"}
|
data/test/sass/engine_test.rb
CHANGED
@@ -1570,11 +1570,11 @@ foo
|
|
1570
1570
|
*/
|
1571
1571
|
SASS
|
1572
1572
|
end
|
1573
|
+
|
1573
1574
|
def test_loud_comment_in_silent_comment
|
1574
|
-
assert_equal <<CSS, render(<<SASS, :style => :compressed)
|
1575
|
+
silence_warnings {assert_equal <<CSS, render(<<SASS, :style => :compressed)}
|
1575
1576
|
foo{color:blue;/* foo */
|
1576
1577
|
/* bar */
|
1577
|
-
/* */
|
1578
1578
|
/* bip */
|
1579
1579
|
/* baz */}
|
1580
1580
|
CSS
|
@@ -1590,8 +1590,7 @@ SASS
|
|
1590
1590
|
|
1591
1591
|
def test_loud_comment_is_evaluated
|
1592
1592
|
assert_equal <<CSS, render(<<SASS)
|
1593
|
-
/*
|
1594
|
-
* Hue: 327.216deg */
|
1593
|
+
/* Hue: 327.216deg */
|
1595
1594
|
CSS
|
1596
1595
|
/*!
|
1597
1596
|
Hue: \#{hue(#f836a0)}
|
@@ -2030,6 +2029,31 @@ CSS
|
|
2030
2029
|
|
2031
2030
|
# Regression tests
|
2032
2031
|
|
2032
|
+
def test_interpolated_comment_in_mixin
|
2033
|
+
assert_equal <<CSS, render(<<SASS)
|
2034
|
+
/* color: red */
|
2035
|
+
.foo {
|
2036
|
+
color: red; }
|
2037
|
+
|
2038
|
+
/* color: blue */
|
2039
|
+
.foo {
|
2040
|
+
color: blue; }
|
2041
|
+
|
2042
|
+
/* color: green */
|
2043
|
+
.foo {
|
2044
|
+
color: green; }
|
2045
|
+
CSS
|
2046
|
+
=foo($var)
|
2047
|
+
/*! color: \#{$var}
|
2048
|
+
.foo
|
2049
|
+
color: $var
|
2050
|
+
|
2051
|
+
+foo(red)
|
2052
|
+
+foo(blue)
|
2053
|
+
+foo(green)
|
2054
|
+
SASS
|
2055
|
+
end
|
2056
|
+
|
2033
2057
|
def test_parens_in_mixins
|
2034
2058
|
assert_equal(<<CSS, render(<<SASS))
|
2035
2059
|
.foo {
|
@@ -2308,7 +2332,16 @@ SASS
|
|
2308
2332
|
WARNING:
|
2309
2333
|
On line 1 of 'test_comment_interpolation_warning_inline.sass'
|
2310
2334
|
Comments will evaluate the contents of interpolations (\#{ ... }) in Sass 3.2.
|
2311
|
-
Please escape the interpolation by adding a backslash before the
|
2335
|
+
Please escape the interpolation by adding a backslash before the `#`.
|
2336
|
+
END
|
2337
|
+
end
|
2338
|
+
|
2339
|
+
def test_loud_silent_comment_warning
|
2340
|
+
assert_warning(<<END) {render("//! \#{foo}")}
|
2341
|
+
WARNING:
|
2342
|
+
On line 1 of 'test_loud_silent_comment_warning_inline.sass'
|
2343
|
+
`//` comments will no longer be allowed to use the `!` flag in Sass 3.2.
|
2344
|
+
Please change to `/*` comments.
|
2312
2345
|
END
|
2313
2346
|
end
|
2314
2347
|
|
data/test/sass/scss/css_test.rb
CHANGED
@@ -800,6 +800,12 @@ SCSS
|
|
800
800
|
assert_selector_parses('E*:hover')
|
801
801
|
end
|
802
802
|
|
803
|
+
def test_spaceless_combo_selectors
|
804
|
+
assert_equal "E > F {\n a: b; }\n", render("E>F { a: b;} ")
|
805
|
+
assert_equal "E ~ F {\n a: b; }\n", render("E~F { a: b;} ")
|
806
|
+
assert_equal "E + F {\n a: b; }\n", render("E+F { a: b;} ")
|
807
|
+
end
|
808
|
+
|
803
809
|
## Errors
|
804
810
|
|
805
811
|
def test_invalid_directives
|
data/test/sass/util_test.rb
CHANGED
@@ -208,6 +208,18 @@ class UtilTest < Test::Unit::TestCase
|
|
208
208
|
assert(set_eql?(s1, s2))
|
209
209
|
end
|
210
210
|
|
211
|
+
def test_extract_and_inject_values
|
212
|
+
test = lambda {|arr| assert_equal(arr, with_extracted_values(arr) {|str| str})}
|
213
|
+
|
214
|
+
test[['foo bar']]
|
215
|
+
test[['foo {12} bar']]
|
216
|
+
test[['foo {{12} bar']]
|
217
|
+
test[['foo {{1', 12, '2} bar']]
|
218
|
+
test[['foo 1', 2, '{3', 4, 5, 6, '{7}', 8]]
|
219
|
+
test[['foo 1', [2, 3, 4], ' bar']]
|
220
|
+
test[['foo ', 1, "\n bar\n", [2, 3, 4], "\n baz"]]
|
221
|
+
end
|
222
|
+
|
211
223
|
def test_caller_info
|
212
224
|
assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle'"))
|
213
225
|
assert_equal(["/tmp/foo.rb", 12, nil], caller_info("/tmp/foo.rb:12"))
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 3.1.
|
9
|
+
- 9
|
10
|
+
version: 3.1.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Nathan Weizenbaum
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-10-06 00:00:00 -07:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|