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.
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