Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / remoting / webapp / build-html.py
blob5c74b5f2d6eecf68e4ede19bd69f920a0cbf12b3
1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Builds the complete main.html file from the basic components.
7 """
9 from HTMLParser import HTMLParser
10 import argparse
11 import os
12 import re
13 import sys
16 def error(msg):
17 print 'Error: %s' % msg
18 sys.exit(1)
21 class HtmlChecker(HTMLParser):
22 def __init__(self):
23 HTMLParser.__init__(self)
24 self.ids = set()
26 def handle_starttag(self, tag, attrs):
27 for (name, value) in attrs:
28 if name == 'id':
29 if value in self.ids:
30 error('Duplicate id: %s' % value)
31 self.ids.add(value)
34 class GenerateWebappHtml:
35 def __init__(self, template_files, js_files, instrumented_js_files,
36 template_rel_dir):
38 self.js_files = js_files
39 self.instrumented_js_files = instrumented_js_files
40 self.template_rel_dir = template_rel_dir
42 self.templates_expected = set()
43 for template in template_files:
44 self.templates_expected.add(os.path.basename(template))
46 self.templates_found = set()
48 def includeJavascript(self, output):
49 for js_path in sorted(self.js_files):
50 js_file = os.path.basename(js_path)
51 output.write(' <script src="' + js_file + '"></script>\n')
53 for js_path in sorted(self.instrumented_js_files):
54 js_file = os.path.basename(js_path)
55 output.write(' <script src="' + js_file + '" data-cover></script>\n')
57 def verifyTemplateList(self):
58 """Verify that all the expected templates were found."""
59 if self.templates_expected > self.templates_found:
60 extra = self.templates_expected - self.templates_found
61 print 'Extra templates specified:', extra
62 return False
63 return True
65 def validateTemplate(self, template_path):
66 template = os.path.basename(template_path)
67 if template in self.templates_expected:
68 self.templates_found.add(template)
69 return True
70 return False
72 def processTemplate(self, output, template_file, indent):
73 with open(os.path.join(self.template_rel_dir, template_file), 'r') as \
74 input_template:
75 first_line = True
76 skip_header_comment = False
78 for line in input_template:
79 # If the first line is the start of a copyright notice, then
80 # skip over the entire comment.
81 # This will remove the copyright info from the included files,
82 # but leave the one on the main template.
83 if first_line and re.match(r'<!--', line):
84 skip_header_comment = True
85 first_line = False
86 if skip_header_comment:
87 if re.search(r'-->', line):
88 skip_header_comment = False
89 continue
91 m = re.match(
92 r'^(\s*)<meta-include src="(.+)"\s*/>\s*$',
93 line)
94 if m:
95 prefix = m.group(1)
96 template_name = m.group(2)
97 if not self.validateTemplate(template_name):
98 error('Found template not in list of expected templates: %s' %
99 template_name)
100 self.processTemplate(output, template_name, indent + len(prefix))
101 continue
103 m = re.match(r'^\s*<meta-include type="javascript"\s*/>\s*$', line)
104 if m:
105 self.includeJavascript(output)
106 continue
108 if line.strip() == '':
109 output.write('\n')
110 else:
111 output.write((' ' * indent) + line)
114 def parseArgs():
115 parser = argparse.ArgumentParser()
116 parser.add_argument(
117 '--js', nargs='+', help='The Javascript files to include in HTML <head>')
118 parser.add_argument(
119 '--templates',
120 nargs='*',
121 default=[],
122 help='The html template files used by input-template')
123 parser.add_argument(
124 '--exclude-js',
125 nargs='*',
126 default=[],
127 help='The Javascript files to exclude from <--js> and <--instrumentedjs>')
128 parser.add_argument(
129 '--instrument-js',
130 nargs='*',
131 default=[],
132 help='Javascript to include and instrument for code coverage')
133 parser.add_argument(
134 '--dir-for-templates',
135 default = ".",
136 help='Directory template references in html are relative to')
137 parser.add_argument('output_file')
138 parser.add_argument('input_template')
139 return parser.parse_args(sys.argv[1:])
142 def main():
143 args = parseArgs()
145 out_file = args.output_file
146 js_files = set(args.js) - set(args.exclude_js)
148 # Create the output directory if it does not exist.
149 out_directory = os.path.dirname(out_file)
150 if not os.path.exists(out_directory):
151 os.makedirs(out_directory)
153 # Generate the main HTML file from the templates.
154 with open(out_file, 'w') as output:
155 gen = GenerateWebappHtml(args.templates, js_files, args.instrument_js,
156 args.dir_for_templates)
157 gen.processTemplate(output, args.input_template, 0)
159 # Verify that all the expected templates were found.
160 if not gen.verifyTemplateList():
161 error('Extra templates specified')
163 # Verify that the generated HTML file is valid.
164 with open(out_file, 'r') as input_html:
165 parser = HtmlChecker()
166 parser.feed(input_html.read())
169 if __name__ == '__main__':
170 sys.exit(main())