unboxed-less 1.2.12
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/CHANGELOG +62 -0
- data/LICENSE +179 -0
- data/README.md +48 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/bin/lessc +92 -0
- data/lib/ext.rb +31 -0
- data/lib/less.rb +32 -0
- data/lib/less/command.rb +98 -0
- data/lib/less/engine.rb +55 -0
- data/lib/less/engine/grammar/common.tt +29 -0
- data/lib/less/engine/grammar/entity.tt +130 -0
- data/lib/less/engine/grammar/less.tt +326 -0
- data/lib/less/engine/nodes.rb +9 -0
- data/lib/less/engine/nodes/element.rb +278 -0
- data/lib/less/engine/nodes/entity.rb +79 -0
- data/lib/less/engine/nodes/function.rb +84 -0
- data/lib/less/engine/nodes/literal.rb +171 -0
- data/lib/less/engine/nodes/property.rb +231 -0
- data/lib/less/engine/nodes/ruleset.rb +12 -0
- data/lib/less/engine/nodes/selector.rb +44 -0
- data/spec/command_spec.rb +102 -0
- data/spec/css/accessors.css +18 -0
- data/spec/css/big.css +3768 -0
- data/spec/css/colors.css +14 -0
- data/spec/css/comments.css +9 -0
- data/spec/css/css-3.css +17 -0
- data/spec/css/css.css +50 -0
- data/spec/css/functions.css +6 -0
- data/spec/css/import.css +12 -0
- data/spec/css/lazy-eval.css +1 -0
- data/spec/css/mixins-args.css +32 -0
- data/spec/css/mixins.css +28 -0
- data/spec/css/operations.css +28 -0
- data/spec/css/parens.css +20 -0
- data/spec/css/rulesets.css +17 -0
- data/spec/css/scope.css +11 -0
- data/spec/css/selectors.css +13 -0
- data/spec/css/strings.css +12 -0
- data/spec/css/variables.css +7 -0
- data/spec/css/whitespace.css +7 -0
- data/spec/engine_spec.rb +112 -0
- data/spec/less/accessors.less +20 -0
- data/spec/less/big.less +4810 -0
- data/spec/less/colors.less +35 -0
- data/spec/less/comments.less +46 -0
- data/spec/less/css-3.less +45 -0
- data/spec/less/css.less +104 -0
- data/spec/less/exceptions/mixed-units-error.less +3 -0
- data/spec/less/exceptions/name-error-1.0.less +3 -0
- data/spec/less/exceptions/syntax-error-1.0.less +3 -0
- data/spec/less/functions.less +6 -0
- data/spec/less/hidden.less +25 -0
- data/spec/less/import.less +8 -0
- data/spec/less/import/import-test-a.less +2 -0
- data/spec/less/import/import-test-b.less +8 -0
- data/spec/less/import/import-test-c.less +7 -0
- data/spec/less/import/import-test-d.css +1 -0
- data/spec/less/lazy-eval.less +6 -0
- data/spec/less/literal-css.less +11 -0
- data/spec/less/mixins-args.less +59 -0
- data/spec/less/mixins.less +43 -0
- data/spec/less/operations.less +39 -0
- data/spec/less/parens.less +26 -0
- data/spec/less/rulesets.less +30 -0
- data/spec/less/scope.less +32 -0
- data/spec/less/selectors.less +24 -0
- data/spec/less/strings.less +14 -0
- data/spec/less/variables.less +24 -0
- data/spec/less/whitespace.less +34 -0
- data/spec/spec.css +50 -0
- data/spec/spec_helper.rb +8 -0
- data/unboxed-less.gemspec +121 -0
- metadata +140 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
module Less
|
2
|
+
module Node
|
3
|
+
module Literal
|
4
|
+
include Entity
|
5
|
+
|
6
|
+
def unit
|
7
|
+
nil
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# rgb(255, 0, 0) #f0f0f0
|
13
|
+
#
|
14
|
+
class Color
|
15
|
+
include Literal
|
16
|
+
attr_reader :r, :g, :b, :a
|
17
|
+
|
18
|
+
def initialize r, g, b, a = 1.0
|
19
|
+
@r, @g, @b = [r, g, b].map do |c|
|
20
|
+
normalize(c.is_a?(String) ? c.to_i(16) : c)
|
21
|
+
end
|
22
|
+
@a = normalize(a, 1.0)
|
23
|
+
end
|
24
|
+
|
25
|
+
def alpha v
|
26
|
+
self.class.new r, g, b, v
|
27
|
+
end
|
28
|
+
|
29
|
+
def rgb
|
30
|
+
[r, g, b]
|
31
|
+
end
|
32
|
+
|
33
|
+
def operate op, other
|
34
|
+
color = if other.is_a? Numeric
|
35
|
+
rgb.map {|c| c.send(op, other) }
|
36
|
+
else
|
37
|
+
rgb.zip(other.rgb).map {|a, b| a.send(op, b) }
|
38
|
+
end
|
39
|
+
self.class.new *[color, @a].flatten # Ruby 1.8 hack
|
40
|
+
end
|
41
|
+
|
42
|
+
def + other; operate :+, other end
|
43
|
+
def - other; operate :-, other end
|
44
|
+
def * other; operate :*, other end
|
45
|
+
def / other; operate :/, other end
|
46
|
+
|
47
|
+
def coerce other
|
48
|
+
return self, other
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
if a < 1.0
|
53
|
+
"rgba(#{r.to_i}, #{g.to_i}, #{b.to_i}, #{a})"
|
54
|
+
else
|
55
|
+
"#%02x%02x%02x" % [r, g, b]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def inspect
|
60
|
+
if a < 1.0
|
61
|
+
"rgba(#{r}, #{g}, #{b}, #{a})"
|
62
|
+
else
|
63
|
+
"rgb(#{r}, #{g}, #{b})"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_css
|
68
|
+
to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_ruby
|
72
|
+
"#{self.class}.new(#{r},#{g},#{b},#{a})"
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
def normalize(v, max = 255, min = 0)
|
77
|
+
[[min, v].max, max].min
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# 6 10px 125%
|
83
|
+
#
|
84
|
+
class Number < DelegateClass(Float)
|
85
|
+
include Literal
|
86
|
+
|
87
|
+
attr_accessor :unit
|
88
|
+
|
89
|
+
def initialize value, unit = nil
|
90
|
+
super value.to_f
|
91
|
+
@unit = (unit.nil? || unit.empty?) ? nil : unit
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_s
|
95
|
+
"#{super}#@unit"
|
96
|
+
end
|
97
|
+
|
98
|
+
def dup
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_ruby
|
103
|
+
self.to_f
|
104
|
+
end
|
105
|
+
|
106
|
+
def inspect
|
107
|
+
to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_css
|
111
|
+
"#{(self % 1).zero?? "#{self.to_i}#@unit" : self}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# "hello world"
|
117
|
+
#
|
118
|
+
class Quoted < String
|
119
|
+
include Literal
|
120
|
+
|
121
|
+
attr_reader :quotes, :content
|
122
|
+
|
123
|
+
# Strip quotes if necessary, and save them in @quotes
|
124
|
+
def initialize str
|
125
|
+
@quotes, @content = unless str.nil? or str.empty?
|
126
|
+
str.match(/('|")(.*?)(\1)/).captures rescue [nil, str]
|
127
|
+
else
|
128
|
+
[nil, ""]
|
129
|
+
end
|
130
|
+
super @content
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_css
|
134
|
+
"#@quotes#{@content}#@quotes"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Font
|
139
|
+
include Literal
|
140
|
+
end
|
141
|
+
|
142
|
+
class FontFamily
|
143
|
+
include Literal
|
144
|
+
|
145
|
+
def initialize family = []
|
146
|
+
@family = family
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_css
|
150
|
+
@family.map(&:to_css) * ', '
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Any un-quoted word
|
156
|
+
#
|
157
|
+
# ex: red, small, border-collapse
|
158
|
+
#
|
159
|
+
class Keyword < String
|
160
|
+
include Entity
|
161
|
+
|
162
|
+
def to_css
|
163
|
+
self
|
164
|
+
end
|
165
|
+
|
166
|
+
def inspect
|
167
|
+
"#{self}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
module Less
|
2
|
+
module Node
|
3
|
+
class Property < String
|
4
|
+
include Entity
|
5
|
+
|
6
|
+
attr_accessor :value
|
7
|
+
|
8
|
+
def initialize key, value = nil, parent = nil
|
9
|
+
super key, parent
|
10
|
+
value = if value.is_a? Array
|
11
|
+
value.each {|v| v.parent = self if v.respond_to? :parent }.
|
12
|
+
map {|v| v.is_a?(Expression) ? v : Expression.new(v, self) }
|
13
|
+
elsif value.nil?
|
14
|
+
[]
|
15
|
+
else
|
16
|
+
value
|
17
|
+
end
|
18
|
+
@value = value.is_a?(Expression) ? value : Expression.new(value, self)
|
19
|
+
@value.parent = self
|
20
|
+
@value.delimiter = ','
|
21
|
+
# puts "new property #{to_s}: #{value} => #{@value}, contains: #{@value[0].class}"
|
22
|
+
# puts
|
23
|
+
end
|
24
|
+
|
25
|
+
def parent= obj
|
26
|
+
@parent = obj
|
27
|
+
value.parent = self
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy
|
31
|
+
ret = clone
|
32
|
+
ret.value = value.copy
|
33
|
+
ret
|
34
|
+
end
|
35
|
+
|
36
|
+
def << token
|
37
|
+
token = Node::Anonymous.new(*token) unless token.is_a? Entity or token.respond_to? :to_ruby
|
38
|
+
token.parent = self if token.respond_to? :parent
|
39
|
+
@value << token
|
40
|
+
end
|
41
|
+
|
42
|
+
def empty?; !@value || @value.empty? end
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
self + (empty?? "" : ": `#{value.map {|i| i.to_s } * ' | '}`")
|
46
|
+
end
|
47
|
+
|
48
|
+
def == other
|
49
|
+
self.to_s == other.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
def eql? other
|
53
|
+
self == other and value.eql? other.value
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
super
|
58
|
+
end
|
59
|
+
|
60
|
+
def nearest node
|
61
|
+
parent.nearest node
|
62
|
+
end
|
63
|
+
|
64
|
+
def evaluate env = nil
|
65
|
+
# puts "evaluating property `#{to_s}`: #{value.inspect}"
|
66
|
+
if value.is_a?(Expression) #Value
|
67
|
+
# puts "value is a Value"
|
68
|
+
value.map {|e| e.evaluate(env) } #6
|
69
|
+
else
|
70
|
+
# puts "value is a #{value.class}"
|
71
|
+
[value.evaluate(env)]
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_css env = nil
|
78
|
+
# puts "property.to_css `#{to_s}` env:#{env ? env.variables : "nil"}"
|
79
|
+
val = evaluate(env)
|
80
|
+
"#{self}: #{if val.respond_to? :to_css
|
81
|
+
val.to_css
|
82
|
+
else
|
83
|
+
# p val
|
84
|
+
# puts "#{val.class} #{val.first.class}"
|
85
|
+
val.map {|i| i.to_css }.join(", ")
|
86
|
+
end};"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class Variable < Property
|
91
|
+
attr_reader :declaration
|
92
|
+
|
93
|
+
def initialize key, value = nil, parent = nil
|
94
|
+
@declaration = value ? true : false
|
95
|
+
super key.delete('@'), value, parent
|
96
|
+
end
|
97
|
+
|
98
|
+
def inspect
|
99
|
+
"@#{super}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"@#{super}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def evaluate env = nil
|
107
|
+
if declaration
|
108
|
+
# puts "evaluating DEC"
|
109
|
+
value.evaluate #2
|
110
|
+
else
|
111
|
+
# puts "evaluating #{to_s} par: #{parent} env: #{env ? env.variables : "nil"}"
|
112
|
+
begin
|
113
|
+
var = (env || self.parent).nearest(to_s) #3
|
114
|
+
rescue VariableNameError
|
115
|
+
var = self.parent.nearest(to_s)
|
116
|
+
end
|
117
|
+
var.evaluate
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_ruby
|
122
|
+
evaluate.to_ruby
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_css env = nil
|
126
|
+
val = evaluate env
|
127
|
+
if val.respond_to? :to_css
|
128
|
+
env ? val.to_css(env) : val.to_css
|
129
|
+
else
|
130
|
+
val.map {|i| env ? i.to_css(env) : i.to_css }.join ', '
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Expression < Array
|
136
|
+
attr_accessor :parent, :delimiter
|
137
|
+
|
138
|
+
def initialize ary, parent = nil, delimiter = ' '
|
139
|
+
self.parent = parent
|
140
|
+
self.delimiter = delimiter
|
141
|
+
# puts "new expression #{ary} |#{delimiter}|"
|
142
|
+
super(ary.is_a?(Array) ? ary : [ary].flatten)
|
143
|
+
end
|
144
|
+
|
145
|
+
def expressions; select {|i| i.kind_of? Expression } end
|
146
|
+
def variables; select {|i| i.kind_of? Variable } end
|
147
|
+
def operators; select {|i| i.is_a? Operator } end
|
148
|
+
def entities; select {|i| i.kind_of? Entity } end
|
149
|
+
def literals; select {|i| i.kind_of? Literal } end
|
150
|
+
|
151
|
+
def parent= obj
|
152
|
+
@parent = obj
|
153
|
+
each {|e| e.parent = obj if e.respond_to? :parent }
|
154
|
+
end
|
155
|
+
|
156
|
+
def inspect
|
157
|
+
'[' + map {|i| i.inspect }.join(', ') + ']'
|
158
|
+
end
|
159
|
+
|
160
|
+
def delimiter= d
|
161
|
+
@delimiter = d.strip + ' '
|
162
|
+
end
|
163
|
+
|
164
|
+
def flatten
|
165
|
+
self
|
166
|
+
end
|
167
|
+
|
168
|
+
def terminal?
|
169
|
+
expressions.empty? #&& variables.empty?
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_css env = nil
|
173
|
+
# puts "TOCSS, delim: |#{@delimiter}|"
|
174
|
+
map do |i|
|
175
|
+
i.respond_to?(:to_css) ? i.to_css() : i.to_s
|
176
|
+
end * @delimiter
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_ruby
|
180
|
+
map do |i|
|
181
|
+
i.respond_to?(:to_ruby) ? i.to_ruby : i.to_s
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Evaluates the expression and instantiates a new Literal with the result
|
187
|
+
# ex: [#111, +, #111] will evaluate to a Color node, with value #222
|
188
|
+
#
|
189
|
+
def evaluate env = nil
|
190
|
+
# puts "expression #{self.inspect} env: #{env ? env.variables : "nil"}"
|
191
|
+
if size > 2 or !terminal?
|
192
|
+
# puts " SIZE > 2 or !terminal"
|
193
|
+
|
194
|
+
# puts "--- sub evaluation ---"
|
195
|
+
|
196
|
+
# Replace self with an evaluated sub-expression
|
197
|
+
evaled = self.class.new(map {|e| e.respond_to?(:evaluate) ? e.evaluate(env) : e }, parent, delimiter) #5
|
198
|
+
|
199
|
+
# puts "======================"
|
200
|
+
# puts "evaled => #{evaled.inspect}"
|
201
|
+
|
202
|
+
unit = evaled.literals.map do |node|
|
203
|
+
node.unit
|
204
|
+
end.compact.uniq
|
205
|
+
raise MixedUnitsError, evaled * ' ' if unit.size > 1 && !evaled.operators.empty?
|
206
|
+
unit = unit.join
|
207
|
+
|
208
|
+
entity = evaled.literals.find {|e| e.unit == unit } || evaled.literals.first || evaled.entities.first
|
209
|
+
result = evaled.operators.empty?? evaled : eval(evaled.to_ruby.join)
|
210
|
+
|
211
|
+
# puts "entity is a #{entity.class}"
|
212
|
+
# puts "delimiter is |#{@delimiter}|"
|
213
|
+
|
214
|
+
case result
|
215
|
+
when Entity then result
|
216
|
+
when Expression then result.size == 1 ? result.first : self.class.new(result, parent, delimiter)
|
217
|
+
else entity.class.new(result, *(unit if entity.class == Node::Number))
|
218
|
+
end
|
219
|
+
elsif size == 1
|
220
|
+
if first.is_a? Variable
|
221
|
+
first.evaluate(env)
|
222
|
+
else
|
223
|
+
first
|
224
|
+
end
|
225
|
+
else
|
226
|
+
self
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Less
|
2
|
+
module Node
|
3
|
+
class Selector < String
|
4
|
+
include Entity
|
5
|
+
|
6
|
+
Selectors = {
|
7
|
+
:Descendant => '',
|
8
|
+
:Child => '>',
|
9
|
+
:Adjacent => '+',
|
10
|
+
:PseudoClass => ':',
|
11
|
+
:PseudoElement => '::',
|
12
|
+
:Sibling => '~'
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
super Selectors[ self.class.to_s.split('::').last.to_sym ]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.[] key
|
20
|
+
Node.const_get(Selectors.find {|k, v| v == key }.first)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Descendant < Selector
|
25
|
+
def to_css; " " end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Child < Selector
|
29
|
+
def to_css; " #{self} " end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Adjacent < Selector
|
33
|
+
def to_css; " #{self} " end
|
34
|
+
end
|
35
|
+
|
36
|
+
class PseudoClass < Selector
|
37
|
+
def to_css; self end
|
38
|
+
end
|
39
|
+
|
40
|
+
class PseudoElement < Selector
|
41
|
+
def to_css; self end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|