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 """Prepares a Chrome HTML file by inlining resources and adding references to | 6 """Prepares a Chrome HTML file by inlining resources and adding references to |
7 high DPI resources and removing references to unsupported scale factors. | 7 high DPI resources and removing references to unsupported scale factors. |
8 | 8 |
9 This is a small gatherer that takes a HTML file, looks for src attributes | 9 This is a small gatherer that takes a HTML file, looks for src attributes |
10 and inlines the specified file, producing one HTML file with no external | 10 and inlines the specified file, producing one HTML file with no external |
(...skipping 30 matching lines...) Expand all Loading... |
41 '([,\r\n ]*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)', | 41 '([,\r\n ]*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)', |
42 re.MULTILINE) | 42 re.MULTILINE) |
43 # Matches a single image in a CSS image set with the capture group scale. | 43 # Matches a single image in a CSS image set with the capture group scale. |
44 _CSS_IMAGE_SET_IMAGE = lazy_re.compile('[,\r\n ]*' + | 44 _CSS_IMAGE_SET_IMAGE = lazy_re.compile('[,\r\n ]*' + |
45 'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)', | 45 'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)', |
46 re.MULTILINE) | 46 re.MULTILINE) |
47 _HTML_IMAGE_SRC = lazy_re.compile( | 47 _HTML_IMAGE_SRC = lazy_re.compile( |
48 '<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>') | 48 '<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>') |
49 | 49 |
50 def GetImageList( | 50 def GetImageList( |
51 base_path, filename, scale_factors, distribution): | 51 base_path, filename, scale_factors, distribution, |
| 52 filename_expansion_function=None): |
52 """Generate the list of images which match the provided scale factors. | 53 """Generate the list of images which match the provided scale factors. |
53 | 54 |
54 Takes an image filename and checks for files of the same name in folders | 55 Takes an image filename and checks for files of the same name in folders |
55 corresponding to the supported scale factors. If the file is from a | 56 corresponding to the supported scale factors. If the file is from a |
56 chrome://theme/ source, inserts supported @Nx scale factors as high DPI | 57 chrome://theme/ source, inserts supported @Nx scale factors as high DPI |
57 versions. | 58 versions. |
58 | 59 |
59 Args: | 60 Args: |
60 base_path: path to look for relative file paths in | 61 base_path: path to look for relative file paths in |
61 filename: name of the base image file | 62 filename: name of the base image file |
(...skipping 10 matching lines...) Expand all Loading... |
72 images = [('1x', filename)] | 73 images = [('1x', filename)] |
73 for scale_factor in scale_factors: | 74 for scale_factor in scale_factors: |
74 images.append((scale_factor, "%s@%s" % (filename, scale_factor))) | 75 images.append((scale_factor, "%s@%s" % (filename, scale_factor))) |
75 return images | 76 return images |
76 | 77 |
77 if filename.find(':') != -1: | 78 if filename.find(':') != -1: |
78 # filename is probably a URL, only return filename itself. | 79 # filename is probably a URL, only return filename itself. |
79 return [('1x', filename)] | 80 return [('1x', filename)] |
80 | 81 |
81 filename = filename.replace(DIST_SUBSTR, distribution) | 82 filename = filename.replace(DIST_SUBSTR, distribution) |
| 83 if filename_expansion_function: |
| 84 filename = filename_expansion_function(filename) |
82 filepath = os.path.join(base_path, filename) | 85 filepath = os.path.join(base_path, filename) |
83 images = [('1x', filename)] | 86 images = [('1x', filename)] |
84 | 87 |
85 for scale_factor in scale_factors: | 88 for scale_factor in scale_factors: |
86 # Check for existence of file and add to image set. | 89 # Check for existence of file and add to image set. |
87 scale_path = os.path.split(os.path.join(base_path, filename)) | 90 scale_path = os.path.split(os.path.join(base_path, filename)) |
88 scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1]) | 91 scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1]) |
89 if os.path.isfile(scale_image_path): | 92 if os.path.isfile(scale_image_path): |
90 # HTML/CSS always uses forward slashed paths. | 93 # HTML/CSS always uses forward slashed paths. |
91 scale_image_name = re.sub('(?P<path>(.*/)?)(?P<file>[^/]*)', | 94 scale_image_name = re.sub('(?P<path>(.*/)?)(?P<file>[^/]*)', |
(...skipping 15 matching lines...) Expand all Loading... |
107 string giving a -webkit-image-set rule referencing the provided images. | 110 string giving a -webkit-image-set rule referencing the provided images. |
108 (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)') | 111 (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)') |
109 """ | 112 """ |
110 imageset = [] | 113 imageset = [] |
111 for (scale_factor, filename) in images: | 114 for (scale_factor, filename) in images: |
112 imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor)) | 115 imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor)) |
113 return "-webkit-image-set(%s)" % (', '.join(imageset)) | 116 return "-webkit-image-set(%s)" % (', '.join(imageset)) |
114 | 117 |
115 | 118 |
116 def InsertImageSet( | 119 def InsertImageSet( |
117 src_match, base_path, scale_factors, distribution): | 120 src_match, base_path, scale_factors, distribution, |
| 121 filename_expansion_function=None): |
118 """Regex replace function which inserts -webkit-image-set. | 122 """Regex replace function which inserts -webkit-image-set. |
119 | 123 |
120 Takes a regex match for url('path'). If the file is local, checks for | 124 Takes a regex match for url('path'). If the file is local, checks for |
121 files of the same name in folders corresponding to the supported scale | 125 files of the same name in folders corresponding to the supported scale |
122 factors. If the file is from a chrome://theme/ source, inserts the | 126 factors. If the file is from a chrome://theme/ source, inserts the |
123 supported @Nx scale factor request. In either case inserts a | 127 supported @Nx scale factor request. In either case inserts a |
124 -webkit-image-set rule to fetch the appropriate image for the current | 128 -webkit-image-set rule to fetch the appropriate image for the current |
125 scale factor. | 129 scale factor. |
126 | 130 |
127 Args: | 131 Args: |
128 src_match: regex match object from _CSS_IMAGE_URLS | 132 src_match: regex match object from _CSS_IMAGE_URLS |
129 base_path: path to look for relative file paths in | 133 base_path: path to look for relative file paths in |
130 scale_factors: a list of the supported scale factors (i.e. ['2x']) | 134 scale_factors: a list of the supported scale factors (i.e. ['2x']) |
131 distribution: string that should replace %DISTRIBUTION%. | 135 distribution: string that should replace %DISTRIBUTION%. |
132 | 136 |
133 Returns: | 137 Returns: |
134 string | 138 string |
135 """ | 139 """ |
136 quote = src_match.group('quote') | 140 quote = src_match.group('quote') |
137 filename = src_match.group('filename') | 141 filename = src_match.group('filename') |
138 attr = src_match.group('attribute') | 142 attr = src_match.group('attribute') |
139 image_list = GetImageList(base_path, filename, scale_factors, distribution) | 143 image_list = GetImageList( |
| 144 base_path, filename, scale_factors, distribution, |
| 145 filename_expansion_function=filename_expansion_function) |
140 | 146 |
141 # Don't modify the source if there is only one image. | 147 # Don't modify the source if there is only one image. |
142 if len(image_list) == 1: | 148 if len(image_list) == 1: |
143 return src_match.group(0) | 149 return src_match.group(0) |
144 | 150 |
145 return "%s: %s" % (attr, GenerateImageSet(image_list, quote)[:-1]) | 151 return "%s: %s" % (attr, GenerateImageSet(image_list, quote)[:-1]) |
146 | 152 |
147 | 153 |
148 def InsertImageStyle( | 154 def InsertImageStyle( |
149 src_match, base_path, scale_factors, distribution): | 155 src_match, base_path, scale_factors, distribution, |
| 156 filename_expansion_function=None): |
150 """Regex replace function which adds a content style to an <img>. | 157 """Regex replace function which adds a content style to an <img>. |
151 | 158 |
152 Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS | 159 Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS |
153 style which defines the image set. | 160 style which defines the image set. |
154 """ | 161 """ |
155 filename = src_match.group('filename') | 162 filename = src_match.group('filename') |
156 image_list = GetImageList(base_path, filename, scale_factors, distribution) | 163 image_list = GetImageList( |
| 164 base_path, filename, scale_factors, distribution, |
| 165 filename_expansion_function=filename_expansion_function) |
157 | 166 |
158 # Don't modify the source if there is only one image or image already defines | 167 # Don't modify the source if there is only one image or image already defines |
159 # a style. | 168 # a style. |
160 if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1: | 169 if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1: |
161 return src_match.group(0) | 170 return src_match.group(0) |
162 | 171 |
163 return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1], | 172 return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1], |
164 GenerateImageSet(image_list, "'")) | 173 GenerateImageSet(image_list, "'")) |
165 | 174 |
166 | 175 |
167 def InsertImageSets( | 176 def InsertImageSets( |
168 filepath, text, scale_factors, distribution): | 177 filepath, text, scale_factors, distribution, |
| 178 filename_expansion_function=None): |
169 """Helper function that adds references to external images available in any of | 179 """Helper function that adds references to external images available in any of |
170 scale_factors in CSS backgrounds. | 180 scale_factors in CSS backgrounds. |
171 """ | 181 """ |
172 # Add high DPI urls for css attributes: content, background, | 182 # Add high DPI urls for css attributes: content, background, |
173 # or *-image or <img src="foo">. | 183 # or *-image or <img src="foo">. |
174 return _CSS_IMAGE_URLS.sub( | 184 return _CSS_IMAGE_URLS.sub( |
175 lambda m: InsertImageSet(m, filepath, scale_factors, distribution), | 185 lambda m: InsertImageSet( |
| 186 m, filepath, scale_factors, distribution, |
| 187 filename_expansion_function=filename_expansion_function), |
176 _HTML_IMAGE_SRC.sub( | 188 _HTML_IMAGE_SRC.sub( |
177 lambda m: InsertImageStyle(m, filepath, scale_factors, distribution), | 189 lambda m: InsertImageStyle( |
| 190 m, filepath, scale_factors, distribution, |
| 191 filename_expansion_function=filename_expansion_function), |
178 text)).decode('utf-8').encode('utf-8') | 192 text)).decode('utf-8').encode('utf-8') |
179 | 193 |
180 | 194 |
181 def RemoveImagesNotIn(scale_factors, src_match): | 195 def RemoveImagesNotIn(scale_factors, src_match): |
182 """Regex replace function which removes images for scale factors not in | 196 """Regex replace function which removes images for scale factors not in |
183 scale_factors. | 197 scale_factors. |
184 | 198 |
185 Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images, | 199 Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images, |
186 checks if this scale factor is in scale_factors and if not, removes it. | 200 checks if this scale factor is in scale_factors and if not, removes it. |
187 | 201 |
(...skipping 13 matching lines...) Expand all Loading... |
201 | 215 |
202 def RemoveImageSetImages(text, scale_factors): | 216 def RemoveImageSetImages(text, scale_factors): |
203 """Helper function which removes images in image sets not in the list of | 217 """Helper function which removes images in image sets not in the list of |
204 supported scale_factors. | 218 supported scale_factors. |
205 """ | 219 """ |
206 return _CSS_IMAGE_SETS.sub( | 220 return _CSS_IMAGE_SETS.sub( |
207 lambda m: RemoveImagesNotIn(scale_factors, m), text) | 221 lambda m: RemoveImagesNotIn(scale_factors, m), text) |
208 | 222 |
209 | 223 |
210 def ProcessImageSets( | 224 def ProcessImageSets( |
211 filepath, text, scale_factors, distribution): | 225 filepath, text, scale_factors, distribution, |
| 226 filename_expansion_function=None): |
212 """Helper function that adds references to external images available in other | 227 """Helper function that adds references to external images available in other |
213 scale_factors and removes images from image-sets in unsupported scale_factors. | 228 scale_factors and removes images from image-sets in unsupported scale_factors. |
214 """ | 229 """ |
215 # Explicitly add 1x to supported scale factors so that it is not removed. | 230 # Explicitly add 1x to supported scale factors so that it is not removed. |
216 supported_scale_factors = ['1x'] | 231 supported_scale_factors = ['1x'] |
217 supported_scale_factors.extend(scale_factors) | 232 supported_scale_factors.extend(scale_factors) |
218 return InsertImageSets(filepath, | 233 return InsertImageSets( |
219 RemoveImageSetImages(text, supported_scale_factors), | 234 filepath, |
220 scale_factors, | 235 RemoveImageSetImages(text, supported_scale_factors), |
221 distribution) | 236 scale_factors, |
| 237 distribution, |
| 238 filename_expansion_function=filename_expansion_function) |
222 | 239 |
223 | 240 |
224 class ChromeHtml(interface.GathererBase): | 241 class ChromeHtml(interface.GathererBase): |
225 """Represents an HTML document processed for Chrome WebUI. | 242 """Represents an HTML document processed for Chrome WebUI. |
226 | 243 |
227 HTML documents used in Chrome WebUI have local resources inlined and | 244 HTML documents used in Chrome WebUI have local resources inlined and |
228 automatically insert references to high DPI assets used in CSS properties | 245 automatically insert references to high DPI assets used in CSS properties |
229 with the use of the -webkit-image-set value. References to unsupported scale | 246 with the use of the -webkit-image-set value. References to unsupported scale |
230 factors in image sets are also removed. This does not generate any | 247 factors in image sets are also removed. This does not generate any |
231 translateable messages and instead generates a single DataPack resource. | 248 translateable messages and instead generates a single DataPack resource. |
232 """ | 249 """ |
233 | 250 |
234 def __init__(self, *args, **kwargs): | 251 def __init__(self, *args, **kwargs): |
235 super(ChromeHtml, self).__init__(*args, **kwargs) | 252 super(ChromeHtml, self).__init__(*args, **kwargs) |
236 self.allow_external_script_ = False | 253 self.allow_external_script_ = False |
237 self.flatten_html_ = False | 254 self.flatten_html_ = False |
238 # 1x resources are implicitly already in the source and do not need to be | 255 # 1x resources are implicitly already in the source and do not need to be |
239 # added. | 256 # added. |
240 self.scale_factors_ = [] | 257 self.scale_factors_ = [] |
| 258 self.filename_expansion_function = None |
241 | 259 |
242 def SetAttributes(self, attrs): | 260 def SetAttributes(self, attrs): |
243 self.allow_external_script_ = ('allowexternalscript' in attrs and | 261 self.allow_external_script_ = ('allowexternalscript' in attrs and |
244 attrs['allowexternalscript'] == 'true') | 262 attrs['allowexternalscript'] == 'true') |
245 self.flatten_html_ = ('flattenhtml' in attrs and | 263 self.flatten_html_ = ('flattenhtml' in attrs and |
246 attrs['flattenhtml'] == 'true') | 264 attrs['flattenhtml'] == 'true') |
247 | 265 |
248 def SetDefines(self, defines): | 266 def SetDefines(self, defines): |
249 if 'scale_factors' in defines: | 267 if 'scale_factors' in defines: |
250 self.scale_factors_ = defines['scale_factors'].split(',') | 268 self.scale_factors_ = defines['scale_factors'].split(',') |
251 | 269 |
252 def GetText(self): | 270 def GetText(self): |
253 """Returns inlined text of the HTML document.""" | 271 """Returns inlined text of the HTML document.""" |
254 return self.inlined_text_ | 272 return self.inlined_text_ |
255 | 273 |
256 def GetTextualIds(self): | 274 def GetTextualIds(self): |
257 return [self.extkey] | 275 return [self.extkey] |
258 | 276 |
259 def GetData(self, lang, encoding): | 277 def GetData(self, lang, encoding): |
260 """Returns inlined text of the HTML document.""" | 278 """Returns inlined text of the HTML document.""" |
261 return self.inlined_text_ | 279 return self.inlined_text_ |
262 | 280 |
263 def GetHtmlResourceFilenames(self): | 281 def GetHtmlResourceFilenames(self): |
264 """Returns a set of all filenames inlined by this file.""" | 282 """Returns a set of all filenames inlined by this file.""" |
265 if self.flatten_html_: | 283 if self.flatten_html_: |
266 return html_inline.GetResourceFilenames( | 284 return html_inline.GetResourceFilenames( |
267 self.grd_node.ToRealPath(self.GetInputPath()), | 285 self.grd_node.ToRealPath(self.GetInputPath()), |
268 allow_external_script=self.allow_external_script_, | 286 allow_external_script=self.allow_external_script_, |
269 rewrite_function=lambda fp, t, d: ProcessImageSets( | 287 rewrite_function=lambda fp, t, d: ProcessImageSets( |
270 fp, t, self.scale_factors_, d)) | 288 fp, t, self.scale_factors_, d, |
| 289 filename_expansion_function=self.filename_expansion_function), |
| 290 filename_expansion_function=self.filename_expansion_function) |
271 return [] | 291 return [] |
272 | 292 |
273 def Translate(self, lang, pseudo_if_not_available=True, | 293 def Translate(self, lang, pseudo_if_not_available=True, |
274 skeleton_gatherer=None, fallback_to_english=False): | 294 skeleton_gatherer=None, fallback_to_english=False): |
275 """Returns this document translated.""" | 295 """Returns this document translated.""" |
276 return self.inlined_text_ | 296 return self.inlined_text_ |
277 | 297 |
| 298 def SetFilenameExpansionFunction(self, fn): |
| 299 self.filename_expansion_function = fn |
| 300 |
278 def Parse(self): | 301 def Parse(self): |
279 """Parses and inlines the represented file.""" | 302 """Parses and inlines the represented file.""" |
280 | 303 |
281 filename = self.GetInputPath() | 304 filename = self.GetInputPath() |
| 305 if self.filename_expansion_function: |
| 306 filename = self.filename_expansion_function(filename) |
282 # Hack: some unit tests supply an absolute path and no root node. | 307 # Hack: some unit tests supply an absolute path and no root node. |
283 if not os.path.isabs(filename): | 308 if not os.path.isabs(filename): |
284 filename = self.grd_node.ToRealPath(filename) | 309 filename = self.grd_node.ToRealPath(filename) |
285 if self.flatten_html_: | 310 if self.flatten_html_: |
286 self.inlined_text_ = html_inline.InlineToString( | 311 self.inlined_text_ = html_inline.InlineToString( |
287 filename, | 312 filename, |
288 self.grd_node, | 313 self.grd_node, |
289 allow_external_script = self.allow_external_script_, | 314 allow_external_script = self.allow_external_script_, |
290 rewrite_function=lambda fp, t, d: ProcessImageSets( | 315 rewrite_function=lambda fp, t, d: ProcessImageSets( |
291 fp, t, self.scale_factors_, d)) | 316 fp, t, self.scale_factors_, d, |
| 317 filename_expansion_function=self.filename_expansion_function), |
| 318 filename_expansion_function=self.filename_expansion_function) |
292 else: | 319 else: |
293 distribution = html_inline.GetDistribution() | 320 distribution = html_inline.GetDistribution() |
294 self.inlined_text_ = ProcessImageSets( | 321 self.inlined_text_ = ProcessImageSets( |
295 os.path.dirname(filename), | 322 os.path.dirname(filename), |
296 util.ReadFile(filename, 'utf-8'), | 323 util.ReadFile(filename, 'utf-8'), |
297 self.scale_factors_, | 324 self.scale_factors_, |
298 distribution) | 325 distribution, |
| 326 filename_expansion_function=self.filename_expansion_function) |
OLD | NEW |