sass 3.1.21 → 3.2.0.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. data/README.md +5 -4
  2. data/REVISION +1 -1
  3. data/Rakefile +6 -15
  4. data/VERSION +1 -1
  5. data/VERSION_NAME +1 -1
  6. data/lib/sass.rb +0 -1
  7. data/lib/sass/cache_stores/base.rb +1 -3
  8. data/lib/sass/cache_stores/filesystem.rb +0 -3
  9. data/lib/sass/css.rb +49 -145
  10. data/lib/sass/engine.rb +23 -47
  11. data/lib/sass/environment.rb +5 -30
  12. data/lib/sass/exec.rb +7 -30
  13. data/lib/sass/importers/base.rb +1 -2
  14. data/lib/sass/importers/filesystem.rb +13 -18
  15. data/lib/sass/less.rb +1 -1
  16. data/lib/sass/plugin.rb +8 -4
  17. data/lib/sass/plugin/compiler.rb +67 -93
  18. data/lib/sass/plugin/configuration.rb +2 -0
  19. data/lib/sass/plugin/staleness_checker.rb +4 -14
  20. data/lib/sass/repl.rb +3 -2
  21. data/lib/sass/script.rb +1 -0
  22. data/lib/sass/script/color.rb +9 -4
  23. data/lib/sass/script/funcall.rb +3 -16
  24. data/lib/sass/script/functions.rb +55 -98
  25. data/lib/sass/script/interpolation.rb +0 -9
  26. data/lib/sass/script/lexer.rb +4 -2
  27. data/lib/sass/script/list.rb +0 -8
  28. data/lib/sass/script/literal.rb +20 -5
  29. data/lib/sass/script/node.rb +0 -8
  30. data/lib/sass/script/number.rb +11 -35
  31. data/lib/sass/script/operation.rb +0 -16
  32. data/lib/sass/script/parser.rb +5 -12
  33. data/lib/sass/script/string_interpolation.rb +0 -9
  34. data/lib/sass/script/unary_operation.rb +0 -7
  35. data/lib/sass/script/variable.rb +1 -5
  36. data/lib/sass/scss/parser.rb +54 -191
  37. data/lib/sass/scss/rx.rb +3 -15
  38. data/lib/sass/scss/static_parser.rb +3 -3
  39. data/lib/sass/selector.rb +3 -15
  40. data/lib/sass/selector/abstract_sequence.rb +2 -11
  41. data/lib/sass/selector/comma_sequence.rb +3 -8
  42. data/lib/sass/selector/sequence.rb +11 -74
  43. data/lib/sass/selector/simple.rb +1 -7
  44. data/lib/sass/selector/simple_sequence.rb +8 -28
  45. data/lib/sass/shared.rb +5 -3
  46. data/lib/sass/tree/comment_node.rb +12 -25
  47. data/lib/sass/tree/debug_node.rb +1 -1
  48. data/lib/sass/tree/directive_node.rb +0 -5
  49. data/lib/sass/tree/each_node.rb +1 -1
  50. data/lib/sass/tree/extend_node.rb +1 -1
  51. data/lib/sass/tree/for_node.rb +2 -2
  52. data/lib/sass/tree/function_node.rb +1 -1
  53. data/lib/sass/tree/if_node.rb +14 -1
  54. data/lib/sass/tree/media_node.rb +4 -4
  55. data/lib/sass/tree/mixin_def_node.rb +1 -1
  56. data/lib/sass/tree/mixin_node.rb +2 -2
  57. data/lib/sass/tree/node.rb +26 -10
  58. data/lib/sass/tree/return_node.rb +1 -1
  59. data/lib/sass/tree/root_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -9
  61. data/lib/sass/tree/variable_node.rb +1 -1
  62. data/lib/sass/tree/visitors/base.rb +1 -1
  63. data/lib/sass/tree/visitors/check_nesting.rb +36 -29
  64. data/lib/sass/tree/visitors/convert.rb +9 -16
  65. data/lib/sass/tree/visitors/cssize.rb +9 -40
  66. data/lib/sass/tree/visitors/perform.rb +23 -79
  67. data/lib/sass/tree/visitors/to_css.rb +21 -23
  68. data/lib/sass/tree/warn_node.rb +1 -1
  69. data/lib/sass/tree/while_node.rb +1 -1
  70. data/lib/sass/util.rb +9 -147
  71. data/lib/sass/version.rb +0 -14
  72. data/test/sass/cache_test.rb +0 -15
  73. data/test/sass/conversion_test.rb +8 -50
  74. data/test/sass/css2sass_test.rb +0 -33
  75. data/test/sass/engine_test.rb +32 -283
  76. data/test/sass/extend_test.rb +0 -315
  77. data/test/sass/functions_test.rb +23 -60
  78. data/test/sass/importer_test.rb +0 -110
  79. data/test/sass/more_results/more_import.css +2 -2
  80. data/test/sass/plugin_test.rb +13 -40
  81. data/test/sass/results/import.css +2 -2
  82. data/test/sass/results/import_charset.css +0 -1
  83. data/test/sass/results/import_charset_1_8.css +0 -1
  84. data/test/sass/results/import_charset_ibm866.css +0 -1
  85. data/test/sass/results/scss_import.css +2 -2
  86. data/test/sass/results/units.css +1 -1
  87. data/test/sass/script_conversion_test.rb +0 -2
  88. data/test/sass/script_test.rb +4 -28
  89. data/test/sass/scss/css_test.rb +1 -79
  90. data/test/sass/scss/scss_test.rb +16 -96
  91. data/test/sass/templates/import_charset.sass +0 -2
  92. data/test/sass/templates/import_charset_1_8.sass +0 -2
  93. data/test/sass/templates/import_charset_ibm866.sass +0 -2
  94. data/test/sass/test_helper.rb +1 -1
  95. data/test/sass/util_test.rb +0 -28
  96. data/test/test_helper.rb +0 -2
  97. data/vendor/{listen → fssm}/LICENSE +1 -1
  98. data/vendor/fssm/README.markdown +55 -0
  99. data/vendor/fssm/Rakefile +59 -0
  100. data/vendor/fssm/VERSION.yml +5 -0
  101. data/vendor/fssm/example.rb +9 -0
  102. data/vendor/fssm/fssm.gemspec +77 -0
  103. data/vendor/fssm/lib/fssm.rb +33 -0
  104. data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  105. data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  106. data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  107. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  108. data/vendor/fssm/lib/fssm/monitor.rb +26 -0
  109. data/vendor/fssm/lib/fssm/path.rb +91 -0
  110. data/vendor/fssm/lib/fssm/pathname.rb +502 -0
  111. data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  112. data/vendor/fssm/lib/fssm/state/file.rb +24 -0
  113. data/vendor/fssm/lib/fssm/support.rb +63 -0
  114. data/vendor/fssm/lib/fssm/tree.rb +176 -0
  115. data/vendor/fssm/profile/prof-cache.rb +40 -0
  116. data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  117. data/vendor/fssm/profile/prof-pathname.rb +68 -0
  118. data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  119. data/vendor/fssm/profile/prof.html +2379 -0
  120. data/vendor/fssm/spec/path_spec.rb +75 -0
  121. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  122. data/vendor/fssm/spec/root/file.css +0 -0
  123. data/vendor/fssm/spec/root/file.rb +0 -0
  124. data/vendor/fssm/spec/root/file.yml +0 -0
  125. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  126. data/vendor/fssm/spec/spec_helper.rb +14 -0
  127. metadata +246 -281
  128. data/VERSION_DATE +0 -1
  129. data/lib/sass/logger.rb +0 -15
  130. data/lib/sass/logger/base.rb +0 -32
  131. data/lib/sass/logger/log_level.rb +0 -49
  132. data/lib/sass/tree/visitors/deep_copy.rb +0 -87
  133. data/lib/sass/tree/visitors/extend.rb +0 -42
  134. data/lib/sass/tree/visitors/set_options.rb +0 -97
  135. data/lib/sass/util/multibyte_string_scanner.rb +0 -134
  136. data/test/Gemfile +0 -4
  137. data/test/Gemfile.lock +0 -19
  138. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  139. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  140. data/test/sass/logger_test.rb +0 -58
  141. data/test/sass/templates/_double_import_loop2.sass +0 -1
  142. data/test/sass/templates/bork5.sass +0 -3
  143. data/test/sass/templates/double_import_loop1.sass +0 -1
  144. data/test/sass/templates/nested_bork5.sass +0 -2
  145. data/test/sass/templates/single_import_loop.sass +0 -1
  146. data/test/sass/util/multibyte_string_scanner_test.rb +0 -147
  147. data/vendor/listen/CHANGELOG.md +0 -147
  148. data/vendor/listen/Gemfile +0 -23
  149. data/vendor/listen/Guardfile +0 -8
  150. data/vendor/listen/README.md +0 -312
  151. data/vendor/listen/Rakefile +0 -47
  152. data/vendor/listen/Vagrantfile +0 -96
  153. data/vendor/listen/lib/listen.rb +0 -38
  154. data/vendor/listen/lib/listen/adapter.rb +0 -167
  155. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -84
  156. data/vendor/listen/lib/listen/adapters/linux.rb +0 -110
  157. data/vendor/listen/lib/listen/adapters/polling.rb +0 -66
  158. data/vendor/listen/lib/listen/adapters/windows.rb +0 -81
  159. data/vendor/listen/lib/listen/directory_record.rb +0 -318
  160. data/vendor/listen/lib/listen/listener.rb +0 -203
  161. data/vendor/listen/lib/listen/multi_listener.rb +0 -121
  162. data/vendor/listen/lib/listen/turnstile.rb +0 -28
  163. data/vendor/listen/lib/listen/version.rb +0 -3
  164. data/vendor/listen/listen.gemspec +0 -26
  165. data/vendor/listen/spec/listen/adapter_spec.rb +0 -142
  166. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -31
  167. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -41
  168. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  169. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -24
  170. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1138
  171. data/vendor/listen/spec/listen/listener_spec.rb +0 -155
  172. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -156
  173. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  174. data/vendor/listen/spec/listen_spec.rb +0 -73
  175. data/vendor/listen/spec/spec_helper.rb +0 -18
  176. data/vendor/listen/spec/support/adapter_helper.rb +0 -716
  177. data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
  178. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  179. data/vendor/listen/spec/support/listeners_helper.rb +0 -144
  180. data/vendor/listen/spec/support/platform_helper.rb +0 -11
@@ -24,13 +24,6 @@ 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
-
34
27
  # @see Node#eq
35
28
  def eq(other)
36
29
  Sass::Script::Bool.new(
@@ -46,7 +39,6 @@ module Sass::Script
46
39
 
47
40
  # @see Node#to_sass
48
41
  def to_sass(opts = {})
49
- return "()" if value.empty?
50
42
  precedence = Sass::Script::Parser.precedence_of(separator)
51
43
  value.map do |v|
52
44
  if v.is_a?(List) && Sass::Script::Parser.precedence_of(v.separator) <= precedence
@@ -33,11 +33,6 @@ module Sass::Script
33
33
  []
34
34
  end
35
35
 
36
- # @see Node#deep_copy
37
- def deep_copy
38
- dup
39
- end
40
-
41
36
  # Returns the options hash for this node.
42
37
  #
43
38
  # @return [{Symbol => Object}]
@@ -55,6 +50,26 @@ The #options attribute is not set on this #{self.class}.
55
50
  MSG
56
51
  end
57
52
 
53
+ # The SassScript `and` operation.
54
+ #
55
+ # @param other [Literal] The right-hand side of the operator
56
+ # @return [Literal] The result of a logical and:
57
+ # `other` if this literal isn't a false {Bool},
58
+ # and this literal otherwise
59
+ def and(other)
60
+ to_bool ? other : self
61
+ end
62
+
63
+ # The SassScript `or` operation.
64
+ #
65
+ # @param other [Literal] The right-hand side of the operator
66
+ # @return [Literal] The result of the logical or:
67
+ # this literal if it isn't a false {Bool},
68
+ # and `other` otherwise
69
+ def or(other)
70
+ to_bool ? self : other
71
+ end
72
+
58
73
  # The SassScript `==` operation.
59
74
  # **Note that this returns a {Sass::Script::Bool} object,
60
75
  # not a Ruby boolean**.
@@ -57,14 +57,6 @@ 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
-
68
60
  protected
69
61
 
70
62
  # Converts underscores to dashes if the :dasherize option is set.
@@ -35,34 +35,11 @@ module Sass::Script
35
35
  # @return [Boolean, nil]
36
36
  attr_accessor :original
37
37
 
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`,
38
+ # The precision with which numbers will be printed to CSS files.
39
+ # For example, if this is `1000.0`,
44
40
  # `3.1415926` will be printed as `3.142`.
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
41
+ # @api public
42
+ PRECISION = 1000.0
66
43
 
67
44
  # Used so we don't allocate two new arrays for each new number.
68
45
  NO_UNITS = []
@@ -360,7 +337,7 @@ module Sass::Script
360
337
  elsif num % 1 == 0.0
361
338
  num.to_i
362
339
  else
363
- ((num * self.precision_factor).round / self.precision_factor).to_f
340
+ (num * PRECISION).round / PRECISION
364
341
  end
365
342
  end
366
343
 
@@ -422,13 +399,12 @@ module Sass::Script
422
399
  end
423
400
 
424
401
  # A hash of unit names to their index in the conversion table
425
- CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4, "px" => 5 }
426
- CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 , 96 ], # in
427
- [ nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
428
- [ nil, nil, 1, 4.23333333, 12 , 16 ], # pc
429
- [ nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
430
- [ nil, nil, nil, nil, 1 , 1.3333333333], # pt
431
- [ nil, nil, nil, nil, nil , 1 ]] # px
402
+ CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4}
403
+ CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in
404
+ [ nil, 1, 2.36220473, 10, 28.3464567], # cm
405
+ [ nil, nil, 1, 4.23333333, 12 ], # pc
406
+ [ nil, nil, nil, 1, 2.83464567], # mm
407
+ [ nil, nil, nil, nil, 1 ]] # pt
432
408
 
433
409
  def conversion_factor(from_unit, to_unit)
434
410
  res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
@@ -55,14 +55,6 @@ 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
-
66
58
  protected
67
59
 
68
60
  # Evaluates the operation.
@@ -72,14 +64,6 @@ module Sass::Script
72
64
  # @raise [Sass::SyntaxError] if the operation is undefined for the operands
73
65
  def _perform(environment)
74
66
  literal1 = @operand1.perform(environment)
75
-
76
- # Special-case :and and :or to support short-circuiting.
77
- if @operator == :and
78
- return literal1.to_bool ? @operand2.perform(environment) : literal1
79
- elsif @operator == :or
80
- return literal1.to_bool ? literal1 : @operand2.perform(environment)
81
- end
82
-
83
67
  literal2 = @operand2.perform(environment)
84
68
 
85
69
  begin
@@ -182,11 +182,7 @@ module Sass
182
182
  interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}) and return interp
183
183
  return unless e = #{sub}
184
184
  while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
185
- if interp = try_op_before_interp(tok, e)
186
- return interp unless other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
187
- return other_interp
188
- end
189
-
185
+ interp = try_op_before_interp(tok, e) and return interp
190
186
  line = @lexer.line
191
187
  e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
192
188
  e.line = line
@@ -221,10 +217,7 @@ RUBY
221
217
  return unless e = interpolation
222
218
  arr = [e]
223
219
  while tok = try_tok(:comma)
224
- if interp = try_op_before_interp(tok, e)
225
- return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
226
- return other_interp
227
- end
220
+ interp = try_op_before_interp(tok, e) and return interp
228
221
  arr << assert_expr(:interpolation)
229
222
  end
230
223
  arr.size == 1 ? arr.first : node(List.new(arr, :comma), line)
@@ -242,15 +235,15 @@ RUBY
242
235
  interpolation(interp)
243
236
  end
244
237
 
245
- def try_ops_after_interp(ops, name, prev = nil)
238
+ def try_ops_after_interp(ops, name)
246
239
  return unless @lexer.after_interpolation?
247
240
  return unless op = try_tok(*ops)
248
- interp = try_op_before_interp(op, prev) and return interp
241
+ interp = try_op_before_interp(op) and return interp
249
242
 
250
243
  wa = @lexer.whitespace?
251
244
  str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
252
245
  str.line = @lexer.line
253
- interp = Script::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text)
246
+ interp = Script::Interpolation.new(nil, str, assert_expr(name), !:wb, wa, :originally_text)
254
247
  interp.line = @lexer.line
255
248
  return interp
256
249
  end
@@ -60,15 +60,6 @@ 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
-
72
63
  protected
73
64
 
74
65
  # Evaluates the interpolation.
@@ -38,13 +38,6 @@ 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
-
48
41
  protected
49
42
 
50
43
  # Evaluates the operation.
@@ -21,6 +21,7 @@ module Sass
21
21
 
22
22
  # @return [String] A string representation of the variable
23
23
  def inspect(opts = {})
24
+ return "!important" if name == "important"
24
25
  "$#{dasherize(name, opts)}"
25
26
  end
26
27
  alias_method :to_sass, :inspect
@@ -33,11 +34,6 @@ module Sass
33
34
  []
34
35
  end
35
36
 
36
- # @see Node#deep_copy
37
- def deep_copy
38
- dup
39
- end
40
-
41
37
  protected
42
38
 
43
39
  # Evaluates the variable.
@@ -1,3 +1,4 @@
1
+ require 'strscan'
1
2
  require 'set'
2
3
 
3
4
  module Sass
@@ -8,12 +9,10 @@ module Sass
8
9
  # @param str [String, StringScanner] The source document to parse.
9
10
  # Note that `Parser` *won't* raise a nice error message if this isn't properly parsed;
10
11
  # for that, you should use the higher-level {Sass::Engine} or {Sass::CSS}.
11
- # @param filename [String] The name of the file being parsed. Used for warnings.
12
12
  # @param line [Fixnum] The line on which the source string appeared,
13
- # if it's part of another document.
14
- def initialize(str, filename, line = 1)
13
+ # if it's part of another document
14
+ def initialize(str, line = 1)
15
15
  @template = str
16
- @filename = filename
17
16
  @line = line
18
17
  @strs = []
19
18
  end
@@ -49,7 +48,7 @@ module Sass
49
48
  if @template.is_a?(StringScanner)
50
49
  @template
51
50
  else
52
- Sass::Util::MultibyteStringScanner.new(@template.gsub("\r", ""))
51
+ StringScanner.new(@template.gsub("\r", ""))
53
52
  end
54
53
  end
55
54
 
@@ -88,35 +87,19 @@ module Sass
88
87
  end
89
88
 
90
89
  def process_comment(text, node)
91
- silent = text =~ /^\/\//
92
- line = @line - text.count("\n")
93
- if loud = text =~ %r{^/[/*]!}
94
- value = Sass::Engine.parse_interp(text, line, @scanner.pos - text.size, :filename => @filename)
95
- value[0].slice!(2) # get rid of the "!"
96
- else
97
- value = [text]
98
- end
99
-
100
- if silent
101
- value = Sass::Util.with_extracted_values(value) do |str|
102
- str.sub(/^\s*\/\//, '/*').gsub(/^\s*\/\//, ' *') + ' */'
103
- end
104
- else
105
- value.unshift(@scanner.
106
- string[0...@scanner.pos].
107
- reverse[/.*?\*\/(.*?)($|\Z)/, 1].
108
- reverse.gsub(/[^\s]/, ' '))
109
- end
110
-
111
- comment = Sass::Tree::CommentNode.new(value, silent, loud)
112
- comment.line = line
90
+ single_line = text =~ /^\/\//
91
+ pre_str = single_line ? "" : @scanner.
92
+ string[0...@scanner.pos].
93
+ reverse[/.*?\*\/(.*?)($|\Z)/, 1].
94
+ reverse.gsub(/[^\s]/, ' ')
95
+ text = text.sub(/^\s*\/\//, '/*').gsub(/^\s*\/\//, ' *') + ' */' if single_line
96
+ comment = Sass::Tree::CommentNode.new(pre_str + text, single_line)
97
+ comment.line = @line - text.count("\n")
113
98
  node << comment
114
99
  end
115
100
 
116
101
  DIRECTIVES = Set[:mixin, :include, :function, :return, :debug, :warn, :for,
117
- :each, :while, :if, :else, :extend, :import, :media, :charset, :_moz_document]
118
-
119
- PREFIXED_DIRECTIVES = Set[:supports]
102
+ :each, :while, :if, :else, :extend, :import, :media, :charset]
120
103
 
121
104
  def directive
122
105
  return unless tok(/@/)
@@ -125,19 +108,13 @@ module Sass
125
108
 
126
109
  if dir = special_directive(name)
127
110
  return dir
128
- elsif dir = prefixed_directive(name)
129
- return dir
130
111
  end
131
112
 
132
113
  # Most at-rules take expressions (e.g. @import),
133
114
  # but some (e.g. @page) take selector-like arguments
134
115
  val = str {break unless expr}
135
116
  val ||= CssParser.new(@scanner, @line).parse_selector_string
136
- directive_body("@#{name} #{val}")
137
- end
138
-
139
- def directive_body(value)
140
- node = node(Sass::Tree::DirectiveNode.new(value.strip))
117
+ node = node(Sass::Tree::DirectiveNode.new("@#{name} #{val}".strip))
141
118
 
142
119
  if tok(/\{/)
143
120
  node.has_children = true
@@ -153,11 +130,6 @@ module Sass
153
130
  DIRECTIVES.include?(sym) && send("#{sym}_directive")
154
131
  end
155
132
 
156
- def prefixed_directive(name)
157
- sym = name.gsub(/^-[a-z0-9]+-/i, '').gsub('-', '_').to_sym
158
- PREFIXED_DIRECTIVES.include?(sym) && send("#{sym}_directive", name)
159
- end
160
-
161
133
  def mixin_directive
162
134
  name = tok! IDENT
163
135
  args = sass_script(:parse_mixin_definition_arglist)
@@ -268,7 +240,7 @@ module Sass
268
240
  end
269
241
 
270
242
  def extend_directive
271
- node(Sass::Tree::ExtendNode.new(expr!(:selector_sequence)))
243
+ node(Sass::Tree::ExtendNode.new(expr!(:selector)))
272
244
  end
273
245
 
274
246
  def import_directive
@@ -299,23 +271,20 @@ module Sass
299
271
  def use_css_import?; false; end
300
272
 
301
273
  def media_directive
302
- block(node(Sass::Tree::MediaNode.new(media_query_list)), :directive)
274
+ val = str {media_query_list}.strip
275
+ block(node(Sass::Tree::MediaNode.new(val)), :directive)
303
276
  end
304
277
 
305
278
  # http://www.w3.org/TR/css3-mediaqueries/#syntax
306
279
  def media_query_list
307
- has_q = false
308
- q = str {has_q = media_query}
309
-
310
- return unless has_q
311
- queries = [q.strip]
280
+ return unless media_query
312
281
 
313
282
  ss
314
283
  while tok(/,/)
315
- ss; queries << str {expr!(:media_query)}.strip; ss
284
+ ss; expr!(:media_query); ss
316
285
  end
317
286
 
318
- queries
287
+ true
319
288
  end
320
289
 
321
290
  def media_query
@@ -359,76 +328,6 @@ module Sass
359
328
  node(Sass::Tree::CharsetNode.new(name))
360
329
  end
361
330
 
362
- # The document directive is specified in
363
- # http://www.w3.org/TR/css3-conditional/, but Gecko allows the
364
- # `url-prefix` and `domain` functions to omit quotation marks, contrary to
365
- # the standard.
366
- #
367
- # We could parse all document directives according to Mozilla's syntax,
368
- # but if someone's using e.g. @-webkit-document we don't want them to
369
- # think WebKit works sans quotes.
370
- def _moz_document_directive
371
- value = str do
372
- begin
373
- ss
374
- expr!(:moz_document_function)
375
- end while tok(/,/)
376
- end
377
- directive_body("@-moz-document #{value}")
378
- end
379
-
380
- def moz_document_function
381
- return unless tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) || function
382
- ss
383
- end
384
-
385
- # http://www.w3.org/TR/css3-conditional/
386
- def supports_directive(name)
387
- value = str {expr!(:supports_condition)}
388
- directive_body("@#{name} #{value}")
389
- end
390
-
391
- def supports_condition
392
- supports_negation || supports_operator || supports_declaration_condition
393
- end
394
-
395
- def supports_negation
396
- return unless tok(/not/i)
397
- ss
398
- expr!(:supports_condition_in_parens)
399
- end
400
-
401
- def supports_operator
402
- return unless supports_condition_in_parens
403
- tok!(/and|or/i)
404
- begin
405
- ss
406
- expr!(:supports_condition_in_parens)
407
- end while tok(/and|or/i)
408
- true
409
- end
410
-
411
- def supports_condition_in_parens
412
- return unless tok(/\(/); ss
413
- if supports_condition
414
- tok!(/\)/); ss
415
- else
416
- supports_declaration_body
417
- end
418
- end
419
-
420
- def supports_declaration_condition
421
- return unless tok(/\(/); ss
422
- supports_declaration_body
423
- end
424
-
425
- def supports_declaration_body
426
- tok!(IDENT); ss
427
- tok!(/:/); ss
428
- expr!(:expr); ss
429
- tok!(/\)/); ss
430
- end
431
-
432
331
  def variable
433
332
  return unless tok(/\$/)
434
333
  name = tok!(IDENT)
@@ -522,7 +421,7 @@ module Sass
522
421
  end
523
422
 
524
423
  def selector_sequence
525
- if sel = tok(STATIC_SELECTOR, true)
424
+ if sel = tok(STATIC_SELECTOR)
526
425
  return [sel]
527
426
  end
528
427
 
@@ -588,30 +487,21 @@ module Sass
588
487
  res = [e]
589
488
 
590
489
  # The tok(/\*/) allows the "E*" hack
591
- while v = id_selector || class_selector || attrib || negation || pseudo ||
592
- interpolation_selector || (tok(/\*/) && Selector::Universal.new(nil))
490
+ while v = element_name || id_selector || class_selector ||
491
+ attrib || negation || pseudo || interpolation_selector ||
492
+ (tok(/\*/) && Selector::Universal.new(nil))
593
493
  res << v
594
494
  end
595
495
 
596
- pos = @scanner.pos
597
- line = @line
598
- if sel = str? {simple_selector_sequence}
599
- @scanner.pos = pos
600
- @line = line
601
-
602
- if sel =~ /^&/
603
- begin
604
- throw_error {expected('"{"')}
605
- rescue Sass::SyntaxError => e
606
- e.message << "\n\n\"#{sel}\" may only be used at the beginning of a selector."
607
- raise e
608
- end
609
- else
610
- Sass::Util.sass_warn(<<MESSAGE)
611
- DEPRECATION WARNING:
612
- On line #{@line}#{" of \"#{@filename}\"" if @filename}, after "#{self.class.prior_snippet(@scanner)}"
613
- Starting in Sass 3.2, "#{sel}" may only be used at the beginning of a selector.
496
+ if tok?(/&/)
497
+ begin
498
+ expected('"{"')
499
+ 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.
614
503
  MESSAGE
504
+ raise e
615
505
  end
616
506
  end
617
507
 
@@ -669,10 +559,14 @@ MESSAGE
669
559
  tok(SUBSTRINGMATCH)
670
560
  @expected = "identifier or string"
671
561
  ss
672
- val = interp_ident || expr!(:interp_string)
562
+ if val = tok(IDENT)
563
+ val = [val]
564
+ else
565
+ val = expr!(:interp_string)
566
+ end
673
567
  ss
674
568
  end
675
- tok!(/\]/)
569
+ tok(/\]/)
676
570
 
677
571
  Selector::Attribute.new(merge(name), merge(ns), op, merge(val))
678
572
  end
@@ -762,7 +656,7 @@ MESSAGE
762
656
  # we don't parse it at all, and instead return a plain old string
763
657
  # containing the value.
764
658
  # This results in a dramatic speed increase.
765
- if val = tok(STATIC_VALUE, true)
659
+ if val = tok(STATIC_VALUE)
766
660
  return space, Sass::Script::String.new(val.strip)
767
661
  end
768
662
  return space, sass_script(:parse)
@@ -851,7 +745,7 @@ MESSAGE
851
745
  end
852
746
 
853
747
  def interp_ident(start = IDENT)
854
- return unless val = tok(start) || interpolation || tok(IDENT_HYPHEN_INTERP, true)
748
+ return unless val = tok(start) || interpolation
855
749
  res = [val]
856
750
  while val = tok(NAME) || interpolation
857
751
  res << val
@@ -872,14 +766,8 @@ MESSAGE
872
766
  end
873
767
 
874
768
  def str?
875
- pos = @scanner.pos
876
- line = @line
877
769
  @strs.push ""
878
- throw_error {yield} && @strs.last
879
- rescue Sass::SyntaxError => e
880
- @scanner.pos = pos
881
- @line = line
882
- nil
770
+ yield && @strs.last
883
771
  ensure
884
772
  @strs.pop
885
773
  end
@@ -920,9 +808,6 @@ MESSAGE
920
808
  :selector_comma_sequence => "selector",
921
809
  :simple_selector_sequence => "selector",
922
810
  :import_arg => "file to import (string or url())",
923
- :moz_document_function => "matching function (e.g. url-prefix(), domain())",
924
- :supports_condition => "@supports condition (e.g. (display: flexbox))",
925
- :supports_condition_in_parens => "@supports condition (e.g. (display: flexbox))",
926
811
  }
927
812
 
928
813
  TOK_NAMES = Sass::Util.to_hash(
@@ -961,13 +846,6 @@ MESSAGE
961
846
  raise Sass::SyntaxError.new(msg, :line => @line)
962
847
  end
963
848
 
964
- def throw_error
965
- old_throw_error, @throw_error = @throw_error, false
966
- yield
967
- ensure
968
- @throw_error = old_throw_error
969
- end
970
-
971
849
  def catch_error(&block)
972
850
  old_throw_error, @throw_error = @throw_error, true
973
851
  pos = @scanner.pos
@@ -987,7 +865,7 @@ MESSAGE
987
865
  if @throw_err
988
866
  throw :_sass_parser_error, err
989
867
  else
990
- @scanner = Sass::Util::MultibyteStringScanner.new(@scanner.string)
868
+ @scanner = StringScanner.new(@scanner.string)
991
869
  @scanner.pos = err[:pos]
992
870
  @line = err[:line]
993
871
  @expected = err[:expected]
@@ -997,6 +875,16 @@ MESSAGE
997
875
 
998
876
  # @private
999
877
  def self.expected(scanner, expected, line)
878
+ pos = scanner.pos
879
+
880
+ after = scanner.string[0...pos]
881
+ # Get rid of whitespace between pos and the last token,
882
+ # but only if there's a newline in there
883
+ after.gsub!(/\s*\n\s*$/, '')
884
+ # Also get rid of stuff before the last newline
885
+ after.gsub!(/.*\n/, '')
886
+ after = "..." + after[-15..-1] if after.size > 18
887
+
1000
888
  was = scanner.rest.dup
1001
889
  # Get rid of whitespace between pos and the next token,
1002
890
  # but only if there's a newline in there
@@ -1006,42 +894,17 @@ MESSAGE
1006
894
  was = was[0...15] + "..." if was.size > 18
1007
895
 
1008
896
  raise Sass::SyntaxError.new(
1009
- "Invalid CSS after \"#{prior_snippet(scanner)}\": expected #{expected}, was \"#{was}\"",
897
+ "Invalid CSS after \"#{after}\": expected #{expected}, was \"#{was}\"",
1010
898
  :line => line)
1011
899
  end
1012
900
 
1013
- # @private
1014
- def self.prior_snippet(scanner)
1015
- pos = scanner.pos
1016
-
1017
- after = scanner.string[0...pos]
1018
- # Get rid of whitespace between pos and the last token,
1019
- # but only if there's a newline in there
1020
- after.gsub!(/\s*\n\s*$/, '')
1021
- # Also get rid of stuff before the last newline
1022
- after.gsub!(/.*\n/, '')
1023
- after = "..." + after[-15..-1] if after.size > 18
1024
- after
1025
- end
1026
-
1027
901
  # Avoid allocating lots of new strings for `#tok`.
1028
902
  # This is important because `#tok` is called all the time.
1029
903
  NEWLINE = "\n"
1030
904
 
1031
- def tok(rx, last_group_lookahead = false)
905
+ def tok(rx)
1032
906
  res = @scanner.scan(rx)
1033
907
  if res
1034
- # This fixes https://github.com/nex3/sass/issues/104, which affects
1035
- # Ruby 1.8.7 and REE. This fix is to replace the ?= zero-width
1036
- # positive lookahead operator in the Regexp (which matches without
1037
- # consuming the matched group), with a match that does consume the
1038
- # group, but then rewinds the scanner and removes the group from the
1039
- # end of the matched string. This fix makes the assumption that the
1040
- # matched group will always occur at the end of the match.
1041
- if last_group_lookahead && @scanner[-1]
1042
- @scanner.pos -= @scanner[-1].length
1043
- res.slice!(-@scanner[-1].length..-1)
1044
- end
1045
908
  @line += res.count(NEWLINE)
1046
909
  @expected = nil
1047
910
  if !@strs.empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT