diff --git a/compressor/base.py b/compressor/base.py
index 44c07ed..03c1d9e 100644
--- a/compressor/base.py
+++ b/compressor/base.py
@@ -21,6 +21,7 @@ from compressor.conf import settings
from compressor.exceptions import (CompressorError, UncompressableFileError,
FilterDoesNotExist)
from compressor.filters import CachedCompilerFilter
+from compressor.filters.css_default import CssAbsoluteFilter
from compressor.storage import compressor_file_storage
from compressor.signals import post_compress
from compressor.utils import get_class, get_mod_func, staticfiles
@@ -211,20 +212,24 @@ class Compressor(object):
precompiled, value = self.precompile(value, **options)
if enabled:
- yield self.filter(value, **options)
+ yield self.filter(value, self.cached_filters, **options)
+ elif precompiled:
+ # since precompiling moves files around, it breaks url()
+ # statements in css files. therefore we run the absolute filter
+ # on precompiled css files even if compression is disabled.
+ if CssAbsoluteFilter in self.cached_filters:
+ value = self.filter(value, [CssAbsoluteFilter], **options)
+ yield self.handle_output(kind, value, forced=True,
+ basename=basename)
else:
- if precompiled:
- yield self.handle_output(kind, value, forced=True,
- basename=basename)
- else:
- yield self.parser.elem_str(elem)
+ yield self.parser.elem_str(elem)
def filter_output(self, content):
"""
Passes the concatenated content to the 'output' methods
of the compressor filters.
"""
- return self.filter(content, method=METHOD_OUTPUT)
+ return self.filter(content, self.cached_filters, method=METHOD_OUTPUT)
def filter_input(self, forced=False):
"""
@@ -275,8 +280,8 @@ class Compressor(object):
filename=filename)
return True, filter.input(**kwargs)
- def filter(self, content, method, **kwargs):
- for filter_cls in self.cached_filters:
+ def filter(self, content, filters, method, **kwargs):
+ for filter_cls in filters:
filter_func = getattr(
filter_cls(content, filter_type=self.type), method)
try:
diff --git a/compressor/tests/static/css/relative_url.css b/compressor/tests/static/css/relative_url.css
new file mode 100644
index 0000000..c690cde
--- /dev/null
+++ b/compressor/tests/static/css/relative_url.css
@@ -0,0 +1 @@
+p { background: url('../img/python.png'); }
\ No newline at end of file
diff --git a/compressor/tests/test_base.py b/compressor/tests/test_base.py
index 108b34d..c96f398 100644
--- a/compressor/tests/test_base.py
+++ b/compressor/tests/test_base.py
@@ -48,9 +48,55 @@ class TestPrecompiler(object):
return 'OUTPUT'
+class PassthroughPrecompiler(object):
+ """A filter whose outputs the input unmodified """
+ def __init__(self, content, attrs, filter_type=None, filename=None,
+ charset=None):
+ self.content = content
+
+ def input(self, **kwargs):
+ return self.content
+
+
test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__)))
+class PrecompilerAndAbsoluteFilterTestCase(SimpleTestCase):
+
+ def setUp(self):
+ self.html_orig = ''
+ self.html_link_to_precompiled_css = ''
+ self.html_link_to_absolutized_css = ''
+ self.css_orig = "p { background: url('../img/python.png'); }" # content of relative_url.css
+ self.css_absolutized = "p { background: url('/static/img/python.png?c2281c83670e'); }"
+
+ def helper(self, enabled, use_precompiler, use_absolute_filter, expected_output):
+ precompiler = (('text/css', 'compressor.tests.test_base.PassthroughPrecompiler'),) if use_precompiler else ()
+ filters = ('compressor.filters.css_default.CssAbsoluteFilter',) if use_absolute_filter else ()
+
+ with self.settings(COMPRESS_ENABLED=enabled, COMPRESS_PRECOMPILERS=precompiler, COMPRESS_CSS_FILTERS=filters):
+ css_node = CssCompressor(self.html_orig)
+ output = list(css_node.hunks())[0]
+ self.assertEqual(output, expected_output)
+
+ @override_settings(COMPRESS_CSS_HASHING_METHOD="content")
+ def test_precompiler_enables_absolute(self):
+ """
+ Tests whether specifying a precompiler also runs the CssAbsoluteFilter even if
+ compression is disabled, but only if the CssAbsoluteFilter is actually contained
+ in the filters setting.
+ While at it, ensure that everything runs as expected when compression is enabled.
+ """
+ self.helper(enabled=False, use_precompiler=False, use_absolute_filter=False, expected_output=self.html_orig)
+ self.helper(enabled=False, use_precompiler=False, use_absolute_filter=True, expected_output=self.html_orig)
+ self.helper(enabled=False, use_precompiler=True, use_absolute_filter=False, expected_output=self.html_link_to_precompiled_css)
+ self.helper(enabled=False, use_precompiler=True, use_absolute_filter=True, expected_output=self.html_link_to_absolutized_css)
+ self.helper(enabled=True, use_precompiler=False, use_absolute_filter=False, expected_output=self.css_orig)
+ self.helper(enabled=True, use_precompiler=False, use_absolute_filter=True, expected_output=self.css_absolutized)
+ self.helper(enabled=True, use_precompiler=True, use_absolute_filter=False, expected_output=self.css_orig)
+ self.helper(enabled=True, use_precompiler=True, use_absolute_filter=True, expected_output=self.css_absolutized)
+
+
class CompressorTestCase(SimpleTestCase):
def setUp(self):