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
@@ -123,29 +123,8 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
123
123
|
|
124
124
|
# Registers an extension in the `@extends` subset map.
|
125
125
|
def visit_extend(node)
|
126
|
-
node.resolved_selector
|
127
|
-
|
128
|
-
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
|
129
|
-
end
|
130
|
-
|
131
|
-
sseq = seq.members.first
|
132
|
-
if !sseq.is_a?(Sass::Selector::SimpleSequence)
|
133
|
-
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
|
134
|
-
elsif sseq.members.any? {|ss| ss.is_a?(Sass::Selector::Parent)}
|
135
|
-
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend parent selectors")
|
136
|
-
end
|
137
|
-
|
138
|
-
sel = sseq.members
|
139
|
-
parent.resolved_rules.members.each do |member|
|
140
|
-
unless member.members.last.is_a?(Sass::Selector::SimpleSequence)
|
141
|
-
raise Sass::SyntaxError.new("#{member} can't extend: invalid selector")
|
142
|
-
end
|
143
|
-
|
144
|
-
parent_directives = @parents.select {|p| p.is_a?(Sass::Tree::DirectiveNode)}
|
145
|
-
@extends[sel] = Extend.new(member, sel, node, parent_directives, :not_found)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
126
|
+
parent.resolved_rules.populate_extends(@extends, node.resolved_selector, node,
|
127
|
+
@parents.select {|p| p.is_a?(Sass::Tree::DirectiveNode)})
|
149
128
|
[]
|
150
129
|
end
|
151
130
|
|
@@ -232,10 +211,22 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
232
211
|
rules
|
233
212
|
end
|
234
213
|
|
214
|
+
def visit_keyframerule(node)
|
215
|
+
return node unless node.has_children
|
216
|
+
|
217
|
+
yield
|
218
|
+
|
219
|
+
debubble(node.children, node)
|
220
|
+
end
|
221
|
+
|
235
222
|
# Bubbles a directive up through RuleNodes.
|
236
223
|
def visit_directive(node)
|
237
224
|
return node unless node.has_children
|
238
|
-
|
225
|
+
if parent.is_a?(Sass::Tree::RuleNode)
|
226
|
+
# @keyframes shouldn't include the rule nodes, so we manually create a
|
227
|
+
# bubble that doesn't have the parent's contents for them.
|
228
|
+
return node.normalized_name == '@keyframes' ? Bubble.new(node) : bubble(node)
|
229
|
+
end
|
239
230
|
|
240
231
|
yield
|
241
232
|
|
@@ -249,7 +240,8 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
249
240
|
child.node.resolved_value == node.resolved_value
|
250
241
|
end
|
251
242
|
|
252
|
-
|
243
|
+
# We know empty @keyframes directives do nothing.
|
244
|
+
if directive_exists || node.name == '@keyframes'
|
253
245
|
[]
|
254
246
|
else
|
255
247
|
empty_node = node.dup
|
@@ -315,19 +307,31 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
315
307
|
# omitted.
|
316
308
|
# @return [List<Sass::Tree::Node, Bubble>]
|
317
309
|
def debubble(children, parent = nil)
|
310
|
+
# Keep track of the previous parent so that we don't divide `parent`
|
311
|
+
# unnecessarily if the `@at-root` doesn't produce any new nodes (e.g.
|
312
|
+
# `@at-root {@extend %foo}`).
|
313
|
+
previous_parent = nil
|
314
|
+
|
318
315
|
Sass::Util.slice_by(children) {|c| c.is_a?(Bubble)}.map do |(is_bubble, slice)|
|
319
316
|
unless is_bubble
|
320
317
|
next slice unless parent
|
321
|
-
|
322
|
-
|
323
|
-
|
318
|
+
if previous_parent
|
319
|
+
previous_parent.children.push(*slice)
|
320
|
+
next []
|
321
|
+
else
|
322
|
+
previous_parent = new_parent = parent.dup
|
323
|
+
new_parent.children = slice
|
324
|
+
next new_parent
|
325
|
+
end
|
324
326
|
end
|
325
327
|
|
326
|
-
|
328
|
+
slice.map do |bubble|
|
327
329
|
next unless (node = block_given? ? yield(bubble.node) : bubble.node)
|
328
330
|
node.tabs += bubble.tabs
|
329
331
|
node.group_end = bubble.group_end
|
330
|
-
[visit(node)].flatten
|
332
|
+
results = [visit(node)].flatten
|
333
|
+
previous_parent = nil unless results.empty?
|
334
|
+
results
|
331
335
|
end.compact
|
332
336
|
end.flatten
|
333
337
|
end
|
@@ -16,6 +16,11 @@ class Sass::Tree::Visitors::DeepCopy < Sass::Tree::Visitors::Base
|
|
16
16
|
yield
|
17
17
|
end
|
18
18
|
|
19
|
+
def visit_error(node)
|
20
|
+
node.expr = node.expr.deep_copy
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
|
19
24
|
def visit_each(node)
|
20
25
|
node.list = node.list.deep_copy
|
21
26
|
yield
|
@@ -50,7 +55,7 @@ class Sass::Tree::Visitors::DeepCopy < Sass::Tree::Visitors::Base
|
|
50
55
|
|
51
56
|
def visit_mixin(node)
|
52
57
|
node.args = node.args.map {|a| a.deep_copy}
|
53
|
-
node.keywords = Hash[node.keywords.map {|k, v| [k, v.deep_copy]}]
|
58
|
+
node.keywords = Sass::Util::NormalizedMap.new(Hash[node.keywords.map {|k, v| [k, v.deep_copy]}])
|
54
59
|
yield
|
55
60
|
end
|
56
61
|
|
@@ -44,25 +44,27 @@ class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
|
|
44
44
|
node.resolved_rules = node.resolved_rules.do_extend(@extends, @parent_directives)
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
class << self
|
48
|
+
private
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
50
|
+
def check_extends_fired!(extends)
|
51
|
+
extends.each_value do |ex|
|
52
|
+
next if ex.result == :succeeded || ex.node.optional?
|
53
|
+
message = "\"#{ex.extender}\" failed to @extend \"#{ex.target.join}\"."
|
54
|
+
reason =
|
55
|
+
if ex.result == :not_found
|
56
|
+
"The selector \"#{ex.target.join}\" was not found."
|
57
|
+
else
|
58
|
+
"No selectors matching \"#{ex.target.join}\" could be unified with \"#{ex.extender}\"."
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
# TODO(nweiz): this should use the Sass stack trace of the extend node.
|
62
|
+
raise Sass::SyntaxError.new(<<MESSAGE, :filename => ex.node.filename, :line => ex.node.line)
|
62
63
|
#{message}
|
63
64
|
#{reason}
|
64
65
|
Use "@extend #{ex.target.join} !optional" if the extend should be able to fail.
|
65
66
|
MESSAGE
|
67
|
+
end
|
66
68
|
end
|
67
69
|
end
|
68
70
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# A visitor for converting a dynamic Sass tree into a static Sass tree.
|
2
2
|
class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
3
|
+
@@function_name_deprecation = Sass::Deprecation.new
|
4
|
+
|
3
5
|
class << self
|
4
6
|
# @param root [Tree::Node] The root node of the tree to visit.
|
5
7
|
# @param environment [Sass::Environment] The lexical environment.
|
@@ -11,7 +13,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
11
13
|
# @api private
|
12
14
|
# @comment
|
13
15
|
# rubocop:disable MethodLength
|
14
|
-
def perform_arguments(callable, args, splat)
|
16
|
+
def perform_arguments(callable, args, splat, environment)
|
15
17
|
desc = "#{callable.type.capitalize} #{callable.name}"
|
16
18
|
downcase_desc = "#{callable.type} #{callable.name}"
|
17
19
|
|
@@ -41,20 +43,26 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
41
43
|
# raising happens in the ensure clause at the end of this function.
|
42
44
|
return if keyword_exception && !callable.splat
|
43
45
|
|
44
|
-
if args.size > callable.args.size && !callable.splat
|
45
|
-
takes = callable.args.size
|
46
|
-
passed = args.size
|
47
|
-
raise Sass::SyntaxError.new(
|
48
|
-
"#{desc} takes #{takes} argument#{'s' unless takes == 1} " +
|
49
|
-
"but #{passed} #{passed == 1 ? 'was' : 'were'} passed.")
|
50
|
-
end
|
51
|
-
|
52
46
|
splat_sep = :comma
|
53
47
|
if splat
|
54
48
|
args += splat.to_a
|
55
49
|
splat_sep = splat.separator
|
56
50
|
end
|
57
51
|
|
52
|
+
if args.size > callable.args.size && !callable.splat
|
53
|
+
extra_args_because_of_splat = splat && args.size - splat.to_a.size <= callable.args.size
|
54
|
+
|
55
|
+
takes = callable.args.size
|
56
|
+
passed = args.size
|
57
|
+
message = "#{desc} takes #{takes} argument#{'s' unless takes == 1} " +
|
58
|
+
"but #{passed} #{passed == 1 ? 'was' : 'were'} passed."
|
59
|
+
raise Sass::SyntaxError.new(message) unless extra_args_because_of_splat
|
60
|
+
# TODO: when the deprecation period is over, make this an error.
|
61
|
+
Sass::Util.sass_warn("WARNING: #{message}\n" +
|
62
|
+
environment.stack.to_s.gsub(/^/m, " " * 8) + "\n" +
|
63
|
+
"This will be an error in future versions of Sass.")
|
64
|
+
end
|
65
|
+
|
58
66
|
env = Sass::Environment.new(callable.environment)
|
59
67
|
callable.args.zip(args[0...callable.args.length]) do |(var, default), value|
|
60
68
|
if value && keywords.has_key?(var.name)
|
@@ -144,6 +152,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
144
152
|
|
145
153
|
def initialize(env)
|
146
154
|
@environment = env
|
155
|
+
@in_keyframes = false
|
156
|
+
@at_root_without_rule = false
|
147
157
|
end
|
148
158
|
|
149
159
|
# If an exception is raised, this adds proper metadata to the backtrace.
|
@@ -207,11 +217,22 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
207
217
|
[]
|
208
218
|
end
|
209
219
|
|
220
|
+
# Throws the expression as an error.
|
221
|
+
def visit_error(node)
|
222
|
+
res = node.expr.perform(@environment)
|
223
|
+
if res.is_a?(Sass::Script::Value::String)
|
224
|
+
res = res.value
|
225
|
+
else
|
226
|
+
res = res.to_sass
|
227
|
+
end
|
228
|
+
raise Sass::SyntaxError.new(res)
|
229
|
+
end
|
230
|
+
|
210
231
|
# Runs the child nodes once for each value in the list.
|
211
232
|
def visit_each(node)
|
212
233
|
list = node.list.perform(@environment)
|
213
234
|
|
214
|
-
with_environment Sass::
|
235
|
+
with_environment Sass::SemiGlobalEnvironment.new(@environment) do
|
215
236
|
list.to_a.map do |value|
|
216
237
|
if node.vars.length == 1
|
217
238
|
@environment.set_local_var(node.vars.first, value)
|
@@ -245,7 +266,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
245
266
|
direction = from.to_i > to.to_i ? -1 : 1
|
246
267
|
range = Range.new(direction * from.to_i, direction * to.to_i, node.exclusive)
|
247
268
|
|
248
|
-
with_environment Sass::
|
269
|
+
with_environment Sass::SemiGlobalEnvironment.new(@environment) do
|
249
270
|
range.map do |i|
|
250
271
|
@environment.set_local_var(node.var,
|
251
272
|
Sass::Script::Value::Number.new(direction * i,
|
@@ -258,9 +279,18 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
258
279
|
# Loads the function into the environment.
|
259
280
|
def visit_function(node)
|
260
281
|
env = Sass::Environment.new(@environment, node.options)
|
282
|
+
|
283
|
+
if node.normalized_name == 'calc' || node.normalized_name == 'element' ||
|
284
|
+
node.name == 'expression' || node.name == 'url'
|
285
|
+
@@function_name_deprecation.warn(node.filename, node.line, <<WARNING)
|
286
|
+
Naming a function "#{node.name}" is disallowed and will be an error in future versions of Sass.
|
287
|
+
This name conflicts with an existing CSS function with special parse rules.
|
288
|
+
WARNING
|
289
|
+
end
|
290
|
+
|
261
291
|
@environment.set_local_function(node.name,
|
262
292
|
Sass::Callable.new(node.name, node.args, node.splat, env,
|
263
|
-
node.children,
|
293
|
+
node.children, false, "function"))
|
264
294
|
[]
|
265
295
|
end
|
266
296
|
|
@@ -268,8 +298,9 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
268
298
|
# otherwise, tries the else nodes.
|
269
299
|
def visit_if(node)
|
270
300
|
if node.expr.nil? || node.expr.perform(@environment).to_bool
|
271
|
-
|
272
|
-
|
301
|
+
with_environment Sass::SemiGlobalEnvironment.new(@environment) do
|
302
|
+
node.children.map {|c| visit(c)}
|
303
|
+
end.flatten
|
273
304
|
elsif node.else
|
274
305
|
visit(node.else)
|
275
306
|
else
|
@@ -282,6 +313,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
282
313
|
def visit_import(node)
|
283
314
|
if (path = node.css_import?)
|
284
315
|
resolved_node = Sass::Tree::CssImportNode.resolved("url(#{path})")
|
316
|
+
resolved_node.options = node.options
|
285
317
|
resolved_node.source_range = node.source_range
|
286
318
|
return resolved_node
|
287
319
|
end
|
@@ -320,14 +352,14 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
320
352
|
raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin
|
321
353
|
|
322
354
|
if node.children.any? && !mixin.has_content
|
323
|
-
raise Sass::SyntaxError.new(%
|
355
|
+
raise Sass::SyntaxError.new(%(Mixin "#{node.name}" does not accept a content block.))
|
324
356
|
end
|
325
357
|
|
326
358
|
args = node.args.map {|a| a.perform(@environment)}
|
327
359
|
keywords = Sass::Util.map_vals(node.keywords) {|v| v.perform(@environment)}
|
328
360
|
splat = self.class.perform_splat(node.splat, keywords, node.kwarg_splat, @environment)
|
329
361
|
|
330
|
-
self.class.perform_arguments(mixin, args, splat) do |env|
|
362
|
+
self.class.perform_arguments(mixin, args, splat, @environment) do |env|
|
331
363
|
env.caller = Sass::Environment.new(@environment)
|
332
364
|
env.content = [node.children, @environment] if node.has_children
|
333
365
|
|
@@ -377,18 +409,32 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
377
409
|
# Runs SassScript interpolation in the selector,
|
378
410
|
# and then parses the result into a {Sass::Selector::CommaSequence}.
|
379
411
|
def visit_rule(node)
|
380
|
-
old_at_root_without_rule
|
412
|
+
old_at_root_without_rule = @at_root_without_rule
|
381
413
|
parser = Sass::SCSS::StaticParser.new(run_interp(node.rule),
|
382
414
|
node.filename, node.options[:importer], node.line)
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
415
|
+
if @in_keyframes
|
416
|
+
keyframe_rule_node = Sass::Tree::KeyframeRuleNode.new(parser.parse_keyframes_selector)
|
417
|
+
keyframe_rule_node.options = node.options
|
418
|
+
keyframe_rule_node.line = node.line
|
419
|
+
keyframe_rule_node.filename = node.filename
|
420
|
+
keyframe_rule_node.source_range = node.source_range
|
421
|
+
keyframe_rule_node.has_children = node.has_children
|
422
|
+
with_environment Sass::Environment.new(@environment, node.options) do
|
423
|
+
keyframe_rule_node.children = node.children.map {|c| visit(c)}.flatten
|
424
|
+
end
|
425
|
+
keyframe_rule_node
|
426
|
+
else
|
427
|
+
@at_root_without_rule = false
|
428
|
+
node.parsed_rules ||= parser.parse_selector
|
429
|
+
node.resolved_rules = node.parsed_rules.resolve_parent_refs(
|
430
|
+
@environment.selector, !old_at_root_without_rule)
|
431
|
+
node.stack_trace = @environment.stack.to_s if node.options[:trace_selectors]
|
432
|
+
with_environment Sass::Environment.new(@environment, node.options) do
|
433
|
+
@environment.selector = node.resolved_rules
|
434
|
+
node.children = node.children.map {|c| visit(c)}.flatten
|
435
|
+
end
|
436
|
+
node
|
390
437
|
end
|
391
|
-
node
|
392
438
|
ensure
|
393
439
|
@at_root_without_rule = old_at_root_without_rule
|
394
440
|
end
|
@@ -405,36 +451,24 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
405
451
|
end
|
406
452
|
|
407
453
|
old_at_root_without_rule = @at_root_without_rule
|
454
|
+
old_in_keyframes = @in_keyframes
|
408
455
|
@at_root_without_rule = true if node.exclude?('rule')
|
456
|
+
@in_keyframes = false if node.exclude?('keyframes')
|
409
457
|
yield
|
410
458
|
ensure
|
459
|
+
@in_keyframes = old_in_keyframes
|
411
460
|
@at_root_without_rule = old_at_root_without_rule
|
412
461
|
end
|
413
462
|
|
414
463
|
# Loads the new variable value into the environment.
|
415
464
|
def visit_variable(node)
|
416
465
|
env = @environment
|
417
|
-
|
418
|
-
if node.
|
419
|
-
|
420
|
-
|
421
|
-
!env.global_env.global_warning_given.include?(identifier)
|
422
|
-
env.global_env.global_warning_given.add(identifier)
|
423
|
-
var_expr = "$#{node.name}: #{node.expr.to_sass(env.options)} !global"
|
424
|
-
var_expr << " !default" if node.guarded
|
425
|
-
location = "on line #{node.line}"
|
426
|
-
location << " of #{node.filename}" if node.filename
|
427
|
-
Sass::Util.sass_warn <<WARNING
|
428
|
-
DEPRECATION WARNING #{location}:
|
429
|
-
Assigning to global variable "$#{node.name}" by default is deprecated.
|
430
|
-
In future versions of Sass, this will create a new local variable.
|
431
|
-
If you want to assign to the global variable, use "#{var_expr}" instead.
|
432
|
-
Note that this will be incompatible with Sass 3.2.
|
433
|
-
WARNING
|
466
|
+
env = env.global_env if node.global
|
467
|
+
if node.guarded
|
468
|
+
var = env.var(node.name)
|
469
|
+
return [] if var && !var.null?
|
434
470
|
end
|
435
471
|
|
436
|
-
var = env.var(node.name)
|
437
|
-
return [] if node.guarded && var && !var.null?
|
438
472
|
val = node.expr.perform(@environment)
|
439
473
|
if node.expr.source_range
|
440
474
|
val.source_range = node.expr.source_range
|
@@ -458,7 +492,7 @@ WARNING
|
|
458
492
|
# Runs the child nodes until the continuation expression becomes false.
|
459
493
|
def visit_while(node)
|
460
494
|
children = []
|
461
|
-
with_environment Sass::
|
495
|
+
with_environment Sass::SemiGlobalEnvironment.new(@environment) do
|
462
496
|
children += node.children.map {|c| visit(c)} while node.expr.perform(@environment).to_bool
|
463
497
|
end
|
464
498
|
children.flatten
|
@@ -466,10 +500,13 @@ WARNING
|
|
466
500
|
|
467
501
|
def visit_directive(node)
|
468
502
|
node.resolved_value = run_interp(node.value)
|
503
|
+
old_in_keyframes, @in_keyframes = @in_keyframes, node.normalized_name == "@keyframes"
|
469
504
|
with_environment Sass::Environment.new(@environment) do
|
470
505
|
node.children = node.children.map {|c| visit(c)}.flatten
|
471
506
|
node
|
472
507
|
end
|
508
|
+
ensure
|
509
|
+
@in_keyframes = old_in_keyframes
|
473
510
|
end
|
474
511
|
|
475
512
|
def visit_media(node)
|
@@ -487,11 +524,14 @@ WARNING
|
|
487
524
|
|
488
525
|
def visit_cssimport(node)
|
489
526
|
node.resolved_uri = run_interp([node.uri])
|
490
|
-
if node.query
|
527
|
+
if node.query && !node.query.empty?
|
491
528
|
parser = Sass::SCSS::StaticParser.new(run_interp(node.query),
|
492
529
|
node.filename, node.options[:importer], node.line)
|
493
530
|
node.resolved_query ||= parser.parse_media_query_list
|
494
531
|
end
|
532
|
+
if node.supports_condition
|
533
|
+
node.supports_condition.perform(@environment)
|
534
|
+
end
|
495
535
|
yield
|
496
536
|
end
|
497
537
|
|
@@ -500,10 +540,7 @@ WARNING
|
|
500
540
|
def run_interp_no_strip(text)
|
501
541
|
text.map do |r|
|
502
542
|
next r if r.is_a?(String)
|
503
|
-
|
504
|
-
# Interpolated strings should never render with quotes
|
505
|
-
next val.value if val.is_a?(Sass::Script::Value::String)
|
506
|
-
val.to_s
|
543
|
+
r.perform(@environment).to_s(:quote => :none)
|
507
544
|
end.join
|
508
545
|
end
|
509
546
|
|
@@ -15,11 +15,21 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
|
|
15
15
|
super
|
16
16
|
end
|
17
17
|
|
18
|
+
def visit_comment(node)
|
19
|
+
node.value.each {|c| c.options = @options if c.is_a?(Sass::Script::Tree::Node)}
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
|
18
23
|
def visit_debug(node)
|
19
24
|
node.expr.options = @options
|
20
25
|
yield
|
21
26
|
end
|
22
27
|
|
28
|
+
def visit_error(node)
|
29
|
+
node.expr.options = @options
|
30
|
+
yield
|
31
|
+
end
|
32
|
+
|
23
33
|
def visit_each(node)
|
24
34
|
node.list.options = @options
|
25
35
|
yield
|
@@ -41,6 +51,7 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
|
|
41
51
|
k.options = @options
|
42
52
|
v.options = @options if v
|
43
53
|
end
|
54
|
+
node.splat.options = @options if node.splat
|
44
55
|
yield
|
45
56
|
end
|
46
57
|
|
@@ -63,12 +74,15 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
|
|
63
74
|
k.options = @options
|
64
75
|
v.options = @options if v
|
65
76
|
end
|
77
|
+
node.splat.options = @options if node.splat
|
66
78
|
yield
|
67
79
|
end
|
68
80
|
|
69
81
|
def visit_mixin(node)
|
70
82
|
node.args.each {|a| a.options = @options}
|
71
|
-
node.keywords.each {|
|
83
|
+
node.keywords.each {|_k, v| v.options = @options}
|
84
|
+
node.splat.options = @options if node.splat
|
85
|
+
node.kwarg_splat.options = @options if node.kwarg_splat
|
72
86
|
yield
|
73
87
|
end
|
74
88
|
|