Commit 980dd0d3 by Christian Hammond Committed by Timothée Peignier

Support disabling asset path normalization in CSS.

This introduces an option in PIPELINE_CSS package rules for turning off
the feature to make relative paths absolute. In certain deployments,
relative paths are important and need to be preserved.

Packages can now set absolute_asset_paths to False to turn off this
functionality.

Signed-off-by: Timothée Peignier <timothee.peignier@tryphon.org>
parent 2fea3118
...@@ -100,6 +100,16 @@ Group options ...@@ -100,6 +100,16 @@ Group options
For CSS, if you do not specify ``extra_context``/``media``, the default media in For CSS, if you do not specify ``extra_context``/``media``, the default media in
the ``<link>`` output will be ``media="all"``. the ``<link>`` output will be ``media="all"``.
``absolute_asset_paths``
........................
**Optional**
Indicates if relative paths in CSS files should be made absolute, based on
``PIPELINE_URL``. This only applies to entries in ``PIPELINE_CSS``.
Defaults to ``True``.
.. note:: .. note::
Note that all filenames are specified relative to ``PIPELINE_ROOT``, and thus the source Note that all filenames are specified relative to ``PIPELINE_ROOT``, and thus the source
...@@ -257,7 +267,8 @@ Rewriting CSS urls ...@@ -257,7 +267,8 @@ Rewriting CSS urls
================== ==================
If source CSS contain a relative URL (i.e. relative to current file), If source CSS contain a relative URL (i.e. relative to current file),
those URL will be converted to full relative path using ``PIPELINE_URL``. and ``absolute_asset_paths`` is set to ``True`` or left out in the package
entry, the URL will be converted to full relative path using ``PIPELINE_URL``.
This conversion is performed before any compressors are applied :: This conversion is performed before any compressors are applied ::
media/js/fancybox/ media/js/fancybox/
......
...@@ -61,10 +61,11 @@ class Compressor(object): ...@@ -61,10 +61,11 @@ class Compressor(object):
return js return js
def compress_css(self, paths, variant=None, asset_url=None, **kwargs): def compress_css(self, paths, variant=None, asset_url=None,
absolute_asset_paths=True, **kwargs):
"""Concatenate and compress CSS files""" """Concatenate and compress CSS files"""
css = self.concatenate_and_rewrite(paths, variant) css = self.concatenate_and_rewrite(paths, variant,
absolute_asset_paths)
compressor = self.css_compressor compressor = self.css_compressor
if compressor: if compressor:
css = getattr(compressor(verbose=self.verbose), 'compress_css')(css) css = getattr(compressor(verbose=self.verbose), 'compress_css')(css)
...@@ -116,7 +117,8 @@ class Compressor(object): ...@@ -116,7 +117,8 @@ class Compressor(object):
), r"\1", path) ), r"\1", path)
return re.sub(r"[\/\\]", "_", name) return re.sub(r"[\/\\]", "_", name)
def concatenate_and_rewrite(self, paths, variant=None): def concatenate_and_rewrite(self, paths, variant=None,
absolute_asset_paths=True):
"""Concatenate together files and rewrite urls""" """Concatenate together files and rewrite urls"""
stylesheets = [] stylesheets = []
for path in paths: for path in paths:
...@@ -124,7 +126,8 @@ class Compressor(object): ...@@ -124,7 +126,8 @@ class Compressor(object):
asset_path = match.group(1) asset_path = match.group(1)
if asset_path.startswith("http") or asset_path.startswith("//"): if asset_path.startswith("http") or asset_path.startswith("//"):
return "url(%s)" % asset_path return "url(%s)" % asset_path
asset_url = self.construct_asset_path(asset_path, path, variant) asset_url = self.construct_asset_path(asset_path, path, variant,
absolute_asset_paths)
return "url(%s)" % asset_url return "url(%s)" % asset_url
content = self.read_file(path) content = self.read_file(path)
content = re.sub(URL_DETECTOR, reconstruct, content) content = re.sub(URL_DETECTOR, reconstruct, content)
...@@ -135,11 +138,14 @@ class Compressor(object): ...@@ -135,11 +138,14 @@ class Compressor(object):
"""Concatenate together a list of files""" """Concatenate together a list of files"""
return '\n'.join([self.read_file(path) for path in paths]) return '\n'.join([self.read_file(path) for path in paths])
def construct_asset_path(self, asset_path, css_path, variant=None): def construct_asset_path(self, asset_path, css_path, variant=None,
absolute_asset_paths=True):
"""Return a rewritten asset URL for a stylesheet""" """Return a rewritten asset URL for a stylesheet"""
public_path = self.absolute_path(asset_path, os.path.dirname(css_path)) public_path = self.absolute_path(asset_path, os.path.dirname(css_path))
if self.embeddable(public_path, variant): if self.embeddable(public_path, variant):
return "__EMBED__%s" % public_path return "__EMBED__%s" % public_path
if not absolute_asset_paths:
return asset_path
if not os.path.isabs(asset_path): if not os.path.isabs(asset_path):
asset_path = self.relative_path(public_path) asset_path = self.relative_path(public_path)
asset_url = asset_path.replace(os.sep, '/') asset_url = asset_path.replace(os.sep, '/')
......
...@@ -45,8 +45,10 @@ class Packager(object): ...@@ -45,8 +45,10 @@ class Packager(object):
def pack_stylesheets(self, package, **kwargs): def pack_stylesheets(self, package, **kwargs):
variant = package.get('variant', None) variant = package.get('variant', None)
absolute_asset_paths = package.get('absolute_asset_paths', True)
return self.pack(package, self.compressor.compress_css, css_compressed, return self.pack(package, self.compressor.compress_css, css_compressed,
variant=variant, **kwargs) variant=variant, absolute_asset_paths=absolute_asset_paths,
**kwargs)
def compile(self, paths): def compile(self, paths):
return self.compiler.compile(paths) return self.compiler.compile(paths)
...@@ -104,6 +106,9 @@ class Packager(object): ...@@ -104,6 +106,9 @@ class Packager(object):
packages[name]['output'] = config[name]['output_filename'] packages[name]['output'] = config[name]['output_filename']
packages[name]['context'] = {} packages[name]['context'] = {}
packages[name]['manifest'] = True packages[name]['manifest'] = True
if 'absolute_asset_paths' in config[name]:
packages[name]['absolute_asset_paths'] = \
config[name]['absolute_asset_paths']
if 'extra_context' in config[name]: if 'extra_context' in config[name]:
packages[name]['context'] = config[name]['extra_context'] packages[name]['context'] = config[name]['extra_context']
if 'template_name' in config[name]: if 'template_name' in config[name]:
......
...@@ -94,6 +94,15 @@ class CompressorTest(TestCase): ...@@ -94,6 +94,15 @@ class CompressorTest(TestCase):
"css/plugins/gallery.css") "css/plugins/gallery.css")
self.assertEquals(asset_path, "http://localhost/static/images/sprite.png") self.assertEquals(asset_path, "http://localhost/static/images/sprite.png")
asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
"css/plugins/gallery.css",
absolute_asset_paths=False)
self.assertEquals(asset_path, "../../images/sprite.png")
asset_path = self.compressor.construct_asset_path("/images/sprite.png",
"css/plugins/gallery.css",
absolute_asset_paths=False)
self.assertEquals(asset_path, "/images/sprite.png")
def test_url_rewrite(self): def test_url_rewrite(self):
self.maxDiff = None self.maxDiff = None
output = self.compressor.concatenate_and_rewrite([ output = self.compressor.concatenate_and_rewrite([
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment