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.
9 from HTMLParser
import HTMLParser
17 print 'Error: %s' % msg
21 class HtmlChecker(HTMLParser
):
23 HTMLParser
.__init
__(self
)
26 def handle_starttag(self
, tag
, attrs
):
27 for (name
, value
) in attrs
:
30 error('Duplicate id: %s' % value
)
34 class GenerateWebappHtml
:
35 def __init__(self
, template_files
, js_files
, instrumented_js_files
):
37 self
.js_files
= js_files
38 self
.instrumented_js_files
= instrumented_js_files
41 self
.templates_expected
= set()
42 for template
in template_files
:
43 self
.templates_expected
.add(os
.path
.basename(template
))
45 self
.templates_found
= set()
47 def includeJavascript(self
, output
):
48 for js_path
in sorted(self
.js_files
):
49 js_file
= os
.path
.basename(js_path
)
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
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
)
71 def processTemplate(self
, output
, template_file
, indent
):
72 with
open(template_file
, 'r') as input_template
:
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
84 if skip_header_comment
:
85 if re
.search(r
'-->', line
):
86 skip_header_comment
= False
90 r
'^(\s*)<meta-include src="(.+)"\s*/>\s*$',
94 template_name
= m
.group(2)
95 if not self
.validateTemplate(template_name
):
96 error('Found template not in list of expected templates: %s' %
98 self
.processTemplate(output
, template_name
, indent
+ len(prefix
))
101 m
= re
.match(r
'^\s*<meta-include type="javascript"\s*/>\s*$', line
)
103 self
.includeJavascript(output
)
106 if line
.strip() == '':
109 output
.write((' ' * indent
) + line
)
113 parser
= argparse
.ArgumentParser()
115 '--js', nargs
='+', help='The Javascript files to include in HTML <head>')
120 help='The html template files used by input-template')
125 help='The Javascript files to exclude from <--js> and <--instrumentedjs>')
130 help='Javascript to include and instrument for code coverage')
131 parser
.add_argument('output_file')
132 parser
.add_argument('input_template')
133 return parser
.parse_args(sys
.argv
[1:])
139 out_file
= args
.output_file
140 js_files
= set(args
.js
) - set(args
.exclude_js
)
142 # Create the output directory if it does not exist.
143 out_directory
= os
.path
.dirname(out_file
)
144 if not os
.path
.exists(out_directory
):
145 os
.makedirs(out_directory
)
147 # Generate the main HTML file from the templates.
148 with
open(out_file
, 'w') as output
:
149 gen
= GenerateWebappHtml(args
.templates
, js_files
, args
.instrument_js
)
150 gen
.processTemplate(output
, args
.input_template
, 0)
152 # Verify that all the expected templates were found.
153 if not gen
.verifyTemplateList():
154 error('Extra templates specified')
156 # Verify that the generated HTML file is valid.
157 with
open(out_file
, 'r') as input_html
:
158 parser
= HtmlChecker()
159 parser
.feed(input_html
.read())
162 if __name__
== '__main__':