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
|
||||
from os.path import dirname, abspath, join
|
||||
TEST_DIR = [dirname(abspath(__file__))]
|
||||
TEST_DIR = dirname(abspath(__file__))
|
||||
|
||||
DEBUG = True
|
||||
XDADD = ""
|
||||
|
||||
ROOT_URLCONF = 'urls'
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = join(TEST_DIR, 'media')
|
||||
|
||||
DATABASE_ENGINE = 'sqlite3'
|
||||
DATABASE_NAME = 'django_inlines_tests.db'
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'core',
|
||||
'django-compress',
|
||||
'compressor',
|
||||
]
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
)
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
join (TEST_DIR, 'templates'),
|
||||
join(TEST_DIR, 'templates'),
|
||||
)
|
||||
Reference in New Issue
Block a user