zulip/tools/check-templates

113 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python
import os
import sys
import subprocess
class Record:
pass
def validate(fn, check_indent=True):
text = open(fn).read()
state = Record()
def NoStartTag(end_tag):
raise Exception('''
No start tag
fn: %s
end tag:
%s
line %d, col %d
''' % (fn, end_tag, state.line, state.col))
def start_tag_matcher(s):
start_line = state.line
start_col = state.col
state.depth += 1
tag = s[1:-1]
start_tag = tag.split()[0]
old_matcher = state.matcher
def f(end_tag):
problem = None
if start_tag != end_tag[2:-1]:
problem = 'Mismatched tag.'
elif check_indent and state.line > start_line + 1 and state.col != start_col:
problem = 'Bad indentation.'
if problem:
raise Exception('''
fn: %s
%s
start:
%s
line %d, col %d
end tag:
%s
line %d, col %d
''' % (fn, problem, s, start_line, start_col, end_tag, state.line, state.col))
state.matcher = old_matcher
state.depth -= 1
state.matcher = f
state.depth = 0
state.i = 0
state.line = 1
state.col = 1
state.matcher = NoStartTag
def advance(n):
for _ in range(n):
state.i += 1
if state.i >= 0 and text[state.i - 1] == '\n':
state.line += 1
state.col = 1
else:
state.col += 1
while True:
if state.i >= len(text):
break
c = text[state.i]
if c == '<':
end = state.i + 1
while end < len(text) and text[end] != '>':
end += 1
if text[end] != '>':
raise Exception('Tag missing >')
s = text[state.i:end+1]
if s.startswith('</'):
state.matcher(s)
else:
tag = s[1:-1].split()[0]
ignore = s.startswith('<!--') or s.endswith('/>') or tag in ['meta', '!DOCTYPE']
if not ignore:
start_tag_matcher(s)
advance(len(s))
continue
advance(1)
if state.depth != 0:
return state.matcher("(NO TAG)")
git_files = map(str.strip, subprocess.check_output(['git', 'ls-files']).split('\n'))
# Check all our handlebars templates.
templates = [fn for fn in git_files if fn.endswith('.handlebars')]
assert len(templates) >= 10 # sanity check that we are actually doing work
for fn in templates:
validate(fn)
# Django templates are pretty messy now, so we do minimal checking.
templates = sorted([fn for fn in git_files if fn.endswith('.html') and 'templates' in fn])
def ok(fn):
if 'api.html' in fn: return False
if 'base.html' in fn: return False
return True
templates = filter(ok, templates)
assert len(templates) >= 10 # sanity check that we are actually doing work
for fn in templates:
validate(fn, check_indent=False)