sass 3.2.0.alpha.11 → 3.2.0.alpha.21

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.
Files changed (81) hide show
  1. data/REVISION +1 -1
  2. data/VERSION +1 -1
  3. data/lib/sass/cache_stores/base.rb +4 -9
  4. data/lib/sass/cache_stores/filesystem.rb +2 -0
  5. data/lib/sass/css.rb +2 -1
  6. data/lib/sass/engine.rb +28 -8
  7. data/lib/sass/environment.rb +26 -0
  8. data/lib/sass/exec.rb +13 -0
  9. data/lib/sass/importers/base.rb +2 -1
  10. data/lib/sass/script/funcall.rb +8 -0
  11. data/lib/sass/script/interpolation.rb +9 -0
  12. data/lib/sass/script/list.rb +7 -0
  13. data/lib/sass/script/literal.rb +5 -0
  14. data/lib/sass/script/node.rb +8 -0
  15. data/lib/sass/script/number.rb +28 -5
  16. data/lib/sass/script/operation.rb +8 -0
  17. data/lib/sass/script/string_interpolation.rb +9 -0
  18. data/lib/sass/script/unary_operation.rb +7 -0
  19. data/lib/sass/script/variable.rb +5 -0
  20. data/lib/sass/scss/parser.rb +26 -13
  21. data/lib/sass/scss/rx.rb +1 -1
  22. data/lib/sass/scss/static_parser.rb +2 -2
  23. data/lib/sass/tree/content_node.rb +9 -0
  24. data/lib/sass/tree/debug_node.rb +1 -6
  25. data/lib/sass/tree/each_node.rb +1 -7
  26. data/lib/sass/tree/extend_node.rb +1 -1
  27. data/lib/sass/tree/for_node.rb +2 -7
  28. data/lib/sass/tree/function_node.rb +1 -6
  29. data/lib/sass/tree/if_node.rb +1 -19
  30. data/lib/sass/tree/mixin_def_node.rb +5 -6
  31. data/lib/sass/tree/mixin_node.rb +2 -7
  32. data/lib/sass/tree/node.rb +4 -19
  33. data/lib/sass/tree/prop_node.rb +0 -5
  34. data/lib/sass/tree/return_node.rb +1 -6
  35. data/lib/sass/tree/rule_node.rb +9 -7
  36. data/lib/sass/tree/trace_node.rb +32 -0
  37. data/lib/sass/tree/variable_node.rb +1 -7
  38. data/lib/sass/tree/visitors/check_nesting.rb +30 -13
  39. data/lib/sass/tree/visitors/convert.rb +5 -1
  40. data/lib/sass/tree/visitors/cssize.rb +3 -3
  41. data/lib/sass/tree/visitors/deep_copy.rb +87 -0
  42. data/lib/sass/tree/visitors/perform.rb +36 -16
  43. data/lib/sass/tree/visitors/set_options.rb +97 -0
  44. data/lib/sass/tree/visitors/to_css.rb +5 -1
  45. data/lib/sass/tree/warn_node.rb +1 -7
  46. data/lib/sass/tree/while_node.rb +1 -7
  47. data/test/sass/cache_test.rb +15 -0
  48. data/test/sass/conversion_test.rb +38 -0
  49. data/test/sass/css2sass_test.rb +9 -0
  50. data/test/sass/engine_test.rb +248 -17
  51. data/test/sass/scss/css_test.rb +4 -2
  52. data/test/sass/scss/scss_test.rb +53 -12
  53. data/vendor/fssm/Gemfile +3 -0
  54. data/vendor/fssm/LICENSE +1 -1
  55. data/vendor/fssm/README.markdown +55 -27
  56. data/vendor/fssm/Rakefile +6 -54
  57. data/vendor/fssm/example.rb +6 -3
  58. data/vendor/fssm/fssm.gemspec +17 -70
  59. data/vendor/fssm/lib/fssm.rb +7 -3
  60. data/vendor/fssm/lib/fssm/backends/fsevents.rb +1 -1
  61. data/vendor/fssm/lib/fssm/backends/inotify.rb +2 -2
  62. data/vendor/fssm/lib/fssm/backends/polling.rb +2 -2
  63. data/vendor/fssm/lib/fssm/backends/rbfsevent.rb +42 -0
  64. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +10 -10
  65. data/vendor/fssm/lib/fssm/monitor.rb +19 -9
  66. data/vendor/fssm/lib/fssm/path.rb +24 -21
  67. data/vendor/fssm/lib/fssm/pathname.rb +13 -479
  68. data/vendor/fssm/lib/fssm/state/directory.rb +29 -11
  69. data/vendor/fssm/lib/fssm/state/file.rb +1 -1
  70. data/vendor/fssm/lib/fssm/support.rb +41 -12
  71. data/vendor/fssm/lib/fssm/tree.rb +6 -6
  72. data/vendor/fssm/lib/fssm/version.rb +3 -0
  73. data/vendor/fssm/profile/prof-cache.rb +3 -3
  74. data/vendor/fssm/profile/prof-pathname-rubinius.rb +35 -0
  75. data/vendor/fssm/profile/prof-pathname.rb +7 -7
  76. data/vendor/fssm/spec/count_down_latch.rb +151 -0
  77. data/vendor/fssm/spec/monitor_spec.rb +202 -0
  78. data/vendor/fssm/spec/path_spec.rb +36 -15
  79. data/vendor/fssm/spec/spec_helper.rb +6 -6
  80. metadata +14 -4
  81. data/vendor/fssm/VERSION.yml +0 -5
data/REVISION CHANGED
@@ -1 +1 @@
1
- bf9eafb0036f01dc23350e0dc1db29b7e5ddf463
1
+ 4ddfd6971c9a04129f3a184c15868ecacf46120f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0.alpha.11
1
+ 3.2.0.alpha.21
@@ -42,20 +42,15 @@ module Sass
42
42
  raise "#{self.class} must implement #_retrieve."
43
43
  end
44
44
 
45
- # Store an object to the Sass Cache.
45
+ # Store a {Sass::Tree::RootNode}.
46
46
  #
47
47
  # @param key [String] The key to store it under.
48
48
  # @param sha [String] The checksum for the contents that are being stored.
49
49
  # @param obj [Object] The object to cache.
50
- def store(key, sha, obj)
51
- temp = obj.before_sass_cache_store if obj.respond_to?(:before_sass_cache_store)
52
- begin
53
- _store(key, Sass::VERSION, sha, Marshal.dump(obj))
54
- ensure
55
- obj.after_sass_cache_store(temp) if obj.respond_to?(:after_sass_cache_store)
56
- end
50
+ def store(key, sha, root)
51
+ _store(key, Sass::VERSION, sha, Marshal.dump(root))
57
52
  rescue TypeError, LoadError => e
58
- Sass::Util.sass_warn "Warning. Error encountered while saving a #{obj.class.name} to cache #{path_to(key)}: #{e}"
53
+ Sass::Util.sass_warn "Warning. Error encountered while saving cache #{path_to(key)}: #{e}"
59
54
  end
60
55
 
61
56
  # Retrieve a {Sass::Tree::RootNode}.
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module Sass
2
4
  module CacheStores
3
5
  # A backend for the Sass cache using the filesystem.
@@ -75,7 +75,7 @@ module Sass
75
75
  #
76
76
  # @return [Tree::Node] The root node of the parsed tree
77
77
  def build_tree
78
- root = Sass::SCSS::CssParser.new(@template).parse
78
+ root = Sass::SCSS::CssParser.new(@template, @options[:filename]).parse
79
79
  expand_commas root
80
80
  parent_ref_rules root
81
81
  remove_parent_refs root
@@ -106,6 +106,7 @@ module Sass
106
106
  next child
107
107
  end
108
108
  child.rule.first.split(',').map do |rule|
109
+ next if rule.strip.empty?
109
110
  node = Tree::RuleNode.new([rule.strip])
110
111
  node.children = child.children
111
112
  node
@@ -12,6 +12,8 @@ require 'sass/tree/media_node'
12
12
  require 'sass/tree/variable_node'
13
13
  require 'sass/tree/mixin_def_node'
14
14
  require 'sass/tree/mixin_node'
15
+ require 'sass/tree/trace_node'
16
+ require 'sass/tree/content_node'
15
17
  require 'sass/tree/function_node'
16
18
  require 'sass/tree/return_node'
17
19
  require 'sass/tree/extend_node'
@@ -28,6 +30,8 @@ require 'sass/tree/visitors/perform'
28
30
  require 'sass/tree/visitors/cssize'
29
31
  require 'sass/tree/visitors/convert'
30
32
  require 'sass/tree/visitors/to_css'
33
+ require 'sass/tree/visitors/deep_copy'
34
+ require 'sass/tree/visitors/set_options'
31
35
  require 'sass/tree/visitors/check_nesting'
32
36
  require 'sass/selector'
33
37
  require 'sass/environment'
@@ -56,7 +60,10 @@ module Sass
56
60
  #
57
61
  # `tree`: `Array<Tree::Node>`
58
62
  # : The parse tree for the mixin/function.
59
- Callable = Struct.new(:name, :args, :environment, :tree)
63
+ #
64
+ # `has_content`: `Boolean`
65
+ # : Whether the callable accepts a content block.
66
+ Callable = Struct.new(:name, :args, :environment, :tree, :has_content)
60
67
 
61
68
  # This class handles the parsing and compilation of the Sass template.
62
69
  # Example usage:
@@ -307,7 +314,6 @@ module Sass
307
314
  sha = Digest::SHA1.hexdigest(@template)
308
315
 
309
316
  if root = @options[:cache_store].retrieve(key, sha)
310
- @options = root.options.merge(@options)
311
317
  root.options = @options
312
318
  return root
313
319
  end
@@ -316,7 +322,7 @@ module Sass
316
322
  check_encoding!
317
323
 
318
324
  if @options[:syntax] == :scss
319
- root = Sass::SCSS::Parser.new(@template).parse
325
+ root = Sass::SCSS::Parser.new(@template, @options[:filename]).parse
320
326
  else
321
327
  root = Tree::RootNode.new(@template)
322
328
  append_children(root, tree(tabulate(@template)).first, true)
@@ -558,7 +564,7 @@ WARNING
558
564
  def parse_property_or_rule(line)
559
565
  scanner = StringScanner.new(line.text)
560
566
  hack_char = scanner.scan(/[:\*\.]|\#(?!\{)/)
561
- parser = Sass::SCSS::SassParser.new(scanner, @line)
567
+ parser = Sass::SCSS::SassParser.new(scanner, @options[:filename], @line)
562
568
 
563
569
  unless res = parser.parse_interp_ident
564
570
  return Tree::RuleNode.new(parse_interp(line.text))
@@ -619,6 +625,8 @@ WARNING
619
625
  parse_import(line, value)
620
626
  elsif directive == "mixin"
621
627
  parse_mixin_definition(line)
628
+ elsif directive == "content"
629
+ parse_content_directive(line)
622
630
  elsif directive == "include"
623
631
  parse_mixin_include(line, root)
624
632
  elsif directive == "function"
@@ -744,6 +752,11 @@ WARNING
744
752
  break unless scanner.scan(/,\s*/)
745
753
  end
746
754
 
755
+ if scanner.scan(/;/)
756
+ raise SyntaxError.new("Invalid @import: expected end of line, was \";\".",
757
+ :line => @line)
758
+ end
759
+
747
760
  return values
748
761
  end
749
762
 
@@ -751,12 +764,12 @@ WARNING
751
764
  return if scanner.eos?
752
765
  unless (str = scanner.scan(Sass::SCSS::RX::STRING)) ||
753
766
  (uri = scanner.scan(Sass::SCSS::RX::URI))
754
- return Tree::ImportNode.new(scanner.scan(/[^,]+/))
767
+ return Tree::ImportNode.new(scanner.scan(/[^,;]+/))
755
768
  end
756
769
 
757
770
  val = scanner[1] || scanner[2]
758
771
  scanner.scan(/\s*/)
759
- if media = scanner.scan(/[^,].*/)
772
+ if media = scanner.scan(/[^,;].*/)
760
773
  Tree::DirectiveNode.new("@import #{str || uri} #{media}")
761
774
  elsif uri
762
775
  Tree::DirectiveNode.new("@import #{uri}")
@@ -778,6 +791,15 @@ WARNING
778
791
  Tree::MixinDefNode.new(name, args)
779
792
  end
780
793
 
794
+ CONTENT_RE = /^@content\s*(.+)?$/
795
+ def parse_content_directive(line)
796
+ trailing = line.text.scan(CONTENT_RE).first.first
797
+ raise SyntaxError.new("Invalid content directive. Trailing characters found: \"#{trailing}\".") unless trailing.nil?
798
+ raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath @content directives.",
799
+ :line => line.index + 1) unless line.children.empty?
800
+ Tree::ContentNode.new
801
+ end
802
+
781
803
  MIXIN_INCLUDE_RE = /^(?:\+|@include)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
782
804
  def parse_mixin_include(line, root)
783
805
  name, arg_string = line.text.scan(MIXIN_INCLUDE_RE).first
@@ -786,8 +808,6 @@ WARNING
786
808
  offset = line.offset + line.text.size - arg_string.size
787
809
  args, keywords = Script::Parser.new(arg_string.strip, @line, offset, @options).
788
810
  parse_mixin_include_arglist
789
- raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath mixin directives.",
790
- :line => @line + 1) unless line.children.empty?
791
811
  Tree::MixinNode.new(name, args, keywords)
792
812
  end
793
813
 
@@ -19,6 +19,8 @@ module Sass
19
19
  # @return [Environment]
20
20
  attr_reader :parent
21
21
  attr_writer :options
22
+ attr_writer :caller
23
+ attr_writer :content
22
24
 
23
25
  # @param parent [Environment] See \{#parent}
24
26
  def initialize(parent = nil)
@@ -30,6 +32,19 @@ module Sass
30
32
  end
31
33
  end
32
34
 
35
+ # The environment of the caller of this environment's mixin or function.
36
+ # @return {Environment?}
37
+ def caller
38
+ @caller || (@parent && @parent.caller)
39
+ end
40
+
41
+ # The content passed to this environmnet. This is naturally only set
42
+ # for mixin body environments with content passed in.
43
+ # @return {Environment?}
44
+ def content
45
+ @content || (@parent && @parent.content)
46
+ end
47
+
33
48
  # The options hash.
34
49
  # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
35
50
  #
@@ -93,6 +108,17 @@ module Sass
93
108
  @mixins_in_use ||= @parent.mixins_in_use
94
109
  end
95
110
 
111
+ def stack_trace
112
+ trace = []
113
+ stack.reverse.each_with_index do |entry, i|
114
+ msg = "#{i == 0 ? "on" : "from"} line #{entry[:line]}"
115
+ msg << " of #{entry[:filename] || "an unknown file"}"
116
+ msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
117
+ trace << msg
118
+ end
119
+ trace
120
+ end
121
+
96
122
  private
97
123
 
98
124
  def parent_options
@@ -229,6 +229,10 @@ END
229
229
  'Only meaningful for --watch and --update.') do
230
230
  @options[:stop_on_error] = true
231
231
  end
232
+ opts.on('-f', '--force', 'Recompile all Sass files, even if the CSS file is newer.',
233
+ 'Only meaningful for --update.') do
234
+ @options[:force] = true
235
+ end
232
236
  opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
233
237
  require 'stringio'
234
238
  @options[:check_syntax] = true
@@ -238,6 +242,10 @@ END
238
242
  'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
239
243
  @options[:for_engine][:style] = name.to_sym
240
244
  end
245
+ opts.on('--precision NUMBER_OF_DIGITS', Integer,
246
+ 'How many digits of precision to use when outputting decimal numbers. Defaults to 3.') do |precision|
247
+ ::Sass::Script::Number.precision = precision
248
+ end
241
249
  opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
242
250
  @options[:for_engine][:quiet] = true
243
251
  end
@@ -350,6 +358,11 @@ END
350
358
  ::Sass::Plugin.options.merge! @options[:for_engine]
351
359
  ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
352
360
 
361
+ if @options[:force]
362
+ raise "The --force flag may only be used with --update." unless @options[:update]
363
+ ::Sass::Plugin.options[:always_update] = true
364
+ end
365
+
353
366
  raise <<MSG if @args.empty?
354
367
  What files should I watch? Did you mean something like:
355
368
  #{@default_syntax} --watch input.#{@default_syntax}:output.css
@@ -72,7 +72,8 @@ module Sass
72
72
  # If no such files exist, it should return nil.
73
73
  #
74
74
  # The {Sass::Engine} to be returned should be passed `options`,
75
- # with a few modifications. `:filename` and `:syntax` should be set appropriately,
75
+ # with a few modifications. `:syntax` should be set appropriately,
76
+ # `:filename` should be set to `uri`,
76
77
  # and `:importer` should be set to this importer.
77
78
  #
78
79
  # @param uri [String] The URI to import.
@@ -57,6 +57,14 @@ module Sass
57
57
  @args + @keywords.values
58
58
  end
59
59
 
60
+ # @see Node#deep_copy
61
+ def deep_copy
62
+ node = dup
63
+ node.instance_variable_set('@args', args.map {|a| a.deep_copy})
64
+ node.instance_variable_set('@keywords', Hash[keywords.map {|k, v| [k, v.deep_copy]}])
65
+ node
66
+ end
67
+
60
68
  protected
61
69
 
62
70
  # Evaluates the function call.
@@ -50,6 +50,15 @@ module Sass::Script
50
50
  [@before, @mid, @after].compact
51
51
  end
52
52
 
53
+ # @see Node#deep_copy
54
+ def deep_copy
55
+ node = dup
56
+ node.instance_variable_set('@before', @before.deep_copy) if @before
57
+ node.instance_variable_set('@mid', @mid.deep_copy)
58
+ node.instance_variable_set('@after', @after.deep_copy) if @after
59
+ node
60
+ end
61
+
53
62
  protected
54
63
 
55
64
  # Evaluates the interpolation.
@@ -24,6 +24,13 @@ module Sass::Script
24
24
  @separator = separator
25
25
  end
26
26
 
27
+ # @see Node#deep_copy
28
+ def deep_copy
29
+ node = dup
30
+ node.instance_variable_set('@value', value.map {|c| c.deep_copy})
31
+ node
32
+ end
33
+
27
34
  # @see Node#eq
28
35
  def eq(other)
29
36
  Sass::Script::Bool.new(
@@ -33,6 +33,11 @@ module Sass::Script
33
33
  []
34
34
  end
35
35
 
36
+ # @see Node#deep_copy
37
+ def deep_copy
38
+ dup
39
+ end
40
+
36
41
  # Returns the options hash for this node.
37
42
  #
38
43
  # @return [{Symbol => Object}]
@@ -57,6 +57,14 @@ module Sass::Script
57
57
  Sass::Util.abstract(self)
58
58
  end
59
59
 
60
+ # Returns a deep clone of this node.
61
+ # The child nodes are cloned, but options are not.
62
+ #
63
+ # @return [Node]
64
+ def deep_copy
65
+ Sass::Util.abstract(self)
66
+ end
67
+
60
68
  protected
61
69
 
62
70
  # Converts underscores to dashes if the :dasherize option is set.
@@ -35,11 +35,34 @@ module Sass::Script
35
35
  # @return [Boolean, nil]
36
36
  attr_accessor :original
37
37
 
38
- # The precision with which numbers will be printed to CSS files.
39
- # For example, if this is `1000.0`,
38
+ def self.precision
39
+ @precision ||= 3
40
+ end
41
+
42
+ # Sets the number of digits of precision
43
+ # For example, if this is `3`,
40
44
  # `3.1415926` will be printed as `3.142`.
41
- # @api public
42
- PRECISION = 1000.0
45
+ def self.precision=(digits)
46
+ @precision = digits.round
47
+ @precision_factor = 10.0**@precision
48
+ end
49
+
50
+ # the precision factor used in numeric output
51
+ # it is derived from the `precision` method.
52
+ def self.precision_factor
53
+ @precision_factor ||= 10.0**precision
54
+ end
55
+
56
+ # Handles the deprecation warning for the PRECISION constant
57
+ # This can be removed in 3.2.
58
+ def self.const_missing(const)
59
+ if const == :PRECISION
60
+ Sass::Util.sass_warn("Sass::Script::Number::PRECISION is deprecated and will be removed in a future release. Use Sass::Script::Number.precision_factor instead.")
61
+ const_set(:PRECISION, self.precision_factor)
62
+ else
63
+ super
64
+ end
65
+ end
43
66
 
44
67
  # Used so we don't allocate two new arrays for each new number.
45
68
  NO_UNITS = []
@@ -337,7 +360,7 @@ module Sass::Script
337
360
  elsif num % 1 == 0.0
338
361
  num.to_i
339
362
  else
340
- (num * PRECISION).round / PRECISION
363
+ (num * self.precision_factor).round / self.precision_factor
341
364
  end
342
365
  end
343
366
 
@@ -55,6 +55,14 @@ module Sass::Script
55
55
  [@operand1, @operand2]
56
56
  end
57
57
 
58
+ # @see Node#deep_copy
59
+ def deep_copy
60
+ node = dup
61
+ node.instance_variable_set('@operand1', @operand1.deep_copy)
62
+ node.instance_variable_set('@operand2', @operand2.deep_copy)
63
+ node
64
+ end
65
+
58
66
  protected
59
67
 
60
68
  # Evaluates the operation.
@@ -60,6 +60,15 @@ module Sass::Script
60
60
  [@before, @mid, @after].compact
61
61
  end
62
62
 
63
+ # @see Node#deep_copy
64
+ def deep_copy
65
+ node = dup
66
+ node.instance_variable_set('@before', @before.deep_copy) if @before
67
+ node.instance_variable_set('@mid', @mid.deep_copy)
68
+ node.instance_variable_set('@after', @after.deep_copy) if @after
69
+ node
70
+ end
71
+
63
72
  protected
64
73
 
65
74
  # Evaluates the interpolation.
@@ -38,6 +38,13 @@ module Sass::Script
38
38
  [@operand]
39
39
  end
40
40
 
41
+ # @see Node#deep_copy
42
+ def deep_copy
43
+ node = dup
44
+ node.instance_variable_set('@operand', @operand.deep_copy)
45
+ node
46
+ end
47
+
41
48
  protected
42
49
 
43
50
  # Evaluates the operation.
@@ -34,6 +34,11 @@ module Sass
34
34
  []
35
35
  end
36
36
 
37
+ # @see Node#deep_copy
38
+ def deep_copy
39
+ dup
40
+ end
41
+
37
42
  protected
38
43
 
39
44
  # Evaluates the variable.
@@ -9,10 +9,12 @@ module Sass
9
9
  # @param str [String, StringScanner] The source document to parse.
10
10
  # Note that `Parser` *won't* raise a nice error message if this isn't properly parsed;
11
11
  # for that, you should use the higher-level {Sass::Engine} or {Sass::CSS}.
12
+ # @param filename [String] The name of the file being parsed. Used for warnings.
12
13
  # @param line [Fixnum] The line on which the source string appeared,
13
- # if it's part of another document
14
- def initialize(str, line = 1)
14
+ # if it's part of another document.
15
+ def initialize(str, filename, line = 1)
15
16
  @template = str
17
+ @filename = filename
16
18
  @line = line
17
19
  @strs = []
18
20
  end
@@ -99,7 +101,7 @@ module Sass
99
101
  end
100
102
 
101
103
  DIRECTIVES = Set[:mixin, :include, :function, :return, :debug, :warn, :for,
102
- :each, :while, :if, :else, :extend, :import, :media, :charset]
104
+ :each, :while, :if, :else, :extend, :import, :media, :charset, :content]
103
105
 
104
106
  def directive
105
107
  return unless tok(/@/)
@@ -141,7 +143,18 @@ module Sass
141
143
  name = tok! IDENT
142
144
  args, keywords = sass_script(:parse_mixin_include_arglist)
143
145
  ss
144
- node(Sass::Tree::MixinNode.new(name, args, keywords))
146
+ include_node = node(Sass::Tree::MixinNode.new(name, args, keywords))
147
+ if tok?(/\{/)
148
+ include_node.has_children = true
149
+ block(include_node, :directive)
150
+ else
151
+ include_node
152
+ end
153
+ end
154
+
155
+ def content_directive
156
+ ss
157
+ node(Sass::Tree::ContentNode.new)
145
158
  end
146
159
 
147
160
  def function_directive
@@ -487,20 +500,20 @@ module Sass
487
500
  res = [e]
488
501
 
489
502
  # The tok(/\*/) allows the "E*" hack
490
- while v = element_name || id_selector || class_selector ||
491
- attrib || negation || pseudo || interpolation_selector ||
492
- (tok(/\*/) && Selector::Universal.new(nil))
503
+ while v = id_selector || class_selector || attrib || negation || pseudo ||
504
+ interpolation_selector || (tok(/\*/) && Selector::Universal.new(nil))
493
505
  res << v
494
506
  end
495
507
 
496
- if tok?(/&/)
508
+ pos = @scanner.pos
509
+ line = @line
510
+ if sel = str? {simple_selector_sequence}
511
+ @scanner.pos = pos
512
+ @line = line
497
513
  begin
498
514
  expected('"{"')
499
515
  rescue Sass::SyntaxError => e
500
- e.message << "\n\n" << <<MESSAGE
501
- In Sass 3, the parent selector & can only be used where element names are valid,
502
- since it could potentially be replaced by an element name.
503
- MESSAGE
516
+ e.message << "\n\n\"#{sel}\" may only be used at the beginning of a selector."
504
517
  raise e
505
518
  end
506
519
  end
@@ -613,7 +626,7 @@ MESSAGE
613
626
  end
614
627
 
615
628
  def negation
616
- return unless name = tok(NOT) || tok(MOZ_ANY)
629
+ return unless name = tok(NOT) || tok(ANY)
617
630
  ss
618
631
  @expected = "selector"
619
632
  sel = selector_comma_sequence