Commit 4464bbba authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

Fixed #14502 -- Added a verbatim template tag.

Thanks SmileyChris for the patch.
parent 2c57809a
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@ class Lexer(object):
        self.template_string = template_string
        self.origin = origin
        self.lineno = 1
        self.verbatim = False

    def tokenize(self):
        """
@@ -203,15 +204,26 @@ class Lexer(object):
        If in_tag is True, we are processing something that matched a tag,
        otherwise it should be treated as a literal string.
        """
        if in_tag:
        if in_tag and token_string.startswith(BLOCK_TAG_START):
            # The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.
            # We could do len(BLOCK_TAG_START) to be more "correct", but we've
            # hard-coded the 2s here for performance. And it's not like
            # the TAG_START values are going to change anytime, anyway.
            block_content = token_string[2:-2].strip()
            if self.verbatim and block_content == self.verbatim:
                self.verbatim = False
        if in_tag and not self.verbatim:
            if token_string.startswith(VARIABLE_TAG_START):
                token = Token(TOKEN_VAR, token_string[2:-2].strip())
            elif token_string.startswith(BLOCK_TAG_START):
                token = Token(TOKEN_BLOCK, token_string[2:-2].strip())
                if block_content.startswith('verbatim'):
                    bits = block_content.split(' ', 1)
                    if bits[0] == 'verbatim':
                        if len(bits) > 1:
                            self.verbatim = bits[1]
                        else:
                            self.verbatim = 'endverbatim'
                token = Token(TOKEN_BLOCK, block_content)
            elif token_string.startswith(COMMENT_TAG_START):
                content = ''
                if token_string.find(TRANSLATOR_COMMENT_MARK):
+34 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ from datetime import datetime
from itertools import groupby, cycle as itertools_cycle

from django.conf import settings
from django.template.base import (Node, NodeList, Template, Library,
from django.template.base import (Node, NodeList, Template, Context, Library,
    TemplateSyntaxError, VariableDoesNotExist, InvalidTemplateLibrary,
    BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END,
    SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END,
@@ -425,6 +425,13 @@ class URLNode(Node):
        else:
            return url

class VerbatimNode(Node):
    def __init__(self, content):
        self.content = content

    def render(self, context):
        return self.content

class WidthRatioNode(Node):
    def __init__(self, val_expr, max_expr, max_width):
        self.val_expr = val_expr
@@ -1272,6 +1279,32 @@ def url(parser, token):

    return URLNode(viewname, args, kwargs, asvar)

@register.tag
def verbatim(parser, token):
    """
    Stops the template engine from rendering the contents of this block tag.

    Usage::

        {% verbatim %}
            {% don't process this %}
        {% endverbatim %}

    You can also specify an alternate closing tag::

        {% verbatim -- %}
            ...
        {% -- %}
    """
    bits = token.contents.split(' ', 1)
    if len(bits) > 1:
        closing_tag = bits[1]
    else:
        closing_tag = 'endverbatim'
    nodelist = parser.parse((closing_tag,))
    parser.delete_first_token()
    return VerbatimNode(nodelist.render(Context()))

@register.tag
def widthratio(parser, token):
    """
+23 −0
Original line number Diff line number Diff line
@@ -1040,6 +1040,29 @@ This will follow the normal :ref:`namespaced URL resolution strategy
<topics-http-reversing-url-namespaces>`, including using any hints provided
by the context as to the current application.

.. templatetag:: verbatim

verbatim
^^^^^^^^

.. versionadded:: 1.5

Stops the template engine from rendering the contents of this block tag.

A common use is to allow a Javascript template layer that collides with
Django's syntax. For example::

    {% verbatim %}
        {{if dying}}Still alive.{{/if}}
    {% endverbatim %}

You can also specify an alternate closing tag::

    {% verbatim finished %}
        The verbatim tag looks like this:
        {% verbatim %}{% endverbatim %}
    {% finished %}

.. templatetag:: widthratio

widthratio
+7 −0
Original line number Diff line number Diff line
@@ -62,6 +62,13 @@ For one-to-one relationships, both sides can be cached. For many-to-one
relationships, only the single side of the relationship can be cached. This
is particularly helpful in combination with ``prefetch_related``.

``{% verbatim %}`` template tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To make it easier to deal with javascript templates which collide with Django's
syntax, you can now use the :ttag:`verbatim` block tag to avoid parsing the
tag's content.

Minor features
~~~~~~~~~~~~~~

+8 −0
Original line number Diff line number Diff line
@@ -1616,6 +1616,14 @@ class Templates(unittest.TestCase):
            'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL),
            'static-statictag01': ('{% load static %}{% static "admin/base.css" %}', {}, urljoin(settings.STATIC_URL, 'admin/base.css')),
            'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')),

            # Verbatim template tag outputs contents without rendering.
            'verbatim-tag01': ('{% verbatim %}{{bare   }}{% endverbatim %}', {}, '{{bare   }}'),
            'verbatim-tag02': ('{% verbatim %}{% endif %}{% endverbatim %}', {}, '{% endif %}'),
            'verbatim-tag03': ("{% verbatim %}It's the {% verbatim %} tag{% endverbatim %}", {}, "It's the {% verbatim %} tag"),
            'verbatim-tag04': ('{% verbatim %}{% verbatim %}{% endverbatim %}{% endverbatim %}', {}, template.TemplateSyntaxError),
            'verbatim-tag05': ('{% verbatim %}{% endverbatim %}{% verbatim %}{% endverbatim %}', {}, ''),
            'verbatim-tag06': ("{% verbatim -- %}Don't {% endverbatim %} just yet{% -- %}", {}, "Don't {% endverbatim %} just yet"),
        }
        return tests