1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import base64
import os
import re
class Image(object):
def __init__(self, resource):
self.resource = resource
self.aliases = []
@property
def relative_path(self):
return self.resource.relative_path
@property
def absolute_path(self):
return self.resource.absolute_path
@property
def contents(self):
return self.resource.contents
class ParsedStyleSheet(object):
def __init__(self, loader, containing_dirname, contents):
self.loader = loader
self.contents = contents
self._images = None
self._Load(containing_dirname)
@property
def images(self):
return self._images
def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
for i in self.images:
dependent_filenames.append(i.resource.absolute_path)
@property
def contents_with_inlined_images(self):
images_by_url = {}
for i in self.images:
for a in i.aliases:
images_by_url[a] = i
def InlineUrl(m):
url = m.group('url')
image = images_by_url[url]
ext = os.path.splitext(image.absolute_path)[1]
data = base64.standard_b64encode(image.contents)
return 'url(data:image/%s;base64,%s)' % (ext[1:], data)
# I'm assuming we only have url()'s associated with images
return re.sub('url\((?P<quote>"|\'|)(?P<url>[^"\'()]*)(?P=quote)\)',
InlineUrl, self.contents)
def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
for i in self.images:
dependent_filenames.append(i.resource.absolute_path)
def _Load(self, containing_dirname):
if self.contents.find('@import') != -1:
raise Exception('@imports are not supported')
matches = re.findall(
'url\((?:["|\']?)([^"\'()]*)(?:["|\']?)\)',
self.contents)
def resolve_url(url):
if os.path.isabs(url):
# FIXME: module is used here, but py_vulcanize.module is never imported.
# However, py_vulcanize.module cannot be imported since py_vulcanize.module may import
# style_sheet, leading to an import loop.
raise module.DepsException('URL references must be relative')
# URLS are relative to this module's directory
abs_path = os.path.abspath(os.path.join(containing_dirname, url))
image = self.loader.LoadImage(abs_path)
image.aliases.append(url)
return image
self._images = [resolve_url(x) for x in matches]
class StyleSheet(object):
"""Represents a stylesheet resource referenced by a module via the
base.requireStylesheet(xxx) directive."""
def __init__(self, loader, name, resource):
self.loader = loader
self.name = name
self.resource = resource
self._parsed_style_sheet = None
@property
def filename(self):
return self.resource.absolute_path
@property
def contents(self):
return self.resource.contents
def __repr__(self):
return 'StyleSheet(%s)' % self.name
@property
def images(self):
self._InitParsedStyleSheetIfNeeded()
return self._parsed_style_sheet.images
def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
self._InitParsedStyleSheetIfNeeded()
dependent_filenames.append(self.resource.absolute_path)
self._parsed_style_sheet.AppendDirectlyDependentFilenamesTo(
dependent_filenames)
@property
def contents_with_inlined_images(self):
self._InitParsedStyleSheetIfNeeded()
return self._parsed_style_sheet.contents_with_inlined_images
def load(self):
self._InitParsedStyleSheetIfNeeded()
def _InitParsedStyleSheetIfNeeded(self):
if self._parsed_style_sheet:
return
module_dirname = os.path.dirname(self.resource.absolute_path)
self._parsed_style_sheet = ParsedStyleSheet(
self.loader, module_dirname, self.contents)
|