sass 3.2.19 → 3.3.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CONTRIBUTING +1 -1
  2. data/MIT-LICENSE +2 -2
  3. data/README.md +13 -14
  4. data/REVISION +1 -1
  5. data/Rakefile +4 -6
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -1
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +1 -6
  10. data/bin/sass-convert +1 -6
  11. data/bin/scss +1 -6
  12. data/lib/sass/cache_stores/base.rb +0 -2
  13. data/lib/sass/cache_stores/chain.rb +1 -1
  14. data/lib/sass/cache_stores/filesystem.rb +3 -6
  15. data/lib/sass/callbacks.rb +1 -1
  16. data/lib/sass/css.rb +1 -1
  17. data/lib/sass/engine.rb +4 -11
  18. data/lib/sass/error.rb +2 -2
  19. data/lib/sass/exec.rb +10 -40
  20. data/lib/sass/importers/filesystem.rb +15 -52
  21. data/lib/sass/logger/log_level.rb +3 -3
  22. data/lib/sass/media.rb +4 -1
  23. data/lib/sass/plugin.rb +1 -2
  24. data/lib/sass/plugin/compiler.rb +18 -40
  25. data/lib/sass/plugin/staleness_checker.rb +5 -21
  26. data/lib/sass/railtie.rb +0 -1
  27. data/lib/sass/script/funcall.rb +8 -62
  28. data/lib/sass/script/functions.rb +457 -557
  29. data/lib/sass/script/lexer.rb +30 -25
  30. data/lib/sass/script/list.rb +1 -2
  31. data/lib/sass/script/literal.rb +18 -0
  32. data/lib/sass/script/null.rb +1 -4
  33. data/lib/sass/script/operation.rb +1 -0
  34. data/lib/sass/script/parser.rb +35 -42
  35. data/lib/sass/script/string.rb +1 -1
  36. data/lib/sass/script/unary_operation.rb +3 -8
  37. data/lib/sass/scss/parser.rb +14 -33
  38. data/lib/sass/scss/rx.rb +10 -3
  39. data/lib/sass/selector.rb +16 -19
  40. data/lib/sass/selector/sequence.rb +7 -16
  41. data/lib/sass/selector/simple.rb +1 -1
  42. data/lib/sass/selector/simple_sequence.rb +15 -25
  43. data/lib/sass/tree/comment_node.rb +2 -2
  44. data/lib/sass/tree/import_node.rb +2 -9
  45. data/lib/sass/tree/visitors/check_nesting.rb +2 -3
  46. data/lib/sass/tree/visitors/convert.rb +4 -9
  47. data/lib/sass/tree/visitors/cssize.rb +15 -36
  48. data/lib/sass/tree/visitors/perform.rb +20 -23
  49. data/lib/sass/tree/visitors/set_options.rb +0 -8
  50. data/lib/sass/tree/visitors/to_css.rb +1 -0
  51. data/lib/sass/util.rb +2 -120
  52. data/lib/sass/util/multibyte_string_scanner.rb +8 -29
  53. data/test/sass/conversion_test.rb +8 -33
  54. data/test/sass/css2sass_test.rb +0 -19
  55. data/test/sass/engine_test.rb +17 -129
  56. data/test/sass/extend_test.rb +24 -169
  57. data/test/sass/functions_test.rb +73 -93
  58. data/test/sass/plugin_test.rb +11 -72
  59. data/test/sass/script_conversion_test.rb +0 -14
  60. data/test/sass/script_test.rb +1 -40
  61. data/test/sass/scss/css_test.rb +3 -44
  62. data/test/sass/scss/scss_test.rb +3 -134
  63. data/test/sass/util_test.rb +0 -93
  64. data/vendor/listen/CHANGELOG.md +2 -83
  65. data/vendor/listen/Gemfile +1 -8
  66. data/vendor/listen/Guardfile +1 -1
  67. data/vendor/listen/LICENSE +1 -1
  68. data/vendor/listen/README.md +5 -8
  69. data/vendor/listen/lib/listen.rb +5 -7
  70. data/vendor/listen/lib/listen/adapter.rb +29 -76
  71. data/vendor/listen/lib/listen/adapters/darwin.rb +10 -11
  72. data/vendor/listen/lib/listen/adapters/linux.rb +30 -33
  73. data/vendor/listen/lib/listen/adapters/polling.rb +1 -2
  74. data/vendor/listen/lib/listen/adapters/windows.rb +21 -27
  75. data/vendor/listen/lib/listen/directory_record.rb +10 -63
  76. data/vendor/listen/lib/listen/listener.rb +0 -22
  77. data/vendor/listen/lib/listen/multi_listener.rb +0 -22
  78. data/vendor/listen/lib/listen/version.rb +1 -1
  79. data/vendor/listen/listen.gemspec +4 -0
  80. data/vendor/listen/spec/listen/adapter_spec.rb +4 -45
  81. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -6
  82. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -6
  83. data/vendor/listen/spec/listen/adapters/windows_spec.rb +1 -7
  84. data/vendor/listen/spec/listen/directory_record_spec.rb +4 -91
  85. data/vendor/listen/spec/listen/listener_spec.rb +0 -14
  86. data/vendor/listen/spec/listen/multi_listener_spec.rb +1 -19
  87. data/vendor/listen/spec/spec_helper.rb +3 -6
  88. data/vendor/listen/spec/support/adapter_helper.rb +212 -125
  89. data/vendor/listen/spec/support/listeners_helper.rb +1 -13
  90. data/vendor/listen/spec/support/platform_helper.rb +0 -4
  91. metadata +113 -105
  92. checksums.yaml +0 -7
  93. data/lib/sass/util/test.rb +0 -10
  94. data/test/sass/exec_test.rb +0 -86
  95. data/test/sass/results/cached_import_option.css +0 -3
  96. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  97. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  98. data/test/sass/templates/bork5.sass +0 -3
  99. data/test/sass/templates/cached_import_option.scss +0 -3
  100. data/test/sass/templates/same_name_different_ext.sass +0 -2
  101. data/test/sass/templates/same_name_different_ext.scss +0 -1
  102. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  103. data/test/sass/templates/subdir/import_up1.scss +0 -1
  104. data/test/sass/templates/subdir/import_up2.scss +0 -1
  105. data/vendor/listen/CONTRIBUTING.md +0 -38
  106. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -112
  107. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  108. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  109. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
@@ -124,9 +124,16 @@ module Sass
124
124
  STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
125
125
  STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
126
126
  STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
127
-
128
- STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
129
- STATIC_VALUE = /#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*([;}])/i
127
+ # Can't use IDENT here, because it seems to take exponential time on 1.8.
128
+ # We could use it for 1.9 only, but I don't want to introduce a cross-version
129
+ # behavior difference.
130
+ # In any case, almost all CSS idents will be matched by this.
131
+ #
132
+ # We explicitly avoid parsing newlines or values/selectors longer than
133
+ # about 50 characters. This mitigates the problem of exponential parsing
134
+ # time when a value has a long string of valid, parsable content followed
135
+ # by something invalid.
136
+ STATIC_VALUE = /(-?#{NMSTART}|#{STRING_NOINTERP}|[ \t](?!%)|#[a-f0-9]|[,%]|#{NUM}|\!important){1,50}([;}])/i
130
137
  STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){0,50}([{])/i
131
138
  end
132
139
  end
@@ -120,7 +120,7 @@ module Sass
120
120
 
121
121
  # @see AbstractSequence#specificity
122
122
  def specificity
123
- SPECIFICITY_BASE
123
+ 0
124
124
  end
125
125
  end
126
126
 
@@ -346,19 +346,19 @@ module Sass
346
346
  # A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`) selector.
347
347
  # It can have arguments (e.g. `:nth-child(2n+1)`).
348
348
  class Pseudo < Simple
349
- # Some psuedo-class-syntax selectors are actually considered
350
- # pseudo-elements and must be treated differently. This is a list of such
351
- # selectors
349
+ # The type of the selector.
350
+ # `:class` if this is a pseudoclass selector,
351
+ # `:element` if it's a pseudoelement.
352
352
  #
353
- # @return [Array<String>]
354
- ACTUALLY_ELEMENTS = %w[after before first-line first-letter]
353
+ # @return [Symbol]
354
+ attr_reader :type
355
355
 
356
- # Like \{#type}, but returns the type of selector this looks like, rather
357
- # than the type it is semantically. This only differs from type for
358
- # selectors in \{ACTUALLY\_ELEMENTS}.
356
+ # Some psuedo-class-syntax selectors (`:after` and `:before)
357
+ # are actually considered pseudo-elements
358
+ # and must be at the end of the selector to function properly.
359
359
  #
360
- # @return [Symbol]
361
- attr_reader :syntactic_type
360
+ # @return [Array<String>]
361
+ FINAL_SELECTORS = %w[after before]
362
362
 
363
363
  # The name of the selector.
364
364
  #
@@ -380,22 +380,18 @@ module Sass
380
380
  # @param arg [nil, Array<String, Sass::Script::Node>] The argument to the selector,
381
381
  # or nil if no argument was given
382
382
  def initialize(type, name, arg)
383
- @syntactic_type = type
383
+ @type = type
384
384
  @name = name
385
385
  @arg = arg
386
386
  end
387
387
 
388
- # The type of the selector. `:class` if this is a pseudoclass selector,
389
- # `:element` if it's a pseudoelement.
390
- #
391
- # @return [Symbol]
392
- def type
393
- ACTUALLY_ELEMENTS.include?(name.first) ? :element : syntactic_type
388
+ def final?
389
+ type == :class && FINAL_SELECTORS.include?(name.first)
394
390
  end
395
391
 
396
392
  # @see Selector#to_a
397
393
  def to_a
398
- res = [syntactic_type == :class ? ":" : "::"] + @name
394
+ res = [@type == :class ? ":" : "::"] + @name
399
395
  (res << "(").concat(Sass::Util.strip_string_array(@arg)) << ")" if @arg
400
396
  res
401
397
  end
@@ -409,6 +405,7 @@ module Sass
409
405
  sel.is_a?(Pseudo) && sel.type == :element &&
410
406
  (sel.name != self.name || sel.arg != self.arg)
411
407
  end
408
+ return sels + [self] if final?
412
409
  super
413
410
  end
414
411
 
@@ -255,7 +255,7 @@ module Sass
255
255
  # is a supersequence of the other, use that, otherwise give up.
256
256
  lcs = Sass::Util.lcs(ops1, ops2)
257
257
  return unless lcs == ops1 || lcs == ops2
258
- res.unshift(*(ops1.size > ops2.size ? ops1 : ops2).reverse)
258
+ res.unshift *(ops1.size > ops2.size ? ops1 : ops2).reverse
259
259
  return res
260
260
  end
261
261
 
@@ -437,32 +437,23 @@ module Sass
437
437
  # @param seqses [Array<Array<Array<SimpleSequence or String>>>]
438
438
  # @return [Array<Array<Array<SimpleSequence or String>>>]
439
439
  def trim(seqses)
440
- # Avoid truly horrific quadratic behavior. TODO: I think there
441
- # may be a way to get perfect trimming without going quadratic.
442
- return seqses if seqses.size > 100
443
-
444
- # Keep the results in a separate array so we can be sure we aren't
445
- # comparing against an already-trimmed selector. This ensures that two
446
- # identical selectors don't mutually trim one another.
447
- result = seqses.dup
448
-
449
440
  # This is n^2 on the sequences, but only comparing between
450
441
  # separate sequences should limit the quadratic behavior.
451
- seqses.each_with_index do |seqs1, i|
452
- result[i] = seqs1.reject do |seq1|
453
- max_spec = _sources(seq1).map {|seq| seq.specificity}.max || 0
454
- result.any? do |seqs2|
442
+ seqses.map do |seqs1|
443
+ seqs1.reject do |seq1|
444
+ min_spec = 0
445
+ _sources(seq1).map {|seq| min_spec += seq.specificity}
446
+ seqses.any? do |seqs2|
455
447
  next if seqs1.equal?(seqs2)
456
448
  # Second Law of Extend: the specificity of a generated selector
457
449
  # should never be less than the specificity of the extending
458
450
  # selector.
459
451
  #
460
452
  # See https://github.com/nex3/sass/issues/324.
461
- seqs2.any? {|seq2| _specificity(seq2) >= max_spec && _superselector?(seq2, seq1)}
453
+ seqs2.any? {|seq2| _specificity(seq2) >= min_spec && _superselector?(seq2, seq1)}
462
454
  end
463
455
  end
464
456
  end
465
- result
466
457
  end
467
458
 
468
459
  def _hash
@@ -85,7 +85,7 @@ module Sass
85
85
  sels_with_ix = Sass::Util.enum_with_index(sels)
86
86
  _, i =
87
87
  if self.is_a?(Pseudo) || self.is_a?(SelectorPseudoClass)
88
- sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && (sels.last.type == :element)}
88
+ sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && (sels.last.final? || sels.last.type == :element)}
89
89
  else
90
90
  sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)}
91
91
  end
@@ -37,16 +37,11 @@ module Sass
37
37
  @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal))
38
38
  end
39
39
 
40
- def pseudo_elements
41
- @pseudo_elements ||= (members - [base]).
42
- select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
43
- end
44
-
45
- # Returns the non-base, non-pseudo-class selectors in this sequence.
40
+ # Returns the non-base selectors in this sequence.
46
41
  #
47
42
  # @return [Set<Simple>]
48
43
  def rest
49
- @rest ||= Set.new(members - [base] - pseudo_elements)
44
+ @rest ||= Set.new(base ? members[1..-1] : members)
50
45
  end
51
46
 
52
47
  # Whether or not this compound selector is the subject of the parent
@@ -79,16 +74,13 @@ module Sass
79
74
  # Parent selector only appears as the first selector in the sequence
80
75
  return [self] unless @members.first.is_a?(Parent)
81
76
 
82
- members = super_seq.members.dup
83
- newline = members.pop if members.last == "\n"
84
- return members if @members.size == 1
85
- unless members.last.is_a?(SimpleSequence)
77
+ return super_seq.members if @members.size == 1
78
+ unless super_seq.members.last.is_a?(SimpleSequence)
86
79
  raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join)
87
80
  end
88
81
 
89
- members[0...-1] +
90
- [SimpleSequence.new(members.last.members + @members[1..-1], subject?)] +
91
- [newline].compact
82
+ super_seq.members[0...-1] +
83
+ [SimpleSequence.new(super_seq.members.last.members + @members[1..-1], subject?)]
92
84
  end
93
85
 
94
86
  # Non-destrucively extends this selector with the extensions specified in a hash
@@ -109,8 +101,8 @@ module Sass
109
101
  # If A {@extend B} and C {...},
110
102
  # seq is A, sels is B, and self is C
111
103
 
112
- self_without_sel = Sass::Util.array_minus(self.members, sels)
113
- group.each {|e, _| e.result = :failed_to_unify unless e.result == :succeeded}
104
+ self_without_sel = self.members - sels
105
+ group.each {|e, _| e.result = :failed_to_unify}
114
106
  next unless unified = seq.members.last.unify(self_without_sel, subject?)
115
107
  group.each {|e, _| e.result = :succeeded}
116
108
  next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
@@ -137,9 +129,9 @@ module Sass
137
129
  # by the time extension and unification happen,
138
130
  # this exception will only ever be raised as a result of programmer error
139
131
  def unify(sels, other_subject)
140
- return unless sseq = members.inject(sels) do |member, sel|
141
- return unless member
142
- sel.unify(member)
132
+ return unless sseq = members.inject(sels) do |sseq, sel|
133
+ return unless sseq
134
+ sel.unify(sseq)
143
135
  end
144
136
  SimpleSequence.new(sseq, other_subject || subject?)
145
137
  end
@@ -153,9 +145,7 @@ module Sass
153
145
  # @param sseq [SimpleSequence]
154
146
  # @return [Boolean]
155
147
  def superselector?(sseq)
156
- (base.nil? || base.eql?(sseq.base)) &&
157
- pseudo_elements.eql?(sseq.pseudo_elements) &&
158
- rest.subset?(sseq.rest)
148
+ (base.nil? || base.eql?(sseq.base)) && rest.subset?(sseq.rest)
159
149
  end
160
150
 
161
151
  # @see Simple#to_a
@@ -181,7 +171,7 @@ module Sass
181
171
  def with_more_sources(sources)
182
172
  sseq = dup
183
173
  sseq.members = members.dup
184
- sseq.sources = self.sources | sources
174
+ sseq.sources.merge sources
185
175
  sseq
186
176
  end
187
177
 
@@ -207,8 +197,8 @@ WARNING
207
197
  end
208
198
 
209
199
  def _eql?(other)
210
- other.base.eql?(self.base) && other.pseudo_elements == pseudo_elements &&
211
- Sass::Util.set_eql?(other.rest, self.rest) && other.subject? == self.subject?
200
+ other.base.eql?(self.base) && Sass::Util.set_eql?(other.rest, self.rest) &&
201
+ other.subject? == self.subject?
212
202
  end
213
203
  end
214
204
  end
@@ -70,13 +70,13 @@ module Sass::Tree
70
70
  private
71
71
 
72
72
  def normalize_indentation(str)
73
- ind = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
73
+ pre = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
74
74
  line[/^[ \t]*/].split("").zip(pre).inject([]) do |arr, (a, b)|
75
75
  break arr if a != b
76
76
  arr << a
77
77
  end
78
78
  end.join
79
- str.gsub(/^#{ind}/, '')
79
+ str.gsub(/^#{pre}/, '')
80
80
  end
81
81
  end
82
82
  end
@@ -9,9 +9,6 @@ module Sass
9
9
  # @return [String]
10
10
  attr_reader :imported_filename
11
11
 
12
- # Sets the imported file.
13
- attr_writer :imported_file
14
-
15
12
  # @param imported_filename [String] The name of the imported file
16
13
  def initialize(imported_filename)
17
14
  @imported_filename = imported_filename
@@ -46,12 +43,12 @@ module Sass
46
43
 
47
44
  if @options[:importer]
48
45
  f = @options[:importer].find_relative(
49
- @imported_filename, @options[:filename], options_for_importer)
46
+ @imported_filename, @options[:filename], @options.dup)
50
47
  return f if f
51
48
  end
52
49
 
53
50
  paths.each do |p|
54
- if f = p.find(@imported_filename, options_for_importer)
51
+ if f = p.find(@imported_filename, @options.dup)
55
52
  return f
56
53
  end
57
54
  end
@@ -66,10 +63,6 @@ module Sass
66
63
  rescue SyntaxError => e
67
64
  raise SyntaxError.new(e.message, :line => self.line, :filename => @filename)
68
65
  end
69
-
70
- def options_for_importer
71
- @options.merge(:_line => line)
72
- end
73
66
  end
74
67
  end
75
68
  end
@@ -23,8 +23,7 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
23
23
  SCRIPT_NODES = [Sass::Tree::ImportNode] + CONTROL_NODES
24
24
  def visit_children(parent)
25
25
  old_parent = @parent
26
- @parent = parent unless is_any_of?(parent, SCRIPT_NODES) ||
27
- (parent.bubbles? && !old_parent.is_a?(Sass::Tree::RootNode))
26
+ @parent = parent unless is_any_of?(parent, SCRIPT_NODES)
28
27
  @parents.push parent
29
28
  super
30
29
  ensure
@@ -140,7 +139,7 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
140
139
  end
141
140
 
142
141
  def try_send(method, *args)
143
- return unless respond_to?(method, true)
142
+ return unless respond_to?(method)
144
143
  send(method, *args)
145
144
  end
146
145
  end
@@ -89,6 +89,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
89
89
  end.gsub(/^/, spaces) + "\n"
90
90
  content
91
91
  end
92
+ content.sub!(%r{^\s*(/\*)}, '/*!') if node.type == :loud #'
92
93
  content
93
94
  end
94
95
 
@@ -194,19 +195,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
194
195
  end
195
196
 
196
197
  def visit_mixin(node)
197
- arg_to_sass = lambda do |arg|
198
- sass = arg.to_sass(@options)
199
- sass = "(#{sass})" if arg.is_a?(Sass::Script::List) && arg.separator == :comma
200
- sass
201
- end
202
-
203
198
  unless node.args.empty? && node.keywords.empty? && node.splat.nil?
204
- args = node.args.map(&arg_to_sass).join(", ")
199
+ args = node.args.map {|a| a.to_sass(@options)}.join(", ")
205
200
  keywords = Sass::Util.hash_to_a(node.keywords).
206
- map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}.join(', ')
201
+ map {|k, v| "$#{dasherize(k)}: #{v.to_sass(@options)}"}.join(', ')
207
202
  if node.splat
208
203
  splat = (args.empty? && keywords.empty?) ? "" : ", "
209
- splat = "#{splat}#{arg_to_sass[node.splat]}..."
204
+ splat = "#{splat}#{node.splat.to_sass(@options)}..."
210
205
  end
211
206
  arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
212
207
  end
@@ -32,8 +32,6 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
32
32
  end
33
33
  end
34
34
 
35
- MERGEABLE_DIRECTIVES = [Sass::Tree::MediaNode]
36
-
37
35
  # Runs a block of code with the current parent node
38
36
  # replaced with the given node.
39
37
  #
@@ -41,18 +39,11 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
41
39
  # @yield A block in which the parent is set to `parent`.
42
40
  # @return [Object] The return value of the block.
43
41
  def with_parent(parent)
44
- if parent.is_a?(Sass::Tree::DirectiveNode)
45
- if MERGEABLE_DIRECTIVES.any? {|klass| parent.is_a?(klass)}
46
- old_parent_directive = @parent_directives.pop
47
- end
48
- @parent_directives.push parent
49
- end
50
-
42
+ @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
51
43
  old_parent, @parent = @parent, parent
52
44
  yield
53
45
  ensure
54
46
  @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
55
- @parent_directives.push old_parent_directive if old_parent_directive
56
47
  @parent = old_parent
57
48
  end
58
49
 
@@ -73,29 +64,17 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
73
64
  node.children.unshift charset if charset
74
65
  end
75
66
 
76
- imports_to_move = []
77
- import_limit = nil
78
- i = -1
79
- node.children.reject! do |n|
80
- i += 1
81
- if import_limit
82
- next false unless n.is_a?(Sass::Tree::CssImportNode)
83
- imports_to_move << n
84
- next true
85
- end
86
-
87
- if !n.is_a?(Sass::Tree::CommentNode) &&
88
- !n.is_a?(Sass::Tree::CharsetNode) &&
89
- !n.is_a?(Sass::Tree::CssImportNode)
90
- import_limit = i
91
- end
92
-
93
- false
67
+ imports = Sass::Util.extract!(node.children) do |c|
68
+ c.is_a?(Sass::Tree::DirectiveNode) && !c.is_a?(Sass::Tree::MediaNode) &&
69
+ c.resolved_value =~ /^@import /i
94
70
  end
95
-
96
- if import_limit
97
- node.children = node.children[0...import_limit] + imports_to_move +
98
- node.children[import_limit..-1]
71
+ charset_and_index = Sass::Util.ruby1_8? &&
72
+ node.children.each_with_index.find {|c, _| c.is_a?(Sass::Tree::CharsetNode)}
73
+ if charset_and_index
74
+ index = charset_and_index.last
75
+ node.children = node.children[0..index] + imports + node.children[index+1..-1]
76
+ else
77
+ node.children = imports + node.children
99
78
  end
100
79
  end
101
80
 
@@ -136,12 +115,12 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
136
115
  end
137
116
 
138
117
  sel = sseq.members
139
- parent.resolved_rules.members.each do |member|
140
- if !member.members.last.is_a?(Sass::Selector::SimpleSequence)
141
- raise Sass::SyntaxError.new("#{member} can't extend: invalid selector")
118
+ parent.resolved_rules.members.each do |seq|
119
+ if !seq.members.last.is_a?(Sass::Selector::SimpleSequence)
120
+ raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
142
121
  end
143
122
 
144
- @extends[sel] = Extend.new(member, sel, node, @parent_directives.dup, :not_found)
123
+ @extends[sel] = Extend.new(seq, sel, node, @parent_directives.dup, :not_found)
145
124
  end
146
125
  end
147
126
 
@@ -14,13 +14,11 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
14
14
 
15
15
  begin
16
16
  unless keywords.empty?
17
- unknown_args = Sass::Util.array_minus(keywords.keys,
18
- callable.args.map {|var| var.first.underscored_name})
17
+ unknown_args = keywords.keys - callable.args.map {|var| var.first.underscored_name}
19
18
  if callable.splat && unknown_args.include?(callable.splat.underscored_name)
20
19
  raise Sass::SyntaxError.new("Argument $#{callable.splat.name} of #{downcase_desc} cannot be used as a named argument.")
21
20
  elsif unknown_args.any?
22
- description = unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'
23
- raise Sass::SyntaxError.new("#{desc} doesn't have #{description} #{unknown_args.map {|name| "$#{name}"}.join ', '}.")
21
+ raise Sass::SyntaxError.new("#{desc} doesn't have #{unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'} #{unknown_args.map{|name| "$#{name}"}.join ', '}.")
24
22
  end
25
23
  end
26
24
  rescue Sass::SyntaxError => keyword_exception
@@ -68,7 +66,6 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
68
66
  end
69
67
 
70
68
  yield env
71
- rescue Exception => e
72
69
  ensure
73
70
  # If there's a keyword exception, we don't want to throw it immediately,
74
71
  # because the invalid keywords may be part of a glob argument that should be
@@ -80,10 +77,10 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
80
77
  # non-Sass exceptions.
81
78
  if keyword_exception &&
82
79
  !(arg_list && arg_list.keywords_accessed) &&
83
- (e.nil? || e.is_a?(Sass::SyntaxError))
80
+ ($!.nil? || $!.is_a?(Sass::SyntaxError))
84
81
  raise keyword_exception
85
- elsif e
86
- raise e
82
+ elsif $!
83
+ raise $!
87
84
  end
88
85
  end
89
86
 
@@ -144,9 +141,9 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
144
141
  res = node.expr.perform(@environment)
145
142
  res = res.value if res.is_a?(Sass::Script::String)
146
143
  if node.filename
147
- Sass::Util.sass_warn "#{node.filename}:#{node.line} DEBUG: #{res}"
144
+ $stderr.puts "#{node.filename}:#{node.line} DEBUG: #{res}"
148
145
  else
149
- Sass::Util.sass_warn "Line #{node.line} DEBUG: #{res}"
146
+ $stderr.puts "Line #{node.line} DEBUG: #{res}"
150
147
  end
151
148
  []
152
149
  end
@@ -220,17 +217,15 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
220
217
  file = node.imported_file
221
218
  handle_import_loop!(node) if @stack.any? {|e| e[:filename] == file.options[:filename]}
222
219
 
223
- begin
224
- @stack.push(:filename => node.filename, :line => node.line)
225
- root = file.to_tree
226
- Sass::Tree::Visitors::CheckNesting.visit(root)
227
- node.children = root.children.map {|c| visit(c)}.flatten
228
- node
229
- rescue Sass::SyntaxError => e
230
- e.modify_backtrace(:filename => node.imported_file.options[:filename])
231
- e.add_backtrace(:filename => node.filename, :line => node.line)
232
- raise e
233
- end
220
+ @stack.push(:filename => node.filename, :line => node.line)
221
+ root = file.to_tree
222
+ Sass::Tree::Visitors::CheckNesting.visit(root)
223
+ node.children = root.children.map {|c| visit(c)}.flatten
224
+ node
225
+ rescue Sass::SyntaxError => e
226
+ e.modify_backtrace(:filename => node.imported_file.options[:filename])
227
+ e.add_backtrace(:filename => node.filename, :line => node.line)
228
+ raise e
234
229
  ensure
235
230
  @stack.pop unless path
236
231
  end
@@ -335,7 +330,9 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
335
330
  res = node.expr.perform(@environment)
336
331
  res = res.value if res.is_a?(Sass::Script::String)
337
332
  msg = "WARNING: #{res}\n "
338
- msg << stack_trace.join("\n ") << "\n"
333
+ msg << stack_trace.join("\n ")
334
+ # JRuby doesn't automatically add a newline for #warn
335
+ msg << (RUBY_PLATFORM =~ /java/ ? "\n\n" : "\n")
339
336
  Sass::Util.sass_warn msg
340
337
  []
341
338
  ensure
@@ -421,7 +418,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
421
418
  end
422
419
  end
423
420
 
424
- return unless mixins.include?(node.name)
421
+ return if mixins.empty?
425
422
  raise Sass::SyntaxError.new("#{msg} #{node.name} includes itself") if mixins.size == 1
426
423
 
427
424
  msg << "\n" << Sass::Util.enum_cons(mixins.reverse + [node.name], 2).map do |m1, m2|