haml 3.1.0.alpha.33 → 3.1.0.alpha.36

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (61) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/VERSION +1 -1
  3. data/vendor/sass/doc-src/SASS_CHANGELOG.md +177 -2
  4. data/vendor/sass/doc-src/SASS_REFERENCE.md +140 -3
  5. data/vendor/sass/lib/sass/cache_stores.rb +14 -0
  6. data/vendor/sass/lib/sass/cache_stores/active_support.rb +28 -0
  7. data/vendor/sass/lib/sass/cache_stores/base.rb +84 -0
  8. data/vendor/sass/lib/sass/cache_stores/filesystem.rb +56 -0
  9. data/vendor/sass/lib/sass/cache_stores/memory.rb +51 -0
  10. data/vendor/sass/lib/sass/cache_stores/null.rb +25 -0
  11. data/vendor/sass/lib/sass/engine.rb +86 -25
  12. data/vendor/sass/lib/sass/exec.rb +10 -1
  13. data/vendor/sass/lib/sass/importers/rails.rb +75 -0
  14. data/vendor/sass/lib/sass/less.rb +1 -1
  15. data/vendor/sass/lib/sass/plugin/compiler.rb +4 -1
  16. data/vendor/sass/lib/sass/plugin/configuration.rb +4 -2
  17. data/vendor/sass/lib/sass/plugin/rack.rb +15 -2
  18. data/vendor/sass/lib/sass/plugin/rails.rb +89 -9
  19. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +30 -2
  20. data/vendor/sass/lib/sass/script/css_parser.rb +1 -1
  21. data/vendor/sass/lib/sass/script/functions.rb +126 -5
  22. data/vendor/sass/lib/sass/script/lexer.rb +1 -1
  23. data/vendor/sass/lib/sass/script/list.rb +76 -0
  24. data/vendor/sass/lib/sass/script/literal.rb +10 -1
  25. data/vendor/sass/lib/sass/script/number.rb +1 -1
  26. data/vendor/sass/lib/sass/script/operation.rb +3 -2
  27. data/vendor/sass/lib/sass/script/parser.rb +25 -12
  28. data/vendor/sass/lib/sass/scss/css_parser.rb +0 -5
  29. data/vendor/sass/lib/sass/scss/parser.rb +46 -7
  30. data/vendor/sass/lib/sass/scss/static_parser.rb +1 -1
  31. data/vendor/sass/lib/sass/tree/charset_node.rb +37 -0
  32. data/vendor/sass/lib/sass/tree/directive_node.rb +2 -2
  33. data/vendor/sass/lib/sass/tree/each_node.rb +54 -0
  34. data/vendor/sass/lib/sass/tree/if_node.rb +19 -0
  35. data/vendor/sass/lib/sass/tree/media_node.rb +75 -0
  36. data/vendor/sass/lib/sass/tree/prop_node.rb +1 -1
  37. data/vendor/sass/lib/sass/tree/root_node.rb +37 -5
  38. data/vendor/sass/lib/sass/tree/rule_node.rb +4 -6
  39. data/vendor/sass/lib/sass/util.rb +18 -1
  40. data/vendor/sass/test/sass/cache_test.rb +7 -7
  41. data/vendor/sass/test/sass/conversion_test.rb +28 -0
  42. data/vendor/sass/test/sass/engine_test.rb +214 -11
  43. data/vendor/sass/test/sass/functions_test.rb +69 -0
  44. data/vendor/sass/test/sass/plugin_test.rb +13 -4
  45. data/vendor/sass/test/sass/results/import_charset.css +4 -0
  46. data/vendor/sass/test/sass/results/import_charset_1_8.css +4 -0
  47. data/vendor/sass/test/sass/results/import_charset_ibm866.css +4 -0
  48. data/vendor/sass/test/sass/script_conversion_test.rb +27 -25
  49. data/vendor/sass/test/sass/script_test.rb +12 -1
  50. data/vendor/sass/test/sass/scss/css_test.rb +27 -8
  51. data/vendor/sass/test/sass/scss/scss_test.rb +77 -0
  52. data/vendor/sass/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  53. data/vendor/sass/test/sass/templates/_imported_charset_utf8.sass +4 -0
  54. data/vendor/sass/test/sass/templates/import_charset.sass +7 -0
  55. data/vendor/sass/test/sass/templates/import_charset_1_8.sass +4 -0
  56. data/vendor/sass/test/sass/templates/import_charset_ibm866.sass +9 -0
  57. data/vendor/sass/test/sass/templates/script.sass +2 -2
  58. data/vendor/sass/test/test_helper.rb +8 -0
  59. metadata +27 -10
  60. data/REVISION +0 -1
  61. data/vendor/sass/lib/sass/cache_store.rb +0 -208
@@ -92,7 +92,7 @@ module Sass
92
92
  :number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
93
93
  :color => HEXCOLOR,
94
94
  :bool => /(true|false)\b/,
95
- :ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + "(?!#{NMCHAR}|$)")})})},
95
+ :ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + "(?!#{NMCHAR}|\Z)")})})},
96
96
  :op => %r{(#{Regexp.union(*OP_NAMES)})},
97
97
  }
98
98
 
@@ -0,0 +1,76 @@
1
+ module Sass::Script
2
+ # A SassScript object representing a CSS list.
3
+ # This includes both comma-separated lists and space-separated lists.
4
+ class List < Literal
5
+ # The Ruby array containing the contents of the list.
6
+ #
7
+ # @return [Array<Literal>]
8
+ attr_reader :value
9
+ alias_method :children, :value
10
+ alias_method :to_a, :value
11
+
12
+ # The operator separating the values of the list.
13
+ # Either `:comma` or `:space`.
14
+ #
15
+ # @return [Symbol]
16
+ attr_reader :separator
17
+
18
+ # Creates a new list.
19
+ #
20
+ # @param value [Array<Literal>] See \{#value}
21
+ # @param separator [String] See \{#separator}
22
+ def initialize(value, separator)
23
+ super(value)
24
+ @separator = separator
25
+ end
26
+
27
+ # @see Node#eq
28
+ def eq(other)
29
+ Sass::Script::Bool.new(
30
+ self.class == other.class && self.value == other.value &&
31
+ self.separator == other.separator)
32
+ end
33
+
34
+ # @see Node#to_s
35
+ def to_s(opts = {})
36
+ return value.map {|e| e.to_s(opts)}.join(sep_str)
37
+ end
38
+
39
+ # @see Node#to_sass
40
+ def to_sass(opts = {})
41
+ precedence = Sass::Script::Parser.precedence_of(separator)
42
+ value.map do |v|
43
+ if v.is_a?(List) && Sass::Script::Parser.precedence_of(v.separator) <= precedence
44
+ "(#{v.to_sass(opts)})"
45
+ else
46
+ v.to_sass(opts)
47
+ end
48
+ end.join(sep_str(nil))
49
+ end
50
+
51
+ # @see Node#inspect
52
+ def inspect
53
+ "(#{to_sass})"
54
+ end
55
+
56
+ protected
57
+
58
+ # @see Node#_perform
59
+ def _perform(environment)
60
+ list = Sass::Script::List.new(
61
+ value.map {|e| e.perform(environment)},
62
+ separator)
63
+ list.options = self.options
64
+ list.context = self.context
65
+ list
66
+ end
67
+
68
+ private
69
+
70
+ def sep_str(opts = self.options)
71
+ return ' ' if separator == :space
72
+ return ',' if opts && opts[:style] == :compressed
73
+ return ', '
74
+ end
75
+ end
76
+ end
@@ -9,6 +9,7 @@ module Sass::Script
9
9
  require 'sass/script/number'
10
10
  require 'sass/script/color'
11
11
  require 'sass/script/bool'
12
+ require 'sass/script/list'
12
13
 
13
14
  # Returns the Ruby value of the literal.
14
15
  # The type of this value varies based on the subclass.
@@ -107,7 +108,7 @@ MSG
107
108
  # @param other [Literal] The right-hand side of the operator
108
109
  # @return [Script::String] A string containing both literals
109
110
  # separated by a space
110
- def concat(other)
111
+ def space(other)
111
112
  Sass::Script::String.new("#{self.to_s} #{other.to_s}")
112
113
  end
113
114
 
@@ -214,6 +215,14 @@ MSG
214
215
  # @raise [Sass::SyntaxError] if this literal isn't an integer
215
216
  def assert_int!; to_i; end
216
217
 
218
+ # Returns the value of this literal as a list.
219
+ # Single literals are considered the same as single-element lists.
220
+ #
221
+ # @return [Array<Literal>] The of this literal as a list
222
+ def to_a
223
+ [self]
224
+ end
225
+
217
226
  # Returns the string representation of this literal
218
227
  # as it would be output to the CSS document.
219
228
  #
@@ -238,7 +238,7 @@ module Sass::Script
238
238
  # @return [String] The CSS representation of this number
239
239
  # @raise [Sass::SyntaxError] if this number has units that can't be used in CSS
240
240
  # (e.g. `px*in`)
241
- def to_s
241
+ def to_s(opts = {})
242
242
  return original if original
243
243
  raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
244
244
  inspect
@@ -41,7 +41,7 @@ module Sass::Script
41
41
  sep =
42
42
  case @operator
43
43
  when :comma; ", "
44
- when :concat; " "
44
+ when :space; " "
45
45
  else; " #{Lexer::OPERATORS_REVERSE[@operator]} "
46
46
  end
47
47
  "#{o1}#{sep}#{o2}"
@@ -66,7 +66,7 @@ module Sass::Script
66
66
  literal1 = @operand1.perform(environment)
67
67
  literal2 = @operand2.perform(environment)
68
68
 
69
- if @operator == :concat && context == :equals
69
+ if @operator == :space && context == :equals
70
70
  literal1 = Sass::Script::String.new(literal1.value) if literal1.is_a?(Sass::Script::String)
71
71
  literal2 = Sass::Script::String.new(literal2.value) if literal2.is_a?(Sass::Script::String)
72
72
  end
@@ -82,6 +82,7 @@ module Sass::Script
82
82
  private
83
83
 
84
84
  def operand_to_sass(op, side, opts)
85
+ return "(#{op.to_sass(opts)})" if op.is_a?(List)
85
86
  return op.to_sass(opts) unless op.is_a?(Operation)
86
87
 
87
88
  pred = Sass::Script::Parser.precedence_of(@operator)
@@ -123,14 +123,14 @@ module Sass
123
123
  end
124
124
 
125
125
  PRECEDENCE = [
126
- :comma, :single_eq, :concat, :or, :and,
126
+ :comma, :single_eq, :space, :or, :and,
127
127
  [:eq, :neq],
128
128
  [:gt, :gte, :lt, :lte],
129
129
  [:plus, :minus],
130
130
  [:times, :div, :mod],
131
131
  ]
132
132
 
133
- ASSOCIATIVE = [:comma, :concat, :plus, :times]
133
+ ASSOCIATIVE = [:plus, :times]
134
134
 
135
135
  class << self
136
136
  # Returns an integer representing the precedence
@@ -193,7 +193,18 @@ RUBY
193
193
  # @private
194
194
  def lexer_class; Lexer; end
195
195
 
196
- production :expr, :interpolation, :comma
196
+ def expr
197
+ interp = try_ops_after_interp([:comma], :expr) and return interp
198
+ line = @lexer.line
199
+ return unless e = interpolation
200
+ arr = [e]
201
+ while tok = try_tok(:comma)
202
+ interp = try_op_before_interp(tok, e) and return interp
203
+ arr << assert_expr(:interpolation)
204
+ end
205
+ arr.size == 1 ? arr.first : node(List.new(arr, :comma), line)
206
+ end
207
+
197
208
  production :equals, :interpolation, :single_eq
198
209
 
199
210
  def try_op_before_interp(op, prev = nil)
@@ -219,25 +230,27 @@ RUBY
219
230
  return interp
220
231
  end
221
232
 
222
- def interpolation(first = concat)
233
+ def interpolation(first = space)
223
234
  e = first
224
235
  while interp = try_tok(:begin_interpolation)
225
236
  wb = @lexer.whitespace?(interp)
226
237
  line = @lexer.line
227
238
  mid = parse_interpolated
228
239
  wa = @lexer.whitespace?
229
- e = Script::Interpolation.new(e, mid, concat, wb, wa)
240
+ e = Script::Interpolation.new(e, mid, space, wb, wa)
230
241
  e.line = line
231
242
  end
232
243
  e
233
244
  end
234
245
 
235
- def concat
246
+ def space
247
+ line = @lexer.line
236
248
  return unless e = or_expr
237
- while sub = or_expr
238
- e = node(Operation.new(e, sub, :concat))
249
+ arr = [e]
250
+ while e = or_expr
251
+ arr << e
239
252
  end
240
- e
253
+ arr.size == 1 ? arr.first : node(List.new(arr, :space), line)
241
254
  end
242
255
 
243
256
  production :or_expr, :and_expr, :or
@@ -280,7 +293,7 @@ RUBY
280
293
  c = assert_tok(:const)
281
294
  var = Script::Variable.new(c.value)
282
295
  if tok = (try_tok(:colon) || try_tok(:single_eq))
283
- val = assert_expr(:concat)
296
+ val = assert_expr(:space)
284
297
 
285
298
  if tok.type == :single_eq
286
299
  val.context = :equals
@@ -427,8 +440,8 @@ RUBY
427
440
  @lexer.expected!(EXPR_NAMES[:default])
428
441
  end
429
442
 
430
- def node(node)
431
- node.line = @lexer.line
443
+ def node(node, line = @lexer.line)
444
+ node.line = line
432
445
  node
433
446
  end
434
447
  end
@@ -24,11 +24,6 @@ module Sass
24
24
  def interp_ident(ident = IDENT); tok(ident); end
25
25
  def use_css_import?; true; end
26
26
 
27
- def special_directive(name)
28
- return unless name == 'media' || name == 'import'
29
- super
30
- end
31
-
32
27
  def block_child(context)
33
28
  case context
34
29
  when :ruleset
@@ -98,7 +98,8 @@ module Sass
98
98
  node << comment
99
99
  end
100
100
 
101
- DIRECTIVES = Set[:mixin, :include, :debug, :warn, :for, :while, :if, :extend, :import, :media]
101
+ DIRECTIVES = Set[:mixin, :include, :debug, :warn, :for, :each, :while, :if,
102
+ :else, :extend, :import, :media, :charset]
102
103
 
103
104
  def directive
104
105
  return unless tok(/@/)
@@ -168,6 +169,18 @@ module Sass
168
169
  block(node(Sass::Tree::ForNode.new(var, from, to, exclusive)), :directive)
169
170
  end
170
171
 
172
+ def each_directive
173
+ tok!(/\$/)
174
+ var = tok! IDENT
175
+ ss
176
+
177
+ tok!(/in/)
178
+ list = sass_script(:parse)
179
+ ss
180
+
181
+ block(node(Sass::Tree::EachNode.new(var, list)), :directive)
182
+ end
183
+
171
184
  def while_directive
172
185
  expr = sass_script(:parse)
173
186
  ss
@@ -179,12 +192,14 @@ module Sass
179
192
  ss
180
193
  node = block(node(Sass::Tree::IfNode.new(expr)), :directive)
181
194
  pos = @scanner.pos
195
+ line = @line
182
196
  ss
183
197
 
184
198
  else_block(node) ||
185
199
  begin
186
200
  # Backtrack in case there are any comments we want to parse
187
201
  @scanner.pos = pos
202
+ @line = line
188
203
  node
189
204
  end
190
205
  end
@@ -197,16 +212,23 @@ module Sass
197
212
  :directive)
198
213
  node.add_else(else_node)
199
214
  pos = @scanner.pos
215
+ line = @line
200
216
  ss
201
217
 
202
218
  else_block(node) ||
203
219
  begin
204
220
  # Backtrack in case there are any comments we want to parse
205
221
  @scanner.pos = pos
222
+ @line = line
206
223
  node
207
224
  end
208
225
  end
209
226
 
227
+ def else_directive
228
+ raise Sass::SyntaxError.new(
229
+ "Invalid CSS: @else must come after @if", :line => @line)
230
+ end
231
+
210
232
  def extend_directive
211
233
  node(Sass::Tree::ExtendNode.new(expr!(:selector)))
212
234
  end
@@ -240,7 +262,7 @@ module Sass
240
262
 
241
263
  def media_directive
242
264
  val = str {media_query_list}.strip
243
- block(node(Sass::Tree::DirectiveNode.new("@media #{val}")), :directive)
265
+ block(node(Sass::Tree::MediaNode.new(val)), :directive)
244
266
  end
245
267
 
246
268
  # http://www.w3.org/TR/css3-mediaqueries/#syntax
@@ -289,6 +311,13 @@ module Sass
289
311
  true
290
312
  end
291
313
 
314
+ def charset_directive
315
+ tok! STRING
316
+ name = @scanner[1] || @scanner[2]
317
+ ss
318
+ node(Sass::Tree::CharsetNode.new(name))
319
+ end
320
+
292
321
  def variable
293
322
  return unless tok(/\$/)
294
323
  name = tok!(IDENT)
@@ -398,9 +427,14 @@ module Sass
398
427
  return unless v = selector
399
428
  rules.concat v
400
429
 
430
+ ws = ''
401
431
  while tok(/,/)
402
- rules << ',' << str {ss}
403
- rules.concat expr!(:selector)
432
+ ws << str {ss}
433
+ if v = selector
434
+ rules << ',' << ws
435
+ rules.concat v
436
+ ws = ''
437
+ end
404
438
  end
405
439
  rules
406
440
  end
@@ -413,10 +447,14 @@ module Sass
413
447
  def selector_comma_sequence
414
448
  return unless sel = _selector
415
449
  selectors = [sel]
450
+ ws = ''
416
451
  while tok(/,/)
417
- ws = str{ss}
418
- selectors << expr!(:_selector)
419
- selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n")
452
+ ws << str{ss}
453
+ if sel = _selector
454
+ selectors << sel
455
+ selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n")
456
+ ws = ''
457
+ end
420
458
  end
421
459
  Selector::CommaSequence.new(selectors)
422
460
  end
@@ -761,6 +799,7 @@ MESSAGE
761
799
  :interp_ident => "identifier",
762
800
  :interp_name => "identifier",
763
801
  :expr => "expression (e.g. 1px, bold)",
802
+ :_selector => "selector",
764
803
  :selector_comma_sequence => "selector",
765
804
  :simple_selector_sequence => "selector",
766
805
  :import_arg => "file to import (string or url())",
@@ -32,7 +32,7 @@ module Sass
32
32
  def use_css_import?; true; end
33
33
 
34
34
  def special_directive(name)
35
- return unless name == 'media' || name == 'import'
35
+ return unless %w[media import charset].include?(name)
36
36
  super
37
37
  end
38
38
  end
@@ -0,0 +1,37 @@
1
+ module Sass::Tree
2
+ # A static node representing an unproccessed Sass `@charset` directive.
3
+ #
4
+ # @see Sass::Tree
5
+ class CharsetNode < Node
6
+ # The name of the charset.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :name
10
+
11
+ # @param name [String] see \{#name}
12
+ def initialize(name)
13
+ @name = name
14
+ super()
15
+ end
16
+
17
+ # @see Node#invisible?
18
+ def invisible?
19
+ !Sass::Util.ruby1_8?
20
+ end
21
+
22
+ protected
23
+
24
+ # @see Node#to_src
25
+ def to_src(tabs, opts, fmt)
26
+ "#{' ' * tabs}@charset \"#{name}\"#{semi fmt}\n"
27
+ end
28
+
29
+ # Computes the CSS for the directive.
30
+ #
31
+ # @param tabs [Fixnum] The level of indentation for the CSS
32
+ # @return [String] The resulting CSS
33
+ def _to_s(tabs)
34
+ "@charset \"#{name}\";"
35
+ end
36
+ end
37
+ end
@@ -4,8 +4,8 @@ module Sass::Tree
4
4
  # are handled by their own nodes;
5
5
  # only CSS directives like `@media` and `@font-face` become {DirectiveNode}s.
6
6
  #
7
- # `@import` is a bit of a weird case;
8
- # it becomes an {ImportNode}.
7
+ # `@import` and `@charset` are special cases;
8
+ # they become {ImportNode}s and {CharsetNode}s, respectively.
9
9
  #
10
10
  # @see Sass::Tree
11
11
  class DirectiveNode < Node
@@ -0,0 +1,54 @@
1
+ require 'sass/tree/node'
2
+
3
+ module Sass::Tree
4
+ # A dynamic node representing a Sass `@each` loop.
5
+ #
6
+ # @see Sass::Tree
7
+ class EachNode < Node
8
+ # @param var [String] The name of the loop variable
9
+ # @param list [Script::Node] The parse tree for the list
10
+ def initialize(var, list)
11
+ @var = var
12
+ @list = list
13
+ super()
14
+ end
15
+
16
+ protected
17
+
18
+ # @see Node#to_src
19
+ def to_src(tabs, opts, fmt)
20
+ "#{' ' * tabs}@each $#{dasherize(@var, opts)} in #{@list.to_sass(opts)}" +
21
+ children_to_src(tabs, opts, fmt)
22
+ end
23
+
24
+ # Runs the child nodes once for each value in the list.
25
+ #
26
+ # @param environment [Sass::Environment] The lexical environment containing
27
+ # variable and mixin values
28
+ # @return [Array<Tree::Node>] The resulting static nodes
29
+ # @see Sass::Tree
30
+ def _perform(environment)
31
+ list = @list.perform(environment)
32
+
33
+ children = []
34
+ environment = Sass::Environment.new(environment)
35
+ list.to_a.each do |v|
36
+ environment.set_local_var(@var, v)
37
+ children += perform_children(environment)
38
+ end
39
+ children
40
+ end
41
+
42
+ # Returns an error message if the given child node is invalid,
43
+ # and false otherwise.
44
+ #
45
+ # {ExtendNode}s are valid within {EachNode}s.
46
+ #
47
+ # @param child [Tree::Node] A potential child node.
48
+ # @return [Boolean, String] Whether or not the child node is valid,
49
+ # as well as the error message to display if it is invalid
50
+ def invalid_child?(child)
51
+ super unless child.is_a?(ExtendNode)
52
+ end
53
+ end
54
+ end