2011-01-17 22:11:35 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
# ship.py
|
|
|
|
#
|
|
|
|
# Licensed under the Apache 2 License as is the rest of the project
|
|
|
|
# Copyright (c) 2011 Jeff Schiller
|
|
|
|
#
|
2011-01-18 19:04:34 +00:00
|
|
|
# This script has very little real-world application. It is only used in our pure-client web app
|
|
|
|
# served on GoogleCode so we can have one HTML file, run a build script and generate a 'release'
|
|
|
|
# version without having to maintain two separate HTML files. It does this by evaluating
|
|
|
|
# 'processing comments' that are suspicously similar to IE conditional comments and then outputting
|
|
|
|
# a new HTML file after evaluating particular variables.
|
2011-01-18 06:13:40 +00:00
|
|
|
#
|
2011-01-17 22:11:35 +00:00
|
|
|
# This script takes the following inputs:
|
|
|
|
#
|
2011-01-18 06:13:40 +00:00
|
|
|
# * a HTML file (--i=in.html)
|
|
|
|
# * a series of flag names (--on=Foo --on=Bar)
|
2011-01-17 22:11:35 +00:00
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
#
|
|
|
|
# in.html:
|
|
|
|
# <!--{if foo}>
|
|
|
|
# FOO!
|
|
|
|
# <!{else}-->
|
|
|
|
# BAR!
|
|
|
|
# <!--{endif}-->
|
|
|
|
#
|
2011-01-18 06:13:40 +00:00
|
|
|
# $ ship.py --i in.html --on foo
|
2011-01-17 22:11:35 +00:00
|
|
|
#
|
|
|
|
# out.html:
|
|
|
|
# <!--{if foo}-->
|
|
|
|
# FOO!
|
|
|
|
# <!--{else}>
|
|
|
|
# BAR!
|
|
|
|
# <!{endif}-->
|
|
|
|
#
|
2011-01-18 06:13:40 +00:00
|
|
|
# It has the following limitations:
|
|
|
|
#
|
|
|
|
# 1) Only if-else-endif are currently supported.
|
|
|
|
# 2) All processing comments must be on one line with no other non-whitespace characters.
|
|
|
|
# 3) Comments cannot be nested.
|
2011-01-17 22:11:35 +00:00
|
|
|
|
|
|
|
import optparse
|
2011-01-18 06:13:40 +00:00
|
|
|
import os
|
|
|
|
|
|
|
|
inside_if = False
|
|
|
|
last_if_true = False
|
2011-01-17 22:11:35 +00:00
|
|
|
|
|
|
|
_options_parser = optparse.OptionParser(
|
2011-01-18 06:13:40 +00:00
|
|
|
usage='%prog --i input.html [--on flag1]',
|
|
|
|
description=('Rewrites an HTML file based on conditional comments and flags'))
|
|
|
|
_options_parser.add_option('--i',
|
|
|
|
action='store', dest='input_html_file', help='Input HTML filename')
|
|
|
|
_options_parser.add_option('--on',
|
|
|
|
action='append', type='string', dest='enabled_flags',
|
|
|
|
help='name of flag to enable')
|
2011-01-17 22:11:35 +00:00
|
|
|
|
|
|
|
def parse_args(args=None):
|
2011-01-18 06:13:40 +00:00
|
|
|
options, rargs = _options_parser.parse_args(args)
|
|
|
|
return options, (None, None)
|
|
|
|
|
|
|
|
def parseComment(line, line_num, enabled_flags):
|
|
|
|
global inside_if
|
|
|
|
global last_if_true
|
|
|
|
|
|
|
|
start = line.find('{')
|
|
|
|
end = line.find('}')
|
|
|
|
statement = line[start+1:end].strip()
|
|
|
|
if statement.startswith('if '):
|
|
|
|
if inside_if == True:
|
|
|
|
print 'Fatal Error: Nested {if} found on line ' + str(line_num)
|
|
|
|
print line
|
|
|
|
quit()
|
|
|
|
|
|
|
|
# Evaluate whether the expression is true/false.
|
|
|
|
# only one variable name allowed for now
|
|
|
|
variable_name = statement[3:].strip()
|
|
|
|
if variable_name in enabled_flags:
|
|
|
|
last_if_true = True
|
|
|
|
line = '<!--{if ' + variable_name + '}-->'
|
|
|
|
else:
|
|
|
|
last_if_true = False
|
|
|
|
line = '<!--{if ' + variable_name + '}>'
|
|
|
|
|
|
|
|
inside_if = True
|
|
|
|
|
|
|
|
elif statement == 'else':
|
|
|
|
if inside_if == False:
|
|
|
|
print 'Fatal Error: {else} found without {if} on line ' + str(line_num)
|
|
|
|
print line
|
|
|
|
quit()
|
2011-01-18 06:57:51 +00:00
|
|
|
if inside_if == 'else':
|
|
|
|
print 'Fatal Error: Multiple {else} clauses found in the same if on line ' + str(line_num)
|
|
|
|
print line
|
|
|
|
quit()
|
2011-01-18 06:13:40 +00:00
|
|
|
|
|
|
|
if last_if_true:
|
|
|
|
line = '<!--{else}>'
|
|
|
|
else:
|
|
|
|
line = '<!{else}-->'
|
2011-01-17 22:11:35 +00:00
|
|
|
|
2011-01-18 06:13:40 +00:00
|
|
|
# invert the logic so the endif clause is closed properly
|
|
|
|
last_if_true = not last_if_true
|
2011-01-17 22:11:35 +00:00
|
|
|
|
2011-01-18 06:57:51 +00:00
|
|
|
# ensure we don't have two else statements in the same if
|
|
|
|
inside_if = 'else'
|
|
|
|
|
2011-01-18 06:13:40 +00:00
|
|
|
elif statement == 'endif':
|
|
|
|
if inside_if == False:
|
|
|
|
print 'Fatal Error: {endif} found without {if} on line ' + str(line_num)
|
|
|
|
print line
|
|
|
|
quit()
|
|
|
|
|
|
|
|
if last_if_true:
|
|
|
|
line = '<!--{endif}-->'
|
|
|
|
else:
|
|
|
|
line = '<!{endif}-->'
|
|
|
|
|
|
|
|
inside_if = False
|
|
|
|
|
|
|
|
return line
|
|
|
|
|
|
|
|
|
|
|
|
def ship(inFileName, enabled_flags):
|
|
|
|
# read in HTML file
|
2011-01-18 19:04:34 +00:00
|
|
|
lines = file(inFileName, 'r').readlines()
|
2011-01-18 06:13:40 +00:00
|
|
|
out_lines = []
|
2011-01-18 19:04:34 +00:00
|
|
|
i = 0
|
2011-01-18 06:13:40 +00:00
|
|
|
|
|
|
|
# loop for each line of markup
|
|
|
|
for line in lines:
|
|
|
|
strline = line.strip()
|
|
|
|
# if we find a comment, process it and print out
|
|
|
|
if strline.startswith('<!--{') or strline.startswith('<!{'):
|
|
|
|
# using the same indentation as the previous line
|
|
|
|
start = line.find('<')
|
|
|
|
out_lines.append(line[:start] \
|
|
|
|
+ parseComment(strline, i, enabled_flags) \
|
|
|
|
+ os.linesep)
|
|
|
|
else: # else append line to the output list
|
|
|
|
out_lines.append(line)
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
return ''.join(out_lines)
|
2011-01-17 22:11:35 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
options, (input, output) = parse_args()
|
2011-01-18 06:13:40 +00:00
|
|
|
|
|
|
|
if options.input_html_file != None:
|
|
|
|
enabled_flags = []
|
|
|
|
if options.enabled_flags != None:
|
|
|
|
enabled_flags.extend(options.enabled_flags)
|
|
|
|
out_file = ship(options.input_html_file, enabled_flags)
|
|
|
|
print out_file
|