Skip to content

Instantly share code, notes, and snippets.

@showell
Created December 4, 2013 18:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save showell/7793101 to your computer and use it in GitHub Desktop.
Save showell/7793101 to your computer and use it in GitHub Desktop.
Python program to extract data structures from handlebars templates
#!/usr/bin/env python
import sys
import re
import json
def debug(obj):
print(json.dumps(obj, indent=4))
def parse_file(fn):
text = open(fn).read()
tags = re.findall('{+\s*(.*?)\s*}+', text)
root = {}
context = root
stack = []
def set_var(var, val):
num_levels_up = len(re.findall('\.\.', var))
if num_levels_up:
var = var.split('/')[-1]
stack[-1 * num_levels_up][var] = val
else:
context[var] = val
for tag in tags:
if tag.startswith('! '):
continue
if tag == 'else':
continue
if tag[0] in '#^' and ' ' not in tag:
var = tag[1:]
set_var(var, True)
stack.append(context)
continue
if tag.startswith('#if'):
vars = tag.split()[1:]
for var in vars:
set_var(var, True)
stack.append(context)
continue
if tag.startswith('/if'):
context = stack.pop()
continue
if tag.startswith('#with '):
var = tag.split()[1]
new_context = {}
context[var] = new_context
stack.append(context)
context = new_context
continue
if tag.startswith('/with'):
context = stack.pop()
continue
if tag.startswith('#unless '):
var = tag.split()[1]
set_var(var, True)
stack.append(context)
continue
if tag.startswith('/unless'):
context = stack.pop()
continue
if tag.startswith('#each '):
var = tag.split()[1]
new_context = {}
context[var] = [new_context]
stack.append(context)
context = new_context
continue
if tag.startswith('/each'):
context = stack.pop()
continue
if tag.startswith('/'):
context = stack.pop()
continue
set_var(tag, '')
def clean_this(obj):
if isinstance(obj, list):
return [clean_this(item) for item in obj]
if isinstance(obj, dict):
if len(obj.keys()) == 1 and 'this' in obj:
return clean_this(obj['this'])
return {k: clean_this(v) for k, v in obj.items()}
return obj
root = clean_this(root)
return root
if __name__ == '__main__':
for fn in sys.argv[1:]:
print '===', fn
root = parse_file(fn)
debug(root)
print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment