aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoaodasilva@chromium.org <joaodasilva@chromium.org@7262f16d-afe8-6277-6482-052fa10e57b1>2013-06-10 08:22:38 +0000
committerjoaodasilva@chromium.org <joaodasilva@chromium.org@7262f16d-afe8-6277-6482-052fa10e57b1>2013-06-10 08:22:38 +0000
commit006588227ffb5ff646051dcb4f04198edcf038c9 (patch)
treecb20009486d620e3712582edc5279d55f27d9f30
parentabf31db73d7f62930be9d3d9b7f5b2b360378821 (diff)
downloadgrit-006588227ffb5ff646051dcb4f04198edcf038c9.tar.gz
GRIT: Enable variable expansion in filenames during HTML inlining.
BUG=232048 R=flackr@chromium.org Review URL: https://codereview.chromium.org/16539002 git-svn-id: http://grit-i18n.googlecode.com/svn/trunk@125 7262f16d-afe8-6277-6482-052fa10e57b1
-rwxr-xr-xgrit/format/html_inline.py55
-rwxr-xr-xgrit/format/html_inline_unittest.py60
-rw-r--r--grit/gather/chrome_html.py60
-rw-r--r--grit/gather/chrome_html_unittest.py57
-rw-r--r--grit/gather/interface.py4
-rw-r--r--grit/node/structure.py6
-rw-r--r--grit/node/structure_unittest.py11
-rw-r--r--grit/testdata/structure_variables.html1
8 files changed, 216 insertions, 38 deletions
diff --git a/grit/format/html_inline.py b/grit/format/html_inline.py
index 569c282..b5e0b0f 100755
--- a/grit/format/html_inline.py
+++ b/grit/format/html_inline.py
@@ -72,7 +72,8 @@ def GetDistribution():
def SrcInlineAsDataURL(
- src_match, base_path, distribution, inlined_files, names_only=False):
+ src_match, base_path, distribution, inlined_files, names_only=False,
+ filename_expansion_function=None):
"""regex replace function.
Takes a regex match for src="filename", attempts to read the file
@@ -93,6 +94,8 @@ def SrcInlineAsDataURL(
string
"""
filename = src_match.group('filename')
+ if filename_expansion_function:
+ filename = filename_expansion_function(filename)
quote = src_match.group('quote')
if filename.find(':') != -1:
@@ -126,7 +129,7 @@ class InlinedData:
def DoInline(
input_filename, grd_node, allow_external_script=False, names_only=False,
- rewrite_function=None):
+ rewrite_function=None, filename_expansion_function=None):
"""Helper function that inlines the resources in a specified file.
Reads input_filename, finds all the src attributes and attempts to
@@ -139,10 +142,14 @@ def DoInline(
names_only: |nil| will be returned for the inlined contents (faster).
rewrite_function: function(filepath, text, distribution) which will be
called to rewrite html content before inlining images.
+ filename_expansion_function: function(filename) which will be called to
+ rewrite filenames before attempting to read them.
Returns:
a tuple of the inlined data as a string and the set of filenames
of all the inlined files
"""
+ if filename_expansion_function:
+ input_filename = filename_expansion_function(input_filename)
input_filepath = os.path.dirname(input_filename)
distribution = GetDistribution()
@@ -153,7 +160,8 @@ def DoInline(
inlined_files=inlined_files):
"""Helper function to provide SrcInlineAsDataURL with the base file path"""
return SrcInlineAsDataURL(
- src_match, filepath, distribution, inlined_files, names_only=names_only)
+ src_match, filepath, distribution, inlined_files, names_only=names_only,
+ filename_expansion_function=filename_expansion_function)
def GetFilepath(src_match, base_path = input_filepath):
filename = src_match.group('filename')
@@ -163,6 +171,8 @@ def DoInline(
return None
filename = filename.replace('%DISTRIBUTION%', distribution)
+ if filename_expansion_function:
+ filename = filename_expansion_function(filename)
return os.path.normpath(os.path.join(base_path, filename))
def IsConditionSatisfied(src_match):
@@ -214,12 +224,16 @@ def DoInline(
inlined_files.add(filepath)
if names_only:
- inlined_files.update(GetResourceFilenames(filepath,
- allow_external_script,
- rewrite_function))
+ inlined_files.update(GetResourceFilenames(
+ filepath,
+ allow_external_script,
+ rewrite_function,
+ filename_expansion_function=filename_expansion_function))
return ""
- return pattern % InlineToString(filepath, grd_node, allow_external_script)
+ return pattern % InlineToString(
+ filepath, grd_node, allow_external_script,
+ filename_expansion_function=filename_expansion_function)
def InlineIncludeFiles(src_match):
"""Helper function to directly inline generic external files (without
@@ -338,7 +352,7 @@ def DoInline(
def InlineToString(input_filename, grd_node, allow_external_script=False,
- rewrite_function=None):
+ rewrite_function=None, filename_expansion_function=None):
"""Inlines the resources in a specified file and returns it as a string.
Args:
@@ -348,10 +362,12 @@ def InlineToString(input_filename, grd_node, allow_external_script=False,
the inlined data as a string
"""
try:
- return DoInline(input_filename,
- grd_node,
- allow_external_script=allow_external_script,
- rewrite_function=rewrite_function).inlined_data
+ return DoInline(
+ input_filename,
+ grd_node,
+ allow_external_script=allow_external_script,
+ rewrite_function=rewrite_function,
+ filename_expansion_function=filename_expansion_function).inlined_data
except IOError, e:
raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
(e.filename, input_filename, e.strerror))
@@ -378,14 +394,17 @@ def InlineToFile(input_filename, output_filename, grd_node):
def GetResourceFilenames(filename,
allow_external_script=False,
- rewrite_function=None):
+ rewrite_function=None,
+ filename_expansion_function=None):
"""For a grd file, returns a set of all the files that would be inline."""
try:
- return DoInline(filename,
- None,
- names_only=True,
- allow_external_script=allow_external_script,
- rewrite_function=rewrite_function).inlined_files
+ return DoInline(
+ filename,
+ None,
+ names_only=True,
+ allow_external_script=allow_external_script,
+ rewrite_function=rewrite_function,
+ filename_expansion_function=filename_expansion_function).inlined_files
except IOError, e:
raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
(e.filename, filename, e.strerror))
diff --git a/grit/format/html_inline_unittest.py b/grit/format/html_inline_unittest.py
index 7d546a5..45840f2 100755
--- a/grit/format/html_inline_unittest.py
+++ b/grit/format/html_inline_unittest.py
@@ -202,6 +202,66 @@ class HtmlInlineUnittest(unittest.TestCase):
self.failUnlessEqual(expected_inlined,
util.FixLineEnd(result.inlined_data, '\n'))
+ def testFilenameVariableExpansion(self):
+ '''Tests that variables are expanded in filenames before inlining.'''
+
+ files = {
+ 'index.html': '''
+ <html>
+ <head>
+ <link rel="stylesheet" href="style[WHICH].css">
+ <script src="script[WHICH].js"></script>
+ </head>
+ <include src="tmpl[WHICH].html">
+ <img src="img[WHICH].png">
+ </html>
+ ''',
+ 'style1.css': '''h1 {}''',
+ 'tmpl1.html': '''<h1></h1>''',
+ 'script1.js': '''console.log('hello');''',
+ 'img1.png': '''abc''',
+ }
+
+ expected_inlined = '''
+ <html>
+ <head>
+ <style>h1 {}</style>
+ <script>console.log('hello');</script>
+ </head>
+ <h1></h1>
+ <img src="data:image/png;base64,YWJj">
+ </html>
+ '''
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ def replacer(var, repl):
+ return lambda filename: filename.replace('[%s]' % var, repl)
+
+ # Test normal inlining.
+ result = html_inline.DoInline(
+ tmp_dir.GetPath('index.html'),
+ None,
+ filename_expansion_function=replacer('WHICH', '1'))
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+ self.failUnlessEqual(expected_inlined,
+ util.FixLineEnd(result.inlined_data, '\n'))
+
+ # Test names-only inlining.
+ result = html_inline.DoInline(
+ tmp_dir.GetPath('index.html'),
+ None,
+ names_only=True,
+ filename_expansion_function=replacer('WHICH', '1'))
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+
if __name__ == '__main__':
unittest.main()
diff --git a/grit/gather/chrome_html.py b/grit/gather/chrome_html.py
index d5a2b07..d554776 100644
--- a/grit/gather/chrome_html.py
+++ b/grit/gather/chrome_html.py
@@ -48,7 +48,8 @@ _HTML_IMAGE_SRC = lazy_re.compile(
'<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>')
def GetImageList(
- base_path, filename, scale_factors, distribution):
+ base_path, filename, scale_factors, distribution,
+ filename_expansion_function=None):
"""Generate the list of images which match the provided scale factors.
Takes an image filename and checks for files of the same name in folders
@@ -79,6 +80,8 @@ def GetImageList(
return [('1x', filename)]
filename = filename.replace(DIST_SUBSTR, distribution)
+ if filename_expansion_function:
+ filename = filename_expansion_function(filename)
filepath = os.path.join(base_path, filename)
images = [('1x', filename)]
@@ -114,7 +117,8 @@ def GenerateImageSet(images, quote):
def InsertImageSet(
- src_match, base_path, scale_factors, distribution):
+ src_match, base_path, scale_factors, distribution,
+ filename_expansion_function=None):
"""Regex replace function which inserts -webkit-image-set.
Takes a regex match for url('path'). If the file is local, checks for
@@ -136,7 +140,9 @@ def InsertImageSet(
quote = src_match.group('quote')
filename = src_match.group('filename')
attr = src_match.group('attribute')
- image_list = GetImageList(base_path, filename, scale_factors, distribution)
+ image_list = GetImageList(
+ base_path, filename, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function)
# Don't modify the source if there is only one image.
if len(image_list) == 1:
@@ -146,14 +152,17 @@ def InsertImageSet(
def InsertImageStyle(
- src_match, base_path, scale_factors, distribution):
+ src_match, base_path, scale_factors, distribution,
+ filename_expansion_function=None):
"""Regex replace function which adds a content style to an <img>.
Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS
style which defines the image set.
"""
filename = src_match.group('filename')
- image_list = GetImageList(base_path, filename, scale_factors, distribution)
+ image_list = GetImageList(
+ base_path, filename, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function)
# Don't modify the source if there is only one image or image already defines
# a style.
@@ -165,16 +174,21 @@ def InsertImageStyle(
def InsertImageSets(
- filepath, text, scale_factors, distribution):
+ filepath, text, scale_factors, distribution,
+ filename_expansion_function=None):
"""Helper function that adds references to external images available in any of
scale_factors in CSS backgrounds.
"""
# Add high DPI urls for css attributes: content, background,
# or *-image or <img src="foo">.
return _CSS_IMAGE_URLS.sub(
- lambda m: InsertImageSet(m, filepath, scale_factors, distribution),
+ lambda m: InsertImageSet(
+ m, filepath, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function),
_HTML_IMAGE_SRC.sub(
- lambda m: InsertImageStyle(m, filepath, scale_factors, distribution),
+ lambda m: InsertImageStyle(
+ m, filepath, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function),
text)).decode('utf-8').encode('utf-8')
@@ -208,17 +222,20 @@ def RemoveImageSetImages(text, scale_factors):
def ProcessImageSets(
- filepath, text, scale_factors, distribution):
+ filepath, text, scale_factors, distribution,
+ filename_expansion_function=None):
"""Helper function that adds references to external images available in other
scale_factors and removes images from image-sets in unsupported scale_factors.
"""
# Explicitly add 1x to supported scale factors so that it is not removed.
supported_scale_factors = ['1x']
supported_scale_factors.extend(scale_factors)
- return InsertImageSets(filepath,
- RemoveImageSetImages(text, supported_scale_factors),
- scale_factors,
- distribution)
+ return InsertImageSets(
+ filepath,
+ RemoveImageSetImages(text, supported_scale_factors),
+ scale_factors,
+ distribution,
+ filename_expansion_function=filename_expansion_function)
class ChromeHtml(interface.GathererBase):
@@ -238,6 +255,7 @@ class ChromeHtml(interface.GathererBase):
# 1x resources are implicitly already in the source and do not need to be
# added.
self.scale_factors_ = []
+ self.filename_expansion_function = None
def SetAttributes(self, attrs):
self.allow_external_script_ = ('allowexternalscript' in attrs and
@@ -267,7 +285,9 @@ class ChromeHtml(interface.GathererBase):
self.grd_node.ToRealPath(self.GetInputPath()),
allow_external_script=self.allow_external_script_,
rewrite_function=lambda fp, t, d: ProcessImageSets(
- fp, t, self.scale_factors_, d))
+ fp, t, self.scale_factors_, d,
+ filename_expansion_function=self.filename_expansion_function),
+ filename_expansion_function=self.filename_expansion_function)
return []
def Translate(self, lang, pseudo_if_not_available=True,
@@ -275,10 +295,15 @@ class ChromeHtml(interface.GathererBase):
"""Returns this document translated."""
return self.inlined_text_
+ def SetFilenameExpansionFunction(self, fn):
+ self.filename_expansion_function = fn
+
def Parse(self):
"""Parses and inlines the represented file."""
filename = self.GetInputPath()
+ if self.filename_expansion_function:
+ filename = self.filename_expansion_function(filename)
# Hack: some unit tests supply an absolute path and no root node.
if not os.path.isabs(filename):
filename = self.grd_node.ToRealPath(filename)
@@ -288,11 +313,14 @@ class ChromeHtml(interface.GathererBase):
self.grd_node,
allow_external_script = self.allow_external_script_,
rewrite_function=lambda fp, t, d: ProcessImageSets(
- fp, t, self.scale_factors_, d))
+ fp, t, self.scale_factors_, d,
+ filename_expansion_function=self.filename_expansion_function),
+ filename_expansion_function=self.filename_expansion_function)
else:
distribution = html_inline.GetDistribution()
self.inlined_text_ = ProcessImageSets(
os.path.dirname(filename),
util.ReadFile(filename, 'utf-8'),
self.scale_factors_,
- distribution)
+ distribution,
+ filename_expansion_function=self.filename_expansion_function)
diff --git a/grit/gather/chrome_html_unittest.py b/grit/gather/chrome_html_unittest.py
index 7d0b702..8f636ff 100644
--- a/grit/gather/chrome_html_unittest.py
+++ b/grit/gather/chrome_html_unittest.py
@@ -345,5 +345,62 @@ class ChromeHtmlUnittest(unittest.TestCase):
'''))
tmp_dir.CleanUp()
+ def testExpandVariablesInFilename(self):
+ '''
+ Tests variable substitution in filenames while flattening images
+ with multiple scale factors.
+ '''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: url('test[WHICH].png');
+ }
+ ''',
+
+ 'test1.png': 'PNG DATA',
+ '1.4x/test1.png': '1.4x PNG DATA',
+ '1.8x/test1.png': '1.8x PNG DATA',
+ })
+
+ def replacer(var, repl):
+ return lambda filename: filename.replace('[%s]' % var, repl)
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.SetFilenameExpansionFunction(replacer('WHICH', '1'));
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <style>
+ .image {
+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/grit/gather/interface.py b/grit/gather/interface.py
index 084392a..c277d37 100644
--- a/grit/gather/interface.py
+++ b/grit/gather/interface.py
@@ -152,6 +152,10 @@ class GathererBase(object):
'''
pass
+ def SetFilenameExpansionFunction(self, fn):
+ '''Sets a function for rewriting filenames before gathering.'''
+ pass
+
# TODO(benrg): Move this elsewhere, since it isn't part of the interface.
def _LoadInputFile(self):
'''A convenience function for subclasses that loads the contents of the
diff --git a/grit/node/structure.py b/grit/node/structure.py
index 99f2014..48968f6 100644
--- a/grit/node/structure.py
+++ b/grit/node/structure.py
@@ -93,6 +93,8 @@ class StructureNode(base.Node):
if hasattr(self.GetRoot(), 'defines'):
self.gatherer.SetDefines(self.GetRoot().defines)
self.gatherer.SetAttributes(self.attrs)
+ if self.ExpandVariables():
+ self.gatherer.SetFilenameExpansionFunction(self._Substitute)
# Parse local variables and instantiate the substituter.
if self.attrs['variables']:
@@ -109,6 +111,10 @@ class StructureNode(base.Node):
is_skeleton=True)
skel.SetGrdNode(self) # TODO(benrg): Or child? Only used for ToRealPath
skel.SetUberClique(self.UberClique())
+ if hasattr(self.GetRoot(), 'defines'):
+ skel.SetDefines(self.GetRoot().defines)
+ if self.ExpandVariables():
+ skel.SetFilenameExpansionFunction(self._Substitute)
self.skeletons[child.attrs['expr']] = skel
def MandatoryAttributes(self):
diff --git a/grit/node/structure_unittest.py b/grit/node/structure_unittest.py
index c07c2bc..a039bce 100644
--- a/grit/node/structure_unittest.py
+++ b/grit/node/structure_unittest.py
@@ -49,7 +49,7 @@ class StructureUnittest(unittest.TestCase):
def testVariables(self):
grd = util.ParseGrdForUnittest('''
<structures>
- <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4"></structure>
+ <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true"></structure>
</structures>''', base_dir=util.PathFromRoot('grit/testdata'))
grd.SetOutputLanguage('en')
grd.RunGatherers()
@@ -57,9 +57,12 @@ class StructureUnittest(unittest.TestCase):
filename = node.Process(tempfile.gettempdir())
with open(os.path.join(tempfile.gettempdir(), filename)) as f:
result = f.read()
- self.failUnless(result == ('<h1>Hello!</h1>\n'
- 'Some cool things are foo, bar, baz.\n'
- 'Did you know that 2+2==4?\n'))
+ self.failUnlessEqual(('<h1>Hello!</h1>\n'
+ 'Some cool things are foo, bar, baz.\n'
+ 'Did you know that 2+2==4?\n'
+ '<p>\n'
+ ' Hello!\n'
+ '</p>\n'), result)
if __name__ == '__main__':
diff --git a/grit/testdata/structure_variables.html b/grit/testdata/structure_variables.html
index c90bfc9..2a15de8 100644
--- a/grit/testdata/structure_variables.html
+++ b/grit/testdata/structure_variables.html
@@ -1,3 +1,4 @@
<h1>[GREETING]!</h1>
Some cool things are [THINGS].
Did you know that [EQUATION]?
+<include src="[filename].html">