blob: 9a93c8e7112cefa6a9bb173bb21a77b089764d59 [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 2015 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 2015 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 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 simplifications
# 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])
# Output
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):
"""Writes a HTML file with the content of all modules in a load sequence.
The load_sequence is a list of (HTML or JS) Module objects; the order that
they're inserted into the file depends on their type and position in the load
sequence.
"""
_AssertIsUTF8(output_file)
extra_scripts = extra_scripts or []
if output_html_head_and_body:
output_file.write(
'<!DOCTYPE HTML>\n'
'<html>\n'
' <head i18n-values="dir:textdirection;">\n'
' <meta http-equiv="Content-Type" content="text/html;'
'charset=utf-8">\n')
if title:
output_file.write(' <title>%s</title>\n ' % 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:
controller = HTMLGenerationController(module)
module.AppendHTMLContentsToFile(output_file, controller, minify=minify)
if flattened_js_url:
output_file.write('<script src="%s"></script>\n' % flattened_js_url)
else:
output_file.write('<script>\n')
js = GenerateJS(load_sequence, minify=minify, report_sizes=report_sizes)
output_file.write(js)
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>\n <body>\n </body>\n</html>\n')