Created
February 3, 2016 09:15
-
-
Save Shaunwei/a09a8c691edde0a5ef62 to your computer and use it in GitHub Desktop.
given HTML template, implement render function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
string = ''' | |
<h1>{{customerName}}</h1> | |
<ul> | |
{% for user in users %} | |
<li><a href="{{ user.url }}">{{ user.username }} {{location.CA}}</a></li> | |
{% endfor %} | |
</ul> | |
''' | |
dict_ = { | |
'customerName': 'uber', | |
'location': { | |
'CA': 'SF' | |
}, | |
'users': [ | |
{ | |
'url': 'myUrl', | |
'username': 'myUsername' | |
} | |
] | |
} | |
import re | |
class Engine: | |
def __init__(self): | |
self.place_holder_pattern = r'(?P<dirty_key>{{\s*(?P<key>[\.\w]+)\s*}})' | |
self.loop_pattern_st = r'{%\s+for\s+(?P<item>\w+)\s+in\s+(?P<items>\w+)\s+%}' | |
self.loop_pattern_ed = r'{%\s+endfor\s+%}' | |
def render(self, string, dict_): | |
ret = [] | |
for_loop = False | |
cache = [] | |
for line in string.splitlines(): | |
if not for_loop: | |
if self.find_for_loop_start(line): | |
for_loop = True | |
cache.append(line) | |
else: | |
ret.append(self.fill_in(line, dict_)) | |
else: | |
if self.find_for_loop_end(line): | |
for_loop = False | |
ret.extend(self.fill_in_for_loop(cache, dict_)) | |
cache = [] | |
else: | |
cache.append(line) | |
return '\n'.join(ret) | |
def find_for_loop_start(self, line): | |
return 'for' in line and 'in' in line | |
def find_for_loop_end(self, line): | |
return 'endfor' in line | |
def fill_in_for_loop(self, lines, dict_): | |
ret = [] | |
item_key, key = re.findall(self.loop_pattern_st, lines[0])[0] | |
if key in dict_: | |
for item_values in dict_[key]: | |
curt_lines = [] | |
for line in lines[1:]: | |
l = self.fill_in(line, dict_, item_key, item_values) | |
curt_lines.append(l) | |
ret.extend(curt_lines) | |
return ret | |
def fill_in(self, line, dict_, item_key='', item_values=''): | |
keys = re.findall(self.place_holder_pattern, line) | |
for dirty_key, key in keys: | |
if '.' not in key: | |
if key in dict_: | |
line = line.replace(dirty_key, dict_[key]) | |
else: | |
attrs = key.split('.') | |
if attrs[0] == item_key: | |
curt = item_values | |
for attr in attrs[1:]: | |
if attr in curt: | |
curt = curt[attr] | |
else: | |
line = line.replace(dirty_key, curt) | |
else: | |
curt = dict_ | |
for attr in attrs: | |
if attr in curt: | |
curt = curt[attr] | |
else: | |
line = line.replace(dirty_key, curt) | |
return line | |
if __name__ == '__main__': | |
e = Engine() | |
print(e.render(string, dict_)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment