| 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. |
| 11 """ | 11 """ |
| 12 | 12 |
| 13 import os | 13 import os |
| 14 import re | 14 import re |
| 15 import sys | 15 import sys |
| 16 import base64 | 16 import base64 |
| 17 import mimetypes | 17 import mimetypes |
| 18 | 18 |
| 19 from grit import lazy_re | 19 from grit import lazy_re |
| 20 from grit import util | 20 from grit import util |
| 21 | 21 |
| 22 # There is a python bug that makes mimetypes crash if the Windows | 22 # There is a python bug that makes mimetypes crash if the Windows |
| 23 # registry contains non-Latin keys ( http://bugs.python.org/issue9291 | 23 # registry contains non-Latin keys ( http://bugs.python.org/issue9291 |
| 24 # ). Initing manually and blocking external mime-type databases will | 24 # ). Initing manually and blocking external mime-type databases will |
| 25 # prevent that bug and still give us the data we need. | 25 # prevent that bug and if we add svg manually, it will still give us |
| 26 # the data we need. |
| 26 mimetypes.init([]) | 27 mimetypes.init([]) |
| 28 mimetypes.add_type('image/svg+xml', '.svg') |
| 27 | 29 |
| 28 DIST_DEFAULT = 'chromium' | 30 DIST_DEFAULT = 'chromium' |
| 29 DIST_ENV_VAR = 'CHROMIUM_BUILD' | 31 DIST_ENV_VAR = 'CHROMIUM_BUILD' |
| 30 DIST_SUBSTR = '%DISTRIBUTION%' | 32 DIST_SUBSTR = '%DISTRIBUTION%' |
| 31 | 33 |
| 32 # Matches beginning of an "if" block with trailing spaces. | 34 # Matches beginning of an "if" block with trailing spaces. |
| 33 _BEGIN_IF_BLOCK = lazy_re.compile( | 35 _BEGIN_IF_BLOCK = lazy_re.compile( |
| 34 '<if [^>]*?expr="(?P<expression>[^"]*)"[^>]*?>\s*') | 36 '<if [^>]*?expr="(?P<expression>[^"]*)"[^>]*?>\s*') |
| 35 | 37 |
| 36 # Matches ending of an "if" block with preceding spaces. | 38 # Matches ending of an "if" block with preceding spaces. |
| 37 _END_IF_BLOCK = lazy_re.compile('\s*</if>') | 39 _END_IF_BLOCK = lazy_re.compile('\s*</if>') |
| 38 | 40 |
| 39 # Used by DoInline to replace various links with inline content. | 41 # Used by DoInline to replace various links with inline content. |
| 40 _STYLESHEET_RE = lazy_re.compile( | 42 _STYLESHEET_RE = lazy_re.compile( |
| 41 '<link rel="stylesheet"[^>]+?href="(?P<filename>[^"]*)".*?>(\s*</link>)?', | 43 '<link rel="stylesheet"[^>]+?href="(?P<filename>[^"]*)".*?>(\s*</link>)?', |
| 42 re.DOTALL) | 44 re.DOTALL) |
| 43 _INCLUDE_RE = lazy_re.compile( | 45 _INCLUDE_RE = lazy_re.compile( |
| 44 '<include[^>]+?src="(?P<filename>[^"\']*)".*?>(\s*</include>)?', | 46 '<include[^>]+?src="(?P<filename>[^"\']*)".*?>(\s*</include>)?', |
| 45 re.DOTALL) | 47 re.DOTALL) |
| 46 _SRC_RE = lazy_re.compile( | 48 _SRC_RE = lazy_re.compile( |
| 47 r'<(?!script)(?:[^>]+?\s)src=(?P<quote>")(?P<filename>[^"\']*)\1', | 49 r'<(?!script)(?:[^>]+?\s)src=(?P<quote>")(?P<filename>[^"\']*)\1', |
| 48 re.MULTILINE) | 50 re.MULTILINE) |
| 49 _ICON_RE = lazy_re.compile( | 51 _ICON_RE = lazy_re.compile( |
| 50 r'<link rel="icon"\s(?:[^>]+?\s)?' | 52 r'<link rel="icon"\s(?:[^>]+?\s)?' |
| 51 'href=(?P<quote>")(?P<filename>[^"\']*)\1', | 53 'href=(?P<quote>")(?P<filename>[^"\']*)\1', |
| 52 re.MULTILINE) | 54 re.MULTILINE) |
| 53 | 55 |
| 54 | 56 |
| 55 | |
| 56 def FixupMimeType(mime_type): | |
| 57 """Helper function that normalizes platform differences in the mime type | |
| 58 returned by the Python's mimetypes.guess_type API. | |
| 59 """ | |
| 60 mappings = { | |
| 61 'image/x-png': 'image/png' | |
| 62 } | |
| 63 return mappings[mime_type] if mime_type in mappings else mime_type | |
| 64 | |
| 65 | |
| 66 def GetDistribution(): | 57 def GetDistribution(): |
| 67 """Helper function that gets the distribution we are building. | 58 """Helper function that gets the distribution we are building. |
| 68 | 59 |
| 69 Returns: | 60 Returns: |
| 70 string | 61 string |
| 71 """ | 62 """ |
| 72 distribution = DIST_DEFAULT | 63 distribution = DIST_DEFAULT |
| 73 if DIST_ENV_VAR in os.environ.keys(): | 64 if DIST_ENV_VAR in os.environ.keys(): |
| 74 distribution = os.environ[DIST_ENV_VAR] | 65 distribution = os.environ[DIST_ENV_VAR] |
| 75 if len(distribution) > 1 and distribution[0] == '_': | 66 if len(distribution) > 1 and distribution[0] == '_': |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 # filename is probably a URL, which we don't want to bother inlining | 99 # filename is probably a URL, which we don't want to bother inlining |
| 109 return src_match.group(0) | 100 return src_match.group(0) |
| 110 | 101 |
| 111 filename = filename.replace(DIST_SUBSTR , distribution) | 102 filename = filename.replace(DIST_SUBSTR , distribution) |
| 112 filepath = os.path.normpath(os.path.join(base_path, filename)) | 103 filepath = os.path.normpath(os.path.join(base_path, filename)) |
| 113 inlined_files.add(filepath) | 104 inlined_files.add(filepath) |
| 114 | 105 |
| 115 if names_only: | 106 if names_only: |
| 116 return "" | 107 return "" |
| 117 | 108 |
| 118 mimetype = FixupMimeType(mimetypes.guess_type(filename)[0]) or 'text/plain' | 109 mimetype = mimetypes.guess_type(filename)[0] |
| 110 if mimetype is None: |
| 111 raise Exception('%s is of an an unknown type and ' |
| 112 'cannot be stored in a data url.' % filename) |
| 119 inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY)) | 113 inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY)) |
| 120 | 114 |
| 121 prefix = src_match.string[src_match.start():src_match.start('filename')] | 115 prefix = src_match.string[src_match.start():src_match.start('filename')] |
| 122 suffix = src_match.string[src_match.end('filename'):src_match.end()] | 116 suffix = src_match.string[src_match.end('filename'):src_match.end()] |
| 123 return '%sdata:%s;base64,%s%s' % (prefix, mimetype, inline_data, suffix) | 117 return '%sdata:%s;base64,%s%s' % (prefix, mimetype, inline_data, suffix) |
| 124 | 118 |
| 125 | 119 |
| 126 class InlinedData: | 120 class InlinedData: |
| 127 """Helper class holding the results from DoInline(). | 121 """Helper class holding the results from DoInline(). |
| 128 | 122 |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 | 412 |
| 419 def main(): | 413 def main(): |
| 420 if len(sys.argv) <= 2: | 414 if len(sys.argv) <= 2: |
| 421 print "Flattens a HTML file by inlining its external resources.\n" | 415 print "Flattens a HTML file by inlining its external resources.\n" |
| 422 print "html_inline.py inputfile outputfile" | 416 print "html_inline.py inputfile outputfile" |
| 423 else: | 417 else: |
| 424 InlineToFile(sys.argv[1], sys.argv[2], None) | 418 InlineToFile(sys.argv[1], sys.argv[2], None) |
| 425 | 419 |
| 426 if __name__ == '__main__': | 420 if __name__ == '__main__': |
| 427 main() | 421 main() |
| OLD | NEW |