Commit 12b09b7a by Timothée Peignier

rewrite assets url as relative url rather than absolute. close #79

parent 35eeaba7
......@@ -92,21 +92,6 @@ Group options
For CSS, if you do not specify ``extra_context``/``media``, the default media in
the ``<link>`` output will be ``media="all"``.
``absolute_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 that all filenames are specified relative to ``PIPELINE_ROOT``, and thus the source
files needs to be in your ``PIPELINE_ROOT``.
``manifest``
............
......
import os
import subprocess
try:
from staticfiles import finders
except ImportError:
from django.contrib.staticfiles import finders # noqa
from django.core.files.base import ContentFile
from django.utils.encoding import smart_str
......@@ -26,7 +31,7 @@ class Compiler(object):
new_path = self.output_path(path, compiler.output_extension)
content = self.read_file(path)
try:
compiled_content = compiler.compile_file(content, self.storage.path(path))
compiled_content = compiler.compile_file(content, finders.find(path))
self.save_file(new_path, compiled_content)
except CompilerError:
if not self.storage.exists(new_path) or not settings.PIPELINE:
......
......@@ -5,8 +5,13 @@ import subprocess
from itertools import takewhile
try:
from staticfiles import finders
except ImportError:
from django.contrib.staticfiles import finders # noqa
from pipeline.conf import settings
from pipeline.utils import to_class, relpath
from pipeline.utils import to_class
from pipeline.storage import default_storage
MAX_IMAGE_SIZE = 32700
......@@ -61,10 +66,9 @@ class Compressor(object):
return js
def compress_css(self, paths, variant=None, absolute_paths=True, **kwargs):
def compress_css(self, paths, output_filename, variant=None, **kwargs):
"""Concatenate and compress CSS files"""
css = self.concatenate_and_rewrite(paths, variant,
absolute_paths)
css = self.concatenate_and_rewrite(paths, output_filename, variant)
compressor = self.css_compressor
if compressor:
css = getattr(compressor(verbose=self.verbose), 'compress_css')(css)
......@@ -116,7 +120,7 @@ class Compressor(object):
), r"\1", path)
return re.sub(r"[\/\\]", "_", name)
def concatenate_and_rewrite(self, paths, variant=None, absolute_paths=True):
def concatenate_and_rewrite(self, paths, output_filename, variant=None):
"""Concatenate together files and rewrite urls"""
stylesheets = []
for path in paths:
......@@ -125,7 +129,7 @@ class Compressor(object):
if asset_path.startswith("http") or asset_path.startswith("//"):
return "url(%s)" % asset_path
asset_url = self.construct_asset_path(asset_path, path,
variant, absolute_paths)
output_filename, variant)
return "url(%s)" % asset_url
content = self.read_file(path)
content = re.sub(URL_DETECTOR, reconstruct, content)
......@@ -136,16 +140,14 @@ class Compressor(object):
"""Concatenate together a list of files"""
return '\n'.join([self.read_file(path) for path in paths])
def construct_asset_path(self, asset_path, css_path, variant=None, absolute_paths=True):
def construct_asset_path(self, asset_path, css_path, output_filename, variant=None):
"""Return a rewritten asset URL for a stylesheet"""
public_path = self.absolute_path(asset_path, os.path.dirname(css_path))
if self.embeddable(public_path, variant):
return "__EMBED__%s" % public_path
if not absolute_paths:
return asset_path
if not os.path.isabs(asset_path):
asset_path = self.relative_path(public_path)
return asset_path[1:]
asset_path = self.relative_path(public_path, output_filename)
return asset_path
def embeddable(self, path, variant):
"""Is the asset embeddable ?"""
......@@ -193,10 +195,11 @@ class Compressor(object):
path = os.path.join(start, path)
return os.path.normpath(path)
def relative_path(self, absolute_path):
def relative_path(self, absolute_path, output_filename):
"""Rewrite paths relative to the output stylesheet path"""
absolute_path = self.absolute_path(absolute_path, default_storage.location)
return os.path.join(os.sep, relpath(absolute_path, default_storage.location))
absolute_path = os.path.join(settings.PIPELINE_ROOT, absolute_path)
output_path = os.path.join(settings.PIPELINE_ROOT, os.path.dirname(output_filename))
return os.path.relpath(absolute_path, output_path)
def read_file(self, path):
"""Read file content in binary mode"""
......
......@@ -2,6 +2,7 @@ from django.conf import settings
PIPELINE = getattr(settings, 'PIPELINE', not settings.DEBUG)
PIPELINE_ROOT = getattr(settings, 'PIPELINE_ROOT', settings.STATIC_URL)
PIPELINE_URL = getattr(settings, 'PIPELINE_URL', settings.STATIC_URL)
PIPELINE_STORAGE = getattr(settings, 'PIPELINE_STORAGE',
......
......@@ -55,10 +55,6 @@ class Package(object):
def manifest(self):
return self.config.get('manifest', True)
@property
def absolute_paths(self):
return self.config.get('absolute_paths', True)
class Packager(object):
def __init__(self, storage=default_storage, verbose=False, css_packages=None, js_packages=None):
......@@ -90,8 +86,8 @@ class Packager(object):
def pack_stylesheets(self, package, **kwargs):
return self.pack(package, self.compressor.compress_css, css_compressed,
variant=package.variant, absolute_paths=package.absolute_paths,
**kwargs)
output_filename=package.output_filename,
variant=package.variant, **kwargs)
def compile(self, paths):
return self.compiler.compile(paths)
......
import os
import sys
import urllib
from django.utils import importlib
......@@ -20,54 +18,3 @@ def filepath_to_uri(path):
if path is None:
return path
return urllib.quote(smart_str(path).replace("\\", "/"), safe="/~!*()'#?")
def _relpath_nt(path, start=os.path.curdir):
"""Return a relative version of a path"""
if not path:
raise ValueError("no path specified")
start_list = os.path.abspath(start).split(os.path.sep)
path_list = os.path.abspath(path).split(os.path.sep)
if start_list[0].lower() != path_list[0].lower():
unc_path, rest = os.path.splitunc(path)
unc_start, rest = os.path.splitunc(start)
if bool(unc_path) ^ bool(unc_start):
raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
% (path, start))
else:
raise ValueError("path is on drive %s, start on drive %s"
% (path_list[0], start_list[0]))
# Work out how much of the filepath is shared by start and path.
for i in range(min(len(start_list), len(path_list))):
if start_list[i].lower() != path_list[i].lower():
break
else:
i += 1
rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:]
if not rel_list:
return os.path.curdir
return os.path.join(*rel_list)
def _relpath_posix(path, start=os.path.curdir):
"""Return a relative version of a path"""
if not path:
raise ValueError("no path specified")
start_list = os.path.abspath(start).split(os.path.sep)
path_list = os.path.abspath(path).split(os.path.sep)
# Work out how much of the filepath is shared by start and path.
i = len(os.path.commonprefix([start_list, path_list]))
rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:]
if not rel_list:
return os.path.curdir
return os.path.join(*rel_list)
if os.path is sys.modules.get('ntpath'):
relpath = _relpath_nt
else:
relpath = _relpath_posix
......@@ -24,7 +24,7 @@ class CompressorTest(TestCase):
css = self.compressor.concatenate_and_rewrite([
'css/first.css',
'css/second.css'
])
], 'css/screen.css')
self.assertEquals(""".concat {\n display: none;\n}\n\n.concatenate {\n display: block;\n}\n""", css)
def test_concatenate(self):
......@@ -43,8 +43,8 @@ class CompressorTest(TestCase):
self.assertFalse(mock.called)
def test_relative_path(self):
relative_path = self.compressor.relative_path("%s/images/sprite.png" % storage.location)
self.assertEquals(relative_path, '/images/sprite.png')
relative_path = self.compressor.relative_path("images/sprite.png", 'css/screen.css')
self.assertEquals(relative_path, '../images/sprite.png')
def test_base_path(self):
base_path = self.compressor.base_path([
......@@ -87,39 +87,29 @@ class CompressorTest(TestCase):
def test_construct_asset_path(self):
asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
"css/plugins/gallery.css")
self.assertEquals(asset_path, "images/sprite.png")
"css/plugins/gallery.css", "css/gallery.css")
self.assertEquals(asset_path, "../images/sprite.png")
asset_path = self.compressor.construct_asset_path("/images/sprite.png",
"css/plugins/gallery.css")
self.assertEquals(asset_path, "images/sprite.png")
def test_construct_asset_path_relative(self):
asset_path = self.compressor.construct_asset_path("../../images/sprite.png",
"css/plugins/gallery.css",
absolute_paths=False)
self.assertEquals(asset_path, "../../images/sprite.png")
asset_path = self.compressor.construct_asset_path("/images/sprite.png",
"css/plugins/gallery.css",
absolute_paths=False)
"css/plugins/gallery.css", "css/gallery.css")
self.assertEquals(asset_path, "/images/sprite.png")
def test_url_rewrite(self):
output = self.compressor.concatenate_and_rewrite([
'css/urls.css',
])
], 'css/screen.css')
self.assertEquals("""@font-face {
font-family: 'Pipeline';
src: url(fonts/pipeline.eot);
src: url(fonts/pipeline.eot?#iefix) format('embedded-opentype');
src: local('☺'), url(fonts/pipeline.woff) format('woff'), url(fonts/pipeline.ttf) format('truetype'), url(fonts/pipeline.svg#IyfZbseF) format('svg');
src: url(../fonts/pipeline.eot);
src: url(../fonts/pipeline.eot?#iefix) format('embedded-opentype');
src: local('☺'), url(../fonts/pipeline.woff) format('woff'), url(../fonts/pipeline.ttf) format('truetype'), url(../fonts/pipeline.svg#IyfZbseF) format('svg');
font-weight: normal;
font-style: normal;
}
.relative-url {
background-image: url(images/sprite-buttons.png);
background-image: url(../images/sprite-buttons.png);
}
.absolute-url {
background-image: url(images/sprite-buttons.png);
background-image: url(/images/sprite-buttons.png);
}
.absolute-full-url {
background-image: url(http://localhost/images/sprite-buttons.png);
......
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