haml 2.0.10 → 2.2.0

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 (107) hide show
  1. data/.yardopts +5 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +347 -0
  4. data/Rakefile +124 -19
  5. data/VERSION +1 -1
  6. data/VERSION_NAME +1 -0
  7. data/extra/haml-mode.el +397 -78
  8. data/extra/sass-mode.el +148 -36
  9. data/extra/update_watch.rb +13 -0
  10. data/lib/haml.rb +15 -993
  11. data/lib/haml/buffer.rb +131 -84
  12. data/lib/haml/engine.rb +129 -97
  13. data/lib/haml/error.rb +7 -7
  14. data/lib/haml/exec.rb +127 -42
  15. data/lib/haml/filters.rb +107 -42
  16. data/lib/haml/helpers.rb +210 -156
  17. data/lib/haml/helpers/action_view_extensions.rb +34 -39
  18. data/lib/haml/helpers/action_view_mods.rb +132 -139
  19. data/lib/haml/html.rb +77 -65
  20. data/lib/haml/precompiler.rb +404 -213
  21. data/lib/haml/shared.rb +78 -0
  22. data/lib/haml/template.rb +14 -14
  23. data/lib/haml/template/patch.rb +2 -2
  24. data/lib/haml/template/plugin.rb +2 -3
  25. data/lib/haml/util.rb +211 -6
  26. data/lib/haml/version.rb +30 -13
  27. data/lib/sass.rb +7 -856
  28. data/lib/sass/css.rb +169 -161
  29. data/lib/sass/engine.rb +344 -328
  30. data/lib/sass/environment.rb +79 -0
  31. data/lib/sass/error.rb +33 -11
  32. data/lib/sass/files.rb +139 -0
  33. data/lib/sass/plugin.rb +160 -117
  34. data/lib/sass/plugin/merb.rb +7 -6
  35. data/lib/sass/plugin/rails.rb +5 -6
  36. data/lib/sass/repl.rb +58 -0
  37. data/lib/sass/script.rb +59 -0
  38. data/lib/sass/script/bool.rb +17 -0
  39. data/lib/sass/script/color.rb +183 -0
  40. data/lib/sass/script/funcall.rb +50 -0
  41. data/lib/sass/script/functions.rb +198 -0
  42. data/lib/sass/script/lexer.rb +178 -0
  43. data/lib/sass/script/literal.rb +177 -0
  44. data/lib/sass/script/node.rb +14 -0
  45. data/lib/sass/script/number.rb +381 -0
  46. data/lib/sass/script/operation.rb +45 -0
  47. data/lib/sass/script/parser.rb +172 -0
  48. data/lib/sass/script/string.rb +12 -0
  49. data/lib/sass/script/unary_operation.rb +34 -0
  50. data/lib/sass/script/variable.rb +31 -0
  51. data/lib/sass/tree/comment_node.rb +73 -10
  52. data/lib/sass/tree/debug_node.rb +30 -0
  53. data/lib/sass/tree/directive_node.rb +42 -17
  54. data/lib/sass/tree/file_node.rb +41 -0
  55. data/lib/sass/tree/for_node.rb +48 -0
  56. data/lib/sass/tree/if_node.rb +54 -0
  57. data/lib/sass/tree/mixin_def_node.rb +29 -0
  58. data/lib/sass/tree/mixin_node.rb +48 -0
  59. data/lib/sass/tree/node.rb +214 -11
  60. data/lib/sass/tree/prop_node.rb +109 -0
  61. data/lib/sass/tree/rule_node.rb +178 -51
  62. data/lib/sass/tree/variable_node.rb +34 -0
  63. data/lib/sass/tree/while_node.rb +31 -0
  64. data/test/haml/engine_test.rb +331 -36
  65. data/test/haml/helper_test.rb +12 -1
  66. data/test/haml/results/content_for_layout.xhtml +0 -3
  67. data/test/haml/results/filters.xhtml +2 -0
  68. data/test/haml/results/list.xhtml +1 -1
  69. data/test/haml/template_test.rb +7 -2
  70. data/test/haml/templates/content_for_layout.haml +0 -2
  71. data/test/haml/templates/list.haml +1 -1
  72. data/test/haml/util_test.rb +92 -0
  73. data/test/sass/css2sass_test.rb +69 -24
  74. data/test/sass/engine_test.rb +586 -64
  75. data/test/sass/functions_test.rb +125 -0
  76. data/test/sass/more_results/more1.css +9 -0
  77. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  78. data/test/sass/more_results/more_import.css +29 -0
  79. data/test/sass/more_templates/_more_partial.sass +2 -0
  80. data/test/sass/more_templates/more1.sass +23 -0
  81. data/test/sass/more_templates/more_import.sass +11 -0
  82. data/test/sass/plugin_test.rb +81 -28
  83. data/test/sass/results/line_numbers.css +49 -0
  84. data/test/sass/results/{constants.css → script.css} +4 -4
  85. data/test/sass/results/subdir/subdir.css +2 -0
  86. data/test/sass/results/units.css +11 -0
  87. data/test/sass/script_test.rb +258 -0
  88. data/test/sass/templates/import.sass +1 -1
  89. data/test/sass/templates/importee.sass +7 -2
  90. data/test/sass/templates/line_numbers.sass +13 -0
  91. data/test/sass/templates/{constants.sass → script.sass} +11 -10
  92. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  93. data/test/sass/templates/subdir/subdir.sass +2 -2
  94. data/test/sass/templates/units.sass +11 -0
  95. data/test/test_helper.rb +14 -0
  96. metadata +77 -19
  97. data/FAQ +0 -138
  98. data/README.rdoc +0 -319
  99. data/lib/sass/constant.rb +0 -216
  100. data/lib/sass/constant/color.rb +0 -101
  101. data/lib/sass/constant/literal.rb +0 -54
  102. data/lib/sass/constant/nil.rb +0 -9
  103. data/lib/sass/constant/number.rb +0 -87
  104. data/lib/sass/constant/operation.rb +0 -30
  105. data/lib/sass/constant/string.rb +0 -22
  106. data/lib/sass/tree/attr_node.rb +0 -57
  107. data/lib/sass/tree/value_node.rb +0 -20
@@ -1,216 +0,0 @@
1
- require 'sass/constant/operation'
2
- require 'sass/constant/literal'
3
-
4
- module Sass
5
- module Constant # :nodoc:
6
- # The character that begins a constant.
7
- CONSTANT_CHAR = ?!
8
-
9
- # Whitespace characters
10
- WHITESPACE = [?\ , ?\t, ?\n, ?\r]
11
-
12
- # The character used to escape values
13
- ESCAPE_CHAR = ?\\
14
-
15
- # The character used to open and close strings
16
- STRING_CHAR = ?"
17
-
18
- # A mapping of syntactically-significant characters
19
- # to parsed symbols
20
- SYMBOLS = {
21
- ?( => :open,
22
- ?) => :close,
23
- ?+ => :plus,
24
- ?- => :minus,
25
- ?* => :times,
26
- ?/ => :div,
27
- ?% => :mod,
28
- CONSTANT_CHAR => :const,
29
- STRING_CHAR => :str,
30
- ESCAPE_CHAR => :esc
31
- }
32
-
33
- # The regular expression used to parse constants
34
- MATCH = /^#{Regexp.escape(CONSTANT_CHAR.chr)}([^\s#{(SYMBOLS.keys + [ ?= ]).map {|c| Regexp.escape("#{c.chr}") }.join}]+)\s*((?:\|\|)?=)\s*(.+)/
35
-
36
- # First-order operations
37
- FIRST_ORDER = [:times, :div, :mod]
38
-
39
- # Second-order operations
40
- SECOND_ORDER = [:plus, :minus]
41
-
42
- class << self
43
- include Haml::Util
44
-
45
- def parse(value, constants, line)
46
- begin
47
- operationalize(parenthesize(tokenize(value)), constants).to_s
48
- rescue Sass::SyntaxError => e
49
- if e.message == "Constant arithmetic error"
50
- e.instance_eval do
51
- @message += ": #{value.dump}."
52
- end
53
- end
54
- e.sass_line = line
55
- raise e
56
- end
57
- end
58
-
59
- private
60
-
61
- def tokenize(value)
62
- escaped = false
63
- is_string = false
64
- beginning_of_token = true
65
- str = ''
66
- to_return = []
67
-
68
- reset_str = Proc.new do
69
- to_return << str unless str.empty?
70
- ''
71
- end
72
-
73
- each_char(value) do |byte|
74
- unless escaped
75
- if byte == ESCAPE_CHAR
76
- escaped = true
77
- next
78
- end
79
-
80
- last = to_return[-1]
81
-
82
- # Do we need to open or close a string literal?
83
- if byte == STRING_CHAR
84
- is_string = !is_string
85
-
86
- # Adjacent strings should be concatenated
87
- if is_string && last && (!last.is_a?(Symbol) || last == :close)
88
- to_return << :concat
89
- end
90
-
91
- str = reset_str.call
92
- next
93
- end
94
-
95
- unless is_string
96
-
97
- # Are we looking at whitespace?
98
- if WHITESPACE.include?(byte)
99
- str = reset_str.call
100
- next
101
- end
102
-
103
- symbol = SYMBOLS[byte]
104
-
105
- # Adjacent values without an operator should be concatenated
106
- if (symbol.nil? || symbol == :open || symbol == :const) &&
107
- last && (!last.is_a?(Symbol) || last == :close)
108
- to_return << :concat
109
- end
110
-
111
- # String then open with no whitespace means funcall
112
- if symbol == :open && !str.empty?
113
- str = reset_str.call
114
- to_return << :funcall
115
- end
116
-
117
- # Time for a unary minus!
118
- if beginning_of_token && symbol == :minus
119
- beginning_of_token = true
120
- to_return << :neg
121
- next
122
- end
123
-
124
- # Are we looking at an operator?
125
- if symbol && (symbol != :mod || str.empty?)
126
- str = reset_str.call
127
- beginning_of_token = symbol != :close
128
- to_return << symbol
129
- next
130
- end
131
- end
132
- end
133
-
134
- escaped = false
135
- beginning_of_token = false
136
- str << byte.chr
137
- end
138
-
139
- if is_string
140
- raise Sass::SyntaxError.new("Unterminated string: #{value.dump}.")
141
- end
142
- str = reset_str.call
143
- to_return
144
- end
145
-
146
- def parenthesize(value, return_after_expr = false)
147
- to_return = []
148
-
149
- while (token = value.shift) && token != :close
150
- case token
151
- when :open
152
- to_return << parenthesize(value)
153
- when :neg
154
- # This is never actually reached, but we'll leave it in just in case.
155
- raise Sass::SyntaxError.new("Unterminated unary minus.") if value.first.nil?
156
- to_return << [:neg, parenthesize(value, true)]
157
- when :const
158
- raise Sass::SyntaxError.new("Unterminated constant.") if value.first.nil?
159
- raise Sass::SyntaxError.new("Invalid constant.") unless value.first.is_a?(::String)
160
-
161
- to_return << [:const, value.first]
162
- value.shift
163
- else
164
- to_return << token
165
- end
166
-
167
- return to_return.first if return_after_expr
168
- end
169
- return to_return
170
- end
171
-
172
- #--
173
- # TODO: Don't pass around original value;
174
- # have Constant.parse automatically add it to exception.
175
- #++
176
- def operationalize(value, constants)
177
- value = [value] unless value.is_a?(Array)
178
- case value.length
179
- when 0
180
- Sass::Constant::Nil.new
181
- when 1
182
- value = value[0]
183
- if value.is_a? Array
184
- operationalize(value, constants)
185
- elsif value.is_a? Operation
186
- value
187
- else
188
- Literal.parse(value)
189
- end
190
- when 2
191
- if value[0] == :neg
192
- Operation.new(Sass::Constant::Number.new('0'), operationalize(value[1], constants), :minus)
193
- elsif value[0] == :const
194
- Literal.parse(get_constant(value[1], constants))
195
- else
196
- raise SyntaxError.new("Constant arithmetic error")
197
- end
198
- when 3
199
- Operation.new(operationalize(value[0], constants), operationalize(value[2], constants), value[1])
200
- else
201
- if SECOND_ORDER.include?(value[1]) && FIRST_ORDER.include?(value[3])
202
- operationalize([value[0], value[1], operationalize(value[2..4], constants), *value[5..-1]], constants)
203
- else
204
- operationalize([operationalize(value[0..2], constants), *value[3..-1]], constants)
205
- end
206
- end
207
- end
208
-
209
- def get_constant(value, constants)
210
- to_return = constants[value]
211
- raise SyntaxError.new("Undefined constant: \"!#{value}\".") unless to_return
212
- to_return
213
- end
214
- end
215
- end
216
- end
@@ -1,101 +0,0 @@
1
- require 'sass/constant/literal'
2
-
3
- module Sass::Constant # :nodoc:
4
- class Color < Literal # :nodoc:
5
-
6
- HTML4_COLORS = {
7
- 'black' => 0x000000,
8
- 'silver' => 0xc0c0c0,
9
- 'gray' => 0x808080,
10
- 'white' => 0xffffff,
11
- 'maroon' => 0x800000,
12
- 'red' => 0xff0000,
13
- 'purple' => 0x800080,
14
- 'fuchsia' => 0xff00ff,
15
- 'green' => 0x008000,
16
- 'lime' => 0x00ff00,
17
- 'olive' => 0x808000,
18
- 'yellow' => 0xffff00,
19
- 'navy' => 0x000080,
20
- 'blue' => 0x0000ff,
21
- 'teal' => 0x008080,
22
- 'aqua' => 0x00ffff
23
- }
24
-
25
- REGEXP = /\##{"([0-9a-fA-F]{1,2})" * 3}/
26
-
27
- def parse(value)
28
- if (value =~ REGEXP)
29
- @value = value.scan(REGEXP)[0].map { |num| num.ljust(2, num).to_i(16) }
30
- else
31
- color = HTML4_COLORS[value.downcase]
32
- @value = (0..2).map{ |n| color >> (n << 3) & 0xff }.reverse
33
- end
34
- end
35
-
36
- def plus(other)
37
- if other.is_a? Sass::Constant::String
38
- Sass::Constant::String.from_value(self.to_s + other.to_s)
39
- else
40
- piecewise(other, :+)
41
- end
42
- end
43
-
44
- def minus(other)
45
- if other.is_a? Sass::Constant::String
46
- raise NoMethodError.new(nil, :minus)
47
- else
48
- piecewise(other, :-)
49
- end
50
- end
51
-
52
- def times(other)
53
- if other.is_a? Sass::Constant::String
54
- raise NoMethodError.new(nil, :times)
55
- else
56
- piecewise(other, :*)
57
- end
58
- end
59
-
60
- def div(other)
61
- if other.is_a? Sass::Constant::String
62
- raise NoMethodError.new(nil, :div)
63
- else
64
- piecewise(other, :/)
65
- end
66
- end
67
-
68
- def mod(other)
69
- if other.is_a? Sass::Constant::String
70
- raise NoMethodError.new(nil, :mod)
71
- else
72
- piecewise(other, :%)
73
- end
74
- end
75
-
76
- def to_s
77
- red, green, blue = @value.map { |num| num.to_s(16).rjust(2, '0') }
78
- "##{red}#{green}#{blue}"
79
- end
80
-
81
- protected
82
-
83
- def self.filter_value(value)
84
- value.map { |num| num.to_i }
85
- end
86
-
87
- private
88
-
89
- def piecewise(other, operation)
90
- other_num = other.is_a? Number
91
- other_val = other.value
92
-
93
- rgb = []
94
- for i in (0...3)
95
- res = @value[i].send(operation, other_num ? other_val : other_val[i])
96
- rgb[i] = [ [res, 255].min, 0 ].max
97
- end
98
- Color.from_value(rgb)
99
- end
100
- end
101
- end
@@ -1,54 +0,0 @@
1
- # Let the subclasses see the superclass
2
- module Sass::Constant; class Literal; end; end; # :nodoc:
3
-
4
- require 'sass/constant/string'
5
- require 'sass/constant/number'
6
- require 'sass/constant/color'
7
- require 'sass/constant/nil'
8
-
9
- class Sass::Constant::Literal # :nodoc:
10
- # The regular expression matching numbers.
11
- NUMBER = /^(-?\d*?\.?)(\d+)([^\d\s]*)$/
12
-
13
- html_color_matcher = Sass::Constant::Color::HTML4_COLORS.keys.map { |c| "^#{c}$" }.join '|'
14
-
15
- # The regular expression matching colors.
16
- COLOR = /^\# (?: [\da-f]{3} | [\da-f]{6} ) | #{html_color_matcher}/ix
17
-
18
- def self.parse(value)
19
- case value
20
- when NUMBER
21
- Sass::Constant::Number.new(value)
22
- when COLOR
23
- Sass::Constant::Color.new(value)
24
- else
25
- Sass::Constant::String.new(value)
26
- end
27
- end
28
-
29
- def initialize(value = nil)
30
- self.parse(value) if value
31
- end
32
-
33
- def perform
34
- self
35
- end
36
-
37
- def concat(other)
38
- Sass::Constant::String.from_value("#{self.to_s} #{other.to_s}")
39
- end
40
-
41
- attr_reader :value
42
-
43
- protected
44
-
45
- def self.filter_value(value)
46
- value
47
- end
48
-
49
- def self.from_value(value)
50
- instance = self.new
51
- instance.instance_variable_set('@value', self.filter_value(value))
52
- instance
53
- end
54
- end
@@ -1,9 +0,0 @@
1
- require 'sass/constant/literal'
2
-
3
- module Sass::Constant # :nodoc:
4
- class Nil < Literal # :nodoc:
5
- def to_s
6
- ''
7
- end
8
- end
9
- end
@@ -1,87 +0,0 @@
1
- require 'sass/constant/literal'
2
-
3
- module Sass::Constant # :nodoc:
4
- class Number < Literal # :nodoc:
5
-
6
- attr_reader :unit
7
-
8
- def parse(value)
9
- first, second, unit = value.scan(Literal::NUMBER)[0]
10
- @value = first.empty? ? second.to_i : "#{first}#{second}".to_f
11
- @unit = unit.empty? ? nil : unit
12
- end
13
-
14
- def plus(other)
15
- if other.is_a? Number
16
- operate(other, :+)
17
- elsif other.is_a? Color
18
- other.plus(self)
19
- else
20
- Sass::Constant::String.from_value(self.to_s + other.to_s)
21
- end
22
- end
23
-
24
- def minus(other)
25
- if other.is_a? Number
26
- operate(other, :-)
27
- else
28
- raise NoMethodError.new(nil, :minus)
29
- end
30
- end
31
-
32
- def times(other)
33
- if other.is_a? Number
34
- operate(other, :*)
35
- elsif other.is_a? Color
36
- other.times(self)
37
- else
38
- raise NoMethodError.new(nil, :times)
39
- end
40
- end
41
-
42
- def div(other)
43
- if other.is_a? Number
44
- operate(other, :/)
45
- else
46
- raise NoMethodError.new(nil, :div)
47
- end
48
- end
49
-
50
- def mod(other)
51
- if other.is_a? Number
52
- operate(other, :%)
53
- else
54
- raise NoMethodError.new(nil, :mod)
55
- end
56
- end
57
-
58
- def to_s
59
- value = @value
60
- value = value.to_i if value % 1 == 0.0
61
- "#{value}#{@unit}"
62
- end
63
-
64
- protected
65
-
66
- def self.from_value(value, unit=nil)
67
- instance = super(value)
68
- instance.instance_variable_set('@unit', unit)
69
- instance
70
- end
71
-
72
- def operate(other, operation)
73
- unit = nil
74
- if other.unit.nil?
75
- unit = self.unit
76
- elsif self.unit.nil?
77
- unit = other.unit
78
- elsif other.unit == self.unit
79
- unit = self.unit
80
- else
81
- raise Sass::SyntaxError.new("Incompatible units: #{self.unit} and #{other.unit}.")
82
- end
83
-
84
- Number.from_value(self.value.send(operation, other.value), unit)
85
- end
86
- end
87
- end