mack-haml 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/gems.rb +13 -0
- data/lib/gems/haml-2.0.4/VERSION +1 -0
- data/lib/gems/haml-2.0.4/bin/css2sass +7 -0
- data/lib/gems/haml-2.0.4/bin/haml +9 -0
- data/lib/gems/haml-2.0.4/bin/html2haml +7 -0
- data/lib/gems/haml-2.0.4/bin/sass +8 -0
- data/lib/gems/haml-2.0.4/lib/haml.rb +1040 -0
- data/lib/gems/haml-2.0.4/lib/haml/buffer.rb +239 -0
- data/lib/gems/haml-2.0.4/lib/haml/engine.rb +265 -0
- data/lib/gems/haml-2.0.4/lib/haml/error.rb +22 -0
- data/lib/gems/haml-2.0.4/lib/haml/exec.rb +364 -0
- data/lib/gems/haml-2.0.4/lib/haml/filters.rb +275 -0
- data/lib/gems/haml-2.0.4/lib/haml/helpers.rb +453 -0
- data/lib/gems/haml-2.0.4/lib/haml/helpers/action_view_extensions.rb +45 -0
- data/lib/gems/haml-2.0.4/lib/haml/helpers/action_view_mods.rb +179 -0
- data/lib/gems/haml-2.0.4/lib/haml/html.rb +227 -0
- data/lib/gems/haml-2.0.4/lib/haml/precompiler.rb +805 -0
- data/lib/gems/haml-2.0.4/lib/haml/template.rb +51 -0
- data/lib/gems/haml-2.0.4/lib/haml/template/patch.rb +58 -0
- data/lib/gems/haml-2.0.4/lib/haml/template/plugin.rb +72 -0
- data/lib/gems/haml-2.0.4/lib/sass.rb +863 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant.rb +214 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant/color.rb +101 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant/literal.rb +54 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant/nil.rb +9 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant/number.rb +87 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant/operation.rb +30 -0
- data/lib/gems/haml-2.0.4/lib/sass/constant/string.rb +22 -0
- data/lib/gems/haml-2.0.4/lib/sass/css.rb +394 -0
- data/lib/gems/haml-2.0.4/lib/sass/engine.rb +466 -0
- data/lib/gems/haml-2.0.4/lib/sass/error.rb +35 -0
- data/lib/gems/haml-2.0.4/lib/sass/plugin.rb +169 -0
- data/lib/gems/haml-2.0.4/lib/sass/plugin/merb.rb +56 -0
- data/lib/gems/haml-2.0.4/lib/sass/plugin/rails.rb +24 -0
- data/lib/gems/haml-2.0.4/lib/sass/tree/attr_node.rb +53 -0
- data/lib/gems/haml-2.0.4/lib/sass/tree/comment_node.rb +20 -0
- data/lib/gems/haml-2.0.4/lib/sass/tree/directive_node.rb +46 -0
- data/lib/gems/haml-2.0.4/lib/sass/tree/node.rb +42 -0
- data/lib/gems/haml-2.0.4/lib/sass/tree/rule_node.rb +89 -0
- data/lib/gems/haml-2.0.4/lib/sass/tree/value_node.rb +16 -0
- data/lib/gems/haml-2.0.4/rails/init.rb +1 -0
- data/lib/mack-haml.rb +1 -0
- metadata +65 -16
@@ -0,0 +1,214 @@
|
|
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
|
+
def parse(value, constants, line)
|
44
|
+
begin
|
45
|
+
operationalize(parenthesize(tokenize(value)), constants).to_s
|
46
|
+
rescue Sass::SyntaxError => e
|
47
|
+
if e.message == "Constant arithmetic error"
|
48
|
+
e.instance_eval do
|
49
|
+
@message += ": #{value.dump}."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
e.sass_line = line
|
53
|
+
raise e
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def tokenize(value)
|
60
|
+
escaped = false
|
61
|
+
is_string = false
|
62
|
+
beginning_of_token = true
|
63
|
+
str = ''
|
64
|
+
to_return = []
|
65
|
+
|
66
|
+
reset_str = Proc.new do
|
67
|
+
to_return << str unless str.empty?
|
68
|
+
''
|
69
|
+
end
|
70
|
+
|
71
|
+
value.each_byte do |byte|
|
72
|
+
unless escaped
|
73
|
+
if byte == ESCAPE_CHAR
|
74
|
+
escaped = true
|
75
|
+
next
|
76
|
+
end
|
77
|
+
|
78
|
+
last = to_return[-1]
|
79
|
+
|
80
|
+
# Do we need to open or close a string literal?
|
81
|
+
if byte == STRING_CHAR
|
82
|
+
is_string = !is_string
|
83
|
+
|
84
|
+
# Adjacent strings should be concatenated
|
85
|
+
if is_string && last && (!last.is_a?(Symbol) || last == :close)
|
86
|
+
to_return << :concat
|
87
|
+
end
|
88
|
+
|
89
|
+
str = reset_str.call
|
90
|
+
next
|
91
|
+
end
|
92
|
+
|
93
|
+
unless is_string
|
94
|
+
|
95
|
+
# Are we looking at whitespace?
|
96
|
+
if WHITESPACE.include?(byte)
|
97
|
+
str = reset_str.call
|
98
|
+
next
|
99
|
+
end
|
100
|
+
|
101
|
+
symbol = SYMBOLS[byte]
|
102
|
+
|
103
|
+
# Adjacent values without an operator should be concatenated
|
104
|
+
if (symbol.nil? || symbol == :open || symbol == :const) &&
|
105
|
+
last && (!last.is_a?(Symbol) || last == :close)
|
106
|
+
to_return << :concat
|
107
|
+
end
|
108
|
+
|
109
|
+
# String then open with no whitespace means funcall
|
110
|
+
if symbol == :open && !str.empty?
|
111
|
+
str = reset_str.call
|
112
|
+
to_return << :funcall
|
113
|
+
end
|
114
|
+
|
115
|
+
# Time for a unary minus!
|
116
|
+
if beginning_of_token && symbol == :minus
|
117
|
+
beginning_of_token = true
|
118
|
+
to_return << :neg
|
119
|
+
next
|
120
|
+
end
|
121
|
+
|
122
|
+
# Are we looking at an operator?
|
123
|
+
if symbol && (symbol != :mod || str.empty?)
|
124
|
+
str = reset_str.call
|
125
|
+
beginning_of_token = symbol != :close
|
126
|
+
to_return << symbol
|
127
|
+
next
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
escaped = false
|
133
|
+
beginning_of_token = false
|
134
|
+
str << byte.chr
|
135
|
+
end
|
136
|
+
|
137
|
+
if is_string
|
138
|
+
raise Sass::SyntaxError.new("Unterminated string: #{value.dump}.")
|
139
|
+
end
|
140
|
+
str = reset_str.call
|
141
|
+
to_return
|
142
|
+
end
|
143
|
+
|
144
|
+
def parenthesize(value, return_after_expr = false)
|
145
|
+
to_return = []
|
146
|
+
|
147
|
+
while (token = value.shift) && token != :close
|
148
|
+
case token
|
149
|
+
when :open
|
150
|
+
to_return << parenthesize(value)
|
151
|
+
when :neg
|
152
|
+
# This is never actually reached, but we'll leave it in just in case.
|
153
|
+
raise Sass::SyntaxError.new("Unterminated unary minus.") if value.first.nil?
|
154
|
+
to_return << [:neg, parenthesize(value, true)]
|
155
|
+
when :const
|
156
|
+
raise Sass::SyntaxError.new("Unterminated constant.") if value.first.nil?
|
157
|
+
raise Sass::SyntaxError.new("Invalid constant.") unless value.first.is_a?(::String)
|
158
|
+
|
159
|
+
to_return << [:const, value.first]
|
160
|
+
value.shift
|
161
|
+
else
|
162
|
+
to_return << token
|
163
|
+
end
|
164
|
+
|
165
|
+
return to_return.first if return_after_expr
|
166
|
+
end
|
167
|
+
return to_return
|
168
|
+
end
|
169
|
+
|
170
|
+
#--
|
171
|
+
# TODO: Don't pass around original value;
|
172
|
+
# have Constant.parse automatically add it to exception.
|
173
|
+
#++
|
174
|
+
def operationalize(value, constants)
|
175
|
+
value = [value] unless value.is_a?(Array)
|
176
|
+
case value.length
|
177
|
+
when 0
|
178
|
+
Sass::Constant::Nil.new
|
179
|
+
when 1
|
180
|
+
value = value[0]
|
181
|
+
if value.is_a? Array
|
182
|
+
operationalize(value, constants)
|
183
|
+
elsif value.is_a? Operation
|
184
|
+
value
|
185
|
+
else
|
186
|
+
Literal.parse(value)
|
187
|
+
end
|
188
|
+
when 2
|
189
|
+
if value[0] == :neg
|
190
|
+
Operation.new(Sass::Constant::Number.new('0'), operationalize(value[1], constants), :minus)
|
191
|
+
elsif value[0] == :const
|
192
|
+
Literal.parse(get_constant(value[1], constants))
|
193
|
+
else
|
194
|
+
raise SyntaxError.new("Constant arithmetic error")
|
195
|
+
end
|
196
|
+
when 3
|
197
|
+
Operation.new(operationalize(value[0], constants), operationalize(value[2], constants), value[1])
|
198
|
+
else
|
199
|
+
if SECOND_ORDER.include?(value[1]) && FIRST_ORDER.include?(value[3])
|
200
|
+
operationalize([value[0], value[1], operationalize(value[2..4], constants), *value[5..-1]], constants)
|
201
|
+
else
|
202
|
+
operationalize([operationalize(value[0..2], constants), *value[3..-1]], constants)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_constant(value, constants)
|
208
|
+
to_return = constants[value]
|
209
|
+
raise SyntaxError.new("Undefined constant: \"!#{value}\".") unless to_return
|
210
|
+
to_return
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,101 @@
|
|
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
|
@@ -0,0 +1,54 @@
|
|
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
|
@@ -0,0 +1,87 @@
|
|
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
|