unboxed-less 1.2.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG +62 -0
  3. data/LICENSE +179 -0
  4. data/README.md +48 -0
  5. data/Rakefile +60 -0
  6. data/VERSION +1 -0
  7. data/bin/lessc +92 -0
  8. data/lib/ext.rb +31 -0
  9. data/lib/less.rb +32 -0
  10. data/lib/less/command.rb +98 -0
  11. data/lib/less/engine.rb +55 -0
  12. data/lib/less/engine/grammar/common.tt +29 -0
  13. data/lib/less/engine/grammar/entity.tt +130 -0
  14. data/lib/less/engine/grammar/less.tt +326 -0
  15. data/lib/less/engine/nodes.rb +9 -0
  16. data/lib/less/engine/nodes/element.rb +278 -0
  17. data/lib/less/engine/nodes/entity.rb +79 -0
  18. data/lib/less/engine/nodes/function.rb +84 -0
  19. data/lib/less/engine/nodes/literal.rb +171 -0
  20. data/lib/less/engine/nodes/property.rb +231 -0
  21. data/lib/less/engine/nodes/ruleset.rb +12 -0
  22. data/lib/less/engine/nodes/selector.rb +44 -0
  23. data/spec/command_spec.rb +102 -0
  24. data/spec/css/accessors.css +18 -0
  25. data/spec/css/big.css +3768 -0
  26. data/spec/css/colors.css +14 -0
  27. data/spec/css/comments.css +9 -0
  28. data/spec/css/css-3.css +17 -0
  29. data/spec/css/css.css +50 -0
  30. data/spec/css/functions.css +6 -0
  31. data/spec/css/import.css +12 -0
  32. data/spec/css/lazy-eval.css +1 -0
  33. data/spec/css/mixins-args.css +32 -0
  34. data/spec/css/mixins.css +28 -0
  35. data/spec/css/operations.css +28 -0
  36. data/spec/css/parens.css +20 -0
  37. data/spec/css/rulesets.css +17 -0
  38. data/spec/css/scope.css +11 -0
  39. data/spec/css/selectors.css +13 -0
  40. data/spec/css/strings.css +12 -0
  41. data/spec/css/variables.css +7 -0
  42. data/spec/css/whitespace.css +7 -0
  43. data/spec/engine_spec.rb +112 -0
  44. data/spec/less/accessors.less +20 -0
  45. data/spec/less/big.less +4810 -0
  46. data/spec/less/colors.less +35 -0
  47. data/spec/less/comments.less +46 -0
  48. data/spec/less/css-3.less +45 -0
  49. data/spec/less/css.less +104 -0
  50. data/spec/less/exceptions/mixed-units-error.less +3 -0
  51. data/spec/less/exceptions/name-error-1.0.less +3 -0
  52. data/spec/less/exceptions/syntax-error-1.0.less +3 -0
  53. data/spec/less/functions.less +6 -0
  54. data/spec/less/hidden.less +25 -0
  55. data/spec/less/import.less +8 -0
  56. data/spec/less/import/import-test-a.less +2 -0
  57. data/spec/less/import/import-test-b.less +8 -0
  58. data/spec/less/import/import-test-c.less +7 -0
  59. data/spec/less/import/import-test-d.css +1 -0
  60. data/spec/less/lazy-eval.less +6 -0
  61. data/spec/less/literal-css.less +11 -0
  62. data/spec/less/mixins-args.less +59 -0
  63. data/spec/less/mixins.less +43 -0
  64. data/spec/less/operations.less +39 -0
  65. data/spec/less/parens.less +26 -0
  66. data/spec/less/rulesets.less +30 -0
  67. data/spec/less/scope.less +32 -0
  68. data/spec/less/selectors.less +24 -0
  69. data/spec/less/strings.less +14 -0
  70. data/spec/less/variables.less +24 -0
  71. data/spec/less/whitespace.less +34 -0
  72. data/spec/spec.css +50 -0
  73. data/spec/spec_helper.rb +8 -0
  74. data/unboxed-less.gemspec +121 -0
  75. 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,12 @@
1
+ module Less
2
+ module Node
3
+ class Ruleset < Array
4
+ def initialize elements = []
5
+ super elements
6
+ end
7
+
8
+ def to_css
9
+ end
10
+ end
11
+ end
12
+ 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