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"]
|