sass 3.3.0.alpha.256 → 3.3.0.alpha.353

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/REVISION +1 -1
  2. data/Rakefile +21 -1
  3. data/VERSION +1 -1
  4. data/VERSION_DATE +1 -1
  5. data/lib/sass.rb +6 -3
  6. data/lib/sass/cache_stores/base.rb +1 -1
  7. data/lib/sass/cache_stores/chain.rb +2 -1
  8. data/lib/sass/cache_stores/filesystem.rb +2 -6
  9. data/lib/sass/cache_stores/memory.rb +1 -1
  10. data/lib/sass/cache_stores/null.rb +2 -2
  11. data/lib/sass/callbacks.rb +1 -0
  12. data/lib/sass/css.rb +6 -6
  13. data/lib/sass/engine.rb +60 -34
  14. data/lib/sass/environment.rb +3 -1
  15. data/lib/sass/error.rb +5 -5
  16. data/lib/sass/exec.rb +52 -25
  17. data/lib/sass/features.rb +0 -2
  18. data/lib/sass/importers/deprecated_path.rb +1 -1
  19. data/lib/sass/importers/filesystem.rb +8 -6
  20. data/lib/sass/logger/base.rb +3 -3
  21. data/lib/sass/logger/log_level.rb +4 -6
  22. data/lib/sass/media.rb +2 -2
  23. data/lib/sass/plugin.rb +4 -2
  24. data/lib/sass/plugin/compiler.rb +28 -15
  25. data/lib/sass/plugin/configuration.rb +15 -7
  26. data/lib/sass/plugin/merb.rb +1 -1
  27. data/lib/sass/plugin/staleness_checker.rb +24 -8
  28. data/lib/sass/repl.rb +3 -3
  29. data/lib/sass/script.rb +2 -1
  30. data/lib/sass/script/css_lexer.rb +8 -3
  31. data/lib/sass/script/css_parser.rb +6 -2
  32. data/lib/sass/script/functions.rb +164 -109
  33. data/lib/sass/script/lexer.rb +30 -20
  34. data/lib/sass/script/parser.rb +66 -37
  35. data/lib/sass/script/tree/funcall.rb +23 -14
  36. data/lib/sass/script/tree/interpolation.rb +5 -1
  37. data/lib/sass/script/tree/list_literal.rb +5 -4
  38. data/lib/sass/script/tree/map_literal.rb +1 -1
  39. data/lib/sass/script/tree/node.rb +2 -2
  40. data/lib/sass/script/tree/operation.rb +2 -1
  41. data/lib/sass/script/tree/selector.rb +3 -2
  42. data/lib/sass/script/tree/string_interpolation.rb +2 -1
  43. data/lib/sass/script/tree/variable.rb +4 -3
  44. data/lib/sass/script/value/base.rb +12 -14
  45. data/lib/sass/script/value/color.rb +35 -16
  46. data/lib/sass/script/value/helpers.rb +146 -0
  47. data/lib/sass/script/value/list.rb +24 -5
  48. data/lib/sass/script/value/map.rb +1 -1
  49. data/lib/sass/script/value/null.rb +13 -3
  50. data/lib/sass/script/value/number.rb +44 -35
  51. data/lib/sass/script/value/string.rb +2 -2
  52. data/lib/sass/scss/css_parser.rb +2 -1
  53. data/lib/sass/scss/parser.rb +143 -93
  54. data/lib/sass/scss/rx.rb +4 -4
  55. data/lib/sass/scss/script_lexer.rb +1 -0
  56. data/lib/sass/scss/script_parser.rb +1 -0
  57. data/lib/sass/scss/static_parser.rb +5 -5
  58. data/lib/sass/selector.rb +5 -2
  59. data/lib/sass/selector/abstract_sequence.rb +1 -1
  60. data/lib/sass/selector/comma_sequence.rb +16 -14
  61. data/lib/sass/selector/sequence.rb +38 -24
  62. data/lib/sass/selector/simple.rb +4 -4
  63. data/lib/sass/selector/simple_sequence.rb +21 -11
  64. data/lib/sass/source/map.rb +7 -2
  65. data/lib/sass/source/range.rb +1 -1
  66. data/lib/sass/supports.rb +3 -3
  67. data/lib/sass/tree/debug_node.rb +1 -1
  68. data/lib/sass/tree/function_node.rb +2 -1
  69. data/lib/sass/tree/if_node.rb +1 -1
  70. data/lib/sass/tree/import_node.rb +3 -4
  71. data/lib/sass/tree/prop_node.rb +4 -2
  72. data/lib/sass/tree/rule_node.rb +5 -2
  73. data/lib/sass/tree/visitors/base.rb +6 -6
  74. data/lib/sass/tree/visitors/check_nesting.rb +12 -9
  75. data/lib/sass/tree/visitors/convert.rb +34 -28
  76. data/lib/sass/tree/visitors/cssize.rb +4 -3
  77. data/lib/sass/tree/visitors/deep_copy.rb +1 -0
  78. data/lib/sass/tree/visitors/perform.rb +31 -16
  79. data/lib/sass/tree/visitors/to_css.rb +34 -16
  80. data/lib/sass/util.rb +88 -37
  81. data/lib/sass/util/multibyte_string_scanner.rb +2 -0
  82. data/lib/sass/util/ordered_hash.rb +20 -18
  83. data/lib/sass/util/subset_map.rb +3 -2
  84. data/lib/sass/util/test.rb +0 -1
  85. data/lib/sass/version.rb +9 -5
  86. data/test/rubocop_extensions.rb +70 -0
  87. data/test/sass/functions_test.rb +20 -1
  88. data/test/sass/importer_test.rb +2 -1
  89. data/test/sass/script_test.rb +4 -0
  90. data/test/sass/source_map_test.rb +1 -1
  91. data/test/sass/util_test.rb +49 -0
  92. data/test/sass/value_helpers_test.rb +181 -0
  93. metadata +13 -9
@@ -26,7 +26,7 @@ module Sass::Source
26
26
  # @param end_pos [Sass::Source::Position] See \{#end_pos}
27
27
  # @param file [String] See \{#file}
28
28
  # @param importer [Sass::Importers::Base] See \{#importer}
29
- def initialize(start_pos, end_pos, file, importer=nil)
29
+ def initialize(start_pos, end_pos, file, importer = nil)
30
30
  @start_pos = start_pos
31
31
  @end_pos = end_pos
32
32
  @file = file
@@ -81,12 +81,12 @@ module Sass::Supports
81
81
 
82
82
  def left_parens(str)
83
83
  return "(#{str})" if @left.is_a?(Negation)
84
- return str
84
+ str
85
85
  end
86
86
 
87
87
  def right_parens(str)
88
88
  return "(#{str})" if @right.is_a?(Negation) || @right.is_a?(Operator)
89
- return str
89
+ str
90
90
  end
91
91
  end
92
92
 
@@ -127,7 +127,7 @@ module Sass::Supports
127
127
 
128
128
  def parens(str)
129
129
  return "(#{str})" if @condition.is_a?(Negation) || @condition.is_a?(Operator)
130
- return str
130
+ str
131
131
  end
132
132
  end
133
133
 
@@ -5,7 +5,7 @@ module Sass
5
5
  # @see Sass::Tree
6
6
  class DebugNode < Node
7
7
  # The expression to print.
8
- # @return [Script::Tree::Node]
8
+ # @return [Script::Tree::Node]
9
9
  attr_accessor :expr
10
10
 
11
11
  # @param expr [Script::Tree::Node] The expression to print
@@ -21,7 +21,8 @@ module Sass
21
21
  attr_accessor :splat
22
22
 
23
23
  # @param name [String] The function name
24
- # @param args [Array<(Script::Tree::Node, Script::Tree::Node)>] The arguments for the function.
24
+ # @param args [Array<(Script::Tree::Node, Script::Tree::Node)>]
25
+ # The arguments for the function.
25
26
  # @param splat [Script::Tree::Node] See \{#splat}
26
27
  def initialize(name, args, splat)
27
28
  @name = name
@@ -36,7 +36,7 @@ module Sass::Tree
36
36
  end
37
37
 
38
38
  def _dump(f)
39
- Marshal.dump([self.expr, self.else, self.children])
39
+ Marshal.dump([expr, self.else, children])
40
40
  end
41
41
 
42
42
  def self._load(data)
@@ -51,9 +51,8 @@ module Sass
51
51
  end
52
52
 
53
53
  paths.each do |p|
54
- if f = p.find(@imported_filename, options_for_importer)
55
- return f
56
- end
54
+ f = p.find(@imported_filename, options_for_importer)
55
+ return f if f
57
56
  end
58
57
 
59
58
  message = "File to import not found or unreadable: #{@imported_filename}.\n"
@@ -64,7 +63,7 @@ module Sass
64
63
  end
65
64
  raise SyntaxError.new(message)
66
65
  rescue SyntaxError => e
67
- raise SyntaxError.new(e.message, :line => self.line, :filename => @filename)
66
+ raise SyntaxError.new(e.message, :line => line, :filename => @filename)
68
67
  end
69
68
 
70
69
  def options_for_importer
@@ -99,7 +99,8 @@ module Sass::Tree
99
99
  def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
100
100
  name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
101
101
  if name[0] == ?:
102
- raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
102
+ raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\"" +
103
+ " hack is not allowed in the Sass indented syntax")
103
104
  end
104
105
 
105
106
  old = opts[:old] && fmt == :sass
@@ -120,7 +121,8 @@ module Sass::Tree
120
121
  def check!
121
122
  if @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
122
123
  raise Sass::SyntaxError.new(
123
- "Illegal property syntax: can't use #{@prop_syntax} syntax when :property_syntax => #{@options[:property_syntax].inspect} is set.")
124
+ "Illegal property syntax: can't use #{@prop_syntax} syntax when " +
125
+ ":property_syntax => #{@options[:property_syntax].inspect} is set.")
124
126
  end
125
127
  end
126
128
 
@@ -111,12 +111,13 @@ module Sass::Tree
111
111
 
112
112
  # A hash that will be associated with this rule in the CSS document
113
113
  # if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled.
114
- # This data is used by e.g. [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
114
+ # This data is used by e.g. [the FireSass Firebug
115
+ # extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
115
116
  #
116
117
  # @return [{#to_s => #to_s}]
117
118
  def debug_info
118
119
  {:filename => filename && ("file://" + Sass::Util.escape_uri(File.expand_path(filename))),
119
- :line => self.line}
120
+ :line => line}
120
121
  end
121
122
 
122
123
  # A rule node is invisible if it has only placeholder selectors.
@@ -131,7 +132,9 @@ module Sass::Tree
131
132
  # We don't use real filename/line info because we don't have it yet.
132
133
  # When we get it, we'll set it on the parsed rules if possible.
133
134
  parser = Sass::SCSS::StaticParser.new(@rule.join.strip, '', nil, 1)
135
+ # rubocop:disable RescueModifier
134
136
  @parsed_rules = parser.parse_selector rescue nil
137
+ # rubocop:enable RescueModifier
135
138
  end
136
139
  end
137
140
  end
@@ -32,9 +32,9 @@ module Sass::Tree::Visitors
32
32
  # @param node [Tree::Node] The node to visit.
33
33
  # @return [Object] The return value of the `visit_*` method for this node.
34
34
  def visit(node)
35
- method = "visit_#{node_name node}"
36
- if self.respond_to?(method, true)
37
- self.send(method, node) {visit_children(node)}
35
+ method = "visit_#{self.class.node_name node}"
36
+ if respond_to?(method, true)
37
+ send(method, node) {visit_children(node)}
38
38
  else
39
39
  visit_children(node)
40
40
  end
@@ -59,9 +59,9 @@ module Sass::Tree::Visitors
59
59
  #
60
60
  # @param [Tree::Node] node The node.
61
61
  # @return [String] The name.
62
- def node_name(node)
63
- @@node_names ||= {}
64
- @@node_names[node.class.name] ||= node.class.name.gsub(NODE_NAME_RE, '\\1').downcase
62
+ def self.node_name(node)
63
+ @node_names ||= {}
64
+ @node_names[node.class.name] ||= node.class.name.gsub(NODE_NAME_RE, '\\1').downcase
65
65
  end
66
66
 
67
67
  # `yield`s, then runs the visitor on the `@else` clause if the node has one.
@@ -1,5 +1,6 @@
1
1
  # A visitor for checking that all nodes are properly nested.
2
2
  class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
3
+
3
4
  protected
4
5
 
5
6
  def initialize
@@ -7,9 +8,9 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
7
8
  end
8
9
 
9
10
  def visit(node)
10
- if error = @parent && (
11
- try_send("invalid_#{node_name @parent}_child?", @parent, node) ||
12
- try_send("invalid_#{node_name node}_parent?", @parent, node))
11
+ if (error = @parent && (
12
+ try_send("invalid_#{self.class.node_name @parent}_child?", @parent, node) ||
13
+ try_send("invalid_#{self.class.node_name node}_parent?", @parent, node)))
13
14
  raise Sass::SyntaxError.new(error)
14
15
  end
15
16
  super
@@ -19,7 +20,7 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
19
20
  end
20
21
 
21
22
  CONTROL_NODES = [Sass::Tree::EachNode, Sass::Tree::ForNode, Sass::Tree::IfNode,
22
- Sass::Tree::WhileNode, Sass::Tree::TraceNode]
23
+ Sass::Tree::WhileNode, Sass::Tree::TraceNode]
23
24
  SCRIPT_NODES = [Sass::Tree::ImportNode] + CONTROL_NODES
24
25
  def visit_children(parent)
25
26
  old_parent = @parent
@@ -110,7 +111,9 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
110
111
  end
111
112
  end
112
113
 
113
- VALID_PROP_CHILDREN = [Sass::Tree::CommentNode, Sass::Tree::PropNode, Sass::Tree::MixinNode] + CONTROL_NODES
114
+ VALID_PROP_CHILDREN = CONTROL_NODES + [Sass::Tree::CommentNode,
115
+ Sass::Tree::PropNode,
116
+ Sass::Tree::MixinNode]
114
117
  def invalid_prop_child?(parent, child)
115
118
  unless is_any_of?(child, VALID_PROP_CHILDREN)
116
119
  "Illegal nesting: Only properties may be nested beneath properties."
@@ -122,7 +125,8 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
122
125
  Sass::Tree::MixinNode]
123
126
  def invalid_prop_parent?(parent, child)
124
127
  unless is_any_of?(parent, VALID_PROP_PARENTS)
125
- "Properties are only allowed within rules, directives, mixin includes, or other properties." + child.pseudo_class_selector_message
128
+ "Properties are only allowed within rules, directives, mixin includes, or other properties." +
129
+ child.pseudo_class_selector_message
126
130
  end
127
131
  end
128
132
 
@@ -133,10 +137,10 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
133
137
  private
134
138
 
135
139
  def is_any_of?(val, classes)
136
- for c in classes
140
+ classes.each do |c|
137
141
  return true if val.is_a?(c)
138
142
  end
139
- return false
143
+ false
140
144
  end
141
145
 
142
146
  def try_send(method, *args)
@@ -144,4 +148,3 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
144
148
  send(method, *args)
145
149
  end
146
150
  end
147
-
@@ -23,7 +23,11 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
23
23
  def visit_children(parent)
24
24
  @tabs += 1
25
25
  return @format == :sass ? "\n" : " {}\n" if parent.children.empty?
26
- (@format == :sass ? "\n" : " {\n") + super.join.rstrip + (@format == :sass ? "\n" : "\n#{ @tab_chars * (@tabs-1)}}\n")
26
+ if @format == :sass
27
+ "\n" + super.join.rstrip + "\n"
28
+ else
29
+ " {\n" + super.join.rstrip + "\n#{ @tab_chars * (@tabs - 1)}}\n"
30
+ end
27
31
  ensure
28
32
  @tabs -= 1
29
33
  end
@@ -52,7 +56,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
52
56
 
53
57
  def visit_comment(node)
54
58
  value = interp_to_src(node.value)
55
- content = if @format == :sass
59
+ if @format == :sass
56
60
  content = value.gsub(/\*\/$/, '').rstrip
57
61
  if content =~ /\A[ \t]/
58
62
  # Re-indent SCSS comments like this:
@@ -63,31 +67,27 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
63
67
  content.sub!(/\A([ \t]*)\/\*/, '/*\1')
64
68
  end
65
69
 
66
- content =
67
- unless content.include?("\n")
68
- content
70
+ if content.include?("\n")
71
+ content.gsub!(%r{\n( \*|//)}, "\n ")
72
+ spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
73
+ sep = node.type == :silent ? "\n//" : "\n *"
74
+ if spaces >= 2
75
+ content.gsub!(/\n /, sep)
69
76
  else
70
- content.gsub!(/\n( \*|\/\/)/, "\n ")
71
- spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
72
- sep = node.type == :silent ? "\n//" : "\n *"
73
- if spaces >= 2
74
- content.gsub(/\n /, sep)
75
- else
76
- content.gsub(/\n#{' ' * spaces}/, sep)
77
- end
77
+ content.gsub!(/\n#{' ' * spaces}/, sep)
78
78
  end
79
+ end
79
80
 
80
81
  content.gsub!(/\A\/\*/, '//') if node.type == :silent
81
82
  content.gsub!(/^/, tab_str)
82
- content.rstrip + "\n"
83
+ content = content.rstrip + "\n"
83
84
  else
84
85
  spaces = (@tab_chars * [@tabs - value[/^ */].size, 0].max)
85
86
  content = if node.type == :silent
86
- value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
87
- else
88
- value
89
- end.gsub(/^/, spaces) + "\n"
90
- content
87
+ value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
88
+ else
89
+ value
90
+ end.gsub(/^/, spaces) + "\n"
91
91
  end
92
92
  content
93
93
  end
@@ -98,7 +98,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
98
98
 
99
99
  def visit_directive(node)
100
100
  res = "#{tab_str}#{interp_to_src(node.value)}"
101
- res.gsub!(/^@import \#\{(.*)\}([^}]*)$/, '@import \1\2');
101
+ res.gsub!(/^@import \#\{(.*)\}([^}]*)$/, '@import \1\2')
102
102
  return res + "#{semi}\n" unless node.has_children
103
103
  res + yield + "\n"
104
104
  end
@@ -109,7 +109,8 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
109
109
  end
110
110
 
111
111
  def visit_extend(node)
112
- "#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}#{" !optional" if node.optional?}\n"
112
+ "#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}" +
113
+ "#{" !optional" if node.optional?}\n"
113
114
  end
114
115
 
115
116
  def visit_for(node)
@@ -131,9 +132,12 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
131
132
 
132
133
  def visit_if(node)
133
134
  name =
134
- if !@is_else; "if"
135
- elsif node.expr; "else if"
136
- else; "else"
135
+ if !@is_else
136
+ "if"
137
+ elsif node.expr
138
+ "else if"
139
+ else
140
+ "else"
137
141
  end
138
142
  @is_else = false
139
143
  str = "#{tab_str}@#{name}"
@@ -206,13 +210,14 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
206
210
  keywords = Sass::Util.hash_to_a(node.keywords).
207
211
  map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}.join(', ')
208
212
  if node.splat
209
- splat = (args.empty? && keywords.empty?) ? "" : ", "
213
+ splat = args.empty? && keywords.empty? ? "" : ", "
210
214
  splat = "#{splat}#{arg_to_sass[node.splat]}..."
211
215
  splat = "#{splat}, #{node.kwarg_splat.inspect}..." if node.kwarg_splat
212
216
  end
213
217
  arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
214
218
  end
215
- "#{tab_str}#{@format == :sass ? '+' : '@include '}#{dasherize(node.name)}#{arglist}#{node.has_children ? yield : semi}\n"
219
+ "#{tab_str}#{@format == :sass ? '+' : '@include '}" +
220
+ "#{dasherize(node.name)}#{arglist}#{node.has_children ? yield : semi}\n"
216
221
  end
217
222
 
218
223
  def visit_content(node)
@@ -246,7 +251,8 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
246
251
  end
247
252
 
248
253
  def visit_variable(node)
249
- "#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}#{' !default' if node.guarded}#{semi}\n"
254
+ "#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}" +
255
+ "#{' !default' if node.guarded}#{semi}\n"
250
256
  end
251
257
 
252
258
  def visit_warn(node)
@@ -280,7 +286,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
280
286
  def media_interp_to_src(interp)
281
287
  Sass::Util.enum_with_index(interp).map do |r, i|
282
288
  next r if r.is_a?(String)
283
- before, after = interp[i-1], interp[i+1]
289
+ before, after = interp[i - 1], interp[i + 1]
284
290
  if before.is_a?(String) && after.is_a?(String) &&
285
291
  ((before[-1] == ?( && after[0] == ?:) ||
286
292
  (before =~ /:\s*/ && after[0] == ?)))
@@ -81,7 +81,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
81
81
  node.children.each_with_index.find {|c, _| c.is_a?(Sass::Tree::CharsetNode)}
82
82
  if charset_and_index
83
83
  index = charset_and_index.last
84
- node.children = node.children[0..index] + imports + node.children[index+1..-1]
84
+ node.children = node.children[0..index] + imports + node.children[index + 1..-1]
85
85
  else
86
86
  node.children = imports + node.children
87
87
  end
@@ -125,7 +125,7 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
125
125
 
126
126
  sel = sseq.members
127
127
  parent.resolved_rules.members.each do |member|
128
- if !member.members.last.is_a?(Sass::Selector::SimpleSequence)
128
+ unless member.members.last.is_a?(Sass::Selector::SimpleSequence)
129
129
  raise Sass::SyntaxError.new("#{member} can't extend: invalid selector")
130
130
  end
131
131
 
@@ -195,7 +195,8 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
195
195
  # and updates the indentation of the rule node based on the nesting level.
196
196
  def visit_rule(node)
197
197
  parent_resolved_rules = parent.is_a?(Sass::Tree::RuleNode) ? parent.resolved_rules : nil
198
- # It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling
198
+ # It's possible for resolved_rules to be set
199
+ # if we've duplicated this node during @media bubbling
199
200
  node.resolved_rules ||= node.parsed_rules.resolve_parent_refs(parent_resolved_rules)
200
201
 
201
202
  yield
@@ -1,5 +1,6 @@
1
1
  # A visitor for copying the full structure of a Sass tree.
2
2
  class Sass::Tree::Visitors::DeepCopy < Sass::Tree::Visitors::Base
3
+
3
4
  protected
4
5
 
5
6
  def visit(node)
@@ -9,6 +9,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
9
9
  end
10
10
 
11
11
  # @api private
12
+ # @comment
13
+ # rubocop:disable MethodLength
12
14
  def perform_arguments(callable, args, keywords, splat)
13
15
  desc = "#{callable.type.capitalize} #{callable.name}"
14
16
  downcase_desc = "#{callable.type} #{callable.name}"
@@ -25,10 +27,12 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
25
27
  unknown_args = Sass::Util.array_minus(keywords.keys,
26
28
  callable.args.map {|var| var.first.underscored_name})
27
29
  if callable.splat && unknown_args.include?(callable.splat.underscored_name)
28
- raise Sass::SyntaxError.new("Argument $#{callable.splat.name} of #{downcase_desc} cannot be used as a named argument.")
30
+ raise Sass::SyntaxError.new("Argument $#{callable.splat.name} of #{downcase_desc} " +
31
+ "cannot be used as a named argument.")
29
32
  elsif unknown_args.any?
30
33
  description = unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'
31
- raise Sass::SyntaxError.new("#{desc} doesn't have #{description} #{unknown_args.map {|name| "$#{name}"}.join ', '}.")
34
+ raise Sass::SyntaxError.new("#{desc} doesn't have #{description} " +
35
+ "#{unknown_args.map {|name| "$#{name}"}.join ', '}.")
32
36
  end
33
37
  end
34
38
  rescue Sass::SyntaxError => keyword_exception
@@ -56,7 +60,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
56
60
  env = Sass::Environment.new(callable.environment)
57
61
  callable.args.zip(args[0...callable.args.length]) do |(var, default), value|
58
62
  if value && keywords.include?(var.underscored_name)
59
- raise Sass::SyntaxError.new("#{desc} was passed argument $#{var.name} both by position and by name.")
63
+ raise Sass::SyntaxError.new("#{desc} was passed argument $#{var.name} " +
64
+ "both by position and by name.")
60
65
  end
61
66
 
62
67
  value ||= keywords.delete(var.underscored_name)
@@ -73,7 +78,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
73
78
  end
74
79
 
75
80
  yield env
76
- rescue Exception => e
81
+ rescue StandardError => e
77
82
  ensure
78
83
  # If there's a keyword exception, we don't want to throw it immediately,
79
84
  # because the invalid keywords may be part of a glob argument that should be
@@ -111,7 +116,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
111
116
 
112
117
  kwarg_splat = kwarg_splat.perform(environment)
113
118
  unless kwarg_splat.is_a?(Sass::Script::Value::Map)
114
- raise Sass::SyntaxError.new("Variable keyword arguments must be a map (was #{kwarg_splat.inspect}).")
119
+ raise Sass::SyntaxError.new("Variable keyword arguments must be a map " +
120
+ "(was #{kwarg_splat.inspect}).")
115
121
  end
116
122
 
117
123
  if splat.is_a?(Sass::Script::Value::ArgList)
@@ -128,10 +134,12 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
128
134
  Sass::Util.map_keys(map.to_h) do |key|
129
135
  next key.value if key.is_a?(Sass::Script::Value::String)
130
136
  raise Sass::SyntaxError.new("Variable keyword argument map must have string keys.\n" +
131
- "#{key.inspect} is not a string in #{map.inspect}.");
137
+ "#{key.inspect} is not a string in #{map.inspect}.")
132
138
  end
133
139
  end
134
140
  end
141
+ # @comment
142
+ # rubocop:enable MethodLength
135
143
 
136
144
  protected
137
145
 
@@ -246,7 +254,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
246
254
  def visit_function(node)
247
255
  env = Sass::Environment.new(@environment, node.options)
248
256
  @environment.set_local_function(node.name,
249
- Sass::Callable.new(node.name, node.args, node.splat, env, node.children, !:has_content, "function"))
257
+ Sass::Callable.new(node.name, node.args, node.splat, env,
258
+ node.children, !:has_content, "function"))
250
259
  []
251
260
  end
252
261
 
@@ -266,7 +275,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
266
275
  # Returns a static DirectiveNode if this is importing a CSS file,
267
276
  # or parses and includes the imported Sass file.
268
277
  def visit_import(node)
269
- if path = node.css_import?
278
+ if (path = node.css_import?)
270
279
  resolved_node = Sass::Tree::CssImportNode.resolved("url(#{path})")
271
280
  resolved_node.source_range = node.source_range
272
281
  return resolved_node
@@ -294,18 +303,22 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
294
303
  def visit_mixindef(node)
295
304
  env = Sass::Environment.new(@environment, node.options)
296
305
  @environment.set_local_mixin(node.name,
297
- Sass::Callable.new(node.name, node.args, node.splat, env, node.children, node.has_content, "mixin"))
306
+ Sass::Callable.new(node.name, node.args, node.splat, env,
307
+ node.children, node.has_content, "mixin"))
298
308
  []
299
309
  end
300
310
 
301
311
  # Runs a mixin.
302
312
  def visit_mixin(node)
303
313
  include_loop = true
304
- handle_include_loop!(node) if @environment.stack.frames.any? {|f| f.is_mixin? && f.name == node.name}
314
+ if @environment.stack.frames.any? {|f| f.is_mixin? && f.name == node.name}
315
+ handle_include_loop!(node)
316
+ end
305
317
  include_loop = false
306
318
 
307
319
  @environment.stack.with_mixin(node.filename, node.line, node.name) do
308
- raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin = @environment.mixin(node.name)
320
+ mixin = @environment.mixin(node.name)
321
+ raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin
309
322
 
310
323
  if node.children.any? && !mixin.has_content
311
324
  raise Sass::SyntaxError.new(%Q{Mixin "#{node.name}" does not accept a content block.})
@@ -333,10 +346,13 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
333
346
  end
334
347
 
335
348
  def visit_content(node)
336
- return [] unless content = @environment.content
349
+ content = @environment.content
350
+ return [] unless content
337
351
  @environment.stack.with_mixin(node.filename, node.line, '@content') do
338
352
  trace_node = Sass::Tree::TraceNode.from_node('@content', node)
339
- with_environment(@environment.caller) {trace_node.children = content.map {|c| visit(c.dup)}.flatten}
353
+ with_environment(@environment.caller) do
354
+ trace_node.children = content.map {|c| visit(c.dup)}.flatten
355
+ end
340
356
  trace_node
341
357
  end
342
358
  rescue Sass::SyntaxError => e
@@ -362,8 +378,6 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
362
378
  # Runs SassScript interpolation in the selector,
363
379
  # and then parses the result into a {Sass::Selector::CommaSequence}.
364
380
  def visit_rule(node)
365
- rule = node.rule
366
- rule = rule.map {|e| e.is_a?(String) && e != ' ' ? e.strip : e} if node.style == :compressed
367
381
  parser = Sass::SCSS::StaticParser.new(run_interp(node.rule),
368
382
  node.filename, node.options[:importer], node.line)
369
383
  node.parsed_rules ||= parser.parse_selector
@@ -455,7 +469,8 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
455
469
  def handle_include_loop!(node)
456
470
  msg = "An @include loop has been found:"
457
471
  content_count = 0
458
- mixins = @environment.stack.frames.select {|f| f.is_mixin?}.reverse.map {|f| f.name}.select do |name|
472
+ mixins = @environment.stack.frames.select {|f| f.is_mixin?}.reverse!.map! {|f| f.name}
473
+ mixins = mixins.select do |name|
459
474
  if name == '@content'
460
475
  content_count += 1
461
476
  false