less 1.0.16 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,271 @@
1
+ module Less
2
+ grammar StyleSheet
3
+ include Common
4
+ include Entity
5
+
6
+ rule primary
7
+ (declaration / ruleset / import / comment)+ <Builder> / declaration* <Builder> / import* <Builder> / comment*
8
+ end
9
+
10
+ rule comment
11
+ ws '/*' (!'*/' . )* '*/' ws / ws '//' (!"\n" .)* "\n" ws
12
+ end
13
+
14
+ #
15
+ # div, .class, body > p {...}
16
+ #
17
+ rule ruleset
18
+ selectors "{" ws primary ws "}" ws {
19
+ def build env
20
+ # Build the ruleset for each selector
21
+ selectors.build(env, :ruleset).each do |sel|
22
+ primary.build sel
23
+ end
24
+ end
25
+ } / ws selectors ';' ws {
26
+ def build env
27
+ selectors.build(env, :mixin).each do |path|
28
+ rules = path.inject(env.root) do |current, node|
29
+ current.descend(node.selector, node) or raise MixinNameError, path.join
30
+ end.rules
31
+ env.rules += rules
32
+ end
33
+ end
34
+ }
35
+ end
36
+
37
+ rule import
38
+ "@import" S url:(string / url) medias? s ';' ws {
39
+ def build env
40
+ path = File.join(env.root.file, url.value)
41
+ path += '.less' unless path =~ /\.(le|c)ss$/
42
+ if File.exist? path
43
+ imported = Less::Engine.new(File.new(path)).to_tree
44
+ env.rules += imported.rules
45
+ else
46
+ raise ImportError, path
47
+ end
48
+ end
49
+ }
50
+ end
51
+
52
+ rule url
53
+ 'url(' path:(string / [-a-zA-Z0-9_%$/.&=:;#+?]+) ')' {
54
+ def build env = nil
55
+ Node::String.new CGI.unescape(path.text_value)
56
+ end
57
+
58
+ def value
59
+ build
60
+ end
61
+ }
62
+ end
63
+
64
+ rule medias
65
+ [-a-z]+ (s ',' s [a-z]+)*
66
+ end
67
+
68
+ rule selectors
69
+ ws selector tail:(s ',' ws selector)* ws {
70
+ def build env, method
71
+ all.map do |e|
72
+ e.send(method, env) if e.respond_to? method
73
+ end.compact
74
+ end
75
+
76
+ def all
77
+ [selector] + tail.elements.map {|e| e.selector }
78
+ end
79
+ }
80
+ end
81
+
82
+ #
83
+ # div > p a {...}
84
+ #
85
+ rule selector
86
+ sel:(s select element s)+ arguments? {
87
+ def ruleset env
88
+ sel.elements.inject(env) do |node, e|
89
+ node << Node::Element.new(e.element.text_value, e.select.text_value)
90
+ node.last
91
+ end
92
+ end
93
+
94
+ def mixin env
95
+ sel.elements.map do |e|
96
+ Node::Element.new(e.element.text_value, e.select.text_value)
97
+ end
98
+ end
99
+ }
100
+ end
101
+
102
+ #
103
+ # @my-var: 12px;
104
+ # height: 100%;
105
+ #
106
+ rule declaration
107
+ ws name:(ident / variable) s ':' s expressions s (';'/ ws &'}') ws {
108
+ def build env
109
+ env << (name.text_value =~ /^@/ ?
110
+ Node::Variable : Node::Property).new(name.text_value, expressions.build(env), env)
111
+ end
112
+ # Empty rule
113
+ } / ws ident s ':' s ';' ws
114
+ end
115
+
116
+ #
117
+ # An operation or compound value
118
+ #
119
+ rule expressions
120
+ # Operation
121
+ expression tail:(operator expression)+ {
122
+ def build env
123
+ all.map {|e| e.build(env) }.dissolve
124
+ end
125
+
126
+ def all
127
+ [expression] + tail.elements.map {|i| [i.operator, i.expression] }.flatten.compact
128
+ end
129
+ # Space-delimited expressions
130
+ } / expression tail:(WS expression)* {
131
+ def build env
132
+ all.map {|e| e.build(env) if e.respond_to? :build }.compact
133
+ end
134
+
135
+ def all
136
+ [expression] + tail.elements.map {|f| f.expression }
137
+ end
138
+ }
139
+ end
140
+
141
+ rule expression
142
+ '(' s expressions s ')' {
143
+ def build env
144
+ Node::Expression.new(['('] + expressions.build(env).flatten + [')'])
145
+ end
146
+ } / entity '' {
147
+ def build env
148
+ entity.method(:build).arity.zero?? entity.build : entity.build(env)
149
+ end
150
+ }
151
+ end
152
+
153
+ #
154
+ # An identifier
155
+ #
156
+ rule ident
157
+ '*'? '-'? [-a-z0-9_]+
158
+ end
159
+
160
+ rule variable
161
+ '@' [-a-zA-Z0-9_]+ {
162
+ def build
163
+ Node::Variable.new(text_value)
164
+ end
165
+ }
166
+ end
167
+
168
+ #
169
+ # div / .class / #id / input[type="text"] / lang(fr)
170
+ #
171
+ rule element
172
+ (class_id / tag / ident) attribute* ('(' ident? attribute* ')')? / attribute+ / '@media' / '@font-face'
173
+ end
174
+
175
+ rule class_id
176
+ tag? (class / id)+
177
+ end
178
+
179
+ #
180
+ # [type="text"]
181
+ #
182
+ rule attribute
183
+ '[' tag ([|~*$^]? '=') (tag / string) ']' / '[' (tag / string) ']'
184
+ end
185
+
186
+ rule class
187
+ '.' [_a-z] [-a-zA-Z0-9_]*
188
+ end
189
+
190
+ rule id
191
+ '#' [_a-z] [-a-zA-Z0-9_]*
192
+ end
193
+
194
+ rule tag
195
+ [a-zA-Z] [-a-zA-Z]* [0-9]? / '*'
196
+ end
197
+
198
+ rule select
199
+ (s [+>~] s / s ':' / S)?
200
+ end
201
+
202
+ # TODO: Merge this with attribute rule
203
+ rule accessor
204
+ ident:(class_id / tag) '[' attr:(string / variable) ']' {
205
+ def build env
206
+ env.nearest(ident.text_value)[attr.text_value.delete(%q["'])].evaluate
207
+ end
208
+ }
209
+ end
210
+
211
+ rule operator
212
+ S [-+*/] S {
213
+ def build env
214
+ Node::Operator.new(text_value.strip)
215
+ end
216
+ } / [-+*/] {
217
+ def build env
218
+ Node::Operator.new(text_value)
219
+ end
220
+ }
221
+ end
222
+
223
+ #
224
+ # Functions and arguments
225
+ #
226
+ rule function
227
+ name:([-a-zA-Z_]+) arguments {
228
+ def build
229
+ Node::Function.new(name.text_value, [arguments.build].flatten)
230
+ end
231
+ }
232
+ end
233
+
234
+ rule arguments
235
+ '(' s argument s tail:(',' s argument s)* ')' {
236
+ def build
237
+ all.map do |e|
238
+ e.build if e.respond_to? :build
239
+ end.compact
240
+ end
241
+
242
+ def all
243
+ [argument] + tail.elements.map {|e| e.argument }
244
+ end
245
+ }
246
+ end
247
+
248
+ rule argument
249
+ color / number unit {
250
+ def build
251
+ Node::Number.new number.text_value, unit.text_value
252
+ end
253
+ } / string {
254
+ def build
255
+ Node::String.new text_value
256
+ end
257
+ } / [a-zA-Z]+ '=' dimension {
258
+ def build
259
+ Node::Anonymous.new text_value
260
+ end
261
+ } / [-a-zA-Z0-9_%$/.&=:;#+?]+ {
262
+ def build
263
+ Node::String.new text_value
264
+ end
265
+ } / function / keyword other:(S keyword)* {
266
+ def build
267
+ end
268
+ }
269
+ end
270
+ end
271
+ end
@@ -36,6 +36,10 @@ module Less
36
36
 
37
37
  rgba hue[ h + 1/3 ], hue[ h ], hue[ h - 1/3 ], a
38
38
  end
39
+
40
+ def self.available
41
+ self.instance_methods.map(&:to_sym)
42
+ end
39
43
  end
40
44
 
41
45
  module Node
@@ -45,31 +49,30 @@ module Less
45
49
  # it calls functions from the Functions module
46
50
  #
47
51
  class Function < ::String
48
- include Functions
49
52
  include Entity
53
+ include Functions
50
54
 
51
55
  def initialize name, *args
52
56
  @args = args.flatten
53
57
  super name
54
58
  end
55
-
59
+
56
60
  def to_css
57
61
  self.evaluate.to_css
58
62
  end
59
63
 
60
64
  #
61
65
  # Call the function
62
- #
63
- def evaluate
64
- send self.to_sym, *@args
65
- end
66
-
67
66
  #
68
67
  # If the function isn't found, we just print it out,
69
68
  # this is the case for url(), for example,
70
69
  #
71
- def method_missing meth, *args
72
- Node::Anonymous.new("#{meth}(#{args.map(&:to_css) * ', '})")
70
+ def evaluate
71
+ if Functions.available.include? self.to_sym
72
+ send to_sym, *@args
73
+ else
74
+ Node::Anonymous.new("#{to_sym}(#{@args.map(&:to_css) * ', '})")
75
+ end
73
76
  end
74
77
  end
75
78
  end
@@ -4,4 +4,13 @@
4
4
  width: 36;
5
5
  padding: 2px 36px;
6
6
  }
7
- .more-parens { padding: 8 4 4 4px; }
7
+ .more-parens {
8
+ padding: 8 4 4 4px;
9
+ width: 96;
10
+ height: 113;
11
+ margin: 12;
12
+ }
13
+ .nested-parens {
14
+ width: 71;
15
+ height: 6;
16
+ }
@@ -9,7 +9,13 @@
9
9
  .more-parens {
10
10
  @var: (2 * 2);
11
11
  padding: (2 * @var) 4 4 (@var * 1px);
12
- //width: (@var * @var) * 6;
12
+ width: (@var * @var) * 6;
13
+ height: (7 * 7) + (8 * 8);
14
+ margin: 4 * (5 + 5) / 2 - (@var * 2);
13
15
  //margin: (6 * 6)px;
14
- //height: (7 * 7) + (8 * 8);
15
16
  }
17
+
18
+ .nested-parens {
19
+ width: 2 * (4 * (2 + (1 + 6))) - 1;
20
+ height: ((2+3)*(2+3) / (9-4)) + 1;
21
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: less
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.16
4
+ version: 1.1.3
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-07-23 00:00:00 -04:00
12
+ date: 2009-07-27 00:00:00 -04:00
13
13
  default_executable: lessc
14
14
  dependencies: []
15
15
 
@@ -30,11 +30,14 @@ files:
30
30
  - VERSION
31
31
  - bin/lessc
32
32
  - less.gemspec
33
+ - lib/ext.rb
33
34
  - lib/less.rb
34
35
  - lib/less/command.rb
35
36
  - lib/less/engine.rb
36
37
  - lib/less/engine/builder.rb
37
- - lib/less/engine/less.tt
38
+ - lib/less/engine/grammar/common.tt
39
+ - lib/less/engine/grammar/entity.tt
40
+ - lib/less/engine/grammar/less.tt
38
41
  - lib/less/engine/nodes.rb
39
42
  - lib/less/engine/nodes/element.rb
40
43
  - lib/less/engine/nodes/entity.rb
@@ -43,7 +46,6 @@ files:
43
46
  - lib/less/engine/nodes/property.rb
44
47
  - lib/less/engine/nodes/ruleset.rb
45
48
  - lib/less/engine/nodes/selector.rb
46
- - lib/less/engine/parser.rb
47
49
  - lib/vendor/treetop/.gitignore
48
50
  - lib/vendor/treetop/LICENSE
49
51
  - lib/vendor/treetop/README
@@ -1,422 +0,0 @@
1
- grammar Less
2
- rule primary
3
- (declaration / ruleset / import / comment)+ <Builder> / declaration* <Builder> / import* <Builder> / comment*
4
- end
5
-
6
- rule comment
7
- ws '/*' (!'*/' . )* '*/' ws / ws '//' (!"\n" .)* "\n" ws
8
- end
9
-
10
- #
11
- # div, .class, body > p {...}
12
- #
13
- rule ruleset
14
- selectors "{" ws primary ws "}" ws {
15
- def build env
16
- # Build the ruleset for each selector
17
- selectors.build(env, :ruleset).each do |sel|
18
- primary.build sel
19
- end
20
- end
21
- } / ws selectors ';' ws {
22
- def build env
23
- selectors.build(env, :mixin).each do |path|
24
- rules = path.inject(env.root) do |current, node|
25
- current.descend(node.selector, node) or raise MixinNameError, path.join
26
- end.rules
27
- env.rules += rules
28
- end
29
- end
30
- }
31
- end
32
-
33
- rule import
34
- "@import" S url:(string / url) medias? s ';' ws {
35
- def build env
36
- path = File.join(env.root.file, url.value)
37
- path += '.less' unless path =~ /\.(le|c)ss$/
38
- if File.exist? path
39
- imported = Less::Engine.new(File.new(path)).to_tree
40
- env.rules += imported.rules
41
- else
42
- raise ImportError, path
43
- end
44
- end
45
- }
46
- end
47
-
48
- rule url
49
- 'url(' path:(string / [-a-zA-Z0-9_%$/.&=:;#+?]+) ')' {
50
- def build env = nil
51
- Node::String.new CGI.unescape(path.text_value)
52
- end
53
-
54
- def value
55
- build
56
- end
57
- }
58
- end
59
-
60
- rule medias
61
- [-a-z]+ (s ',' s [a-z]+)*
62
- end
63
-
64
- rule selectors
65
- ws selector tail:(s ',' ws selector)* ws {
66
- def build env, method
67
- all.map do |e|
68
- e.send(method, env) if e.respond_to? method
69
- end.compact
70
- end
71
-
72
- def all
73
- [selector] + tail.elements.map {|e| e.selector }
74
- end
75
- }
76
- end
77
-
78
- #
79
- # div > p a {...}
80
- #
81
- rule selector
82
- sel:(s select element s)+ arguments? {
83
- def ruleset env
84
- sel.elements.inject(env) do |node, e|
85
- node << Node::Element.new(e.element.text_value, e.select.text_value)
86
- node.last
87
- end
88
- end
89
-
90
- def mixin env
91
- sel.elements.map do |e|
92
- Node::Element.new(e.element.text_value, e.select.text_value)
93
- end
94
- end
95
- }
96
- end
97
-
98
- #
99
- # @my-var: 12px;
100
- # height: 100%;
101
- #
102
- rule declaration
103
- ws name:(ident / variable) s ':' s expressions s (';'/ ws &'}') ws {
104
- def build env
105
- env << (name.text_value =~ /^@/ ?
106
- Node::Variable : Node::Property).new(name.text_value, expressions.build(env), env)
107
-
108
- end
109
- # Empty rule
110
- } / ws ident s ':' s ';' ws
111
- end
112
-
113
- rule expressions
114
- expression+ {
115
- def build env
116
- elements.map do |e|
117
- e.build(env) if e.respond_to? :build
118
- end.compact
119
- end
120
- }
121
- end
122
-
123
- #
124
- # An operation or compound value
125
- #
126
- rule expression
127
- s '(' s expressions s ')' s {
128
- def build env
129
- Node::Expression.new(['('] + expressions.build(env).flatten + [')'])
130
- end
131
- } / entity tail:(operator entity)* ws {
132
- def build env
133
- exp = all.map do |e|
134
- e.method(:build).arity.zero??
135
- e.build : e.build(env) if e.respond_to? :build
136
- end.dissolve
137
- exp.is_a?(Array) ? Node::Expression.new(exp) : exp
138
- end
139
-
140
- def all
141
- [entity] + tail.elements.map {|i| [i.operator, i.entity] }.flatten.compact
142
- end
143
- }
144
- end
145
-
146
- #
147
- # Entity: Any whitespace delimited token
148
- #
149
- rule entity
150
- function / fonts / keyword / accessor / variable / literal / important
151
- end
152
-
153
- rule fonts
154
- font family:(s ',' s font)+ {
155
- def build
156
- Node::FontFamily.new(all.map(&:build))
157
- end
158
-
159
- def all
160
- [font] + family.elements.map {|f| f.font }
161
- end
162
- }
163
- end
164
-
165
- rule font
166
- [a-zA-Z] [-a-zA-Z0-9]* {
167
- def build
168
- Node::Keyword.new(text_value)
169
- end
170
- } / string {
171
- def build
172
- Node::String.new(text_value)
173
- end
174
- }
175
- end
176
-
177
- #
178
- # An identifier
179
- #
180
- rule ident
181
- '*'? '-'? [-a-z0-9_]+
182
- end
183
-
184
- rule variable
185
- '@' [-a-zA-Z0-9_]+ {
186
- def build
187
- Node::Variable.new(text_value)
188
- end
189
- }
190
- end
191
-
192
- #
193
- # div / .class / #id / input[type="text"] / lang(fr)
194
- #
195
- rule element
196
- (class_id / tag / ident) attribute* ('(' ident? attribute* ')')? / attribute+ / '@media' / '@font-face'
197
- end
198
-
199
- rule class_id
200
- tag? (class / id)+
201
- end
202
-
203
- #
204
- # [type="text"]
205
- #
206
- rule attribute
207
- '[' tag ([|~*$^]? '=') (tag / string) ']' / '[' (tag / string) ']'
208
- end
209
-
210
- rule class
211
- '.' [_a-z] [-a-zA-Z0-9_]*
212
- end
213
-
214
- rule id
215
- '#' [_a-z] [-a-zA-Z0-9_]*
216
- end
217
-
218
- rule tag
219
- [a-zA-Z] [-a-zA-Z]* [0-9]? / '*'
220
- end
221
-
222
- rule select
223
- (s [+>~] s / s ':' / S)?
224
- end
225
-
226
- # TODO: Merge this with attribute rule
227
- rule accessor
228
- ident:(class_id / tag) '[' attr:(string / variable) ']' {
229
- def build env
230
- env.nearest(ident.text_value)[attr.text_value.delete(%q["'])].evaluate
231
- end
232
- }
233
- end
234
-
235
- rule operator
236
- S [-+*/] S {
237
- def build
238
- Node::Operator.new(text_value.strip)
239
- end
240
- } / [-+*/] {
241
- def build
242
- Node::Operator.new(text_value)
243
- end
244
- }
245
- end
246
-
247
- #
248
- # Tokens which don't need to be evaluated
249
- #
250
- rule literal
251
- color / (dimension / [-a-z]+) '/' dimension {
252
- def build
253
- Node::Anonymous.new(text_value)
254
- end
255
- } / number unit {
256
- def build
257
- Node::Number.new(number.text_value, unit.text_value)
258
- end
259
- } / string {
260
- def build
261
- Node::String.new(text_value)
262
- end
263
- }
264
- end
265
-
266
- # !important
267
- rule important
268
- '!important' {
269
- def build
270
- Node::Keyword.new(text_value)
271
- end
272
- }
273
- end
274
-
275
- #
276
- # `blue`, `small`, `normal` etc.
277
- #
278
- rule keyword
279
- [-a-zA-Z]+ !ns {
280
- def build
281
- Node::Keyword.new(text_value)
282
- end
283
- }
284
- end
285
-
286
- #
287
- # 'hello world' / "hello world"
288
- #
289
- rule string
290
- "'" content:(!"'" . )* "'" {
291
- def value
292
- content.text_value
293
- end
294
- } / ["] content:(!["] . )* ["] {
295
- def value
296
- content.text_value
297
- end
298
- }
299
- end
300
-
301
- #
302
- # Numbers & Units
303
- #
304
- rule dimension
305
- number unit
306
- end
307
-
308
- rule number
309
- '-'? [0-9]* '.' [0-9]+ / '-'? [0-9]+
310
- end
311
-
312
- rule unit
313
- ('px'/'em'/'pc'/'%'/'pt'/'cm'/'mm')?
314
- end
315
-
316
- #
317
- # Color
318
- #
319
- rule color
320
- '#' rgb {
321
- def build
322
- Node::Color.new(*rgb.build)
323
- end
324
- } / fn:(('hsl'/'rgb') 'a'?) arguments {
325
- def build
326
- Node::Function.new(fn.text_value, arguments.build.flatten)
327
- end
328
- }
329
- end
330
-
331
- #
332
- # 00ffdd / 0fd
333
- #
334
- rule rgb
335
- r:(hex hex) g:(hex hex) b:(hex hex) {
336
- def build
337
- [r.text_value, g.text_value, b.text_value]
338
- end
339
- } / r:hex g:hex b:hex {
340
- def build
341
- [r.text_value, g.text_value, b.text_value].map {|c| c * 2 }
342
- end
343
- }
344
- end
345
-
346
- rule hex
347
- [a-fA-F0-9]
348
- end
349
-
350
- #
351
- # Functions and arguments
352
- #
353
- rule function
354
- name:([-a-zA-Z_]+) arguments {
355
- def build
356
- Node::Function.new(name.text_value, [arguments.build].flatten)
357
- end
358
- }
359
- end
360
-
361
- rule arguments
362
- '(' s argument s tail:(',' s argument s)* ')' {
363
- def build
364
- all.map do |e|
365
- e.build if e.respond_to? :build
366
- end.compact
367
- end
368
-
369
- def all
370
- [argument] + tail.elements.map {|e| e.argument }
371
- end
372
- }
373
- end
374
-
375
- rule argument
376
- color {
377
- def build
378
- Node::Color.new text_value
379
- end
380
- } / number unit {
381
- def build
382
- Node::Number.new number.text_value, unit.text_value
383
- end
384
- } / string {
385
- def build
386
- Node::String.new text_value
387
- end
388
- } / [a-zA-Z]+ '=' dimension {
389
- def build
390
- Node::Anonymous.new text_value
391
- end
392
- } / [-a-zA-Z0-9_%$/.&=:;#+?]+ {
393
- def build
394
- Node::String.new text_value
395
- end
396
- }
397
- end
398
-
399
- #
400
- # Whitespace
401
- #
402
- rule s
403
- [ ]*
404
- end
405
-
406
- rule S
407
- [ ]+
408
- end
409
-
410
- rule ws
411
- [\n ]*
412
- end
413
-
414
- rule WS
415
- [\n ]+
416
- end
417
-
418
- # Non-space char
419
- rule ns
420
- ![ ;\n] .
421
- end
422
- end