cloudhead-less 1.1.13 → 1.2.0
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/VERSION +1 -1
- data/less.gemspec +4 -2
- data/lib/ext.rb +1 -12
- data/lib/less/command.rb +2 -1
- data/lib/less/engine/grammar/common.tt +1 -1
- data/lib/less/engine/grammar/entity.tt +4 -4
- data/lib/less/engine/grammar/less.tt +100 -65
- data/lib/less/engine/nodes/element.rb +48 -7
- data/lib/less/engine/nodes/entity.rb +3 -3
- data/lib/less/engine/nodes/function.rb +9 -4
- data/lib/less/engine/nodes/literal.rb +8 -4
- data/lib/less/engine/nodes/property.rb +63 -11
- data/lib/less/engine/nodes/selector.rb +1 -1
- data/spec/css/css-3.css +9 -0
- data/spec/css/mixins-args.css +17 -0
- data/spec/engine_spec.rb +4 -3
- data/spec/less/css-3.less +12 -0
- data/spec/less/hidden.less +25 -0
- data/spec/less/literal-css.less +11 -0
- data/spec/less/mixins-args.less +30 -0
- metadata +5 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/less.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{less}
|
5
|
-
s.version = "1.
|
5
|
+
s.version = "1.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["cloudhead"]
|
9
|
-
s.date = %q{2009-08-
|
9
|
+
s.date = %q{2009-08-31}
|
10
10
|
s.default_executable = %q{lessc}
|
11
11
|
s.description = %q{LESS is leaner CSS}
|
12
12
|
s.email = %q{self@cloudhead.net}
|
@@ -160,12 +160,14 @@ Gem::Specification.new do |s|
|
|
160
160
|
"spec/less/exceptions/name-error-1.0.less",
|
161
161
|
"spec/less/exceptions/syntax-error-1.0.less",
|
162
162
|
"spec/less/functions.less",
|
163
|
+
"spec/less/hidden.less",
|
163
164
|
"spec/less/import.less",
|
164
165
|
"spec/less/import/import-test-a.less",
|
165
166
|
"spec/less/import/import-test-b.less",
|
166
167
|
"spec/less/import/import-test-c.less",
|
167
168
|
"spec/less/import/import-test-d.css",
|
168
169
|
"spec/less/lazy-eval.less",
|
170
|
+
"spec/less/literal-css.less",
|
169
171
|
"spec/less/mixins-args.less",
|
170
172
|
"spec/less/mixins.less",
|
171
173
|
"spec/less/operations.less",
|
data/lib/ext.rb
CHANGED
@@ -27,11 +27,6 @@ class Object
|
|
27
27
|
yield self
|
28
28
|
self
|
29
29
|
end
|
30
|
-
|
31
|
-
def log(s = '') puts "* #{s}" if $verbose end
|
32
|
-
def log!(s = '') puts "* #{s}" end
|
33
|
-
def error(s) $stderr.puts s end
|
34
|
-
def error!(s) raise Exception, s end
|
35
30
|
end
|
36
31
|
|
37
32
|
class Array
|
@@ -49,16 +44,10 @@ class Array
|
|
49
44
|
end
|
50
45
|
end
|
51
46
|
|
52
|
-
class Class
|
53
|
-
def to_sym
|
54
|
-
self.to_s.to_sym
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
47
|
unless :symbol.respond_to?(:to_proc)
|
59
48
|
class Symbol
|
60
49
|
def to_proc
|
61
|
-
|
50
|
+
Proc.new {|*args| args.shift.__send__(self, *args) }
|
62
51
|
end
|
63
52
|
end
|
64
53
|
end
|
data/lib/less/command.rb
CHANGED
@@ -93,7 +93,7 @@ module Less
|
|
93
93
|
|
94
94
|
def err s = '', type = ''
|
95
95
|
type = type.strip + ' ' unless type.empty?
|
96
|
-
print "#{RED["! #{type}Error"]}: #{s}"
|
96
|
+
$stderr.print "#{RED["! #{type}Error"]}: #{s}"
|
97
97
|
if @options[:growl]
|
98
98
|
growl = Growl.new
|
99
99
|
growl.title = "LESS"
|
@@ -101,6 +101,7 @@ module Less
|
|
101
101
|
growl.run
|
102
102
|
false
|
103
103
|
end
|
104
|
+
return 1
|
104
105
|
end
|
105
106
|
end
|
106
107
|
end
|
@@ -5,7 +5,7 @@ module Less
|
|
5
5
|
# Entity: Any whitespace delimited token
|
6
6
|
#
|
7
7
|
rule entity
|
8
|
-
function /
|
8
|
+
url / function / accessor / keyword / variable / literal / font
|
9
9
|
end
|
10
10
|
|
11
11
|
rule fonts
|
@@ -21,13 +21,13 @@ module Less
|
|
21
21
|
end
|
22
22
|
|
23
23
|
rule font
|
24
|
-
[a-zA-Z] [-a-zA-Z0-9]* {
|
24
|
+
[a-zA-Z] [-a-zA-Z0-9]* !ns {
|
25
25
|
def build
|
26
26
|
Node::Keyword.new(text_value)
|
27
27
|
end
|
28
28
|
} / string {
|
29
29
|
def build
|
30
|
-
Node::
|
30
|
+
Node::Quoted.new(text_value)
|
31
31
|
end
|
32
32
|
}
|
33
33
|
end
|
@@ -46,7 +46,7 @@ module Less
|
|
46
46
|
end
|
47
47
|
} / string {
|
48
48
|
def build
|
49
|
-
Node::
|
49
|
+
Node::Quoted.new(text_value)
|
50
50
|
end
|
51
51
|
}
|
52
52
|
end
|
@@ -4,7 +4,7 @@ module Less
|
|
4
4
|
include Entity
|
5
5
|
|
6
6
|
rule primary
|
7
|
-
(declaration /
|
7
|
+
(import / declaration / mixin / ruleset / comment)* {
|
8
8
|
def build env = Less::Element.new
|
9
9
|
elements.map do |e|
|
10
10
|
e.build env if e.respond_to? :build
|
@@ -21,56 +21,47 @@ module Less
|
|
21
21
|
# div, .class, body > p {...}
|
22
22
|
#
|
23
23
|
rule ruleset
|
24
|
-
selectors "{" ws primary ws "}" ws {
|
24
|
+
selectors "{" ws primary ws "}" s hide:(';'?) ws {
|
25
25
|
def build env
|
26
26
|
# Build the ruleset for each selector
|
27
27
|
selectors.build(env, :ruleset).each do |sel|
|
28
|
+
sel.hide unless hide.empty?
|
28
29
|
primary.build sel
|
29
30
|
end
|
30
31
|
end
|
31
|
-
|
32
|
+
# Mixin Declaration
|
33
|
+
} / '@' name:[-a-zA-Z0-9_]+ s parameters ws "{" ws primary ws "}" ws {
|
34
|
+
def build env
|
35
|
+
env << Node::Mixin.new(name.text_value, parameters.build(env))
|
36
|
+
primary.build env.last
|
37
|
+
#env.last
|
38
|
+
end
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
rule mixin
|
43
|
+
ws selectors ';' ws {
|
32
44
|
def build env
|
33
45
|
selectors.build(env, :mixin).each do |path|
|
34
46
|
rules = path.inject(env.root) do |current, node|
|
35
47
|
current.descend(node.selector, node) or raise MixinNameError, path.join
|
36
48
|
end.rules
|
37
49
|
env.rules += rules
|
50
|
+
#env.mix(rules)
|
38
51
|
end
|
39
52
|
end
|
40
|
-
}
|
41
|
-
end
|
42
|
-
|
43
|
-
rule import
|
44
|
-
ws "@import" S url:(string / url) medias? s ';' ws {
|
53
|
+
} / name:('@' [-a-zA-Z0-9_]+) args:(arguments?) s ';' {
|
45
54
|
def build env
|
46
|
-
|
47
|
-
|
48
|
-
if File.exist? path
|
49
|
-
imported = Less::Engine.new(File.new(path)).to_tree
|
50
|
-
env.rules += imported.rules
|
51
|
-
else
|
52
|
-
raise ImportError, path
|
53
|
-
end
|
54
|
-
end
|
55
|
-
}
|
56
|
-
end
|
55
|
+
mix = env.nearest(name.text_value, :mixin) or raise MixinNameError, name.text_value
|
56
|
+
params = args.build.map {|i| Node::Expression.new i } unless args.empty?
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
Node::String.new CGI.unescape(path.text_value)
|
62
|
-
end
|
63
|
-
|
64
|
-
def value
|
65
|
-
build
|
58
|
+
env.mix ((params.nil? || params.empty?) ?
|
59
|
+
mix.rules + mix.params :
|
60
|
+
mix.pass(params, env))
|
66
61
|
end
|
67
62
|
}
|
68
63
|
end
|
69
|
-
|
70
|
-
rule medias
|
71
|
-
[-a-z]+ (s ',' s [a-z]+)*
|
72
|
-
end
|
73
|
-
|
64
|
+
|
74
65
|
rule selectors
|
75
66
|
ws selector tail:(s ',' ws selector)* ws {
|
76
67
|
def build env, method
|
@@ -89,7 +80,7 @@ module Less
|
|
89
80
|
# div > p a {...}
|
90
81
|
#
|
91
82
|
rule selector
|
92
|
-
sel:(s select element s)+
|
83
|
+
sel:(s select element s)+ '' {
|
93
84
|
def ruleset env
|
94
85
|
sel.elements.inject(env) do |node, e|
|
95
86
|
node << Node::Element.new(e.element.text_value, e.select.text_value)
|
@@ -104,16 +95,78 @@ module Less
|
|
104
95
|
end
|
105
96
|
}
|
106
97
|
end
|
98
|
+
|
99
|
+
rule parameters
|
100
|
+
'(' s ')' {
|
101
|
+
def build env
|
102
|
+
[]
|
103
|
+
end
|
104
|
+
} / '(' parameter tail:(s ',' s parameter)* ')' {
|
105
|
+
def build env
|
106
|
+
all.map do |e|
|
107
|
+
e.build(env)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def all
|
112
|
+
[parameter] + tail.elements.map {|e| e.parameter }
|
113
|
+
end
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
rule parameter
|
118
|
+
variable s ':' s expressions {
|
119
|
+
def build env
|
120
|
+
Node::Variable.new(variable.text_value, expressions.build(env), env)
|
121
|
+
end
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
rule import
|
126
|
+
ws "@import" S url:(string / url) medias? s ';' ws {
|
127
|
+
def build env
|
128
|
+
path = File.join(env.root.file || Dir.pwd, url.value)
|
129
|
+
path += '.less' unless path =~ /\.(le|c)ss$/
|
130
|
+
if File.exist? path
|
131
|
+
imported = Less::Engine.new(File.new(path)).to_tree
|
132
|
+
env.rules += imported.rules
|
133
|
+
else
|
134
|
+
raise ImportError, path
|
135
|
+
end
|
136
|
+
end
|
137
|
+
}
|
138
|
+
end
|
139
|
+
|
140
|
+
rule url
|
141
|
+
'url(' path:(string / [-a-zA-Z0-9_%$/.&=:;#+?]+) ')' {
|
142
|
+
def build env = nil
|
143
|
+
Node::Function.new('url', value)
|
144
|
+
end
|
145
|
+
|
146
|
+
def value
|
147
|
+
Node::Quoted.new CGI.unescape(path.text_value)
|
148
|
+
end
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
rule medias
|
153
|
+
[-a-z]+ (s ',' s [a-z]+)*
|
154
|
+
end
|
107
155
|
|
108
156
|
#
|
109
157
|
# @my-var: 12px;
|
110
158
|
# height: 100%;
|
111
159
|
#
|
112
160
|
rule declaration
|
113
|
-
ws name:(ident / variable) s ':' s expressions s (';'/ ws &'}') ws {
|
161
|
+
ws name:(ident / variable) s ':' s expressions tail:(ws ',' ws expressions)* s (';'/ ws &'}') ws {
|
114
162
|
def build env
|
163
|
+
result = all.map {|e| e.build(env) if e.respond_to? :build }.compact
|
115
164
|
env << (name.text_value =~ /^@/ ?
|
116
|
-
Node::Variable : Node::Property).new(name.text_value,
|
165
|
+
Node::Variable : Node::Property).new(name.text_value, result, env)
|
166
|
+
end
|
167
|
+
|
168
|
+
def all
|
169
|
+
[expressions] + tail.elements.map {|f| f.expressions }
|
117
170
|
end
|
118
171
|
# Empty rule
|
119
172
|
} / ws ident s ':' s ';' ws
|
@@ -125,7 +178,7 @@ module Less
|
|
125
178
|
rule expressions
|
126
179
|
# Operation
|
127
180
|
expression tail:(operator expression)+ {
|
128
|
-
def build env
|
181
|
+
def build env = nil
|
129
182
|
all.map {|e| e.build(env) }.dissolve
|
130
183
|
end
|
131
184
|
|
@@ -134,7 +187,7 @@ module Less
|
|
134
187
|
end
|
135
188
|
# Space-delimited expressions
|
136
189
|
} / expression tail:(WS expression)* i:important? {
|
137
|
-
def build env
|
190
|
+
def build env = nil
|
138
191
|
all.map {|e| e.build(env) if e.respond_to? :build }.compact
|
139
192
|
end
|
140
193
|
|
@@ -151,12 +204,13 @@ module Less
|
|
151
204
|
|
152
205
|
rule expression
|
153
206
|
'(' s expressions s ')' {
|
154
|
-
def build env
|
207
|
+
def build env = nil
|
155
208
|
Node::Expression.new(['('] + expressions.build(env).flatten + [')'])
|
156
209
|
end
|
157
210
|
} / entity '' {
|
158
|
-
def build env
|
159
|
-
entity.method(:build).arity.zero?? entity.build : entity.build(env)
|
211
|
+
def build env = nil
|
212
|
+
e = entity.method(:build).arity.zero?? entity.build : entity.build(env)
|
213
|
+
e.respond_to?(:dissolve) ? e.dissolve : e
|
160
214
|
end
|
161
215
|
}
|
162
216
|
end
|
@@ -164,7 +218,7 @@ module Less
|
|
164
218
|
# !important
|
165
219
|
rule important
|
166
220
|
s '!' s 'important' {
|
167
|
-
def build env
|
221
|
+
def build env = nil
|
168
222
|
Node::Keyword.new(text_value.strip)
|
169
223
|
end
|
170
224
|
}
|
@@ -246,13 +300,13 @@ module Less
|
|
246
300
|
rule function
|
247
301
|
name:([-a-zA-Z_]+) arguments {
|
248
302
|
def build
|
249
|
-
Node::Function.new(name.text_value,
|
303
|
+
Node::Function.new(name.text_value, arguments.build)
|
250
304
|
end
|
251
305
|
}
|
252
306
|
end
|
253
307
|
|
254
308
|
rule arguments
|
255
|
-
'(' s
|
309
|
+
'(' s expressions s tail:(',' s expressions s)* ')' {
|
256
310
|
def build
|
257
311
|
all.map do |e|
|
258
312
|
e.build if e.respond_to? :build
|
@@ -260,30 +314,11 @@ module Less
|
|
260
314
|
end
|
261
315
|
|
262
316
|
def all
|
263
|
-
[
|
264
|
-
end
|
265
|
-
}
|
266
|
-
end
|
267
|
-
|
268
|
-
rule argument
|
269
|
-
color / number unit {
|
270
|
-
def build
|
271
|
-
Node::Number.new number.text_value, unit.text_value
|
272
|
-
end
|
273
|
-
} / string {
|
274
|
-
def build
|
275
|
-
Node::String.new text_value
|
276
|
-
end
|
277
|
-
} / [a-zA-Z]+ '=' dimension {
|
278
|
-
def build
|
279
|
-
Node::Anonymous.new text_value
|
280
|
-
end
|
281
|
-
} / [-a-zA-Z0-9_%$/.&=:;#+?]+ {
|
282
|
-
def build
|
283
|
-
Node::String.new text_value
|
317
|
+
[expressions] + tail.elements.map {|e| e.expressions }
|
284
318
|
end
|
285
|
-
} /
|
319
|
+
} / '(' s ')' {
|
286
320
|
def build
|
321
|
+
[]
|
287
322
|
end
|
288
323
|
}
|
289
324
|
end
|
@@ -76,7 +76,9 @@ module Less
|
|
76
76
|
def identifiers; @rules.select {|r| r.kind_of? Property } end
|
77
77
|
def properties; @rules.select {|r| r.instance_of? Property } end
|
78
78
|
def variables; @rules.select {|r| r.instance_of? Variable } end
|
79
|
-
def elements; @rules.select {|r| r.
|
79
|
+
def elements; @rules.select {|r| r.kind_of? Element } end
|
80
|
+
def mixins; @rules.select {|r| r.instance_of? Mixin } end
|
81
|
+
def parameters; [] end
|
80
82
|
|
81
83
|
# Select a child element
|
82
84
|
# TODO: Implement full selector syntax & merge with descend()
|
@@ -84,7 +86,7 @@ module Less
|
|
84
86
|
case key
|
85
87
|
when Entity
|
86
88
|
@rules.find {|i| i.eql? key }
|
87
|
-
when
|
89
|
+
when String
|
88
90
|
@rules.find {|i| i.to_s == key }
|
89
91
|
else raise ArgumentError
|
90
92
|
end
|
@@ -117,7 +119,13 @@ module Less
|
|
117
119
|
self[element.name] if self[element.name].selector.class == selector.class
|
118
120
|
end
|
119
121
|
end
|
120
|
-
|
122
|
+
|
123
|
+
def mix arr = []
|
124
|
+
@rules += arr.map do |r|
|
125
|
+
r.copy.tap {|i| i.parent = self }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
121
129
|
#
|
122
130
|
# Add an arbitrary node to this element
|
123
131
|
#
|
@@ -158,10 +166,10 @@ module Less
|
|
158
166
|
end
|
159
167
|
|
160
168
|
#
|
161
|
-
# Find the nearest
|
169
|
+
# Find the nearest node in the hierarchy or raise a NameError
|
162
170
|
#
|
163
|
-
def nearest ident
|
164
|
-
ary = ident =~ /^[.#]/ ? :elements : :variables
|
171
|
+
def nearest ident, type = nil
|
172
|
+
ary = type || ident =~ /^[.#]/ ? :elements : :variables
|
165
173
|
path.map do |node|
|
166
174
|
node.send(ary).find {|i| i.to_s == ident }
|
167
175
|
end.compact.first.tap do |result|
|
@@ -188,11 +196,44 @@ module Less
|
|
188
196
|
|
189
197
|
(root?? "\n" : "") + [
|
190
198
|
indent[ depth ] + self.to_s,
|
191
|
-
put[ properties ],
|
192
199
|
put[ variables ],
|
200
|
+
put[ properties ],
|
193
201
|
elements.map {|i| i.inspect( depth + 1 ) } * "\n"
|
194
202
|
].reject(&:empty?).join("\n") + "\n" + indent[ depth ]
|
195
203
|
end
|
196
204
|
end
|
205
|
+
|
206
|
+
class Mixin < Element
|
207
|
+
attr_accessor :params
|
208
|
+
|
209
|
+
def initialize name, params = []
|
210
|
+
super name
|
211
|
+
@params = params.each do |param|
|
212
|
+
param.parent = self
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def variables
|
217
|
+
@params + super
|
218
|
+
end
|
219
|
+
|
220
|
+
def pass args, parent
|
221
|
+
params.zip(args).map do |a, b|
|
222
|
+
b ? Node::Variable.new(a.to_s, Expression.new([b])) : a
|
223
|
+
end + identifiers + elements
|
224
|
+
end
|
225
|
+
|
226
|
+
def parameters
|
227
|
+
@params
|
228
|
+
end
|
229
|
+
|
230
|
+
def to_s
|
231
|
+
'@' + name
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_css *args
|
235
|
+
""
|
236
|
+
end
|
237
|
+
end
|
197
238
|
end
|
198
239
|
end
|
@@ -57,20 +57,20 @@ module Less
|
|
57
57
|
# An anonymous node, for all the 'other' stuff
|
58
58
|
# which doesn't need any specific functionality.
|
59
59
|
#
|
60
|
-
class Anonymous <
|
60
|
+
class Anonymous < String
|
61
61
|
include Entity
|
62
62
|
end
|
63
63
|
|
64
64
|
#
|
65
65
|
# + * - /
|
66
66
|
#
|
67
|
-
class Operator <
|
67
|
+
class Operator < String
|
68
68
|
def to_ruby
|
69
69
|
self
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
class Paren <
|
73
|
+
class Paren < String
|
74
74
|
def to_ruby
|
75
75
|
self
|
76
76
|
end
|
@@ -48,12 +48,17 @@ module Less
|
|
48
48
|
#
|
49
49
|
# it calls functions from the Functions module
|
50
50
|
#
|
51
|
-
class Function <
|
51
|
+
class Function < String
|
52
52
|
include Entity
|
53
53
|
include Functions
|
54
54
|
|
55
|
-
def initialize name,
|
56
|
-
@args = args.
|
55
|
+
def initialize name, args
|
56
|
+
@args = if args.is_a? Array
|
57
|
+
Value.new(args, self)
|
58
|
+
else
|
59
|
+
[args]
|
60
|
+
end
|
61
|
+
|
57
62
|
super name
|
58
63
|
end
|
59
64
|
|
@@ -67,7 +72,7 @@ module Less
|
|
67
72
|
# If the function isn't found, we just print it out,
|
68
73
|
# this is the case for url(), for example,
|
69
74
|
#
|
70
|
-
def evaluate
|
75
|
+
def evaluate context = nil
|
71
76
|
if Functions.available.include? self.to_sym
|
72
77
|
send to_sym, *@args
|
73
78
|
else
|
@@ -17,7 +17,7 @@ module Less
|
|
17
17
|
|
18
18
|
def initialize r, g, b, a = 1.0
|
19
19
|
@r, @g, @b = [r, g, b].map do |c|
|
20
|
-
normalize(c.is_a?(
|
20
|
+
normalize(c.is_a?(String) ? c.to_i(16) : c)
|
21
21
|
end
|
22
22
|
@a = normalize(a, 1.0)
|
23
23
|
end
|
@@ -94,7 +94,11 @@ module Less
|
|
94
94
|
def to_s
|
95
95
|
"#{super}#@unit"
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
|
+
def dup
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
98
102
|
def to_ruby
|
99
103
|
self.to_f
|
100
104
|
end
|
@@ -111,7 +115,7 @@ module Less
|
|
111
115
|
#
|
112
116
|
# "hello world"
|
113
117
|
#
|
114
|
-
class
|
118
|
+
class Quoted < String
|
115
119
|
include Literal
|
116
120
|
|
117
121
|
attr_reader :quotes, :content
|
@@ -152,7 +156,7 @@ module Less
|
|
152
156
|
#
|
153
157
|
# ex: red, small, border-collapse
|
154
158
|
#
|
155
|
-
class Keyword <
|
159
|
+
class Keyword < String
|
156
160
|
include Entity
|
157
161
|
|
158
162
|
def to_css
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Less
|
2
2
|
module Node
|
3
|
-
class Property <
|
3
|
+
class Property < String
|
4
4
|
include Entity
|
5
5
|
|
6
6
|
attr_accessor :value
|
@@ -15,11 +15,20 @@ module Less
|
|
15
15
|
else
|
16
16
|
value
|
17
17
|
end
|
18
|
-
|
19
|
-
@value =
|
18
|
+
|
19
|
+
@value = value.is_a?(Value) ? value : Value.new(value, self)
|
20
20
|
@eval = false # Store the first evaluation in here
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
|
+
def parent= obj
|
24
|
+
@parent = obj
|
25
|
+
value.parent = self
|
26
|
+
end
|
27
|
+
|
28
|
+
def copy
|
29
|
+
clone.tap {|c| c.value = value.copy }
|
30
|
+
end
|
31
|
+
|
23
32
|
def << token
|
24
33
|
token = Node::Anonymous.new(*token) unless token.is_a? Entity or token.respond_to? :to_ruby
|
25
34
|
token.parent = self if token.respond_to? :parent
|
@@ -50,12 +59,12 @@ module Less
|
|
50
59
|
end
|
51
60
|
|
52
61
|
# TODO: @eval and @value should be merged
|
53
|
-
def evaluate
|
54
|
-
@eval ||= value.evaluate
|
62
|
+
def evaluate
|
63
|
+
@eval ||= value.is_a?(Value) ? value.map {|e| e.evaluate } : [value.evaluate]
|
55
64
|
end
|
56
65
|
|
57
66
|
def to_css
|
58
|
-
"#{self}: #{evaluate.to_css};"
|
67
|
+
"#{self}: #{evaluate.map {|i| i.to_css }.join(", ")};"
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
@@ -88,7 +97,42 @@ module Less
|
|
88
97
|
end
|
89
98
|
|
90
99
|
def to_css
|
91
|
-
evaluate
|
100
|
+
evaluate
|
101
|
+
if @eval.respond_to? :to_css
|
102
|
+
@eval.to_css
|
103
|
+
else
|
104
|
+
@eval.map {|i| i.to_css }.join ', '
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class Value < Array
|
110
|
+
attr_reader :parent
|
111
|
+
|
112
|
+
def initialize ary, parent = nil
|
113
|
+
@parent = parent
|
114
|
+
if ary.size == 1 && !ary.first.is_a?(Array)
|
115
|
+
super [Expression.new([ary.first])]
|
116
|
+
else
|
117
|
+
super ary.map {|e| e.is_a?(Expression) ? e : Expression.new(e, self) }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def parent= obj
|
122
|
+
@parent = obj
|
123
|
+
each {|e| e.parent = obj if e.respond_to? :parent }
|
124
|
+
end
|
125
|
+
|
126
|
+
def evaluate
|
127
|
+
map {|e| e.evaluate }.dissolve
|
128
|
+
end
|
129
|
+
|
130
|
+
def copy
|
131
|
+
first.copy
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_css
|
135
|
+
map {|e| e.to_css } * ', '
|
92
136
|
end
|
93
137
|
end
|
94
138
|
|
@@ -97,7 +141,7 @@ module Less
|
|
97
141
|
|
98
142
|
def initialize ary, parent = nil
|
99
143
|
self.parent = parent
|
100
|
-
super ary
|
144
|
+
super ary.dup
|
101
145
|
end
|
102
146
|
|
103
147
|
def expressions; select {|i| i.kind_of? Expression } end
|
@@ -114,10 +158,18 @@ module Less
|
|
114
158
|
'[' + map {|i| i.inspect }.join(', ') + ']'
|
115
159
|
end
|
116
160
|
|
161
|
+
def flatten
|
162
|
+
self
|
163
|
+
end
|
164
|
+
|
117
165
|
def terminal?
|
118
166
|
expressions.empty?
|
119
167
|
end
|
120
|
-
|
168
|
+
|
169
|
+
def copy
|
170
|
+
self.class.new(map {|i| i.dup }, parent)
|
171
|
+
end
|
172
|
+
|
121
173
|
def to_css
|
122
174
|
map do |i|
|
123
175
|
i.respond_to?(:to_css) ? i.to_css : i.to_s
|
@@ -145,7 +197,7 @@ module Less
|
|
145
197
|
raise MixedUnitsError, self * ' ' if ary.size > 1 && !operators.empty?
|
146
198
|
end.join
|
147
199
|
|
148
|
-
entity = literals.find {|e| e.unit == unit } || entities.first
|
200
|
+
entity = literals.find {|e| e.unit == unit } || literals.first || entities.first
|
149
201
|
result = operators.empty?? self : eval(to_ruby.join)
|
150
202
|
|
151
203
|
case result
|
data/spec/css/css-3.css
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
.comma-delimited {
|
2
|
+
background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
|
3
|
+
text-shadow: -1px -1px 1px red, 6px 5px 5px yellow;
|
4
|
+
-moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset;
|
5
|
+
}
|
6
|
+
@font-face {
|
7
|
+
font-family: Headline;
|
8
|
+
src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg");
|
9
|
+
}
|
1
10
|
p:not([class*="lead"]) { color: black; }
|
2
11
|
a[href^="http://"], a[href$="http://"] { color: black; }
|
3
12
|
p::before { color: black; }
|
data/spec/css/mixins-args.css
CHANGED
data/spec/engine_spec.rb
CHANGED
@@ -84,16 +84,17 @@ describe Less::Engine do
|
|
84
84
|
|
85
85
|
it "should handle custom functions" do
|
86
86
|
module Less::Functions
|
87
|
-
def color
|
87
|
+
def color args
|
88
|
+
arg = args.first
|
88
89
|
Less::Node::Color.new("99", "99", "99") if arg == "evil red"
|
89
90
|
end
|
90
91
|
|
91
92
|
def increment a
|
92
|
-
Less::Node::Number.new(a.to_i + 1)
|
93
|
+
Less::Node::Number.new(a.evaluate.to_i + 1)
|
93
94
|
end
|
94
95
|
|
95
96
|
def add a, b
|
96
|
-
Less::Node::Number.new(a + b)
|
97
|
+
Less::Node::Number.new(a.evaluate + b.evaluate)
|
97
98
|
end
|
98
99
|
end
|
99
100
|
lessify(:functions).should == css(:functions)
|
data/spec/less/css-3.less
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
.comma-delimited {
|
2
|
+
background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
|
3
|
+
text-shadow: -1px -1px 1px red, 6px 5px 5px yellow;
|
4
|
+
-moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset,
|
5
|
+
0pt 4px 6px rgba(255, 255, 255, 0.4) inset;
|
6
|
+
}
|
7
|
+
@font-face {
|
8
|
+
font-family: Headline;
|
9
|
+
src: local(Futura-Medium),
|
10
|
+
url(fonts.svg#MyGeometricModern) format("svg");
|
11
|
+
}
|
12
|
+
|
1
13
|
p:not([class*="lead"]) {
|
2
14
|
color: black;
|
3
15
|
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
.hidden {
|
2
|
+
color: transparent;
|
3
|
+
.inside {
|
4
|
+
width: 0%;
|
5
|
+
}
|
6
|
+
};
|
7
|
+
|
8
|
+
.fully-hidden {
|
9
|
+
color: none;
|
10
|
+
};
|
11
|
+
|
12
|
+
.visible {
|
13
|
+
width: 100%;
|
14
|
+
.hidden {
|
15
|
+
color: black;
|
16
|
+
};
|
17
|
+
}
|
18
|
+
|
19
|
+
.mix {
|
20
|
+
.hidden;
|
21
|
+
}
|
22
|
+
|
23
|
+
.mix2 {
|
24
|
+
.visible;
|
25
|
+
}
|
data/spec/less/mixins-args.less
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
@mixin (@a: 1px, @b: 50%) {
|
2
|
+
width: @a * 5;
|
3
|
+
height: @b - 1%;
|
4
|
+
}
|
5
|
+
|
6
|
+
@hidden() {
|
7
|
+
color: transparent;
|
8
|
+
}
|
9
|
+
|
10
|
+
.two-args {
|
11
|
+
color: blue;
|
12
|
+
@mixin(2px, 100%);
|
13
|
+
}
|
14
|
+
|
15
|
+
.one-arg {
|
16
|
+
@mixin(3px);
|
17
|
+
}
|
18
|
+
|
19
|
+
.no-parens {
|
20
|
+
@mixin;
|
21
|
+
}
|
22
|
+
|
23
|
+
.no-args {
|
24
|
+
@mixin();
|
25
|
+
}
|
26
|
+
|
27
|
+
.var-args {
|
28
|
+
@var: 9;
|
29
|
+
@mixin(@var, @var * 2);
|
30
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudhead-less
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cloudhead
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-31 00:00:00 -07:00
|
13
13
|
default_executable: lessc
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -167,12 +167,14 @@ files:
|
|
167
167
|
- spec/less/exceptions/name-error-1.0.less
|
168
168
|
- spec/less/exceptions/syntax-error-1.0.less
|
169
169
|
- spec/less/functions.less
|
170
|
+
- spec/less/hidden.less
|
170
171
|
- spec/less/import.less
|
171
172
|
- spec/less/import/import-test-a.less
|
172
173
|
- spec/less/import/import-test-b.less
|
173
174
|
- spec/less/import/import-test-c.less
|
174
175
|
- spec/less/import/import-test-d.css
|
175
176
|
- spec/less/lazy-eval.less
|
177
|
+
- spec/less/literal-css.less
|
176
178
|
- spec/less/mixins-args.less
|
177
179
|
- spec/less/mixins.less
|
178
180
|
- spec/less/operations.less
|
@@ -188,7 +190,6 @@ files:
|
|
188
190
|
- spec/spec_helper.rb
|
189
191
|
has_rdoc: false
|
190
192
|
homepage: http://www.lesscss.org
|
191
|
-
licenses:
|
192
193
|
post_install_message:
|
193
194
|
rdoc_options:
|
194
195
|
- --charset=UTF-8
|
@@ -209,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
210
|
requirements: []
|
210
211
|
|
211
212
|
rubyforge_project: less
|
212
|
-
rubygems_version: 1.
|
213
|
+
rubygems_version: 1.2.0
|
213
214
|
signing_key:
|
214
215
|
specification_version: 3
|
215
216
|
summary: LESS compiler
|