Template tags classes work through concatenation and have passing tests for most for everything implemented so far.
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
import os
|
||||||
|
from BeautifulSoup import BeautifulSoup
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from compressor.conf import settings
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
class CompressedNode(template.Node):
|
||||||
|
|
||||||
|
def __init__(self, content, ouput_prefix="compressed"):
|
||||||
|
self.content = content
|
||||||
|
self.ouput_prefix = ouput_prefix
|
||||||
|
self.hunks = []
|
||||||
|
self.split_content = []
|
||||||
|
self.soup = BeautifulSoup(self.content)
|
||||||
|
|
||||||
|
def content_hash(self):
|
||||||
|
"""docstring for content_hash"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def split_contents(self):
|
||||||
|
raise NotImplementedError('split_contents must be defined in a subclass')
|
||||||
|
|
||||||
|
def get_filename(self, url):
|
||||||
|
if not url.startswith(settings.MEDIA_URL):
|
||||||
|
# TODO: Put a proper exception here. Maybe one that only shows up
|
||||||
|
# if debug is on.
|
||||||
|
raise Exception('FIX THIS EXCPETIONS@!@')
|
||||||
|
basename = url[len(settings.MEDIA_URL):]
|
||||||
|
filename = os.path.join(settings.MEDIA_ROOT, basename)
|
||||||
|
return filename
|
||||||
|
|
||||||
|
def get_hunks(self):
|
||||||
|
if self.hunks:
|
||||||
|
return self.hunks
|
||||||
|
for k, v in self.split_contents():
|
||||||
|
if k == 'hunk':
|
||||||
|
self.hunks.append(v)
|
||||||
|
if k == 'file':
|
||||||
|
fd = open(v, 'rb')
|
||||||
|
self.hunks.append(fd.read())
|
||||||
|
fd.close()
|
||||||
|
return self.hunks
|
||||||
|
|
||||||
|
def concat(self):
|
||||||
|
return "\n".join(self.get_hunks())
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
if not settings.COMPRESS:
|
||||||
|
return self.content
|
||||||
|
return "fail"
|
||||||
|
|
||||||
|
|
||||||
|
class CompressedCssNode(CompressedNode):
|
||||||
|
|
||||||
|
def __init__(self, content, ouput_prefix="css", media="all"):
|
||||||
|
self.media = media
|
||||||
|
super(CompressedCssNode, self).__init__(content, ouput_prefix)
|
||||||
|
|
||||||
|
def split_contents(self):
|
||||||
|
if self.split_content:
|
||||||
|
return self.split_content
|
||||||
|
split = self.soup.findAll({'link' : True, 'style' : True})
|
||||||
|
for elem in split:
|
||||||
|
if elem.name == 'link' and elem['rel'] == 'stylesheet':
|
||||||
|
self.split_content.append(('file', self.get_filename(elem['href'])))
|
||||||
|
if elem.name == 'style':
|
||||||
|
self.split_content.append(('hunk', elem.string))
|
||||||
|
return self.split_content
|
||||||
|
|
||||||
|
|
||||||
|
class CompressedJsNode(CompressedNode):
|
||||||
|
|
||||||
|
def __init__(self, content, ouput_prefix="js"):
|
||||||
|
super(CompressedJsNode, self).__init__(content, ouput_prefix)
|
||||||
|
|
||||||
|
def split_contents(self):
|
||||||
|
if self.split_content:
|
||||||
|
return self.split_content
|
||||||
|
split = self.soup.findAll('script')
|
||||||
|
for elem in split:
|
||||||
|
if elem.has_key('src'):
|
||||||
|
self.split_content.append(('file', self.get_filename(elem['src'])))
|
||||||
|
else:
|
||||||
|
self.split_content.append(('hunk', elem.string))
|
||||||
|
return self.split_content
|
||||||
|
|
||||||
|
|||||||
71
tests/core/tests.py
Normal file
71
tests/core/tests.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from compressor.templatetags.compress import CompressedCssNode, CompressedJsNode
|
||||||
|
from compressor.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
class CompressedNodeTestCase(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
settings.COMPRESS = True
|
||||||
|
self.css = """
|
||||||
|
<link rel="stylesheet" href="/media/css/one.css" type="text/css" media="screen" charset="utf-8">
|
||||||
|
<style type="text/css" media="screen">p { border:5px solid green;}</style>
|
||||||
|
<link rel="stylesheet" href="/media/css/two.css" type="text/css" media="screen" charset="utf-8">
|
||||||
|
"""
|
||||||
|
self.css_output = '<link rel="stylesheet" href="/media/compressed/cssHASH.css" type="text/css" media="all" charset="utf-8">'
|
||||||
|
self.cssNode = CompressedCssNode(self.css)
|
||||||
|
|
||||||
|
self.js = """
|
||||||
|
<script src="/media/js/one.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8">obj.value = "value";</script>
|
||||||
|
"""
|
||||||
|
self.js_output = '<script src="/media/compressed/jsHASH.js" charset="utf-8"></script>'
|
||||||
|
self.jsNode = CompressedJsNode(self.js)
|
||||||
|
|
||||||
|
def test_css_split(self):
|
||||||
|
out = [
|
||||||
|
('file', os.path.join(settings.MEDIA_ROOT, u'css/one.css')),
|
||||||
|
('hunk', u'p { border:5px solid green;}'),
|
||||||
|
('file', os.path.join(settings.MEDIA_ROOT, u'css/two.css')),
|
||||||
|
]
|
||||||
|
self.assertEqual(out, self.cssNode.split_contents())
|
||||||
|
|
||||||
|
def test_css_hunks(self):
|
||||||
|
out = ['body { background:#990; }', u'p { border:5px solid green;}', 'body { color:#fff; }']
|
||||||
|
self.assertEqual(out, self.cssNode.get_hunks())
|
||||||
|
|
||||||
|
def test_css_concat(self):
|
||||||
|
out = u'body { background:#990; }\np { border:5px solid green;}\nbody { color:#fff; }'
|
||||||
|
self.assertEqual(out, self.cssNode.concat())
|
||||||
|
|
||||||
|
def test_css_return_if_off(self):
|
||||||
|
settings.COMPRESS = False
|
||||||
|
self.assertEqual(self.css, self.cssNode.render())
|
||||||
|
|
||||||
|
def test_css_return_if_on(self):
|
||||||
|
self.assertEqual(self.css_output, self.cssNode.render())
|
||||||
|
|
||||||
|
|
||||||
|
def test_js_split(self):
|
||||||
|
out = [
|
||||||
|
('file', os.path.join(settings.MEDIA_ROOT, u'js/one.js')),
|
||||||
|
('hunk', u'obj.value = "value";'),
|
||||||
|
]
|
||||||
|
self.assertEqual(out, self.jsNode.split_contents())
|
||||||
|
|
||||||
|
def test_js_hunks(self):
|
||||||
|
out = ['obj = {};', u'obj.value = "value";']
|
||||||
|
self.assertEqual(out, self.jsNode.get_hunks())
|
||||||
|
|
||||||
|
def test_js_concat(self):
|
||||||
|
out = u'obj = {};\nobj.value = "value";'
|
||||||
|
self.assertEqual(out, self.jsNode.concat())
|
||||||
|
|
||||||
|
def test_js_return_if_off(self):
|
||||||
|
settings.COMPRESS = False
|
||||||
|
self.assertEqual(self.js, self.jsNode.render())
|
||||||
|
|
||||||
|
def test_js_return_if_on(self):
|
||||||
|
self.assertEqual(self.js_output, self.jsNode.render())
|
||||||
1
tests/media/css/one.css
Normal file
1
tests/media/css/one.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
body { background:#990; }
|
||||||
1
tests/media/css/two.css
Normal file
1
tests/media/css/two.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
body { color:#fff; }
|
||||||
1
tests/media/js/one.js
Normal file
1
tests/media/js/one.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
obj = {};
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
import sys
|
import sys
|
||||||
from os.path import dirname, abspath, join
|
from os.path import dirname, abspath, join
|
||||||
TEST_DIR = [dirname(abspath(__file__))]
|
TEST_DIR = dirname(abspath(__file__))
|
||||||
|
|
||||||
|
DEBUG = True
|
||||||
|
XDADD = ""
|
||||||
|
|
||||||
ROOT_URLCONF = 'urls'
|
ROOT_URLCONF = 'urls'
|
||||||
|
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
MEDIA_ROOT = join(TEST_DIR, 'media')
|
||||||
|
|
||||||
DATABASE_ENGINE = 'sqlite3'
|
DATABASE_ENGINE = 'sqlite3'
|
||||||
DATABASE_NAME = 'django_inlines_tests.db'
|
DATABASE_NAME = 'django_inlines_tests.db'
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'core',
|
'core',
|
||||||
'django-compress',
|
'compressor',
|
||||||
]
|
]
|
||||||
TEMPLATE_LOADERS = (
|
TEMPLATE_LOADERS = (
|
||||||
'django.template.loaders.app_directories.load_template_source',
|
'django.template.loaders.app_directories.load_template_source',
|
||||||
)
|
)
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
join (TEST_DIR, 'templates'),
|
join(TEST_DIR, 'templates'),
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user