forked from cowboyd/less.rb
/
parser.rb
86 lines (75 loc) · 2.22 KB
/
parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
module Less
# Utility for calling into the JavaScript runtime.
module CallJS
# @private
# Wrap JavaScript invocations with uniform error handling
#
# @yield code to wrap
def calljs
yield
rescue V8::JSError => e
raise ParseError.new(e)
end
end
# Convert lesscss source into an abstract syntax Tree
class Parser
include CallJS
# Construct and configure new Less::Parser
#
# @param [Hash] opts configuration options
# @option opts [Array] :paths a list of directories to search when handling \@import statements
# @option opts [String] :filename to associate with resulting parse trees (useful for generating errors)
def initialize(options = {})
stringy = {}
options.each do |k,v|
stringy[k.to_s] = v.is_a?(Array) ? v.map(&:to_s) : v.to_s
end
@parser = Less.Parser.new(stringy)
end
# Convert `less` source into a abstract syntaxt tree
# @param [String] less the source to parse
# @return [Less::Tree] the parsed tree
def parse(less)
calljs do
error,tree = nil
@parser.parse(less, lambda {|e, t|
error = e; tree = t
})
Tree.new(tree) if tree
end
end
end
# Abstract LessCSS syntax tree Less. Mainly used to emit CSS
class Tree
include CallJS
# Create a tree from a native javascript object.
# @param [V8::Object] tree the native less.js tree
def initialize(tree)
@tree = tree
end
# Serialize this tree into CSS.
# By default this will be in pretty-printed form.
# @param [Hash] opts modifications to the output
# @option opts [Boolean] :compress minify output instead of pretty-printing
def to_css(options = {})
calljs do
@tree.toCSS(options)
end
end
end
# Thrown whenever an error occurs parsing
# and/or serializing less source. It is intended
# to wrap a native V8::JSError
class ParseError < StandardError
# Copies over `error`'s message and backtrace
# @param [V8::JSError] error native error
def initialize(error)
super(error.message)
@backtrace = error.backtrace
end
# @return [Array] the backtrace frames
def backtrace
@backtrace
end
end
end