| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Flattens a HTML file by inlining its external resources. | 6 """Flattens a HTML file by inlining its external resources. |
| 7 | 7 |
| 8 This is a small script that takes a HTML file, looks for src attributes | 8 This is a small script that takes a HTML file, looks for src attributes |
| 9 and inlines the specified file, producing one HTML file with no external | 9 and inlines the specified file, producing one HTML file with no external |
| 10 dependencies. It recursively inlines the included files. | 10 dependencies. It recursively inlines the included files. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 filename = filename.replace(DIST_SUBSTR , distribution) | 74 filename = filename.replace(DIST_SUBSTR , distribution) |
| 75 filepath = os.path.join(base_path, filename) | 75 filepath = os.path.join(base_path, filename) |
| 76 inlined_files.add(filepath) | 76 inlined_files.add(filepath) |
| 77 | 77 |
| 78 if names_only: | 78 if names_only: |
| 79 return "" | 79 return "" |
| 80 | 80 |
| 81 mimetype = mimetypes.guess_type(filename)[0] or 'text/plain' | 81 mimetype = mimetypes.guess_type(filename)[0] or 'text/plain' |
| 82 inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY)) | 82 inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY)) |
| 83 | 83 |
| 84 prefix = src_match.string[src_match.start():src_match.start('filename')-1] | 84 prefix = src_match.string[src_match.start():src_match.start('filename')] |
| 85 return "%s\"data:%s;base64,%s\"" % (prefix, mimetype, inline_data) | 85 suffix = src_match.string[src_match.end('filename'):src_match.end()] |
| 86 if prefix and prefix[-1] in '\'"': |
| 87 prefix = prefix[:-1] |
| 88 if suffix and suffix[0] in '\'"': |
| 89 suffix = suffix[1:] |
| 90 return '%s"data:%s;base64,%s"%s' % (prefix, mimetype, inline_data, suffix) |
| 86 | 91 |
| 87 | 92 |
| 88 class InlinedData: | 93 class InlinedData: |
| 89 """Helper class holding the results from DoInline(). | 94 """Helper class holding the results from DoInline(). |
| 90 | 95 |
| 91 Holds the inlined data and the set of filenames of all the inlined | 96 Holds the inlined data and the set of filenames of all the inlined |
| 92 files. | 97 files. |
| 93 """ | 98 """ |
| 94 def __init__(self, inlined_data, inlined_files): | 99 def __init__(self, inlined_data, inlined_files): |
| 95 self.inlined_data = inlined_data | 100 self.inlined_data = inlined_data |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 inlined_files.add(filepath) | 235 inlined_files.add(filepath) |
| 231 # When resolving CSS files we need to pass in the path so that relative URLs | 236 # When resolving CSS files we need to pass in the path so that relative URLs |
| 232 # can be resolved. | 237 # can be resolved. |
| 233 return '<style>%s</style>' % InlineCSSText( | 238 return '<style>%s</style>' % InlineCSSText( |
| 234 util.ReadFile(filepath, util.BINARY), filepath) | 239 util.ReadFile(filepath, util.BINARY), filepath) |
| 235 | 240 |
| 236 def InlineCSSImages(text, filepath=input_filepath): | 241 def InlineCSSImages(text, filepath=input_filepath): |
| 237 """Helper function that inlines external images in CSS backgrounds.""" | 242 """Helper function that inlines external images in CSS backgrounds.""" |
| 238 # Replace contents of url() for css attributes: content, background, | 243 # Replace contents of url() for css attributes: content, background, |
| 239 # or *-image. | 244 # or *-image. |
| 240 return re.sub('(?:content|background|[\w-]*-image):[^;]*' + | 245 return re.sub('(content|background|[\w-]*-image):[^;]*' + |
| 241 '(?:url\((?:\'|\")([^"\'\)\(]*)(?:\'|\")\)|' + | 246 '(url\((?P<quote1>"|\'|)[^"\'()]*(?P=quote1)\)|' + |
| 242 'image-set\(' + | 247 'image-set\(' + |
| 243 '([ ]*url\((?:\'|\")([^"\'\)\(]*)(?:\'|\")\)' + | 248 '([ ]*url\((?P<quote2>"|\'|)[^"\'()]*(?P=quote2)\)' + |
| 244 '[ ]*[0-9.]*x[ ]*(,[ ]*)?)*\))', | 249 '[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\))', |
| 245 lambda m: InlineCSSUrls(m, filepath), | 250 lambda m: InlineCSSUrls(m, filepath), |
| 246 text) | 251 text) |
| 247 | 252 |
| 248 def InlineCSSUrls(src_match, filepath=input_filepath): | 253 def InlineCSSUrls(src_match, filepath=input_filepath): |
| 249 """Helper function that inlines each url on a CSS image rule match.""" | 254 """Helper function that inlines each url on a CSS image rule match.""" |
| 250 # Replace contents of url() references in matches. | 255 # Replace contents of url() references in matches. |
| 251 return re.sub('url\((?:\'|\")(?P<filename>[^"\'\)\(]*)(?:\'|\")', | 256 return re.sub('url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)', |
| 252 lambda m: SrcReplace(m, filepath), | 257 lambda m: SrcReplace(m, filepath), |
| 253 src_match.group(0)) | 258 src_match.group(0)) |
| 254 | 259 |
| 255 | 260 |
| 256 | 261 |
| 257 flat_text = util.ReadFile(input_filename, util.BINARY) | 262 flat_text = util.ReadFile(input_filename, util.BINARY) |
| 258 | 263 |
| 259 if not allow_external_script: | 264 if not allow_external_script: |
| 260 # We need to inline css and js before we inline images so that image | 265 # We need to inline css and js before we inline images so that image |
| 261 # references gets inlined in the css and js | 266 # references gets inlined in the css and js |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 | 358 |
| 354 def main(): | 359 def main(): |
| 355 if len(sys.argv) <= 2: | 360 if len(sys.argv) <= 2: |
| 356 print "Flattens a HTML file by inlining its external resources.\n" | 361 print "Flattens a HTML file by inlining its external resources.\n" |
| 357 print "html_inline.py inputfile outputfile" | 362 print "html_inline.py inputfile outputfile" |
| 358 else: | 363 else: |
| 359 InlineToFile(sys.argv[1], sys.argv[2], None) | 364 InlineToFile(sys.argv[1], sys.argv[2], None) |
| 360 | 365 |
| 361 if __name__ == '__main__': | 366 if __name__ == '__main__': |
| 362 main() | 367 main() |
| OLD | NEW |