Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Make css url rewriting also works with absolute pats #5

Merged
merged 4 commits into from

2 participants

@kux
kux commented

Besides the title:

  • added unit tests
  • refactored to use urlparse rather than os.path

NOTE:

  • all css need to be re-uploaded after making a build containing this changeset
kux added some commits
@kux kux * css url rewriting also works with absolute pats.
* added unit tests
* use urlparse rather than os.path
baffe75
@kux kux * removed unused imports
* added more unit tests
52796f2
@kux kux * don't try to clear the url cache when uploading files to the filer …
…clipboard

* when running the unit tests, clear files generated by each test (don't leave garbage behind)
42925d1
@kux kux Added test for testing a css' hash and size after rewriting a4d1201
@mcojocaru mcojocaru merged commit 1888ac5 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 27, 2012
  1. @kux

    * css url rewriting also works with absolute pats.

    kux authored
    * added unit tests
    * use urlparse rather than os.path
Commits on Dec 28, 2012
  1. @kux

    * removed unused imports

    kux authored
    * added more unit tests
Commits on Dec 29, 2012
  1. @kux

    * don't try to clear the url cache when uploading files to the filer …

    kux authored
    …clipboard
    
    * when running the unit tests, clear files generated by each test (don't leave garbage behind)
Commits on Jan 8, 2013
  1. @kux
This page is out of date. Refresh to see the latest.
View
20 filertags/signals.py
@@ -1,7 +1,5 @@
import codecs
import hashlib
-import os
-import os.path
import re
import urlparse
@@ -29,7 +27,7 @@ def _is_in_clipboard(filer_file):
def _construct_logical_folder_path(filer_file):
- return os.path.join(*(folder.name for folder in filer_file.logical_path))
+ return '/%s/' % '/'.join((folder.name for folder in filer_file.logical_path))
def _get_commented_regions(content):
@@ -134,7 +132,7 @@ def resolve_resource_urls(instance, **kwargs):
in css files.
django-filer has two concepts of urls:
- * the logical url: media/images/foobar.png
+ * the logical url: /media/images/foobar.png
* the actual url: filer_public/2012/11/22/foobar.png
Example: the css as written by the an end user uses logical urls:
@@ -155,7 +153,7 @@ def resolve_resource_urls(instance, **kwargs):
After url rewriting the above css example will look like:
.button.nice {
- background: url('filer_public/2012/11/22/foobar.png') /* logicalurl('media/images/misc/foobar.png') /* ;
+ background: url('filer_public/2012/11/22/foobar.png') /* logicalurl('/media/images/misc/foobar.png') /* ;
-moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.5);
}
@@ -191,9 +189,7 @@ def change_urls(match):
# or explicitly specifies a hostname; these are resources
# not served from filer
return match.group()
- relative_path = url
- logical_file_path = os.path.normpath(
- os.path.join(logical_folder_path, relative_path))
+ logical_file_path = urlparse.urljoin(logical_folder_path, url)
if not logical_file_path in local_cache:
local_cache[logical_file_path] = _RESOURCE_URL_TEMPLATE % (
filerfile(logical_file_path), logical_file_path)
@@ -212,7 +208,7 @@ def update_referencing_css_files(instance, **kwargs):
reference the resource pointed by 'instance'.
References are found by parsing all css files and looking for comments such as:
- /* logicalurl('media/images/misc/foobar.png') */
+ /* logicalurl('/media/images/misc/foobar.png') */
If the url between parentheses matches the logical url of the resource
being saved, the actual url (which percedes the comment)
@@ -224,7 +220,7 @@ def update_referencing_css_files(instance, **kwargs):
if _is_in_clipboard(resource_file):
return
resource_name = _get_filer_file_name(resource_file)
- logical_file_path = os.path.join(
+ logical_file_path = urlparse.urljoin(
_construct_logical_folder_path(resource_file),
resource_name)
css_files = File.objects.filter(original_filename__endswith=".css")
@@ -252,7 +248,9 @@ def update_referencing_css_files(instance, **kwargs):
def clear_urls_cache(instance, **kwargs):
"""Clears urls cached by the filerfile tag. """
- logical_file_path = os.path.join(
+ if _is_in_clipboard(instance):
+ return
+ logical_file_path = urlparse.urljoin(
_construct_logical_folder_path(instance),
instance.original_filename)
cache_key = get_filerfile_cache_key(logical_file_path)
View
BIN  filertags/test_files/foobar.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
154 filertags/tests.py
@@ -0,0 +1,154 @@
+import hashlib
+import os.path
+import re
+import shutil
+
+from django.core.cache import cache
+from django.core.files.base import File as DjangoFile, ContentFile
+from django.test import TestCase
+
+from filer.models.filemodels import File
+from filer.models.foldermodels import Folder
+from filer.settings import FILER_PUBLICMEDIA_STORAGE
+from filer.tests.helpers import create_superuser
+
+from filertags.signals import _ALREADY_PARSED_MARKER, _LOGICAL_URL_TEMPLATE
+
+
+class CssRewriteTest(TestCase):
+
+ def _get_test_usermedia_location(self):
+ HERE = os.path.dirname(os.path.realpath(__file__))
+ return os.path.join(HERE, 'tmp_user_media')
+
+ def setUp(self):
+ self.superuser = create_superuser()
+ self.client.login(username='admin', password='secret')
+ media_folder = Folder.objects.create(name='media')
+ producer = Folder.objects.create(name='producer', parent=media_folder)
+ self.producer_css = Folder.objects.create(name='css', parent=producer)
+ self.producer_images = Folder.objects.create(name='images', parent=producer)
+ self.usual_location = FILER_PUBLICMEDIA_STORAGE.location
+ # all files generated during these tests are written to ./tmp_user_media
+ # and get deleted afterwards (see tearDown)
+ FILER_PUBLICMEDIA_STORAGE.location = self._get_test_usermedia_location()
+
+ def tearDown(self):
+ cache.clear()
+ shutil.rmtree(FILER_PUBLICMEDIA_STORAGE.location)
+ FILER_PUBLICMEDIA_STORAGE.location = self.usual_location
+
+ def create_file(self, name, folder, content=None):
+ if content is None:
+ file_obj = DjangoFile(
+ open(os.path.join(os.path.dirname(__file__), 'test_files', name)),
+ name=name)
+ else:
+ file_obj = ContentFile(content, name)
+ return File.objects.create(owner=self.superuser,
+ original_filename=name,
+ file=file_obj,
+ folder=folder)
+
+ def test_abslute_url_css_before_image(self):
+ css = self.create_file('absolute_url_to_image.css', self.producer_css,
+ content="""\
+.pledge-block {
+ background: url('/media/producer/images/foobar.png');
+}
+""")
+ css_content = open(css.path).read()
+ self.assertTrue(css_content.startswith(_ALREADY_PARSED_MARKER))
+ self.assertIn("url('')", css_content)
+ logical_url = _LOGICAL_URL_TEMPLATE % '/media/producer/images/foobar.png'
+ self.assertIn(logical_url, css_content)
+ image = self.create_file('foobar.png', self.producer_images)
+ updated_css = File.objects.get(pk=css.pk)
+ new_content = open(updated_css.path).read()
+ self.assertIsNotNone(re.search(r"\burl\('[^']*foobar[^']*png'\)", new_content))
+
+ def _verify_css_is_corectly_rewritten(self, css):
+ css_content = open(css.path).read()
+ self.assertTrue(css_content.startswith(_ALREADY_PARSED_MARKER))
+ logical_url = _LOGICAL_URL_TEMPLATE % '/media/producer/images/foobar.png'
+ self.assertIn(logical_url, css_content)
+ self.assertIsNotNone(re.search(r"\burl\('[^']*foobar[^']*png'\)", css_content))
+
+ def test_abslute_url_image_before_css(self):
+ image = self.create_file('foobar.png', self.producer_images)
+ css = self.create_file('absolute_url_to_image.css', self.producer_css,
+ content="""\
+.pledge-block {
+ background: url('/media/producer/images/foobar.png');
+}
+""")
+ self._verify_css_is_corectly_rewritten(css)
+
+ def test_relative_url_image_before_css(self):
+ image = self.create_file('foobar.png', self.producer_images)
+ css = self.create_file('relative_url_to_image.css', self.producer_css,
+ content="""\
+.pledge-block {
+ background: url('../images/foobar.png');
+}
+""")
+ self._verify_css_is_corectly_rewritten(css)
+
+ def test_double_quoted_url(self):
+ image = self.create_file('foobar.png', self.producer_images)
+ css = self.create_file('relative_url_to_image.css', self.producer_css,
+ content="""\
+.pledge-block {
+ background: url( " ../images/foobar.png " );
+}
+""")
+ self._verify_css_is_corectly_rewritten(css)
+
+ def test_unquoted_url(self):
+ image = self.create_file('foobar.png', self.producer_images)
+ css = self.create_file('relative_url_to_image.css', self.producer_css,
+ content="""\
+.pledge-block {
+ background: url( ../images/foobar.png );
+}
+""")
+ self._verify_css_is_corectly_rewritten(css)
+
+ def test_commented_url(self):
+ original_content = """\
+.pledge-block {
+/* background: url( ../images/foobar.png ); */
+}
+"""
+ css = self.create_file('relative_url_to_image.css', self.producer_css,
+ content=original_content)
+ css_content = open(css.path).read()
+ # css remains unchanged since the url statement is within a comment
+ expected_content = '%s\n%s' % (_ALREADY_PARSED_MARKER, original_content)
+ self.assertEqual(expected_content, css_content)
+
+ def test_non_http_schema(self):
+ original_content = """\
+.pledge-block {
+ background: url(data:image/png;base64,iVBORw0KGgoAA);
+}
+"""
+ css = self.create_file('relative_url_to_image.css', self.producer_css,
+ content=original_content)
+ css_content = open(css.path).read()
+ expected_content = '%s\n%s' % (_ALREADY_PARSED_MARKER, original_content)
+ self.assertEqual(expected_content, css_content)
+
+ def test_file_size_and_hash(self):
+ image = self.create_file('foobar.png', self.producer_images)
+ css = self.create_file('relative_url_to_image.css', self.producer_css,
+ content="""\
+.pledge-block {
+ background: url('../images/foobar.png');
+}
+""")
+ css_content = open(css.path).read()
+ self.assertEqual(len(css_content), css.size)
+ sha = hashlib.sha1()
+ sha.update(css_content)
+ self.assertEqual(sha.hexdigest(), css.sha1)
Something went wrong with that request. Please try again.