unboxed-less 1.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|