blob: 37e3c1cac73dc054ee752511aa88bd9198ba99a3 [file] [log] [blame]
# Copyright (c) 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
import subprocess
import tempfile
import StringIO
from tvcm import html_generation_controller
html_warning_message = """
<!--
WARNING: This file is auto generated.
Do not edit directly.
-->
"""
js_warning_message = """
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* WARNING: This file is auto generated.
*
* Do not edit directly.
*/
"""
css_warning_message = """
/* Copyright (c) 2014 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
/* WARNING: This file is auto-generated.
*
* Do not edit directly.
*/
"""
def _AssertIsUTF8(f):
if isinstance(f, StringIO.StringIO):
return
assert f.encoding == 'utf-8'
def _MinifyJS(input_js):
tvcm_path = os.path.abspath(os.path.join(
os.path.dirname(__file__), '..'))
rjsmin_path = os.path.abspath(
os.path.join(tvcm_path, 'third_party', 'rjsmin', 'rjsmin.py'))
with tempfile.NamedTemporaryFile() as _:
args = [
'python',
rjsmin_path
]
p = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
res = p.communicate(input=input_js)
errorcode = p.wait()
if errorcode != 0:
sys.stderr.write('rJSmin exited with error code %d' % errorcode)
sys.stderr.write(res[1])
raise Exception('Failed to minify, omgah')
return res[0]
def GenerateJS(load_sequence,
use_include_tags_for_scripts=False,
dir_for_include_tag_root=None,
minify=False,
report_sizes=False):
f = StringIO.StringIO()
GenerateJSToFile(f,
load_sequence,
use_include_tags_for_scripts,
dir_for_include_tag_root,
minify=minify,
report_sizes=report_sizes)
return f.getvalue()
def pt_parts(self):
sl = ['unicode and 8-bit string parts of above page template']
for x in self.buflist:
if type(x) == type(''):
maxcode = 0
for c in x:
maxcode = max(ord(c), maxcode)
# show only unicode objects and non-ascii strings
if type(x) == type('') and maxcode > 127:
t = '****NonAsciiStr: '
elif type(x) == type(u''):
t = '*****UnicodeStr: '
else:
t = None
if t:
sl.append(t + repr(x))
s = '\n'.join(sl)
return s
def GenerateJSToFile(f,
load_sequence,
use_include_tags_for_scripts=False,
dir_for_include_tag_root=None,
minify=False,
report_sizes=False):
_AssertIsUTF8(f)
if use_include_tags_for_scripts and dir_for_include_tag_root is None:
raise Exception('Must provide dir_for_include_tag_root')
f.write(js_warning_message)
f.write('\n')
loader = load_sequence[0].loader
polymer_script = loader.LoadRawScript('components/polymer/polymer.min.js')
f.write(polymer_script.contents)
if not minify:
flatten_to_file = f
else:
flatten_to_file = StringIO.StringIO()
for module in load_sequence:
module.AppendJSContentsToFile(flatten_to_file,
use_include_tags_for_scripts,
dir_for_include_tag_root)
if minify:
js = flatten_to_file.getvalue()
minified_js = _MinifyJS(js)
f.write(minified_js)
f.write('\n')
if report_sizes:
for module in load_sequence:
s = StringIO.StringIO()
module.AppendJSContentsToFile(s,
use_include_tags_for_scripts,
dir_for_include_tag_root)
# Add minified size info.
js = s.getvalue()
min_js_size = str(len(_MinifyJS(js)))
# Print names for this module. Some domain-specific simplifciations
# are included to make pivoting more obvious.
parts = module.name.split('.')
if parts[:2] == ['base', 'ui']:
parts = ['base_ui'] + parts[2:]
if parts[:2] == ['tracing', 'importer']:
parts = ['importer'] + parts[2:]
tln = parts[0]
sln = '.'.join(parts[:2])
# Ouptut
print '%i\t%s\t%s\t%s\t%s' % (len(js), min_js_size, module.name, tln, sln)
sys.stdout.flush()
class ExtraScript(object):
def __init__(self, script_id=None, text_content=None, content_type=None):
if script_id is not None:
assert script_id[0] != '#'
self.script_id = script_id
self.text_content = text_content
self.content_type = content_type
def WriteToFile(self, output_file):
_AssertIsUTF8(output_file)
attrs = []
if self.script_id:
attrs.append('id="%s"' % self.script_id)
if self.content_type:
attrs.append('content-type="%s"' % self.content_type)
if len(attrs) > 0:
output_file.write('<script %s>\n' % ' '.join(attrs))
else:
output_file.write('<script>\n')
if self.text_content:
output_file.write(self.text_content)
output_file.write('</script>\n')
def _MinifyCSS(css_text):
tvcm_path = os.path.abspath(os.path.join(
os.path.dirname(__file__), '..'))
rcssmin_path = os.path.abspath(
os.path.join(tvcm_path, 'third_party', 'rcssmin', 'rcssmin.py'))
with tempfile.NamedTemporaryFile() as _:
rcssmin_args = ['python', rcssmin_path]
p = subprocess.Popen(rcssmin_args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
res = p.communicate(input=css_text)
errorcode = p.wait()
if errorcode != 0:
sys.stderr.write('rCSSmin exited with error code %d' % errorcode)
sys.stderr.write(res[1])
raise Exception('Failed to generate css for %s.' % css_text)
return res[0]
def GenerateStandaloneHTMLAsString(*args, **kwargs):
f = StringIO.StringIO()
GenerateStandaloneHTMLToFile(f, *args, **kwargs)
return f.getvalue()
def GenerateStandaloneHTMLToFile(output_file,
load_sequence,
title=None,
flattened_js_url=None,
extra_scripts=None,
minify=False,
report_sizes=False,
output_html_head_and_body=True):
_AssertIsUTF8(output_file)
extra_scripts = extra_scripts or []
if output_html_head_and_body:
output_file.write("""<!DOCTYPE HTML>
<html>
<head i18n-values="dir:textdirection;">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
""")
if title:
output_file.write(""" <title>%s</title>
""" % title)
else:
assert title is None
loader = load_sequence[0].loader
written_style_sheets = set()
class HTMLGenerationController(
html_generation_controller.HTMLGenerationController):
def __init__(self, module):
self.module = module
def GetHTMLForStylesheetHRef(self, href):
resource = self.module.HRefToResource(
href, '<link rel="stylesheet" href="%s">' % href)
style_sheet = loader.LoadStyleSheet(resource.name)
if style_sheet in written_style_sheets:
return None
written_style_sheets.add(style_sheet)
text = style_sheet.contents_with_inlined_images
if minify:
text = _MinifyCSS(text)
return '<style>\n%s\n</style>' % text
for module in load_sequence:
ctl = HTMLGenerationController(module)
module.AppendHTMLContentsToFile(output_file, ctl, minify=minify)
if flattened_js_url:
output_file.write('<script src="%s"></script>\n' % flattened_js_url)
else:
output_file.write('<script>\n')
x = GenerateJS(load_sequence, minify=minify, report_sizes=report_sizes)
output_file.write(x)
output_file.write('</script>\n')
for extra_script in extra_scripts:
extra_script.WriteToFile(output_file)
if output_html_head_and_body:
output_file.write("""</head>
<body>
</body>
</html>
""")