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
,
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
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(os
.path
.join(self
.template_rel_dir
, template_file
), 'r') as \
75 skip_header_comment
= False
77 for line
in input_template
:
78 # If the first line is the start of a copyright notice, then
79 # skip over the entire comment.
80 # This will remove the copyright info from the included files,
81 # but leave the one on the main template.
82 if first_line
and re
.match(r
'<!--', line
):
83 skip_header_comment
= True
85 if skip_header_comment
:
86 if re
.search(r
'-->', line
):
87 skip_header_comment
= False
91 r
'^(\s*)<meta-include src="(.+)"\s*/>\s*$',
95 template_name
= m
.group(2)
96 if not self
.validateTemplate(template_name
):
97 error('Found template not in list of expected templates: %s' %
99 self
.processTemplate(output
, template_name
, indent
+ len(prefix
))
102 m
= re
.match(r
'^\s*<meta-include type="javascript"\s*/>\s*$', line
)
104 self
.includeJavascript(output
)
107 if line
.strip() == '':
110 output
.write((' ' * indent
) + line
)
114 parser
= argparse
.ArgumentParser()
116 '--js', nargs
='+', help='The Javascript files to include in HTML <head>')
121 help='The html template files used by input-template')
126 help='The Javascript files to exclude from <--js> and <--instrumentedjs>')
131 help='Javascript to include and instrument for code coverage')
133 '--dir-for-templates',
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:])
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 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
.dir_for_templates
)
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__':