Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / remoting / webapp / build-html.py
blobd73ec67e80a7dd8bb73cab9bfd9c90866e672131
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_file in sorted([os.path.basename(x) for x in self.js_files]):
50 output.write(' <script src="' + js_file + '"></script>\n')
52 for js_path in sorted(self.instrumented_js_files):
53 js_file = os.path.basename(js_path)
54 output.write(' <script src="' + js_file + '" data-cover></script>\n')
56 def verifyTemplateList(self):
57 """Verify that all the expected templates were found."""
58 if self.templates_expected > self.templates_found:
59 extra = self.templates_expected - self.templates_found
60 print 'Extra templates specified:', extra
61 return False
62 return True
64 def validateTemplate(self, template_path):
65 template = os.path.basename(template_path)
66 if template in self.templates_expected:
67 self.templates_found.add(template)
68 return True
69 return False
71 def processTemplate(self, output, template_file, indent):
72 with open(template_file, 'r') as input_template:
73 first_line = True
74 skip_header_comment = False
76 for line in input_template:
77 # If the first line is the start of a copyright notice, then
78 # skip over the entire comment.
79 # This will remove the copyright info from the included files,
80 # but leave the one on the main template.
81 if first_line and re.match(r'<!--', line):
82 skip_header_comment = True
83 first_line = False
84 if skip_header_comment:
85 if re.search(r'-->', line):
86 skip_header_comment = False
87 continue
89 m = re.match(
90 r'^(\s*)<meta-include src="(.+)"\s*/>\s*$',
91 line)
92 if m:
93 prefix = m.group(1)
94 template_name = m.group(2)
95 template_path = os.path.join(self.template_rel_dir, template_name)
96 if not self.validateTemplate(template_path):
97 error('Found template not in list of expected templates: %s' %
98 template_name)
99 self.processTemplate(output, template_path, indent + len(prefix))
100 continue
102 m = re.match(r'^\s*<meta-include type="javascript"\s*/>\s*$', line)
103 if m:
104 self.includeJavascript(output)
105 continue
107 if line.strip() == '':
108 output.write('\n')
109 else:
110 output.write((' ' * indent) + line)
113 def parseArgs():
114 parser = argparse.ArgumentParser()
115 parser.add_argument(
116 '--js', nargs='+', help='The Javascript files to include in HTML <head>')
117 parser.add_argument(
118 '--templates',
119 nargs='*',
120 default=[],
121 help='The html template files used by input-template')
122 parser.add_argument(
123 '--exclude-js',
124 nargs='*',
125 default=[],
126 help='The Javascript files to exclude from <--js> and <--instrumentedjs>')
127 parser.add_argument(
128 '--instrument-js',
129 nargs='*',
130 default=[],
131 help='Javascript to include and instrument for code coverage')
132 parser.add_argument(
133 '--template-dir',
134 default = ".",
135 help='Directory template references in html are relative to')
136 parser.add_argument('output_file')
137 parser.add_argument('input_template')
138 return parser.parse_args(sys.argv[1:])
141 def main():
142 args = parseArgs()
144 out_file = args.output_file
145 js_files = set(args.js) - set(args.exclude_js)
147 # Create the output directory if it does not exist.
148 out_directory = os.path.dirname(out_file)
149 if out_directory is not '' and not os.path.exists(out_directory):
150 os.makedirs(out_directory)
152 # Generate the main HTML file from the templates.
153 with open(out_file, 'w') as output:
154 gen = GenerateWebappHtml(args.templates, js_files, args.instrument_js,
155 args.template_dir)
156 gen.processTemplate(output, args.input_template, 0)
158 # Verify that all the expected templates were found.
159 if not gen.verifyTemplateList():
160 error('Extra templates specified')
162 # Verify that the generated HTML file is valid.
163 with open(out_file, 'r') as input_html:
164 parser = HtmlChecker()
165 parser.feed(input_html.read())
168 if __name__ == '__main__':
169 sys.exit(main())