sass 3.3.0 → 3.4.25
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/.yardopts +3 -1
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +148 -0
- data/MIT-LICENSE +1 -1
- data/README.md +76 -62
- data/Rakefile +104 -24
- 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/extra/sass-spec-ref.sh +32 -0
- data/extra/update_watch.rb +1 -1
- data/lib/sass/cache_stores/filesystem.rb +9 -5
- data/lib/sass/cache_stores/memory.rb +4 -5
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +12 -13
- data/lib/sass/deprecation.rb +55 -0
- data/lib/sass/engine.rb +106 -70
- data/lib/sass/environment.rb +39 -19
- data/lib/sass/error.rb +17 -20
- data/lib/sass/exec/base.rb +199 -0
- data/lib/sass/exec/sass_convert.rb +283 -0
- data/lib/sass/exec/sass_scss.rb +440 -0
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/features.rb +9 -2
- data/lib/sass/importers/base.rb +8 -3
- data/lib/sass/importers/filesystem.rb +30 -38
- data/lib/sass/logger/base.rb +8 -2
- data/lib/sass/logger/delayed.rb +50 -0
- data/lib/sass/logger.rb +8 -3
- data/lib/sass/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +224 -90
- data/lib/sass/plugin/configuration.rb +38 -22
- data/lib/sass/plugin/merb.rb +2 -2
- data/lib/sass/plugin/rack.rb +3 -3
- data/lib/sass/plugin/rails.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +4 -4
- data/lib/sass/plugin.rb +6 -5
- data/lib/sass/script/css_lexer.rb +1 -1
- data/lib/sass/script/css_parser.rb +2 -3
- data/lib/sass/script/css_variable_warning.rb +52 -0
- data/lib/sass/script/functions.rb +739 -318
- data/lib/sass/script/lexer.rb +134 -54
- data/lib/sass/script/parser.rb +252 -56
- data/lib/sass/script/tree/funcall.rb +13 -6
- data/lib/sass/script/tree/interpolation.rb +127 -4
- data/lib/sass/script/tree/list_literal.rb +31 -4
- data/lib/sass/script/tree/literal.rb +4 -0
- data/lib/sass/script/tree/node.rb +21 -3
- data/lib/sass/script/tree/operation.rb +54 -1
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +59 -38
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/value/base.rb +17 -14
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +78 -42
- data/lib/sass/script/value/helpers.rb +119 -2
- data/lib/sass/script/value/list.rb +0 -15
- data/lib/sass/script/value/map.rb +1 -1
- data/lib/sass/script/value/null.rb +0 -5
- data/lib/sass/script/value/number.rb +112 -31
- data/lib/sass/script/value/string.rb +102 -13
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/script.rb +3 -3
- data/lib/sass/scss/css_parser.rb +24 -4
- data/lib/sass/scss/parser.rb +290 -383
- data/lib/sass/scss/rx.rb +17 -9
- data/lib/sass/scss/static_parser.rb +306 -4
- data/lib/sass/scss.rb +0 -2
- data/lib/sass/selector/abstract_sequence.rb +35 -18
- data/lib/sass/selector/comma_sequence.rb +114 -19
- data/lib/sass/selector/pseudo.rb +266 -0
- data/lib/sass/selector/sequence.rb +146 -40
- data/lib/sass/selector/simple.rb +22 -33
- data/lib/sass/selector/simple_sequence.rb +122 -39
- data/lib/sass/selector.rb +57 -197
- data/lib/sass/shared.rb +2 -2
- data/lib/sass/source/map.rb +31 -14
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +2 -8
- data/lib/sass/supports.rb +10 -13
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/css_import_node.rb +9 -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 +9 -0
- data/lib/sass/tree/import_node.rb +6 -5
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/node.rb +5 -3
- data/lib/sass/tree/prop_node.rb +6 -7
- data/lib/sass/tree/rule_node.rb +26 -11
- data/lib/sass/tree/visitors/check_nesting.rb +56 -32
- data/lib/sass/tree/visitors/convert.rb +59 -44
- data/lib/sass/tree/visitors/cssize.rb +34 -30
- data/lib/sass/tree/visitors/deep_copy.rb +6 -1
- data/lib/sass/tree/visitors/extend.rb +15 -13
- data/lib/sass/tree/visitors/perform.rb +87 -50
- data/lib/sass/tree/visitors/set_options.rb +15 -1
- data/lib/sass/tree/visitors/to_css.rb +72 -43
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/normalized_map.rb +0 -1
- data/lib/sass/util/subset_map.rb +2 -3
- data/lib/sass/util.rb +334 -154
- data/lib/sass/version.rb +7 -7
- data/lib/sass.rb +10 -8
- data/test/sass/cache_test.rb +62 -20
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +24 -11
- data/test/sass/conversion_test.rb +241 -50
- data/test/sass/css2sass_test.rb +73 -5
- data/test/sass/css_variable_test.rb +132 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +343 -260
- data/test/sass/exec_test.rb +12 -2
- data/test/sass/extend_test.rb +333 -44
- data/test/sass/functions_test.rb +353 -260
- data/test/sass/importer_test.rb +40 -21
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/more_templates/more1.sass +10 -10
- data/test/sass/more_templates/more_import.sass +2 -2
- data/test/sass/plugin_test.rb +24 -21
- 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 +5 -5
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +71 -39
- data/test/sass/script_test.rb +714 -123
- data/test/sass/scss/css_test.rb +213 -30
- data/test/sass/scss/rx_test.rb +8 -4
- data/test/sass/scss/scss_test.rb +766 -22
- data/test/sass/source_map_test.rb +263 -95
- data/test/sass/superselector_test.rb +210 -0
- data/test/sass/templates/_partial.sass +1 -1
- data/test/sass/templates/basic.sass +10 -10
- data/test/sass/templates/bork1.sass +1 -1
- data/test/sass/templates/bork5.sass +1 -1
- data/test/sass/templates/compact.sass +10 -10
- data/test/sass/templates/complex.sass +187 -187
- data/test/sass/templates/compressed.sass +10 -10
- data/test/sass/templates/expanded.sass +10 -10
- data/test/sass/templates/import.sass +2 -2
- data/test/sass/templates/importee.sass +3 -3
- data/test/sass/templates/mixins.sass +22 -22
- data/test/sass/templates/multiline.sass +4 -4
- data/test/sass/templates/nested.sass +13 -13
- data/test/sass/templates/parent_ref.sass +12 -12
- data/test/sass/templates/script.sass +70 -70
- data/test/sass/templates/scss_import.scss +2 -1
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
- data/test/sass/templates/subdir/subdir.sass +3 -3
- data/test/sass/templates/units.sass +10 -10
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
- 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 +46 -45
- data/test/sass/value_helpers_test.rb +5 -7
- data/test/sass-spec.yml +3 -0
- data/test/test_helper.rb +7 -6
- 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 +310 -300
- data/CONTRIBUTING +0 -3
- data/ext/mkrf_conf.rb +0 -27
- data/lib/sass/script/value/deprecated_false.rb +0 -55
- data/lib/sass/scss/script_lexer.rb +0 -15
- data/lib/sass/scss/script_parser.rb +0 -25
- 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/parser.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sass/script/lexer'
|
2
|
+
require 'sass/script/css_variable_warning'
|
2
3
|
|
3
4
|
module Sass
|
4
5
|
module Script
|
@@ -7,28 +8,34 @@ module Sass
|
|
7
8
|
class Parser
|
8
9
|
# The line number of the parser's current position.
|
9
10
|
#
|
10
|
-
# @return [
|
11
|
+
# @return [Integer]
|
11
12
|
def line
|
12
13
|
@lexer.line
|
13
14
|
end
|
14
15
|
|
15
16
|
# The column number of the parser's current position.
|
16
17
|
#
|
17
|
-
# @return [
|
18
|
+
# @return [Integer]
|
18
19
|
def offset
|
19
20
|
@lexer.offset
|
20
21
|
end
|
21
22
|
|
22
23
|
# @param str [String, StringScanner] The source text to parse
|
23
|
-
# @param line [
|
24
|
+
# @param line [Integer] The line on which the SassScript appears.
|
24
25
|
# Used for error reporting and sourcemap building
|
25
|
-
# @param offset [
|
26
|
+
# @param offset [Integer] The character (not byte) offset where the script starts in the line.
|
26
27
|
# Used for error reporting and sourcemap building
|
27
|
-
# @param options [{Symbol => Object}] An options hash;
|
28
|
-
#
|
28
|
+
# @param options [{Symbol => Object}] An options hash; see
|
29
|
+
# {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
30
|
+
# This supports an additional `:allow_extra_text` option that controls
|
31
|
+
# whether the parser throws an error when extra text is encountered
|
32
|
+
# after the parsed construct.
|
29
33
|
def initialize(str, line, offset, options = {})
|
30
34
|
@options = options
|
35
|
+
@allow_extra_text = options.delete(:allow_extra_text)
|
31
36
|
@lexer = lexer_class.new(str, line, offset, options)
|
37
|
+
@stop_at = nil
|
38
|
+
@css_variable_warning = nil
|
32
39
|
end
|
33
40
|
|
34
41
|
# Parses a SassScript expression within an interpolated segment (`#{}`).
|
@@ -36,13 +43,20 @@ module Sass
|
|
36
43
|
# which signals the end of an interpolated segment,
|
37
44
|
# it returns rather than throwing an error.
|
38
45
|
#
|
46
|
+
# @param warn_for_color [Boolean] Whether raw color values passed to
|
47
|
+
# interoplation should cause a warning.
|
39
48
|
# @return [Script::Tree::Node] The root node of the parse tree
|
40
49
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
41
|
-
def parse_interpolated
|
50
|
+
def parse_interpolated(warn_for_color = false)
|
51
|
+
# Start two characters back to compensate for #{
|
52
|
+
start_pos = Sass::Source::Position.new(line, offset - 2)
|
42
53
|
expr = assert_expr :expr
|
43
54
|
assert_tok :end_interpolation
|
55
|
+
expr = Sass::Script::Tree::Interpolation.new(
|
56
|
+
nil, expr, nil, false, false, :warn_for_color => warn_for_color)
|
57
|
+
check_for_interpolation expr
|
44
58
|
expr.options = @options
|
45
|
-
expr
|
59
|
+
node(expr, start_pos)
|
46
60
|
rescue Sass::SyntaxError => e
|
47
61
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
48
62
|
raise e
|
@@ -50,12 +64,23 @@ module Sass
|
|
50
64
|
|
51
65
|
# Parses a SassScript expression.
|
52
66
|
#
|
67
|
+
# @param css_variable [Boolean] Whether this is the value of a CSS variable.
|
53
68
|
# @return [Script::Tree::Node] The root node of the parse tree
|
54
69
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
55
|
-
def parse
|
70
|
+
def parse(css_variable = false)
|
71
|
+
if css_variable
|
72
|
+
@css_variable_warning = CssVariableWarning.new
|
73
|
+
end
|
74
|
+
|
56
75
|
expr = assert_expr :expr
|
57
76
|
assert_done
|
58
77
|
expr.options = @options
|
78
|
+
check_for_interpolation expr
|
79
|
+
|
80
|
+
if css_variable
|
81
|
+
@css_variable_warning.value = expr
|
82
|
+
end
|
83
|
+
|
59
84
|
expr
|
60
85
|
rescue Sass::SyntaxError => e
|
61
86
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -73,6 +98,7 @@ module Sass
|
|
73
98
|
expr = assert_expr :expr
|
74
99
|
assert_done
|
75
100
|
expr.options = @options
|
101
|
+
check_for_interpolation expr
|
76
102
|
expr
|
77
103
|
rescue Sass::SyntaxError => e
|
78
104
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -96,10 +122,26 @@ module Sass
|
|
96
122
|
end
|
97
123
|
assert_done
|
98
124
|
|
99
|
-
args.each
|
100
|
-
|
101
|
-
|
102
|
-
|
125
|
+
args.each do |a|
|
126
|
+
check_for_interpolation a
|
127
|
+
a.options = @options
|
128
|
+
end
|
129
|
+
|
130
|
+
keywords.each do |_k, v|
|
131
|
+
check_for_interpolation v
|
132
|
+
v.options = @options
|
133
|
+
end
|
134
|
+
|
135
|
+
if splat
|
136
|
+
check_for_interpolation splat
|
137
|
+
splat.options = @options
|
138
|
+
end
|
139
|
+
|
140
|
+
if kwarg_splat
|
141
|
+
check_for_interpolation kwarg_splat
|
142
|
+
kwarg_splat.options = @options
|
143
|
+
end
|
144
|
+
|
103
145
|
return args, keywords, splat, kwarg_splat
|
104
146
|
rescue Sass::SyntaxError => e
|
105
147
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -116,10 +158,20 @@ module Sass
|
|
116
158
|
assert_done
|
117
159
|
|
118
160
|
args.each do |k, v|
|
161
|
+
check_for_interpolation k
|
119
162
|
k.options = @options
|
120
|
-
|
163
|
+
|
164
|
+
if v
|
165
|
+
check_for_interpolation v
|
166
|
+
v.options = @options
|
167
|
+
end
|
121
168
|
end
|
122
|
-
|
169
|
+
|
170
|
+
if splat
|
171
|
+
check_for_interpolation splat
|
172
|
+
splat.options = @options
|
173
|
+
end
|
174
|
+
|
123
175
|
return args, splat
|
124
176
|
rescue Sass::SyntaxError => e
|
125
177
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -136,10 +188,20 @@ module Sass
|
|
136
188
|
assert_done
|
137
189
|
|
138
190
|
args.each do |k, v|
|
191
|
+
check_for_interpolation k
|
139
192
|
k.options = @options
|
140
|
-
|
193
|
+
|
194
|
+
if v
|
195
|
+
check_for_interpolation v
|
196
|
+
v.options = @options
|
197
|
+
end
|
141
198
|
end
|
142
|
-
|
199
|
+
|
200
|
+
if splat
|
201
|
+
check_for_interpolation splat
|
202
|
+
splat.options = @options
|
203
|
+
end
|
204
|
+
|
143
205
|
return args, splat
|
144
206
|
rescue Sass::SyntaxError => e
|
145
207
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -159,6 +221,7 @@ module Sass
|
|
159
221
|
end
|
160
222
|
|
161
223
|
expr = assert_expr :funcall
|
224
|
+
check_for_interpolation expr
|
162
225
|
expr.options = @options
|
163
226
|
@lexer.unpeek!
|
164
227
|
expr
|
@@ -169,12 +232,12 @@ module Sass
|
|
169
232
|
|
170
233
|
# Parses a SassScript expression.
|
171
234
|
#
|
172
|
-
# @overload parse(str, line, offset, filename = nil)
|
173
235
|
# @return [Script::Tree::Node] The root node of the parse tree
|
174
236
|
# @see Parser#initialize
|
175
237
|
# @see Parser#parse
|
176
|
-
def self.parse(
|
177
|
-
|
238
|
+
def self.parse(value, line, offset, options = {})
|
239
|
+
css_variable = options.delete :css_variable
|
240
|
+
new(value, line, offset, options).parse(css_variable)
|
178
241
|
end
|
179
242
|
|
180
243
|
PRECEDENCE = [
|
@@ -187,6 +250,8 @@ module Sass
|
|
187
250
|
|
188
251
|
ASSOCIATIVE = [:plus, :times]
|
189
252
|
|
253
|
+
VALID_CSS_OPS = [:comma, :single_eq, :space, :div]
|
254
|
+
|
190
255
|
class << self
|
191
256
|
# Returns an integer representing the precedence
|
192
257
|
# of the given operator.
|
@@ -226,8 +291,12 @@ module Sass
|
|
226
291
|
return other_interp
|
227
292
|
end
|
228
293
|
|
229
|
-
|
230
|
-
|
294
|
+
if @css_variable_warning && !VALID_CSS_OPS.include?(tok.type)
|
295
|
+
@css_variable_warning.warn!
|
296
|
+
end
|
297
|
+
|
298
|
+
e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type),
|
299
|
+
e.source_range.start_pos)
|
231
300
|
end
|
232
301
|
e
|
233
302
|
end
|
@@ -241,6 +310,8 @@ RUBY
|
|
241
310
|
interp = try_op_before_interp(tok)
|
242
311
|
return interp if interp
|
243
312
|
start_pos = source_position
|
313
|
+
|
314
|
+
@css_variable_warning.warn! if @css_variable_warning
|
244
315
|
node(Tree::UnaryOperation.new(assert_expr(:unary_#{op}), :#{op}), start_pos)
|
245
316
|
end
|
246
317
|
RUBY
|
@@ -267,6 +338,7 @@ RUBY
|
|
267
338
|
return list e, start_pos unless @lexer.peek && @lexer.peek.type == :colon
|
268
339
|
|
269
340
|
pair = map_pair(e)
|
341
|
+
@css_variable_warning.warn! if @css_variable_warning
|
270
342
|
map = node(Sass::Script::Tree::MapLiteral.new([pair]), start_pos)
|
271
343
|
while try_tok(:comma)
|
272
344
|
pair = map_pair
|
@@ -302,19 +374,32 @@ RUBY
|
|
302
374
|
end
|
303
375
|
return list unless (e = interpolation)
|
304
376
|
list.elements << e
|
377
|
+
list.source_range.end_pos = list.elements.last.source_range.end_pos
|
305
378
|
end
|
306
379
|
list
|
307
380
|
end
|
308
381
|
|
309
382
|
production :equals, :interpolation, :single_eq
|
310
383
|
|
311
|
-
def try_op_before_interp(op, prev = nil)
|
384
|
+
def try_op_before_interp(op, prev = nil, after_interp = false)
|
312
385
|
return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
|
386
|
+
unary = !prev && !after_interp
|
313
387
|
wb = @lexer.whitespace?(op)
|
314
388
|
str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]),
|
315
389
|
op.source_range)
|
390
|
+
|
391
|
+
deprecation =
|
392
|
+
case op.type
|
393
|
+
when :comma; :potential
|
394
|
+
when :div, :single_eq; :none
|
395
|
+
when :plus; unary ? :none : :immediate
|
396
|
+
when :minus; @lexer.whitespace?(@lexer.peek) ? :immediate : :none
|
397
|
+
else; :immediate
|
398
|
+
end
|
399
|
+
|
316
400
|
interp = node(
|
317
|
-
Script::Tree::Interpolation.new(
|
401
|
+
Script::Tree::Interpolation.new(
|
402
|
+
prev, str, nil, wb, false, :originally_text => true, :deprecation => deprecation),
|
318
403
|
(prev || str).source_range.start_pos)
|
319
404
|
interpolation(interp)
|
320
405
|
end
|
@@ -323,15 +408,25 @@ RUBY
|
|
323
408
|
return unless @lexer.after_interpolation?
|
324
409
|
op = try_toks(*ops)
|
325
410
|
return unless op
|
326
|
-
interp = try_op_before_interp(op, prev)
|
411
|
+
interp = try_op_before_interp(op, prev, :after_interp)
|
327
412
|
return interp if interp
|
328
413
|
|
329
414
|
wa = @lexer.whitespace?
|
330
415
|
str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]),
|
331
416
|
op.source_range)
|
332
417
|
str.line = @lexer.line
|
418
|
+
|
419
|
+
deprecation =
|
420
|
+
case op.type
|
421
|
+
when :comma; :potential
|
422
|
+
when :div, :single_eq; :none
|
423
|
+
when :minus; @lexer.whitespace?(op) ? :immediate : :none
|
424
|
+
else; :immediate
|
425
|
+
end
|
333
426
|
interp = node(
|
334
|
-
Script::Tree::Interpolation.new(
|
427
|
+
Script::Tree::Interpolation.new(
|
428
|
+
prev, str, assert_expr(name), false, wa,
|
429
|
+
:originally_text => true, :deprecation => deprecation),
|
335
430
|
(prev || str).source_range.start_pos)
|
336
431
|
interp
|
337
432
|
end
|
@@ -340,15 +435,60 @@ RUBY
|
|
340
435
|
e = first
|
341
436
|
while (interp = try_tok(:begin_interpolation))
|
342
437
|
wb = @lexer.whitespace?(interp)
|
343
|
-
|
438
|
+
char_before = @lexer.char(interp.pos - 1)
|
439
|
+
mid = without_css_variable_warning {assert_expr :expr}
|
440
|
+
assert_tok :end_interpolation
|
344
441
|
wa = @lexer.whitespace?
|
442
|
+
char_after = @lexer.char
|
443
|
+
|
444
|
+
after = space
|
445
|
+
before_deprecation = e.is_a?(Script::Tree::Interpolation) ? e.deprecation : :none
|
446
|
+
after_deprecation = after.is_a?(Script::Tree::Interpolation) ? after.deprecation : :none
|
447
|
+
|
448
|
+
deprecation =
|
449
|
+
if before_deprecation == :immediate || after_deprecation == :immediate ||
|
450
|
+
# Warn for #{foo}$var and #{foo}(1) but not #{$foo}1.
|
451
|
+
(after && !wa && char_after =~ /[$(]/) ||
|
452
|
+
# Warn for $var#{foo} and (a)#{foo} but not a#{foo}.
|
453
|
+
(e && !wb && is_unsafe_before?(e, char_before))
|
454
|
+
:immediate
|
455
|
+
else
|
456
|
+
:potential
|
457
|
+
end
|
458
|
+
|
345
459
|
e = node(
|
346
|
-
Script::Tree::Interpolation.new(e, mid,
|
347
|
-
(e ||
|
460
|
+
Script::Tree::Interpolation.new(e, mid, after, wb, wa, :deprecation => deprecation),
|
461
|
+
(e || interp).source_range.start_pos)
|
348
462
|
end
|
349
463
|
e
|
350
464
|
end
|
351
465
|
|
466
|
+
# Returns whether `expr` is unsafe to include before an interpolation.
|
467
|
+
#
|
468
|
+
# @param expr [Node] The expression to check.
|
469
|
+
# @param char_before [String] The character immediately before the
|
470
|
+
# interpolation being checked (and presumably the last character of
|
471
|
+
# `expr`).
|
472
|
+
# @return [Boolean]
|
473
|
+
def is_unsafe_before?(expr, char_before)
|
474
|
+
return char_before == ')' if is_safe_value?(expr)
|
475
|
+
|
476
|
+
# Otherwise, it's only safe if it was another interpolation.
|
477
|
+
!expr.is_a?(Script::Tree::Interpolation)
|
478
|
+
end
|
479
|
+
|
480
|
+
# Returns whether `expr` is safe as the value immediately before an
|
481
|
+
# interpolation.
|
482
|
+
#
|
483
|
+
# It's safe as long as the previous expression is an identifier or number,
|
484
|
+
# or a list whose last element is also safe.
|
485
|
+
def is_safe_value?(expr)
|
486
|
+
return is_safe_value?(expr.elements.last) if expr.is_a?(Script::Tree::ListLiteral)
|
487
|
+
return false unless expr.is_a?(Script::Tree::Literal)
|
488
|
+
expr.value.is_a?(Script::Value::Number) ||
|
489
|
+
(expr.value.is_a?(Script::Value::String) && expr.value.type == :identifier)
|
490
|
+
end
|
491
|
+
|
352
492
|
def space
|
353
493
|
start_pos = source_position
|
354
494
|
e = or_expr
|
@@ -382,7 +522,7 @@ RUBY
|
|
382
522
|
|
383
523
|
name = @lexer.next
|
384
524
|
if (color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase])
|
385
|
-
literal_node(Sass::Script::Value::Color.new(color), name.source_range)
|
525
|
+
literal_node(Sass::Script::Value::Color.new(color, name.value), name.source_range)
|
386
526
|
elsif name.value == "true"
|
387
527
|
literal_node(Sass::Script::Value::Bool.new(true), name.source_range)
|
388
528
|
elsif name.value == "false"
|
@@ -487,41 +627,36 @@ RUBY
|
|
487
627
|
end
|
488
628
|
|
489
629
|
def special_fun
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
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
|
630
|
+
first = try_tok(:special_fun)
|
631
|
+
return paren unless first
|
632
|
+
str = literal_node(first.value, first.source_range)
|
633
|
+
return str unless try_tok(:string_interpolation)
|
634
|
+
mid = without_css_variable_warning {assert_expr :expr}
|
635
|
+
assert_tok :end_interpolation
|
636
|
+
last = assert_expr(:special_fun)
|
637
|
+
node(
|
638
|
+
Tree::Interpolation.new(str, mid, last, false, false),
|
639
|
+
first.source_range.start_pos)
|
506
640
|
end
|
507
641
|
|
508
642
|
def paren
|
509
643
|
return variable unless try_tok(:lparen)
|
510
|
-
was_in_parens = @in_parens
|
511
|
-
@in_parens = true
|
512
644
|
start_pos = source_position
|
513
645
|
e = map
|
646
|
+
e.force_division! if e
|
514
647
|
end_pos = source_position
|
515
648
|
assert_tok(:rparen)
|
516
|
-
|
517
|
-
|
518
|
-
|
649
|
+
|
650
|
+
@css_variable_warning.warn! if @css_variable_warning
|
651
|
+
e || node(Sass::Script::Tree::ListLiteral.new([], nil), start_pos, end_pos)
|
519
652
|
end
|
520
653
|
|
521
654
|
def variable
|
522
655
|
start_pos = source_position
|
523
656
|
c = try_tok(:const)
|
524
657
|
return string unless c
|
658
|
+
|
659
|
+
@css_variable_warning.warn! if @css_variable_warning
|
525
660
|
node(Tree::Variable.new(*c.value), start_pos)
|
526
661
|
end
|
527
662
|
|
@@ -529,8 +664,9 @@ RUBY
|
|
529
664
|
first = try_tok(:string)
|
530
665
|
return number unless first
|
531
666
|
str = literal_node(first.value, first.source_range)
|
532
|
-
return str unless try_tok(:
|
533
|
-
mid =
|
667
|
+
return str unless try_tok(:string_interpolation)
|
668
|
+
mid = without_css_variable_warning {assert_expr :expr}
|
669
|
+
assert_tok :end_interpolation
|
534
670
|
last = assert_expr(:string)
|
535
671
|
node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
|
536
672
|
end
|
@@ -539,13 +675,15 @@ RUBY
|
|
539
675
|
tok = try_tok(:number)
|
540
676
|
return selector unless tok
|
541
677
|
num = tok.value
|
542
|
-
num.
|
678
|
+
num.options = @options
|
679
|
+
num.original = num.to_s
|
543
680
|
literal_node(num, tok.source_range.start_pos)
|
544
681
|
end
|
545
682
|
|
546
683
|
def selector
|
547
684
|
tok = try_tok(:selector)
|
548
685
|
return literal unless tok
|
686
|
+
@css_variable_warning.warn! if @css_variable_warning
|
549
687
|
node(tok.value, tok.source_range.start_pos)
|
550
688
|
end
|
551
689
|
|
@@ -563,6 +701,7 @@ RUBY
|
|
563
701
|
:mixin_arglist => "mixin argument",
|
564
702
|
:fn_arglist => "function argument",
|
565
703
|
:splat => "...",
|
704
|
+
:special_fun => '")"',
|
566
705
|
}
|
567
706
|
|
568
707
|
def assert_expr(name, expected = nil)
|
@@ -596,8 +735,14 @@ RUBY
|
|
596
735
|
end
|
597
736
|
|
598
737
|
def assert_done
|
599
|
-
|
600
|
-
|
738
|
+
if @allow_extra_text
|
739
|
+
# If extra text is allowed, just rewind the lexer so that the
|
740
|
+
# StringScanner is pointing to the end of the parsed text.
|
741
|
+
@lexer.unpeek!
|
742
|
+
else
|
743
|
+
return if @lexer.done?
|
744
|
+
@lexer.expected!(EXPR_NAMES[:default])
|
745
|
+
end
|
601
746
|
end
|
602
747
|
|
603
748
|
# @overload node(value, source_range)
|
@@ -626,11 +771,62 @@ RUBY
|
|
626
771
|
range(source_range_or_start_pos, end_pos)
|
627
772
|
end
|
628
773
|
|
774
|
+
node.css_variable_warning = @css_variable_warning
|
629
775
|
node.line = source_range.start_pos.line
|
630
776
|
node.source_range = source_range
|
631
777
|
node.filename = @options[:filename]
|
632
778
|
node
|
633
779
|
end
|
780
|
+
|
781
|
+
# Runs the given block without CSS variable warnings enabled.
|
782
|
+
#
|
783
|
+
# CSS warnings don't apply within interpolation, so this is used to
|
784
|
+
# disable them.
|
785
|
+
#
|
786
|
+
# @yield []
|
787
|
+
def without_css_variable_warning
|
788
|
+
old_css_variable_warning = @css_variable_warning
|
789
|
+
@css_variable_warning = nil
|
790
|
+
yield
|
791
|
+
ensure
|
792
|
+
@css_variable_warning = old_css_variable_warning
|
793
|
+
end
|
794
|
+
|
795
|
+
# Checks a script node for any immediately-deprecated interpolations, and
|
796
|
+
# emits warnings for them.
|
797
|
+
#
|
798
|
+
# @param node [Sass::Script::Tree::Node]
|
799
|
+
def check_for_interpolation(node)
|
800
|
+
nodes = [node]
|
801
|
+
until nodes.empty?
|
802
|
+
node = nodes.pop
|
803
|
+
unless node.is_a?(Sass::Script::Tree::Interpolation) &&
|
804
|
+
node.deprecation == :immediate
|
805
|
+
nodes.concat node.children
|
806
|
+
next
|
807
|
+
end
|
808
|
+
|
809
|
+
interpolation_deprecation(node)
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
813
|
+
# Emits a deprecation warning for an interpolation node.
|
814
|
+
#
|
815
|
+
# @param node [Sass::Script::Tree::Node]
|
816
|
+
def interpolation_deprecation(interpolation)
|
817
|
+
return if @options[:_convert]
|
818
|
+
location = "on line #{interpolation.line}"
|
819
|
+
location << " of #{interpolation.filename}" if interpolation.filename
|
820
|
+
Sass::Util.sass_warn <<WARNING
|
821
|
+
DEPRECATION WARNING #{location}:
|
822
|
+
\#{} interpolation near operators will be simplified in a future version of Sass.
|
823
|
+
To preserve the current behavior, use quotes:
|
824
|
+
|
825
|
+
#{interpolation.to_quoted_equivalent.to_sass}
|
826
|
+
|
827
|
+
You can use the sass-convert command to automatically fix most cases.
|
828
|
+
WARNING
|
829
|
+
end
|
634
830
|
end
|
635
831
|
end
|
636
832
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'sass/script/functions'
|
2
|
-
require 'sass/util
|
2
|
+
require 'sass/util'
|
3
3
|
|
4
4
|
module Sass::Script::Tree
|
5
5
|
# A SassScript parse node representing a function call.
|
@@ -128,12 +128,15 @@ module Sass::Script::Tree
|
|
128
128
|
splat = Sass::Tree::Visitors::Perform.perform_splat(
|
129
129
|
@splat, keywords, @kwarg_splat, environment)
|
130
130
|
if (fn = environment.function(@name))
|
131
|
+
css_variable_warning.warn! if css_variable_warning
|
131
132
|
return without_original(perform_sass_fn(fn, args, splat, environment))
|
132
133
|
end
|
133
134
|
|
134
135
|
args = construct_ruby_args(ruby_name, args, splat, environment)
|
135
136
|
|
136
137
|
if Sass::Script::Functions.callable?(ruby_name)
|
138
|
+
css_variable_warning.warn! if css_variable_warning
|
139
|
+
|
137
140
|
local_environment = Sass::Environment.new(environment.global_env, environment.options)
|
138
141
|
local_environment.caller = Sass::ReadOnlyEnvironment.new(environment, environment.options)
|
139
142
|
result = opts(Sass::Script::Functions::EvaluationContext.new(
|
@@ -208,13 +211,13 @@ module Sass::Script::Tree
|
|
208
211
|
|
209
212
|
argnames = signature.args[args.size..-1] || []
|
210
213
|
deprecated_argnames = (signature.deprecated && signature.deprecated[args.size..-1]) || []
|
211
|
-
args
|
214
|
+
args += argnames.zip(deprecated_argnames).map do |(argname, deprecated_argname)|
|
212
215
|
if keywords.has_key?(argname)
|
213
216
|
keywords.delete(argname)
|
214
217
|
elsif deprecated_argname && keywords.has_key?(deprecated_argname)
|
215
218
|
deprecated_argname = keywords.denormalize(deprecated_argname)
|
216
219
|
Sass::Util.sass_warn("DEPRECATION WARNING: The `$#{deprecated_argname}' argument for " +
|
217
|
-
"`#{name}()' has been renamed to `$#{argname}'.")
|
220
|
+
"`#{@name}()' has been renamed to `$#{argname}'.")
|
218
221
|
keywords.delete(deprecated_argname)
|
219
222
|
else
|
220
223
|
raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}")
|
@@ -241,7 +244,7 @@ module Sass::Script::Tree
|
|
241
244
|
end
|
242
245
|
|
243
246
|
def perform_sass_fn(function, args, splat, environment)
|
244
|
-
Sass::Tree::Visitors::Perform.perform_arguments(function, args, splat) do |env|
|
247
|
+
Sass::Tree::Visitors::Perform.perform_arguments(function, args, splat, environment) do |env|
|
245
248
|
env.caller = Sass::Environment.new(environment)
|
246
249
|
|
247
250
|
val = catch :_sass_return do
|
@@ -296,8 +299,12 @@ module Sass::Script::Tree
|
|
296
299
|
message = "wrong number of arguments (#{given} for #{expected})"
|
297
300
|
end
|
298
301
|
end
|
299
|
-
elsif
|
300
|
-
|
302
|
+
elsif (md = /^wrong number of arguments \(given (\d+), expected (\d+)\)/.match(e.message)) &&
|
303
|
+
e.backtrace[0] =~ /:in `#{ruby_name}'$/
|
304
|
+
# Handle ruby 2.3 error formatting
|
305
|
+
message = "wrong number of arguments (#{md[1]} for #{md[2]})"
|
306
|
+
elsif e.message =~ /^wrong number of arguments/ &&
|
307
|
+
e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
|
301
308
|
raise e
|
302
309
|
end
|
303
310
|
raise Sass::SyntaxError.new("#{message} for `#{name}'")
|