Repository: django-compressor/django-compressor

Issue:
sekizai postprocessor reparses the Template
This seems to be a better solution for the sekizai postprocessor.

The data passed in has already been rendered, so no need to create a Template object. By passing it in to Template, any swig templates in javascript (or text created by {% templatetag %}) will get parsed as django template source, which is probably not intended.

```
from compressor.templatetags.compress import CompressorNode
from django.template.base import TextNode


def compress(context, data, name):
    """
    Data is the string from the template (the list of js files in this case)
    Name is either 'js' or 'css' (the sekizai namespace)
    Basically passes the string through the {% compress 'js' %} template tag
    """
    return CompressorNode(nodelist=TextNode(data), kind=name, mode='file').render(context=context)
```

contrib.sekizai: fix double-rendering: use TextNode, not Template
Use `TextNode(data)` instead of `Template(data).nodelist` to parse the
template only once.

The report and fix was initially provided by Aaron McMillin.

Fixes https://github.com/django-compressor/django-compressor/issues/361
Closes https://github.com/django-compressor/django-compressor/pull/362

I've taken the fix from the initial PR (#361) and have only taken the single test that triggered the bug into the existing tests for template tags.
Not sure about how to handle the credit for this - should I amend the commit (with @aarcro's authorship?)  - but then this could be done when merging / cherry-picking it, too.

sekizai postprocessor reparses the Template
This seems to be a better solution for the sekizai postprocessor.

The data passed in has already been rendered, so no need to create a Template object. By passing it in to Template, any swig templates in javascript (or text created by {% templatetag %}) will get parsed as django template source, which is probably not intended.

```
from compressor.templatetags.compress import CompressorNode
from django.template.base import TextNode


def compress(context, data, name):
    """
    Data is the string from the template (the list of js files in this case)
    Name is either 'js' or 'css' (the sekizai namespace)
    Basically passes the string through the {% compress 'js' %} template tag
    """
    return CompressorNode(nodelist=TextNode(data), kind=name, mode='file').render(context=context)
```

Fix for double render in sekizai postprocessor (fixes #361)
Here's a pull request for the issue I opened. 

(I'm fairly new at git and github, so hope I'm going about this the right way)



Discussion:
Do you think you could you write up a small testcase? You're probably right, but having some test to prove it would be nice :) 
Thanks!

Sure I'll fork and try to write up a couple tests to go with the patch today.


Do you think you could you write up a small testcase? You're probably right, but having some test to prove it would be nice :) 
Thanks!

Sure I'll fork and try to write up a couple tests to go with the patch today.



Resolving patch:
diff --git a/compressor/contrib/sekizai.py b/compressor/contrib/sekizai.py
--- a/compressor/contrib/sekizai.py
+++ b/compressor/contrib/sekizai.py
@@ -6,7 +6,7 @@
  and: https://github.com/ojii/django-sekizai.git@0.6 or later
 """
 from compressor.templatetags.compress import CompressorNode
-from django.template.base import Template
+from django.template.base import TextNode
 
 
 def compress(context, data, name):
@@ -15,4 +15,4 @@ def compress(context, data, name):
     Name is either 'js' or 'css' (the sekizai namespace)
     Basically passes the string through the {% compress 'js' %} template tag
     """
-    return CompressorNode(nodelist=Template(data).nodelist, kind=name, mode='file').render(context=context)
+    return CompressorNode(nodelist=TextNode(data), kind=name, mode='file').render(context=context)


Test patch:
diff --git a/compressor/test_settings.py b/compressor/test_settings.py
--- a/compressor/test_settings.py
+++ b/compressor/test_settings.py
@@ -22,6 +22,7 @@
     'django.contrib.staticfiles',
     'compressor',
     'coffin',
+    'sekizai',
 ]
 if django.VERSION < (1, 8):
     INSTALLED_APPS.append('jingo')
diff --git a/compressor/tests/test_templatetags.py b/compressor/tests/test_templatetags.py
--- a/compressor/tests/test_templatetags.py
+++ b/compressor/tests/test_templatetags.py
@@ -13,14 +13,18 @@
 from compressor.signals import post_compress
 from compressor.tests.test_base import css_tag, test_dir
 
+from sekizai.context import SekizaiContext
 
-def render(template_string, context_dict=None):
+
+def render(template_string, context_dict=None, context=None):
     """
     A shortcut for testing template output.
     """
     if context_dict is None:
         context_dict = {}
-    c = Context(context_dict)
+    if context is None:
+        context = Context
+    c = context(context_dict)
     t = Template(template_string)
     return t.render(c).strip()
 
@@ -126,6 +130,14 @@ def listener(sender, **kwargs):
         context = kwargs['context']
         self.assertEqual('foo', context['compressed']['name'])
 
+    def test_sekizai_only_once(self):
+        template = """{% load sekizai_tags %}{% addtoblock "js" %}
+        <script type="text/javascript">var tmpl="{% templatetag openblock %} if x == 3 %}x IS 3{% templatetag openblock %} endif %}"</script>
+        {% endaddtoblock %}{% render_block "js" postprocessor "compressor.contrib.sekizai.compress" %}
+        """
+        out = '<script type="text/javascript" src="/static/CACHE/js/e9fce10d884d.js"></script>'
+        self.assertEqual(out, render(template, self.context, SekizaiContext))
+
 
 class PrecompilerTemplatetagTestCase(TestCase):
     def setUp(self):
diff --git a/requirements/tests.txt b/requirements/tests.txt
--- a/requirements/tests.txt
+++ b/requirements/tests.txt
@@ -8,3 +8,4 @@ BeautifulSoup==3.2.1
 unittest2==1.0.0
 coffin==0.4.0
 jingo==0.7
+django-sekizai==0.8.2