OLD | NEW |
| (Empty) |
1 import sys, os | |
2 from os.path import abspath, dirname, join, normpath | |
3 from scss import OPRT | |
4 from scss.base import ParseNode, Empty, Node, IncludeNode | |
5 from scss.function import FUNCTION_LIST, unknown, warn | |
6 from scss.value import StringValue, Value, BooleanValue, NumberValue, QuotedStri
ngValue | |
7 | |
8 class Option(Empty): | |
9 """ Set parser option. | |
10 """ | |
11 def parse(self, target): | |
12 opts = map(lambda (x, y): (x.value, BooleanValue(y).value), | |
13 zip(*[iter(self.data[1:])]*2)) | |
14 for v in opts: | |
15 self.root.set_opt(*v) | |
16 | |
17 | |
18 class Variable(Value, ParseNode): | |
19 | |
20 def_value = StringValue('none') | |
21 | |
22 @classmethod | |
23 def _do_op(cls, self, other, op): | |
24 return self.value._do_op(self.value, other, op) | |
25 | |
26 @classmethod | |
27 def _do_cmps(cls, self, other, op): | |
28 return self.value._do_cmps(self.value, other, op) | |
29 | |
30 def __nonzero__(self): | |
31 return True | |
32 | |
33 @property | |
34 def value(self): | |
35 name = self.data[0].strip('-$') | |
36 minus = self.data[0][0] == '-' | |
37 value = self.ctx.get(name) or self.root.ctx.get(name, self.def_value) | |
38 return (0 - value) if minus else value | |
39 | |
40 | |
41 class Variables(ParseNode, Empty): | |
42 pass | |
43 | |
44 | |
45 class Expression(Variable): | |
46 | |
47 @property | |
48 def value(self): | |
49 it = iter(self.data) | |
50 try: | |
51 first = next(it) | |
52 while True: | |
53 res = next(it) | |
54 op = OPRT.get(res.strip(), None) | |
55 if op: | |
56 second = next(it) | |
57 first = op(first, second) | |
58 | |
59 if op == OPRT['and'] and not first: | |
60 raise StopIteration | |
61 | |
62 elif op == OPRT['or'] and first: | |
63 raise StopIteration | |
64 | |
65 except StopIteration: | |
66 while isinstance(first, Variable): | |
67 first = first.value | |
68 return first | |
69 | |
70 | |
71 class SepValString(Expression): | |
72 | |
73 @property | |
74 def value(self): | |
75 return ', '.join(str(e.value) for e in self.data) | |
76 | |
77 | |
78 class Function(Expression): | |
79 | |
80 @property | |
81 def value(self): | |
82 name = self.data[0] | |
83 func_name_a = "%s:%d" % (name, len(self.data) - 1) | |
84 func_name_n = "%s:n" % name | |
85 func = FUNCTION_LIST.get(func_name_a, FUNCTION_LIST.get(func_name_n, unk
nown)) | |
86 | |
87 params = map(lambda v: v.value, self.data[1:]) | |
88 return func(*params, root=self.root, name=name) | |
89 | |
90 | |
91 class FunctionDefinition(Empty): | |
92 | |
93 def parse(self, target): | |
94 name = self.data[1].value | |
95 params = self.data[2] | |
96 func_name = '%s:%s' % (name, len(params)) | |
97 FUNCTION_LIST[func_name] = self.wrapper | |
98 | |
99 def wrapper(self, *args, **kwargs): | |
100 self.ctx = Mixin.get_context(self.data[2], args) | |
101 for node in self.data[2:]: | |
102 if isinstance(node, FunctionReturn): | |
103 return node.value | |
104 elif isinstance(node, Node): | |
105 node.parse(self) | |
106 | |
107 | |
108 class FunctionReturn(Variable): | |
109 | |
110 @property | |
111 def value(self): | |
112 return self.data[1] | |
113 | |
114 | |
115 class MixinParam(Empty): | |
116 def __init__(self, s, n, t): | |
117 super(MixinParam, self).__init__(s, n, t) | |
118 self.name = self.data[0].data[0][1:] | |
119 self.value = self.data[1] if len(self.data) > 1 else None | |
120 | |
121 | |
122 class Extend(Empty): | |
123 | |
124 def parse(self, target): | |
125 for rule in self.root.cache['rset'][self.data[1]]: | |
126 rule.name.extend(target.name) | |
127 | |
128 | |
129 class Mixin(Empty): | |
130 | |
131 def __init__(self, s, n, t): | |
132 super(Mixin, self).__init__(s, n, t) | |
133 self.name = str(self.data[1]) | |
134 self.default = self.data[2] | |
135 | |
136 def parse(self, target): | |
137 self.root.cache['mix'][self.name] = self | |
138 | |
139 def include(self, target, params): | |
140 ctx = self.get_context(self.default, params) | |
141 if target.ctx: | |
142 ctx.update(target.ctx) | |
143 | |
144 self.ctx = ctx | |
145 for n in params: | |
146 n.parse(self) | |
147 | |
148 for node in self.data[3:]: | |
149 if isinstance(node, Node): | |
150 copy = node.copy() | |
151 copy.ctx = ctx | |
152 copy.parse(target) | |
153 | |
154 @staticmethod | |
155 def get_context(default, params=''): | |
156 test = map(lambda x, y: (x, y), default, params) | |
157 return dict(( mp.name, v or mp.value ) for mp, v in test if mp) | |
158 | |
159 | |
160 class Include(IncludeNode): | |
161 | |
162 def parse(self, target): | |
163 from scss import parser | |
164 | |
165 includeValue = self.data[1] | |
166 if isinstance(target, ParseNode) and not(isinstance(includeValue, | |
167 QuotedStringValue)): | |
168 name = str(includeValue) | |
169 params = self.data[2:] | |
170 mixin = self.root.cache['mix'].get(name) | |
171 if mixin: | |
172 mixin.include(target, params) | |
173 else: | |
174 warn("Required mixin not found: %s:%d." % ( name, len(params))) | |
175 elif isinstance(target, parser.Stylesheet) and isinstance(includeValue, | |
176 QuotedStringValue): | |
177 # @include "scss file to include" | |
178 # Parse this file for more class names to emit in Dart class. | |
179 options = target.currentOptions | |
180 f = target.currentFile | |
181 | |
182 s = parser.Stylesheet(options=target.currentOptions) | |
183 f = target.currentFile | |
184 path = dirname(abspath(f.name)) | |
185 includePath = normpath('{0}/{1}'.format(path, self.data[1].value)) | |
186 f = open(includePath, 'r') | |
187 nodes = s.loadReturnNodes(f) | |
188 target.addInclude(includeValue.value, nodes) | |
189 | |
190 class If(IncludeNode): | |
191 | |
192 def parse(self, target): | |
193 self.data[0].parse(self) | |
194 target.ctx.update(self.ctx) | |
195 if isinstance(target, ParseNode): | |
196 if self.data[0].value: | |
197 self.data[1].parse(target) | |
198 elif len(self.data) > 2: | |
199 self.data[2].parse(target) | |
200 | |
201 | |
202 class For(IncludeNode): | |
203 def parse(self, target): | |
204 if isinstance(target, ParseNode): | |
205 name = self.data[1].data[0][1:] | |
206 for i in xrange(int(float(self.data[2])), int(float(self.data[3]))+1
): | |
207 body = self.data[4].copy() | |
208 body.ctx.update({name: NumberValue(i)}) | |
209 body.parse(target) | |
210 | |
211 class Stylet(Empty): | |
212 def __init__(self, s, n, t): | |
213 super(Stylet, self).__init__(s, n, t) | |
214 self.name = str(self.data[1]) | |
OLD | NEW |