Commit a9d0cbc5 by Timothée Peignier

Merge pull request #181 from cyberdelia/jinja-ext

re-add proper Jinja2 support
parents 782de377 10b55850
recursive-include pipeline/templates *.html
recursive-include pipeline/templates *.html *.jinja
include AUTHORS LICENSE README.rst HISTORY.rst
from __future__ import unicode_literals
from jinja2 import nodes, TemplateSyntaxError
from jinja2.ext import Extension
from django.contrib.staticfiles.storage import staticfiles_storage
from pipeline.packager import PackageNotFound
from pipeline.utils import guess_type
from pipeline.templatetags.compressed import CompressedMixin
class PipelineExtension(CompressedMixin, Extension):
tags = set(['compressed_css', 'compressed_js'])
def parse(self, parser):
tag = next(parser.stream)
package_name = parser.parse_expression()
if not package_name:
raise TemplateSyntaxError("Bad package name", tag.lineno)
args = [package_name]
if tag.value == "compressed_css":
return nodes.CallBlock(self.call_method('package_css', args), [], [], []).set_lineno(tag.lineno)
if tag.value == "compressed_js":
return nodes.CallBlock(self.call_method('package_js', args), [], [], []).set_lineno(tag.lineno)
return []
def package_css(self, package_name, *args, **kwargs):
try:
package = self.package_for(package_name, 'css')
except PackageNotFound:
return '' # fail silently, do not return anything if an invalid group is specified
return self.render_compressed(package, 'css')
def render_css(self, package, path):
template_name = package.template_name or "pipeline/css.jinja"
context = package.extra_context
context.update({
'type': guess_type(path, 'text/css'),
'url': staticfiles_storage.url(path)
})
template = self.environment.get_template(template_name)
return template.render(**context)
def render_individual_css(self, package, paths):
tags = [self.render_css(package, path) for path in paths]
return '\n'.join(tags)
def package_js(self, package_name, *args, **kwargs):
try:
package = self.package_for(package_name, 'js')
except PackageNotFound:
return '' # fail silently, do not return anything if an invalid group is specified
return self.render_compressed(package, 'js')
def render_js(self, package, path):
template_name = package.template_name or "pipeline/js.jinja"
context = package.extra_context
context.update({
'type': guess_type(path, 'text/javascript'),
'url': staticfiles_storage.url(path)
})
template = self.environment.get_template(template_name)
return template.render(**context)
def render_inline(self, package, js):
context = package.extra_context
context.update({
'source': js
})
template = self.environment.get_template("pipeline/inline_js.jinja")
return template.render(**context)
def render_individual_js(self, package, paths, templates=None):
tags = [self.render_js(package, js) for js in paths]
if templates:
tags.append(self.render_inline(package, templates))
return '\n'.join(tags)
......@@ -12,27 +12,46 @@ from pipeline.utils import guess_type
register = template.Library()
class CompressedCSSNode(template.Node):
class CompressedMixin(object):
def package_for(self, package_name, package_type):
package = {
'js': getattr(settings, 'PIPELINE_JS', {}).get(package_name, {}),
'css': getattr(settings, 'PIPELINE_CSS', {}).get(package_name, {}),
}[package_type]
if package:
package = {package_name: package}
packager = {
'js': Packager(css_packages={}, js_packages=package),
'css': Packager(css_packages=package, js_packages={}),
}[package_type]
return packager.package_for(package_type, package_name)
def render_compressed(self, package, package_type):
if not settings.DEBUG:
method = getattr(self, "render_{0}".format(package_type))
return method(package, package.output_filename)
else:
packager = Packager()
method = getattr(self, "render_individual_{0}".format(package_type))
paths = packager.compile(package.paths)
templates = packager.pack_templates(package)
return method(package, paths, templates=templates)
class CompressedCSSNode(CompressedMixin, template.Node):
def __init__(self, name):
self.name = name
def render(self, context):
package_name = template.Variable(self.name).resolve(context)
package = settings.PIPELINE_CSS.get(package_name, {})
if package:
package = {package_name: package}
self.packager = Packager(css_packages=package, js_packages={})
try:
package = self.packager.package_for('css', package_name)
package = self.package_for(package_name, 'css')
except PackageNotFound:
return '' # fail silently, do not return anything if an invalid group is specified
if not settings.DEBUG:
return self.render_css(package, package.output_filename)
else:
paths = self.packager.compile(package.paths)
return self.render_individual(package, paths)
return self.render_compressed(package, 'css')
def render_css(self, package, path):
template_name = package.template_name or "pipeline/css.html"
......@@ -43,33 +62,22 @@ class CompressedCSSNode(template.Node):
})
return render_to_string(template_name, context)
def render_individual(self, package, paths):
def render_individual_css(self, package, paths, **kwargs):
tags = [self.render_css(package, path) for path in paths]
return '\n'.join(tags)
class CompressedJSNode(template.Node):
class CompressedJSNode(CompressedMixin, template.Node):
def __init__(self, name):
self.name = name
def render(self, context):
package_name = template.Variable(self.name).resolve(context)
package = settings.PIPELINE_JS.get(package_name, {})
if package:
package = {package_name: package}
self.packager = Packager(css_packages={}, js_packages=package)
try:
package = self.packager.package_for('js', package_name)
package = self.package_for(package_name, 'js')
except PackageNotFound:
return '' # fail silently, do not return anything if an invalid group is specified
if not settings.DEBUG:
return self.render_js(package, package.output_filename)
else:
paths = self.packager.compile(package.paths)
templates = self.packager.pack_templates(package)
return self.render_individual(package, paths, templates)
return self.render_compressed(package, 'js')
def render_js(self, package, path):
template_name = package.template_name or "pipeline/js.html"
......@@ -87,7 +95,7 @@ class CompressedJSNode(template.Node):
})
return render_to_string("pipeline/inline_js.html", context)
def render_individual(self, package, paths, templates=None):
def render_individual_js(self, package, paths, templates=None):
tags = [self.render_js(package, js) for js in paths]
if templates:
tags.append(self.render_inline(package, templates))
......
{{ compressed_css('screen') }}
{{ compressed_js('scripts') }}
# -*- coding: utf-8 flake8: noqa -*-
from .test_compiler import *
from .test_compressor import *
from .test_extension import *
from .test_glob import *
from .test_packager import *
from .test_storage import *
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from jinja2 import Environment, PackageLoader
from django.test import TestCase
from pipeline.jinja2.ext import PipelineExtension
class ExtensionTest(TestCase):
def setUp(self):
self.env = Environment(extensions=[PipelineExtension], loader=
PackageLoader('pipeline', 'templates'))
def test_no_package(self):
template = self.env.from_string(u"""{% compressed_css "unknow" %}""")
self.assertEqual(u'', template.render())
template = self.env.from_string(u"""{% compressed_js "unknow" %}""")
self.assertEqual(u'', template.render())
def test_package_css(self):
template = self.env.from_string(u"""{% compressed_css "screen" %}""")
self.assertEqual(u'<link href="/static/screen.css" rel="stylesheet" type="text/css" />', template.render())
def test_package_js(self):
template = self.env.from_string(u"""{% compressed_js "scripts" %}""")
self.assertEqual(u'<script type="text/css" src="/static/scripts.css" charset="utf-8"></script>', template.render())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment