xyc
2024-05-17 6b24f642b01cf3cd1be0d5833273fa2867d389e1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/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
#
# 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.
#
# This script takes the following inputs:
#
# * a HTML file (--i=in.html)
# * a series of flag names (--on=Foo --on=Bar)
#
# Example:
#
# in.html:
#   <!--{if foo}>
#     FOO!
#   <!{else}-->
#     BAR!
#   <!--{endif}-->
#
# $ ship.py --i in.html --on foo
#
# out.html:
#   <!--{if foo}-->
#     FOO!
#   <!--{else}>
#     BAR!
#   <!{endif}-->
#
# 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.
 
import optparse
import os
 
inside_if = False
last_if_true = False
 
_options_parser = optparse.OptionParser(
    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')
 
def parse_args(args=None):
  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()
    if inside_if == 'else':
      print 'Fatal Error: Multiple {else} clauses found in the same if on line ' + str(line_num)
      print line
      quit()
 
    if last_if_true:
      line = '<!--{else}>'
    else:
      line = '<!{else}-->'
 
    # invert the logic so the endif clause is closed properly
    last_if_true = not last_if_true
 
    # ensure we don't have two else statements in the same if
    inside_if = 'else'
 
  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
  lines = file(inFileName, 'r').readlines()
  out_lines = []
  i = 0
 
  # 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)
 
if __name__ == '__main__':
  options, (input, output) = parse_args()
 
  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