less 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/less.gemspec +1 -1
- data/lib/less/engine.rb +24 -19
- data/spec/spec.less +101 -61
- metadata +1 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.3
|
data/less.gemspec
CHANGED
data/lib/less/engine.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
module Less
|
2
2
|
class Engine < String
|
3
|
-
|
3
|
+
REGEX = {
|
4
4
|
:path => /([#.][->#.\w ]+)?( ?> ?)?@([-\w]+)/, # #header > .title > @var
|
5
|
-
:selector => /[-\w
|
5
|
+
:selector => /[-\w #.,>*:\(\)]/, # .cow .milk > a
|
6
6
|
:variable => /@([-\w]+)/, # @milk-white
|
7
|
-
:property => /@[-\w]+|[-a-z]
|
7
|
+
:property => /@[-\w]+|[-a-z]+/, # font-size
|
8
|
+
:color => /#([a-zA-Z0-9]{3,6})\b/, # #f0f0f0
|
9
|
+
:number => /\d+(?>\.\d+)?/, # 24.8
|
10
|
+
:unit => /px|em|pt|cm|mm|%/ # em
|
8
11
|
}
|
9
|
-
|
12
|
+
REGEX[:numeric] = /#{REGEX[:number]}(#{REGEX[:unit]})?/
|
13
|
+
REGEX[:operand] = /#{REGEX[:color]}|#{REGEX[:numeric]}/
|
14
|
+
|
10
15
|
def initialize s
|
11
16
|
super
|
12
17
|
@tree = Tree.new self.hashify
|
@@ -23,7 +28,7 @@ module Less
|
|
23
28
|
# can then be deleted.
|
24
29
|
#
|
25
30
|
@tree = @tree.traverse :leaf do |key, value, path, node|
|
26
|
-
matched = if match = key.match(
|
31
|
+
matched = if match = key.match( REGEX[:variable] )
|
27
32
|
node[:variables] ||= Tree.new
|
28
33
|
node[:variables][ match.captures.first ] = value
|
29
34
|
elsif value == :mixin
|
@@ -60,25 +65,25 @@ module Less
|
|
60
65
|
# Evaluate operations (2+2)
|
61
66
|
#
|
62
67
|
# Units are: 1px, 1em, 1%, #111
|
63
|
-
@tree = @tree.traverse :leaf do |key, value, path, node|
|
64
|
-
|
65
|
-
if (unit =
|
68
|
+
@tree = @tree.traverse :leaf do |key, value, path, node|
|
69
|
+
node[ key ] = value.gsub /(#{REGEX[:operand]}(\s?)[-+\/*](\4))+(#{REGEX[:operand]})/ do |operation|
|
70
|
+
if (unit = operation.scan(/#{REGEX[:numeric]}|(#)/i).flatten.compact.uniq).size <= 1
|
66
71
|
unit = unit.join
|
67
|
-
|
72
|
+
operation = if unit == '#'
|
68
73
|
evaluate = lambda do |v|
|
69
74
|
result = eval v
|
70
75
|
unit + ( result.zero?? '000' : result.to_s(16) )
|
71
76
|
end
|
72
|
-
|
77
|
+
operation.gsub REGEX[:color] do
|
73
78
|
hex = $1 * ( $1.size < 6 ? 6 / $1.size : 1 )
|
74
79
|
hex.to_i(16)
|
75
80
|
end.delete unit
|
76
81
|
else
|
77
82
|
evaluate = lambda {|v| eval( v ).to_s + unit }
|
78
|
-
|
83
|
+
operation.gsub REGEX[:unit], ''
|
79
84
|
end.to_s
|
80
|
-
next if
|
81
|
-
|
85
|
+
next if operation.match /[a-z]/i
|
86
|
+
evaluate.call operation
|
82
87
|
else
|
83
88
|
raise MixedUnitsError
|
84
89
|
end
|
@@ -92,7 +97,7 @@ module Less
|
|
92
97
|
#
|
93
98
|
def evaluate key, value, node
|
94
99
|
if value.is_a? String and value.include? '@' # There's a var to evaluate
|
95
|
-
value.scan
|
100
|
+
value.scan REGEX[:path] do |p|
|
96
101
|
p = p.join.delete ' '
|
97
102
|
var = if p.include? '>'
|
98
103
|
@tree.find :var, p.split('>') # Try finding it in a specific namespace
|
@@ -101,7 +106,7 @@ module Less
|
|
101
106
|
end
|
102
107
|
|
103
108
|
if var
|
104
|
-
node[ key ] = value.gsub
|
109
|
+
node[ key ] = value.gsub REGEX[:path], var # Substitute variable with value
|
105
110
|
else
|
106
111
|
node.delete key # Discard the declaration if the variable wasn't found
|
107
112
|
end
|
@@ -121,13 +126,13 @@ module Less
|
|
121
126
|
# less: color: black;
|
122
127
|
# hashify: "color" => "black"
|
123
128
|
#
|
124
|
-
hash = self.gsub(
|
125
|
-
gsub(
|
129
|
+
hash = self.gsub(/\/\/.*/, ''). # Comments //
|
130
|
+
gsub(/\/\*.*?\*\//m, ''). # Comments /*
|
126
131
|
gsub(/"/, "'"). # " => '
|
127
132
|
gsub(/("|')(.+?)(\1)/) { $1 + CGI.escape( $2 ) + $1 }. # Escape string values
|
128
|
-
gsub(/(#{
|
133
|
+
gsub(/(#{REGEX[:property]}):[ \t]*(.+?);/, '"\\1" => "\\2",'). # Declarations
|
129
134
|
gsub(/\}/, "},"). # Closing }
|
130
|
-
gsub(/([ \t]*)(#{
|
135
|
+
gsub(/([ \t]*)(#{REGEX[:selector]}+?)[ \t\n]*\{/m, '\\1"\\2" => {'). # Selectors
|
131
136
|
gsub(/([.#][->\w .#]+);/, '"\\1" => :mixin,') # Mixins
|
132
137
|
eval "{" + hash + "}" # Return {hash}
|
133
138
|
end
|
data/spec/spec.less
CHANGED
@@ -1,71 +1,111 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
|
4
|
-
|
5
|
-
/*
|
1
|
+
// ------------------------------------------------
|
2
|
+
// LESS Spec
|
3
|
+
// www.lesscss.org
|
4
|
+
// ------------------------------------------------
|
6
5
|
|
7
|
-
|
6
|
+
// Global vars
|
7
|
+
@main-color: #444;
|
8
|
+
@dark-color: #111;
|
9
|
+
@between-color: @main-color - @dark-color;
|
8
10
|
|
9
|
-
|
10
|
-
.
|
11
|
-
|
11
|
+
// Mixins
|
12
|
+
.theme {
|
13
|
+
color: #ccc;
|
14
|
+
background-color: #aaa;
|
12
15
|
}
|
13
|
-
.
|
14
|
-
|
15
|
-
|
16
|
-
.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
margin: 10px -10px 4px 2px;
|
21
|
-
line-height: 1999px;
|
22
|
-
.blah {
|
23
|
-
.bloop {
|
24
|
-
@supernested: iceberg;
|
25
|
-
}
|
16
|
+
.extra {
|
17
|
+
@main: #888;
|
18
|
+
.dark-borders {
|
19
|
+
border-color: .extra > @main / 2;
|
20
|
+
}
|
21
|
+
.light-borders {
|
22
|
+
border-color: .extra > @main;
|
26
23
|
}
|
27
24
|
}
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@
|
32
|
-
|
33
|
-
#kelkoo {
|
34
|
-
color: .dookoo > .blah > .bloop > @supernested;
|
35
|
-
}
|
36
|
-
.altfoo { color: .alt > @base-color; }
|
37
|
-
.foo { border: 1px solid black; color: @base-color; }
|
38
|
-
.foo2 {
|
39
|
-
width: 10px * 2;
|
25
|
+
|
26
|
+
// Namespaces
|
27
|
+
.borders {
|
28
|
+
@thick: 4px;
|
29
|
+
@thin: 2px;
|
40
30
|
}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
|
32
|
+
// Hierarchy
|
33
|
+
.root {
|
34
|
+
a {
|
35
|
+
color: blue;
|
36
|
+
display: none;
|
47
37
|
}
|
48
|
-
|
49
|
-
|
50
|
-
}
|
51
|
-
.small {
|
52
|
-
color: @base-color;
|
53
|
-
font-size: 12 / 2;
|
54
|
-
.hover_controls {
|
55
|
-
line-height: 16px;
|
56
|
-
display: none;
|
57
|
-
color: #content > @some-color;
|
58
|
-
border: 1px solid #fff;
|
59
|
-
}
|
38
|
+
a:hover, a:focus {
|
39
|
+
color: orange;
|
60
40
|
}
|
61
|
-
.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
41
|
+
.first {
|
42
|
+
@size: 8px;
|
43
|
+
@dark-color: green;
|
44
|
+
@main-color: red;
|
45
|
+
color: @dark-color; // 'green'
|
46
|
+
.second {
|
47
|
+
@color: blue;
|
48
|
+
.third {
|
49
|
+
color: @main-color; // #444
|
50
|
+
border-color: .root > .first > .second > @color; // 'blue'
|
51
|
+
}
|
66
52
|
}
|
67
|
-
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
.root:hover a {
|
56
|
+
display: block;
|
57
|
+
}
|
58
|
+
|
59
|
+
// Standard CSS properties and shorthand
|
60
|
+
body {
|
61
|
+
font-size: 10px;
|
62
|
+
font-family: "Lucida Grande", 'Helvetica', Verdana, sans-serif;
|
63
|
+
margin: -5px 0 5px 10px;
|
64
|
+
border: solid 1px #000;
|
65
|
+
text-shadow: #333 -1px 1px 2px;
|
66
|
+
-moz-border-radius: 3px; /* CSS3 for older Firefox */
|
67
|
+
.theme;
|
68
|
+
.extra > .light-borders;
|
68
69
|
}
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
|
71
|
+
// Operations
|
72
|
+
.operations {
|
73
|
+
@ten: 10;
|
74
|
+
@dark: #111;
|
75
|
+
border-width: .borders > @thick * 5 - 4px; // 16px
|
76
|
+
font-size: 10 - 4 + 6 * @ten; // 66
|
77
|
+
line-height: @ten - .operations > @ten + .root > .first > @size - 1; // 7px
|
78
|
+
color: #fff - #111; // #eeeeee
|
79
|
+
colorb: #111 + #222222; // #333333
|
80
|
+
colorc: @dark + #222 * 3; // #777777
|
81
|
+
}
|
82
|
+
|
83
|
+
td, tr, table {
|
84
|
+
border-width: .borders > @thick;
|
85
|
+
}
|
86
|
+
|
87
|
+
// More complex CSS selectors
|
88
|
+
ul li:first-child {
|
89
|
+
border-top: none;
|
90
|
+
}
|
91
|
+
ul li:first-child, ul li:last-child {
|
92
|
+
background-color: #333;
|
93
|
+
}
|
94
|
+
.p:first-letter {
|
95
|
+
color: red;
|
96
|
+
}
|
97
|
+
q:lang(no) {
|
98
|
+
quotes: "~" "~";
|
99
|
+
}
|
100
|
+
/*input[type="text"] {
|
101
|
+
background-color: blue;
|
102
|
+
}*/
|
103
|
+
.transparent_box {
|
104
|
+
background-color:#FFF;
|
105
|
+
filter:alpha(opacity=60); /* for IE */
|
106
|
+
opacity:0.6; /* CSS3 standard */
|
107
|
+
}
|
108
|
+
|
109
|
+
// Spacing
|
110
|
+
.space
|
111
|
+
{ color: purple ;font-color:yellow; }
|