1import os
2from itertools import count
3from pyjade import Parser, Compiler as _Compiler
4from pyjade.runtime import attrs
5from pyjade.utils import process
6import six
7
8def process_param(key, value, terse=False):
9    if terse:
10        if (key == value) or (value is True):
11            return key
12    if isinstance(value, six.binary_type):
13        value = value.decode('utf8')
14    return '''%s="%s"''' % (key, value)
15
16class Compiler(_Compiler):
17    def __init__(self, *args, **kws):
18      _Compiler.__init__(self, *args, **kws)
19      self._i = count()
20
21    def visitAssignment(self,assignment):
22        self.buffer('<%% var %s = %s; %%>'%(assignment.name,assignment.val))
23
24    def visitCode(self,code):
25        if code.buffer:
26            val = code.val.lstrip()
27            self.buf.append('<%%%s %s %%>'%('=' if code.escape else '-', val))
28        else:
29            self.buf.append('<%% %s'%code.val) #for loop
30
31        if code.block:
32            self.buf.append(' { %>') #for loop
33            # if not code.buffer: self.buf.append('{')
34            self.visit(code.block)
35            # if not code.buffer: self.buf.append('}')
36
37            if not code.buffer:
38              codeTag = code.val.strip().split(' ',1)[0]
39              if codeTag in self.autocloseCode:
40                  self.buf.append('<% } %>')
41        elif not code.buffer:
42            self.buf.append('; %>') #for loop
43
44
45    def visitEach(self,each):
46        #self.buf.append('{%% for %s in %s %%}'%(','.join(each.keys),each.obj))
47        __i = self._i.next()
48        self.buf.append('<%% for (_i_%s = 0, _len_%s = %s.length; _i_%s < _len_%s; _i_%s++) { ' %(__i, __i, each.obj, __i, __i, __i))
49        if len(each.keys) > 1:
50          for i, k in enumerate(each.keys):
51            self.buf.append('%s = %s[_i_%s][%s];' % (k, each.obj, __i, i))
52        else:
53          for k in each.keys:
54            self.buf.append('%s = %s[_i_%s];' % (k, each.obj, __i))
55        self.buf.append(' %>')
56        self.visit(each.block)
57        self.buf.append('<% } %>')
58
59    def _do_eval(self, value):
60        if isinstance(value, six.string_types):
61            value = value.encode('utf-8')
62        try:
63            value = eval(value, {}, {})
64        except:
65            return "<%%= %s %%>" % value
66        return value
67
68    def _get_value(self, attr):
69        value = attr['val']
70        if attr['static']:
71            return attr['val']
72        if isinstance(value, six.string_types):
73            return self._do_eval(value)
74        else:
75            return attr['name']
76
77    def visitAttributes(self,attrs):
78        classes = []
79        params = []
80        for attr in attrs:
81            if attr['name'] == 'class':
82                value = self._get_value(attr)
83                if isinstance(value, list):
84                    classes.extend(value)
85                else:
86                    classes.append(value)
87            else:
88                value = self._get_value(attr)
89                if (value is not None) and (value is not False):
90                    params.append((attr['name'], value))
91        if classes:
92            classes = [six.text_type(c) for c in classes]
93            params.append(('class', " ".join(classes)))
94        if params:
95            self.buf.append(" "+" ".join([process_param(k, v, self.terse) for (k,v) in params]))
96
97    def visitConditional(self,conditional):
98        TYPE_CODE = {
99            'if': lambda x: 'if (%s)'%x,
100            'unless': lambda x: 'if (!%s)'%x,
101            'elif': lambda x: '} else if (%s)'%x,
102            'else': lambda x: '} else'
103        }
104        self.buf.append('\n<%% %s { %%>'%TYPE_CODE[conditional.type](conditional.sentence))
105        if conditional.block:
106            self.visit(conditional.block)
107            for next in conditional.next:
108              self.visitConditional(next)
109        if conditional.type in ['if','unless']: self.buf.append('\n<% } %>\n')
110
111    def interpolate(self, text, escape=True):
112        return self._interpolate(text,lambda x:'<%%= %s %%>'%x)
113