Skip to content

Instantly share code, notes, and snippets.

@Shaunwei
Created February 3, 2016 09:15
Show Gist options
  • Save Shaunwei/a09a8c691edde0a5ef62 to your computer and use it in GitHub Desktop.
Save Shaunwei/a09a8c691edde0a5ef62 to your computer and use it in GitHub Desktop.
given HTML template, implement render function
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