| @@ -1553,6 +1553,12 @@ static int Tokenizer_parse_comment(Tokenizer* self) | |||||
| return -1; | return -1; | ||||
| Py_DECREF(comment); | Py_DECREF(comment); | ||||
| self->head += 2; | self->head += 2; | ||||
| if (self->topstack->context & LC_FAIL_NEXT) { | |||||
| /* _verify_safe() sets this flag while parsing a template name | |||||
| when it encounters what might be a comment -- we must unset | |||||
| it to let _verify_safe() know it was correct: */ | |||||
| self->topstack->context ^= LC_FAIL_NEXT; | |||||
| } | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (Tokenizer_emit_char(self, this)) | if (Tokenizer_emit_char(self, this)) | ||||
| @@ -2478,8 +2484,13 @@ static int Tokenizer_verify_safe(Tokenizer* self, int context, Py_UNICODE data) | |||||
| return 0; | return 0; | ||||
| if (context & LC_HAS_TEXT) { | if (context & LC_HAS_TEXT) { | ||||
| if (context & LC_FAIL_ON_TEXT) { | if (context & LC_FAIL_ON_TEXT) { | ||||
| if (!Py_UNICODE_ISSPACE(data)) | |||||
| if (!Py_UNICODE_ISSPACE(data)) { | |||||
| if (data == '<' && Tokenizer_READ(self, 1) == '!') { | |||||
| self->topstack->context |= LC_FAIL_NEXT; | |||||
| return 0; | |||||
| } | |||||
| return -1; | return -1; | ||||
| } | |||||
| } | } | ||||
| else { | else { | ||||
| if (data == '\n') | if (data == '\n') | ||||
| @@ -2496,8 +2507,8 @@ static int Tokenizer_verify_safe(Tokenizer* self, int context, Py_UNICODE data) | |||||
| } | } | ||||
| } | } | ||||
| else if (context & LC_FAIL_ON_LBRACE) { | else if (context & LC_FAIL_ON_LBRACE) { | ||||
| if (data == '{' || (Tokenizer_READ(self, -1) == '{' && | |||||
| Tokenizer_READ(self, -2) == '{')) { | |||||
| if (data == '{' || (Tokenizer_READ_BACKWARDS(self, 1) == '{' && | |||||
| Tokenizer_READ_BACKWARDS(self, 2) == '{')) { | |||||
| if (context & LC_TEMPLATE) | if (context & LC_TEMPLATE) | ||||
| self->topstack->context |= LC_FAIL_ON_EQUALS; | self->topstack->context |= LC_FAIL_ON_EQUALS; | ||||
| else | else | ||||
| @@ -608,6 +608,11 @@ class Tokenizer(object): | |||||
| self._emit(tokens.CommentEnd()) | self._emit(tokens.CommentEnd()) | ||||
| self._emit_all(self._pop()) | self._emit_all(self._pop()) | ||||
| self._head += 2 | self._head += 2 | ||||
| if self._context & contexts.FAIL_NEXT: | |||||
| # _verify_safe() sets this flag while parsing a template | |||||
| # name when it encounters what might be a comment -- we | |||||
| # must unset it to let _verify_safe() know it was correct: | |||||
| self._context ^= contexts.FAIL_NEXT | |||||
| return | return | ||||
| self._emit_text(this) | self._emit_text(this) | ||||
| self._head += 1 | self._head += 1 | ||||
| @@ -1021,6 +1026,9 @@ class Tokenizer(object): | |||||
| if context & contexts.HAS_TEXT: | if context & contexts.HAS_TEXT: | ||||
| if context & contexts.FAIL_ON_TEXT: | if context & contexts.FAIL_ON_TEXT: | ||||
| if this is self.END or not this.isspace(): | if this is self.END or not this.isspace(): | ||||
| if this == "<" and self._read(1) == "!": | |||||
| self._context |= contexts.FAIL_NEXT | |||||
| return True | |||||
| return False | return False | ||||
| else: | else: | ||||
| if this == "\n": | if this == "\n": | ||||
| @@ -227,3 +227,17 @@ name: newline_and_comment_in_template_name_5 | |||||
| label: a template name containing a newline followed by a comment | label: a template name containing a newline followed by a comment | ||||
| input: "{{foobar\n<!-- comment -->\ninvalid|key=value}}" | input: "{{foobar\n<!-- comment -->\ninvalid|key=value}}" | ||||
| output: [Text(text="{{foobar\n"), CommentStart(), Text(text=" comment "), CommentEnd(), Text(text="\ninvalid|key=value}}")] | output: [Text(text="{{foobar\n"), CommentStart(), Text(text=" comment "), CommentEnd(), Text(text="\ninvalid|key=value}}")] | ||||
| --- | |||||
| name: newline_and_comment_in_template_name_6 | |||||
| label: a template name containing a newline followed by a comment | |||||
| input: "{{foobar\n<!--|key=value}}" | |||||
| output: [Text(text="{{foobar\n<!--|key=value}}")] | |||||
| --- | |||||
| name: newline_and_comment_in_template_name_7 | |||||
| label: a template name containing a newline followed by a comment | |||||
| input: "{{foobar\n<!|key=value}}" | |||||
| output: [Text(text="{{foobar\n<!|key=value}}")] | |||||