Permalink
Browse files

allow for http/https urls to render without media prefix

  • Loading branch information...
1 parent 72432a9 commit 16d813d3f267f7d78477ea0410053e8139b163c3 Jen Fong-Adwent committed with cvan Aug 20, 2012
Showing with 158 additions and 7 deletions.
  1. +10 −0 examples/minify/settings.py
  2. +14 −3 jingo_minify/helpers.py
  3. +45 −1 jingo_minify/management/commands/compress_assets.py
  4. +89 −3 jingo_minify/tests.py
@@ -21,8 +21,18 @@
MINIFY_BUNDLES = {
'css': {
'common': ['css/test.css'],
+ 'common_url': ['http://example.com/test.css'],
+ 'common_protocol_less_url': ['//example.com/test.css'],
+ 'common_bundle': ['css/test.css', 'http://example.com/test.css',
+ '//example.com/test.css',
+ 'https://example.com/test.css']
},
'js': {
'common': ['js/test.js'],
+ 'common_url': ['http://example.com/test.js'],
+ 'common_protocol_less_url': ['//example.com/test.js'],
+ 'common_bundle': ['js/test.js', 'http://example.com/test.js',
+ '//example.com/test.js',
+ 'https://example.com/test.js'],
},
}
View
@@ -16,13 +16,24 @@
path = lambda *a: os.path.join(settings.MEDIA_ROOT, *a)
+
+def _get_item_path(item):
+ """
+ Determine whether to return a relative path or a URL.
+ """
+ if item.startswith(('//', 'http', 'https')):
+ return item
+ return settings.MEDIA_URL + item
+
+
def _build_html(items, wrapping):
"""
Wrap `items` in wrapping.
"""
- return jinja2.Markup("\n".join((wrapping % (settings.MEDIA_URL + item)
+ return jinja2.Markup('\n'.join((wrapping % (_get_item_path(item))
for item in items)))
+
@register.function
def js(bundle, debug=settings.TEMPLATE_DEBUG, defer=False, async=False):
"""
@@ -40,7 +51,7 @@ def js(bundle, debug=settings.TEMPLATE_DEBUG, defer=False, async=False):
bundle_full = "js:%s" % bundle
if bundle_full in BUNDLE_HASHES:
build_id = BUNDLE_HASHES[bundle_full]
- items = ("js/%s-min.js?build=%s" % (bundle, build_id,),)
+ items = ('js/%s-min.js?build=%s' % (bundle, build_id,),)
attrs.append('src="%s"')
@@ -81,7 +92,7 @@ def css(bundle, media=False, debug=settings.TEMPLATE_DEBUG):
if bundle_full in BUNDLE_HASHES:
build_id = BUNDLE_HASHES[bundle_full]
- items = ("css/%s-min.css?build=%s" % (bundle, build_id,),)
+ items = ('css/%s-min.css?build=%s' % (bundle, build_id,),)
return _build_html(items,
'<link rel="stylesheet" media="%s" href="%%s" />' % media)
@@ -2,7 +2,9 @@
from optparse import make_option
import os
import re
+import shutil
import time
+import urllib2
from subprocess import call, PIPE
from django.conf import settings
@@ -29,6 +31,7 @@ class Command(BaseCommand): # pragma: no cover
missing_files = 0
minify_skipped = 0
cmd_errors = False
+ ext_media_path = os.path.join(settings.MEDIA_ROOT, 'external')
def update_hashes(self, update=False):
def gitid(path):
@@ -120,8 +123,50 @@ def _call(self, *args, **kw):
self.cmd_errors = True
return exit
+ def _get_url_or_path(self, item):
+ """
+ Determine whether this is a URL or a relative path.
+ """
+ if item.startswith('//'):
+ return 'http:%s' % item
+ elif item.startswith(('http', 'https')):
+ return item
+ return None
+
def _preprocess_file(self, filename):
"""Preprocess files and return new filenames."""
+ url = self._get_url_or_path(filename)
+ if url:
+ # External files from URLs are placed into a subdirectory.
+ if not os.path.exists(self.ext_media_path):
+ os.makedirs(self.ext_media_path)
+
+ filename = os.path.basename(url)
+ if filename.endswith(('.js', '.css', '.less')):
+ fp = path(filename.lstrip('/'))
+ file_path = '%s/%s' % (self.ext_media_path, filename)
+
+ try:
+ req = urllib2.urlopen(url)
+ print ' - Fetching %s ...' % url
+ except urllib2.HTTPError, e:
+ print ' - HTTP Error %s for %s, %s' % (url, filename,
+ str(e.code))
+ return ''
+ except urllib2.URLError, e:
+ print ' - Invalid URL %s for %s, %s' % (url, filename,
+ str(e.reason))
+ return ''
+
+ with open(file_path, 'w+') as fp:
+ try:
+ shutil.copyfileobj(req, fp)
+ except shutil.Error:
+ print ' - Could not copy file %s' % filename
+ filename = os.path.join('external', filename)
+ else:
+ print ' - Not a valid remote file %s' % filename
+
if filename.endswith('.less'):
fp = path(filename.lstrip('/'))
self._call('%s %s %s.css' % (settings.LESS_BIN, fp, fp),
@@ -217,4 +262,3 @@ def _cachebust_regex(self, img, parent):
url)
return "url(%s?%s)" % (url, self._file_hash(full_url))
-
View
@@ -38,8 +38,46 @@ def test_js_helper(time):
t = env.from_string("{{ js('common', debug=False) }}")
s = t.render()
+ eq_(s, '<script src="%sjs/common-min.js?build=%s"></script>' %
+ (settings.MEDIA_URL, BUILD_ID_JS))
+
+ t = env.from_string("{{ js('common_url', debug=True) }}")
+ s = t.render()
+
+ eq_(s, '<script src="%s"></script>' %
+ "http://example.com/test.js?build=1")
+
+ t = env.from_string("{{ js('common_url', debug=False) }}")
+ s = t.render()
+
+ eq_(s, '<script src="%sjs/common_url-min.js?build=%s"></script>' %
+ (settings.MEDIA_URL, BUILD_ID_JS))
+
+ t = env.from_string("{{ js('common_protocol_less_url', debug=True) }}")
+ s = t.render()
+
eq_(s, '<script src="%s"></script>' %
- (settings.MEDIA_URL + "js/common-min.js?build=%s" % BUILD_ID_JS))
+ "//example.com/test.js?build=1")
+
+ t = env.from_string("{{ js('common_protocol_less_url', debug=False) }}")
+ s = t.render()
+
+ eq_(s, '<script src="%sjs/common_protocol_less_url-min.js?build=%s">'
+ '</script>' % (settings.MEDIA_URL, BUILD_ID_JS))
+
+ t = env.from_string("{{ js('common_bundle', debug=True) }}")
+ s = t.render()
+
+ eq_(s, '<script src="js/test.js?build=1"></script>\n'
+ '<script src="http://example.com/test.js?build=1"></script>\n'
+ '<script src="//example.com/test.js?build=1"></script>\n'
+ '<script src="https://example.com/test.js?build=1"></script>')
+
+ t = env.from_string("{{ js('common_bundle', debug=False) }}")
+ s = t.render()
+
+ eq_(s, '<script src="%sjs/common_bundle-min.js?build=%s"></script>' %
+ (settings.MEDIA_URL, BUILD_ID_JS))
@patch('jingo_minify.helpers.time.time')
@@ -67,5 +105,53 @@ def test_css_helper(time):
s = t.render()
eq_(s,
- '<link rel="stylesheet" media="screen,projection,tv" href="%s" />'
- % (settings.MEDIA_URL + 'css/common-min.css?build=%s' % BUILD_ID_CSS))
+ '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="%scss/common-min.css?build=%s" />'
+ % (settings.MEDIA_URL, BUILD_ID_CSS))
+
+ t = env.from_string("{{ css('common_url', debug=True) }}")
+ s = t.render()
+
+ eq_(s, '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="http://example.com/test.css?build=1" />')
+
+ t = env.from_string("{{ css('common_url', debug=False) }}")
+ s = t.render()
+
+ eq_(s,
+ '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="%scss/common_url-min.css?build=%s" />'
+ % (settings.MEDIA_URL, BUILD_ID_CSS))
+
+ t = env.from_string("{{ css('common_protocol_less_url', debug=True) }}")
+ s = t.render()
+
+ eq_(s, '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="//example.com/test.css?build=1" />')
+
+ t = env.from_string("{{ css('common_protocol_less_url', debug=False) }}")
+ s = t.render()
+
+ eq_(s,
+ '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="%scss/common_protocol_less_url-min.css?build=%s" />'
+ % (settings.MEDIA_URL, BUILD_ID_CSS))
+
+ t = env.from_string("{{ css('common_bundle', debug=True) }}")
+ s = t.render()
+
+ eq_(s, '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="css/test.css?build=1" />\n'
+ '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="http://example.com/test.css?build=1" />\n'
+ '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="//example.com/test.css?build=1" />\n'
+ '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="https://example.com/test.css?build=1" />')
+
+ t = env.from_string("{{ css('common_bundle', debug=False) }}")
+ s = t.render()
+
+ eq_(s, '<link rel="stylesheet" media="screen,projection,tv" '
+ 'href="%scss/common_bundle-min.css?build=%s" />' %
+ (settings.MEDIA_URL, BUILD_ID_CSS))

0 comments on commit 16d813d

Please sign in to comment.