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