railsdog-less 1.2.17

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