File: jinja2ext.py

package info (click to toggle)
python-django-compressor 4.5.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,124 kB
  • sloc: python: 4,906; makefile: 123; javascript: 5
file content (92 lines) | stat: -rw-r--r-- 3,252 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from jinja2 import nodes
from jinja2.ext import Extension
from jinja2.exceptions import TemplateSyntaxError

from compressor.templatetags import compress


# Allow django like definitions which assume constants instead of variables
def const(node):
    if isinstance(node, nodes.Name):
        return nodes.Const(node.name)
    else:
        return node


class CompressorExtension(compress.CompressorMixin, Extension):

    tags = set(["compress"])

    def parse(self, parser):
        # Store the first lineno for the actual function call
        lineno = parser.stream.current.lineno
        next(parser.stream)
        args = []

        kindarg = const(parser.parse_expression())

        if kindarg.value in self.compressors:
            args.append(kindarg)
        else:
            raise TemplateSyntaxError(
                "Compress kind may be one of: %r, got: %r"
                % (self.compressors.keys(), kindarg.value),
                parser.stream.current.lineno,
            )

        # For legacy support, allow for a comma but simply ignore it
        parser.stream.skip_if("comma")

        # Some sane defaults for file output
        namearg = nodes.Const(None)
        modearg = nodes.Const("file")

        # If we're not at the "%}" part yet we must have a output mode argument
        if parser.stream.current.type != "block_end":
            modearg = const(parser.parse_expression())
            args.append(modearg)

            if modearg.value == compress.OUTPUT_FILE:
                # The file mode optionally accepts a name
                if parser.stream.current.type != "block_end":
                    namearg = const(parser.parse_expression())
            elif (
                modearg.value == compress.OUTPUT_INLINE
                or modearg.value == compress.OUTPUT_PRELOAD
            ):
                pass
            else:
                raise TemplateSyntaxError(
                    "Compress mode may be one of: %r, got %r"
                    % (compress.OUTPUT_MODES, modearg.value),
                    parser.stream.current.lineno,
                )

        # Parse everything between the compress and endcompress tags
        body = parser.parse_statements(["name:endcompress"], drop_needle=True)

        # Skip the kind if used in the endblock, by using the kind in the
        # endblock the templates are slightly more readable.
        parser.stream.skip_if("name:" + kindarg.value)

        return nodes.CallBlock(
            self.call_method("_compress_normal", [kindarg, modearg, namearg]),
            [],
            [],
            body,
        ).set_lineno(lineno)

    def _compress_forced(self, kind, mode, name, caller):
        return self._compress(kind, mode, name, caller, True)

    def _compress_normal(self, kind, mode, name, caller):
        return self._compress(kind, mode, name, caller, False)

    def _compress(self, kind, mode, name, caller, forced):
        mode = mode or compress.OUTPUT_FILE
        original_content = caller()
        context = {"original_content": original_content}
        return self.render_compressed(context, kind, mode, name, forced=forced)

    def get_original_content(self, context):
        return context["original_content"]