Template Converter
1 #! /usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @Author: windfic@qq.com 4 # @Last Modified time: 2017-03-01 19:13 5 6 import os 7 import re 8 import chardet 9 10 separators = [(‘<‘, ‘>‘), (‘<?‘, ‘?>‘), (‘{$‘, ‘}‘)] 11 match = {‘opening‘: 0, ‘closing‘: 0, ‘script‘: ‘‘, ‘content‘: ‘‘, ‘cache‘: ‘‘, ‘separator‘: ()} 12 stack = [] 13 14 15 def detect(path): 16 if not os.path.isfile(path): 17 return ‘auto‘ 18 19 fh = open(path, ‘r‘) 20 try: 21 data = fh.read() 22 finally: 23 fh.close() 24 return chardet.detect(data)[‘encoding‘] 25 26 27 def convert_templates(src, dst, src_enc=‘auto‘, dst_enc=‘utf-8‘): 28 if not os.path.isdir(src) or not os.path.isdir(dst): 29 return False 30 31 for root, dirs, files in os.walk(src): 32 for filepath in files: 33 if src_enc == ‘auto‘: 34 src_enc = detect(os.path.join(root, filepath)) 35 sub = os.path.relpath(root, src) 36 convert_template(os.path.join(root, filepath), os.path.join(dst, sub, filepath), src_enc, dst_enc) 37 38 39 def convert_template(src, dst, src_enc=‘auto‘, dst_enc=‘utf-8‘): 40 global match, separators 41 42 if not os.path.isfile(src): 43 return False 44 print(dst) 45 if not os.path.exists(os.path.dirname(dst)): 46 os.makedirs(os.path.dirname(dst)) 47 48 if src_enc == ‘auto‘: 49 src_enc = detect(src) 50 51 sfh = open(src, ‘r‘) 52 dfh = open(dst, ‘w‘) 53 try: 54 for line in sfh.readlines(): 55 line = line.decode(src_enc) 56 for sep in separators: 57 line = next_tag(line, sep) 58 if line is None or line is ‘‘: 59 break 60 if line is None or line is ‘‘: 61 continue 62 line = line.encode(dst_enc) 63 dfh.write(line) 64 if match[‘content‘] is not ‘‘ or match[‘cache‘] is not ‘‘ or match[‘opening‘] > 0: 65 line = (match[‘content‘]+match[‘cache‘]).encode(dst_enc) 66 match = {‘opening‘: 0, ‘closing‘: 0, ‘script‘: ‘‘, ‘content‘: ‘‘, ‘cache‘: ‘‘, ‘separator‘: ()} 67 dfh.write(line) 68 finally: 69 sfh.close() 70 dfh.close() 71 72 73 def next_tag(line, sep): 74 global match 75 76 if match[‘opening‘] > 0: 77 n = line.find(match[‘separator‘][1]) 78 if n >= 0: 79 m = len(match[‘separator‘][1]) 80 match[‘closing‘] += 1 81 match[‘opening‘] += line[:n].count(match[‘separator‘][0]) 82 match[‘cache‘] += line[:n+m] 83 if match[‘opening‘] == match[‘closing‘]: 84 conv = match[‘content‘]+convert_tag(match[‘cache‘]) 85 if len(line) > n + m: 86 match = {‘opening‘: 0, ‘closing‘: 0, ‘script‘: match[‘script‘], 87 ‘content‘: conv, ‘cache‘: ‘‘, ‘separator‘: ()} 88 return next_tag(line[n+m:], sep) 89 else: 90 match = {‘opening‘: 0, ‘closing‘: 0, ‘script‘: match[‘script‘], 91 ‘content‘: ‘‘, ‘cache‘: ‘‘, ‘separator‘: ()} 92 return conv 93 else: 94 if len(line) > n + m: 95 return next_tag(line[n + m:], sep) 96 else: 97 match[‘cache‘] += line 98 else: 99 if match[‘script‘] is not ‘‘: 100 m = re.search(match[‘script‘], line) 101 if m: 102 match[‘script‘] = ‘‘ 103 match[‘content‘] += line[:m.end()] 104 if len(line) > m.end(): 105 return next_tag(line[m.end():], sep) 106 else: 107 return next_tag(‘‘, sep) 108 match[‘content‘] += line 109 return None 110 else: 111 n = line.find(sep[0]) 112 if n >= 0: 113 m = len(sep[0]) 114 match[‘content‘] += line[:n] 115 match[‘cache‘] = line[n:n+m] 116 match[‘opening‘] += 1 117 match[‘separator‘] = sep 118 if len(line) > n + m: 119 return next_tag(line[n + m:], sep) 120 121 content = match[‘content‘]+line 122 match[‘content‘] = ‘‘ 123 return content 124 return None 125 126 127 def convert_tag(tag): 128 m = re.match(r‘<\?(php)*(.*)\?>‘, tag) 129 if m: 130 return build_tag(m.group(2), ‘?php‘) 131 m = re.match(r‘<\s*(\w+)(\s+.*)*(/*)\s*>‘, tag) 132 if m: 133 return build_tag(tag, m.group(1)) 134 m = re.match(r‘<\s*/\s*(\w+)\s*>‘, tag) 135 if m: 136 return build_tag(tag, ‘/‘+m.group(1)) 137 m = re.match(r‘\{\$\s*(.+)\s*\}‘, tag) 138 if m: 139 return build_tag(tag, ‘{$‘) 140 return tag 141 142 143 def build_tag(tag, name): 144 global match 145 146 if name == ‘script‘: 147 match[‘script‘] = r‘<\s*/\s*script\s*>‘ 148 elif name == ‘block‘: 149 m = re.search(r‘name\s*=\s*("|\‘)(.*?)("|\‘)‘, tag) 150 if m: 151 return u‘{% block ‘+m.group(2)+‘ %}‘ 152 elif name == ‘/block‘: 153 return u‘{% endblock %}‘ 154 elif name == ‘extend‘: 155 m = re.search(r‘name\s*=\s*("|\‘)(.*?)("|\‘)‘, tag) 156 if m: 157 return u‘{% extends "‘+m.group(2)+‘.html" %}‘ 158 elif name == ‘/extend‘: 159 return u‘‘ 160 elif name == ‘include‘: 161 m = re.search(r‘file\s*=\s*("|\‘)(.*?)("|\‘)‘, tag) 162 if m: 163 return u‘{% include "‘+m.group(2)+‘.html" %}‘ 164 elif name == ‘/include‘: 165 return u‘‘ 166 elif name == ‘volist‘: 167 m1 = re.search(r‘name\s*=\s*("|\‘)(.*?)("|\‘)‘, tag) 168 m2 = re.search(r‘id\s*=\s*("|\‘)(.*?)("|\‘)‘, tag) 169 if m1 and m2: 170 return u‘{% for ‘+m2.group(2)+‘ in ‘+m1.group(2)+‘ %}‘ 171 elif name == ‘/volist‘: 172 return u‘{% endfor %}‘ 173 elif name == ‘notempty‘: 174 m = re.search(r‘name\s*=\s*("|\‘)(.*?)("|\‘)‘, tag) 175 if m: 176 return u‘{% if ‘+m.group(2)+‘ %}‘ 177 elif name == ‘/notempty‘: 178 return u‘{% endif %}‘ 179 elif name == ‘?php‘: 180 return u‘{# ‘ + tag + u‘ #}‘ 181 elif name == ‘php‘: 182 return u‘{# ‘ 183 elif name == ‘/php‘: 184 return u‘ #}‘ 185 elif name == ‘{$‘: 186 m = re.search(r‘\{\$\s*(.+)\s*\}‘, tag) 187 if m: 188 return u‘{{ ‘ + m.group(1) + u‘ }}‘ 189 return tag 190 191 192 if __name__ == ‘__main__‘: 193 convert_templates(‘src‘, ‘dst‘) 194
原文:http://www.cnblogs.com/windfic/p/6485848.html