blob: 5338762588eb78cb29f2c3448c1295929befbe53 [file] [log] [blame]
# 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)