railsdog-less 1.2.17

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 +61 -0
  6. data/VERSION +1 -0
  7. data/bin/lessc +102 -0
  8. data/lib/less.rb +44 -0
  9. data/lib/less/command.rb +110 -0
  10. data/lib/less/engine.rb +54 -0
  11. data/lib/less/engine/grammar/common.tt +29 -0
  12. data/lib/less/engine/grammar/entity.tt +142 -0
  13. data/lib/less/engine/grammar/less.tt +338 -0
  14. data/lib/less/engine/nodes.rb +9 -0
  15. data/lib/less/engine/nodes/element.rb +281 -0
  16. data/lib/less/engine/nodes/entity.rb +79 -0
  17. data/lib/less/engine/nodes/function.rb +84 -0
  18. data/lib/less/engine/nodes/literal.rb +171 -0
  19. data/lib/less/engine/nodes/property.rb +229 -0
  20. data/lib/less/engine/nodes/ruleset.rb +12 -0
  21. data/lib/less/engine/nodes/selector.rb +44 -0
  22. data/lib/less/ext.rb +60 -0
  23. data/railsdog-less.gemspec +125 -0
  24. data/spec/command_spec.rb +102 -0
  25. data/spec/css/accessors.css +18 -0
  26. data/spec/css/big.css +3768 -0
  27. data/spec/css/colors.css +14 -0
  28. data/spec/css/comments.css +9 -0
  29. data/spec/css/css-3.css +20 -0
  30. data/spec/css/css.css +50 -0
  31. data/spec/css/functions.css +6 -0
  32. data/spec/css/import.css +12 -0
  33. data/spec/css/lazy-eval.css +1 -0
  34. data/spec/css/mixins-args.css +32 -0
  35. data/spec/css/mixins.css +28 -0
  36. data/spec/css/operations.css +28 -0
  37. data/spec/css/parens.css +20 -0
  38. data/spec/css/rulesets.css +17 -0
  39. data/spec/css/scope.css +11 -0
  40. data/spec/css/selectors.css +13 -0
  41. data/spec/css/strings.css +12 -0
  42. data/spec/css/variables.css +8 -0
  43. data/spec/css/whitespace.css +7 -0
  44. data/spec/engine_spec.rb +126 -0
  45. data/spec/less/accessors.less +20 -0
  46. data/spec/less/big.less +4810 -0
  47. data/spec/less/colors.less +35 -0
  48. data/spec/less/comments.less +46 -0
  49. data/spec/less/css-3.less +51 -0
  50. data/spec/less/css.less +104 -0
  51. data/spec/less/exceptions/mixed-units-error.less +3 -0
  52. data/spec/less/exceptions/name-error-1.0.less +3 -0
  53. data/spec/less/exceptions/syntax-error-1.0.less +3 -0
  54. data/spec/less/functions.less +6 -0
  55. data/spec/less/hidden.less +25 -0
  56. data/spec/less/import.less +8 -0
  57. data/spec/less/import/import-test-a.less +2 -0
  58. data/spec/less/import/import-test-b.less +8 -0
  59. data/spec/less/import/import-test-c.less +7 -0
  60. data/spec/less/import/import-test-d.css +1 -0
  61. data/spec/less/lazy-eval.less +6 -0
  62. data/spec/less/literal-css.less +11 -0
  63. data/spec/less/mixins-args.less +59 -0
  64. data/spec/less/mixins.less +43 -0
  65. data/spec/less/operations.less +39 -0
  66. data/spec/less/parens.less +26 -0
  67. data/spec/less/rulesets.less +30 -0
  68. data/spec/less/scope.less +32 -0
  69. data/spec/less/selectors.less +24 -0
  70. data/spec/less/strings.less +14 -0
  71. data/spec/less/variables.less +29 -0
  72. data/spec/less/whitespace.less +34 -0
  73. data/spec/spec.css +50 -0
  74. data/spec/spec_helper.rb +8 -0
  75. metadata +150 -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,229 @@
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
+ clone.tap {|c| c.value = value.copy }
32
+ end
33
+
34
+ def << token
35
+ token = Node::Anonymous.new(*token) unless token.is_a? Entity or token.respond_to? :to_ruby
36
+ token.parent = self if token.respond_to? :parent
37
+ @value << token
38
+ end
39
+
40
+ def empty?; !@value || @value.empty? end
41
+
42
+ def inspect
43
+ self + (empty?? "" : ": `#{value.map {|i| i.to_s } * ' | '}`")
44
+ end
45
+
46
+ def == other
47
+ self.to_s == other.to_s
48
+ end
49
+
50
+ def eql? other
51
+ self == other and value.eql? other.value
52
+ end
53
+
54
+ def to_s
55
+ super
56
+ end
57
+
58
+ def nearest node
59
+ parent.nearest node
60
+ end
61
+
62
+ def evaluate env = nil
63
+ # puts "evaluating property `#{to_s}`: #{value.inspect}"
64
+ if value.is_a?(Expression) #Value
65
+ # puts "value is a Value"
66
+ value.map {|e| e.evaluate(env) } #6
67
+ else
68
+ # puts "value is a #{value.class}"
69
+ [value.evaluate(env)]
70
+ end
71
+
72
+
73
+ end
74
+
75
+ def to_css env = nil
76
+ # puts "property.to_css `#{to_s}` env:#{env ? env.variables : "nil"}"
77
+ val = evaluate(env)
78
+ "#{self}: #{if val.respond_to? :to_css
79
+ val.to_css
80
+ else
81
+ # p val
82
+ # puts "#{val.class} #{val.first.class}"
83
+ val.map {|i| i.to_css }.join(", ")
84
+ end};"
85
+ end
86
+ end
87
+
88
+ class Variable < Property
89
+ attr_reader :declaration
90
+
91
+ def initialize key, value = nil, parent = nil
92
+ @declaration = value ? true : false
93
+ super key.delete('@'), value, parent
94
+ end
95
+
96
+ def inspect
97
+ "@#{super}"
98
+ end
99
+
100
+ def to_s
101
+ "@#{super}"
102
+ end
103
+
104
+ def evaluate env = nil
105
+ if declaration
106
+ # puts "evaluating DEC"
107
+ value.evaluate #2
108
+ else
109
+ # puts "evaluating #{to_s} par: #{parent} env: #{env ? env.variables : "nil"}"
110
+ begin
111
+ var = (env || self.parent).nearest(to_s) #3
112
+ rescue VariableNameError
113
+ var = self.parent.nearest(to_s)
114
+ end
115
+ var.evaluate
116
+ end
117
+ end
118
+
119
+ def to_ruby
120
+ evaluate.to_ruby
121
+ end
122
+
123
+ def to_css env = nil
124
+ val = evaluate env
125
+ if val.respond_to? :to_css
126
+ env ? val.to_css(env) : val.to_css
127
+ else
128
+ val.map {|i| env ? i.to_css(env) : i.to_css }.join ', '
129
+ end
130
+ end
131
+ end
132
+
133
+ class Expression < Array
134
+ attr_accessor :parent, :delimiter
135
+
136
+ def initialize ary, parent = nil, delimiter = ' '
137
+ self.parent = parent
138
+ self.delimiter = delimiter
139
+ # puts "new expression #{ary} |#{delimiter}|"
140
+ super(ary.is_a?(Array) ? ary : [ary].flatten)
141
+ end
142
+
143
+ def expressions; select {|i| i.kind_of? Expression } end
144
+ def variables; select {|i| i.kind_of? Variable } end
145
+ def operators; select {|i| i.is_a? Operator } end
146
+ def entities; select {|i| i.kind_of? Entity } end
147
+ def literals; select {|i| i.kind_of? Literal } end
148
+
149
+ def parent= obj
150
+ @parent = obj
151
+ each {|e| e.parent = obj if e.respond_to? :parent }
152
+ end
153
+
154
+ def inspect
155
+ '[' + map {|i| i.inspect }.join(', ') + ']'
156
+ end
157
+
158
+ def delimiter= d
159
+ @delimiter = d.strip + ' '
160
+ end
161
+
162
+ def flatten
163
+ self
164
+ end
165
+
166
+ def terminal?
167
+ expressions.empty? #&& variables.empty?
168
+ end
169
+
170
+ def to_css env = nil
171
+ # puts "TOCSS, delim: |#{@delimiter}|"
172
+ map do |i|
173
+ i.respond_to?(:to_css) ? i.to_css() : i.to_s
174
+ end * @delimiter
175
+ end
176
+
177
+ def to_ruby
178
+ map do |i|
179
+ i.respond_to?(:to_ruby) ? i.to_ruby : i.to_s
180
+ end
181
+ end
182
+
183
+ #
184
+ # Evaluates the expression and instantiates a new Literal with the result
185
+ # ex: [#111, +, #111] will evaluate to a Color node, with value #222
186
+ #
187
+ def evaluate env = nil
188
+ # puts "expression #{self.inspect} env: #{env ? env.variables : "nil"}"
189
+ if size > 2 or !terminal?
190
+ # puts " SIZE > 2 or !terminal"
191
+
192
+ # puts "--- sub evaluation ---"
193
+
194
+ # Replace self with an evaluated sub-expression
195
+ evaled = self.class.new(map {|e| e.respond_to?(:evaluate) ? e.evaluate(env) : e }, parent, delimiter) #5
196
+
197
+ # puts "======================"
198
+ # puts "evaled => #{evaled.inspect}"
199
+
200
+ unit = evaled.literals.map do |node|
201
+ node.unit
202
+ end.compact.uniq.tap do |ary|
203
+ raise MixedUnitsError, evaled * ' ' if ary.size > 1 && !evaled.operators.empty?
204
+ end.join
205
+
206
+ entity = evaled.literals.find {|e| e.unit == unit } || evaled.literals.first || evaled.entities.first
207
+ result = evaled.operators.empty?? evaled : eval(evaled.to_ruby.join)
208
+
209
+ # puts "entity is a #{entity.class}"
210
+ # puts "delimiter is |#{@delimiter}|"
211
+
212
+ case result
213
+ when Entity then result
214
+ when Expression then result.one?? result.first : self.class.new(result, parent, delimiter)
215
+ else entity.class.new(result, *(unit if entity.class == Node::Number))
216
+ end
217
+ elsif size == 1
218
+ if first.is_a? Variable
219
+ first.evaluate(env)
220
+ else
221
+ first
222
+ end
223
+ else
224
+ self
225
+ end
226
+ end
227
+ end
228
+ end
229
+ 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