Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: grit/gather/chrome_html.py

Issue 1442863002: Remove contents of grit's SVN repository. (Closed) Base URL: http://grit-i18n.googlecode.com/svn/trunk/
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « grit/gather/admin_template_unittest.py ('k') | grit/gather/chrome_html_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
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
4 # found in the LICENSE file.
5
6 """Prepares a Chrome HTML file by inlining resources and adding references to
7 high DPI resources and removing references to unsupported scale factors.
8
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
11 dependencies. It recursively inlines the included files. When inlining CSS
12 image files this script also checks for the existence of high DPI versions
13 of the inlined file including those on relevant platforms. Unsupported scale
14 factors are also removed from existing image sets to support explicitly
15 referencing all available images.
16 """
17
18 import os
19 import re
20
21 from grit import lazy_re
22 from grit import util
23 from grit.format import html_inline
24 from grit.gather import interface
25
26
27 # Distribution string to replace with distribution.
28 DIST_SUBSTR = '%DISTRIBUTION%'
29
30
31 # Matches a chrome theme source URL.
32 _THEME_SOURCE = lazy_re.compile(
33 '(?P<baseurl>chrome://theme/IDR_[A-Z0-9_]*)(?P<query>\?.*)?')
34 # Pattern for matching CSS url() function.
35 _CSS_URL_PATTERN = 'url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)'
36 # Matches CSS url() functions with the capture group 'filename'.
37 _CSS_URL = lazy_re.compile(_CSS_URL_PATTERN)
38 # Matches one or more CSS image urls used in given properties.
39 _CSS_IMAGE_URLS = lazy_re.compile(
40 '(?P<attribute>content|background|[\w-]*-image):\s*' +
41 '(?P<urls>(' + _CSS_URL_PATTERN + '\s*,?\s*)+)')
42 # Matches CSS image sets.
43 _CSS_IMAGE_SETS = lazy_re.compile(
44 '(?P<attribute>content|background|[\w-]*-image):[ ]*' +
45 '-webkit-image-set\((?P<images>' +
46 '(\s*,?\s*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)',
47 re.MULTILINE)
48 # Matches a single image in a CSS image set with the capture group scale.
49 _CSS_IMAGE_SET_IMAGE = lazy_re.compile('\s*,?\s*' +
50 'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)',
51 re.MULTILINE)
52 _HTML_IMAGE_SRC = lazy_re.compile(
53 '<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>')
54
55 def GetImageList(
56 base_path, filename, scale_factors, distribution,
57 filename_expansion_function=None):
58 """Generate the list of images which match the provided scale factors.
59
60 Takes an image filename and checks for files of the same name in folders
61 corresponding to the supported scale factors. If the file is from a
62 chrome://theme/ source, inserts supported @Nx scale factors as high DPI
63 versions.
64
65 Args:
66 base_path: path to look for relative file paths in
67 filename: name of the base image file
68 scale_factors: a list of the supported scale factors (i.e. ['2x'])
69 distribution: string that should replace %DISTRIBUTION%
70
71 Returns:
72 array of tuples containing scale factor and image (i.e.
73 [('1x', 'image.png'), ('2x', '2x/image.png')]).
74 """
75 # Any matches for which a chrome URL handler will serve all scale factors
76 # can simply request all scale factors.
77 theme_match = _THEME_SOURCE.match(filename)
78 if theme_match:
79 images = [('1x', filename)]
80 for scale_factor in scale_factors:
81 scale_filename = "%s@%s" % (theme_match.group('baseurl'), scale_factor)
82 if theme_match.group('query'):
83 scale_filename += theme_match.group('query')
84 images.append((scale_factor, scale_filename))
85 return images
86
87 if filename.find(':') != -1:
88 # filename is probably a URL, only return filename itself.
89 return [('1x', filename)]
90
91 filename = filename.replace(DIST_SUBSTR, distribution)
92 if filename_expansion_function:
93 filename = filename_expansion_function(filename)
94 filepath = os.path.join(base_path, filename)
95 images = [('1x', filename)]
96
97 for scale_factor in scale_factors:
98 # Check for existence of file and add to image set.
99 scale_path = os.path.split(os.path.join(base_path, filename))
100 scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1])
101 if os.path.isfile(scale_image_path):
102 # HTML/CSS always uses forward slashed paths.
103 scale_image_name = re.sub('(?P<path>(.*/)?)(?P<file>[^/]*)',
104 '\\g<path>' + scale_factor + '/\\g<file>',
105 filename)
106 images.append((scale_factor, scale_image_name))
107 return images
108
109
110 def GenerateImageSet(images, quote):
111 """Generates a -webkit-image-set for the provided list of images.
112
113 Args:
114 images: an array of tuples giving scale factor and file path
115 (i.e. [('1x', 'image.png'), ('2x', '2x/image.png')]).
116 quote: a string giving the quotation character to use (i.e. "'")
117
118 Returns:
119 string giving a -webkit-image-set rule referencing the provided images.
120 (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)')
121 """
122 imageset = []
123 for (scale_factor, filename) in images:
124 imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor))
125 return "-webkit-image-set(%s)" % (', '.join(imageset))
126
127
128 def UrlToImageSet(
129 src_match, base_path, scale_factors, distribution,
130 filename_expansion_function=None):
131 """Regex replace function which replaces url() with -webkit-image-set.
132
133 Takes a regex match for url('path'). If the file is local, checks for
134 files of the same name in folders corresponding to the supported scale
135 factors. If the file is from a chrome://theme/ source, inserts the
136 supported @Nx scale factor request. In either case inserts a
137 -webkit-image-set rule to fetch the appropriate image for the current
138 scale factor.
139
140 Args:
141 src_match: regex match object from _CSS_URLS
142 base_path: path to look for relative file paths in
143 scale_factors: a list of the supported scale factors (i.e. ['2x'])
144 distribution: string that should replace %DISTRIBUTION%.
145
146 Returns:
147 string
148 """
149 quote = src_match.group('quote')
150 filename = src_match.group('filename')
151 image_list = GetImageList(
152 base_path, filename, scale_factors, distribution,
153 filename_expansion_function=filename_expansion_function)
154
155 # Don't modify the source if there is only one image.
156 if len(image_list) == 1:
157 return src_match.group(0)
158
159 return GenerateImageSet(image_list, quote)
160
161
162 def InsertImageSet(
163 src_match, base_path, scale_factors, distribution,
164 filename_expansion_function=None):
165 """Regex replace function which inserts -webkit-image-set rules.
166
167 Takes a regex match for `property: url('path')[, url('path')]+`.
168 Replaces one or more occurances of the match with image set rules.
169
170 Args:
171 src_match: regex match object from _CSS_IMAGE_URLS
172 base_path: path to look for relative file paths in
173 scale_factors: a list of the supported scale factors (i.e. ['2x'])
174 distribution: string that should replace %DISTRIBUTION%.
175
176 Returns:
177 string
178 """
179 attr = src_match.group('attribute')
180 urls = _CSS_URL.sub(
181 lambda m: UrlToImageSet(m, base_path, scale_factors, distribution,
182 filename_expansion_function),
183 src_match.group('urls'))
184
185 return "%s: %s" % (attr, urls)
186
187
188 def InsertImageStyle(
189 src_match, base_path, scale_factors, distribution,
190 filename_expansion_function=None):
191 """Regex replace function which adds a content style to an <img>.
192
193 Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS
194 style which defines the image set.
195 """
196 filename = src_match.group('filename')
197 image_list = GetImageList(
198 base_path, filename, scale_factors, distribution,
199 filename_expansion_function=filename_expansion_function)
200
201 # Don't modify the source if there is only one image or image already defines
202 # a style.
203 if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1:
204 return src_match.group(0)
205
206 return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1],
207 GenerateImageSet(image_list, "'"))
208
209
210 def InsertImageSets(
211 filepath, text, scale_factors, distribution,
212 filename_expansion_function=None):
213 """Helper function that adds references to external images available in any of
214 scale_factors in CSS backgrounds.
215 """
216 # Add high DPI urls for css attributes: content, background,
217 # or *-image or <img src="foo">.
218 return _CSS_IMAGE_URLS.sub(
219 lambda m: InsertImageSet(
220 m, filepath, scale_factors, distribution,
221 filename_expansion_function=filename_expansion_function),
222 _HTML_IMAGE_SRC.sub(
223 lambda m: InsertImageStyle(
224 m, filepath, scale_factors, distribution,
225 filename_expansion_function=filename_expansion_function),
226 text)).decode('utf-8').encode('utf-8')
227
228
229 def RemoveImagesNotIn(scale_factors, src_match):
230 """Regex replace function which removes images for scale factors not in
231 scale_factors.
232
233 Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images,
234 checks if this scale factor is in scale_factors and if not, removes it.
235
236 Args:
237 scale_factors: a list of the supported scale factors (i.e. ['1x', '2x'])
238 src_match: regex match object from _CSS_IMAGE_SETS
239
240 Returns:
241 string
242 """
243 attr = src_match.group('attribute')
244 images = _CSS_IMAGE_SET_IMAGE.sub(
245 lambda m: m.group(0) if m.group('scale') in scale_factors else '',
246 src_match.group('images'))
247 return "%s: -webkit-image-set(%s)" % (attr, images)
248
249
250 def RemoveImageSetImages(text, scale_factors):
251 """Helper function which removes images in image sets not in the list of
252 supported scale_factors.
253 """
254 return _CSS_IMAGE_SETS.sub(
255 lambda m: RemoveImagesNotIn(scale_factors, m), text)
256
257
258 def ProcessImageSets(
259 filepath, text, scale_factors, distribution,
260 filename_expansion_function=None):
261 """Helper function that adds references to external images available in other
262 scale_factors and removes images from image-sets in unsupported scale_factors.
263 """
264 # Explicitly add 1x to supported scale factors so that it is not removed.
265 supported_scale_factors = ['1x']
266 supported_scale_factors.extend(scale_factors)
267 return InsertImageSets(
268 filepath,
269 RemoveImageSetImages(text, supported_scale_factors),
270 scale_factors,
271 distribution,
272 filename_expansion_function=filename_expansion_function)
273
274
275 class ChromeHtml(interface.GathererBase):
276 """Represents an HTML document processed for Chrome WebUI.
277
278 HTML documents used in Chrome WebUI have local resources inlined and
279 automatically insert references to high DPI assets used in CSS properties
280 with the use of the -webkit-image-set value. References to unsupported scale
281 factors in image sets are also removed. This does not generate any
282 translateable messages and instead generates a single DataPack resource.
283 """
284
285 def __init__(self, *args, **kwargs):
286 super(ChromeHtml, self).__init__(*args, **kwargs)
287 self.allow_external_script_ = False
288 self.flatten_html_ = False
289 # 1x resources are implicitly already in the source and do not need to be
290 # added.
291 self.scale_factors_ = []
292 self.filename_expansion_function = None
293
294 def SetAttributes(self, attrs):
295 self.allow_external_script_ = ('allowexternalscript' in attrs and
296 attrs['allowexternalscript'] == 'true')
297 self.flatten_html_ = ('flattenhtml' in attrs and
298 attrs['flattenhtml'] == 'true')
299
300 def SetDefines(self, defines):
301 if 'scale_factors' in defines:
302 self.scale_factors_ = defines['scale_factors'].split(',')
303
304 def GetText(self):
305 """Returns inlined text of the HTML document."""
306 return self.inlined_text_
307
308 def GetTextualIds(self):
309 return [self.extkey]
310
311 def GetData(self, lang, encoding):
312 """Returns inlined text of the HTML document."""
313 return self.inlined_text_
314
315 def GetHtmlResourceFilenames(self):
316 """Returns a set of all filenames inlined by this file."""
317 if self.flatten_html_:
318 return html_inline.GetResourceFilenames(
319 self.grd_node.ToRealPath(self.GetInputPath()),
320 allow_external_script=self.allow_external_script_,
321 rewrite_function=lambda fp, t, d: ProcessImageSets(
322 fp, t, self.scale_factors_, d,
323 filename_expansion_function=self.filename_expansion_function),
324 filename_expansion_function=self.filename_expansion_function)
325 return []
326
327 def Translate(self, lang, pseudo_if_not_available=True,
328 skeleton_gatherer=None, fallback_to_english=False):
329 """Returns this document translated."""
330 return self.inlined_text_
331
332 def SetFilenameExpansionFunction(self, fn):
333 self.filename_expansion_function = fn
334
335 def Parse(self):
336 """Parses and inlines the represented file."""
337
338 filename = self.GetInputPath()
339 if self.filename_expansion_function:
340 filename = self.filename_expansion_function(filename)
341 # Hack: some unit tests supply an absolute path and no root node.
342 if not os.path.isabs(filename):
343 filename = self.grd_node.ToRealPath(filename)
344 if self.flatten_html_:
345 self.inlined_text_ = html_inline.InlineToString(
346 filename,
347 self.grd_node,
348 allow_external_script = self.allow_external_script_,
349 rewrite_function=lambda fp, t, d: ProcessImageSets(
350 fp, t, self.scale_factors_, d,
351 filename_expansion_function=self.filename_expansion_function),
352 filename_expansion_function=self.filename_expansion_function)
353 else:
354 distribution = html_inline.GetDistribution()
355 self.inlined_text_ = ProcessImageSets(
356 os.path.dirname(filename),
357 util.ReadFile(filename, 'utf-8'),
358 self.scale_factors_,
359 distribution,
360 filename_expansion_function=self.filename_expansion_function)
OLDNEW
« no previous file with comments | « grit/gather/admin_template_unittest.py ('k') | grit/gather/chrome_html_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698