1
0
mirror of https://github.com/golang/go synced 2024-09-30 18:18:32 -06:00

text/template: allow newlines in raw quotes

This was disallowed for error-checking reasons but people ask for
it, it's easy, and it's clear what it all means.

Fixes #7323.

Change-Id: I26542f5ac6519e45b335ad789713a4d9e356279b
Reviewed-on: https://go-review.googlesource.com/9537
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Rob Pike 2015-04-30 12:11:35 -07:00
parent cf3ac26a4c
commit 042200145f
4 changed files with 32 additions and 16 deletions

View File

@ -18,7 +18,7 @@ structure as execution proceeds.
The input text for a template is UTF-8-encoded text in any format.
"Actions"--data evaluations or control structures--are delimited by
"{{" and "}}"; all text outside actions is copied to the output unchanged.
Actions may not span newlines, although comments can.
Except for raw strings, actions may not span newlines, although comments can.
Once parsed, a template may be executed safely in parallel.
@ -106,7 +106,7 @@ An argument is a simple value, denoted by one of the following.
- A boolean, string, character, integer, floating-point, imaginary
or complex constant in Go syntax. These behave like Go's untyped
constants, although raw strings may not span newlines.
constants.
- The keyword nil, representing an untyped Go nil.
- The character '.' (period):
.

View File

@ -1095,3 +1095,16 @@ func TestMissingMapKey(t *testing.T) {
t.Errorf("expected error; got none")
}
}
// Test that the error message for multiline unterminated string
// refers to the line number of the opening quote.
func TestUnterminatedStringError(t *testing.T) {
_, err := New("X").Parse("hello\n\n{{`unterminated\n\n\n\n}}\n some more\n\n")
if err == nil {
t.Fatal("expected error")
}
str := err.Error()
if !strings.Contains(str, "X:3: unexpected unterminated raw quoted strin") {
t.Fatalf("unexpected error: %s", str)
}
}

View File

@ -525,7 +525,7 @@ func lexRawQuote(l *lexer) stateFn {
Loop:
for {
switch l.next() {
case eof, '\n':
case eof:
return l.errorf("unterminated raw quoted string")
case '`':
break Loop

View File

@ -58,18 +58,20 @@ type lexTest struct {
}
var (
tEOF = item{itemEOF, 0, ""}
tFor = item{itemIdentifier, 0, "for"}
tLeft = item{itemLeftDelim, 0, "{{"}
tLpar = item{itemLeftParen, 0, "("}
tPipe = item{itemPipe, 0, "|"}
tQuote = item{itemString, 0, `"abc \n\t\" "`}
tRange = item{itemRange, 0, "range"}
tRight = item{itemRightDelim, 0, "}}"}
tRpar = item{itemRightParen, 0, ")"}
tSpace = item{itemSpace, 0, " "}
raw = "`" + `abc\n\t\" ` + "`"
tRawQuote = item{itemRawString, 0, raw}
tEOF = item{itemEOF, 0, ""}
tFor = item{itemIdentifier, 0, "for"}
tLeft = item{itemLeftDelim, 0, "{{"}
tLpar = item{itemLeftParen, 0, "("}
tPipe = item{itemPipe, 0, "|"}
tQuote = item{itemString, 0, `"abc \n\t\" "`}
tRange = item{itemRange, 0, "range"}
tRight = item{itemRightDelim, 0, "}}"}
tRpar = item{itemRightParen, 0, ")"}
tSpace = item{itemSpace, 0, " "}
raw = "`" + `abc\n\t\" ` + "`"
rawNL = "`now is{{\n}}the time`" // Contains newline inside raw quote.
tRawQuote = item{itemRawString, 0, raw}
tRawQuoteNL = item{itemRawString, 0, rawNL}
)
var lexTests = []lexTest{
@ -104,6 +106,7 @@ var lexTests = []lexTest{
{"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
{"raw quote with newline", "{{" + rawNL + "}}", []item{tLeft, tRawQuoteNL, tRight, tEOF}},
{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
tLeft,
{itemNumber, 0, "1"},
@ -294,7 +297,7 @@ var lexTests = []lexTest{
tLeft,
{itemError, 0, "unterminated quoted string"},
}},
{"unclosed raw quote", "{{`xx\n`}}", []item{
{"unclosed raw quote", "{{`xx}}", []item{
tLeft,
{itemError, 0, "unterminated raw quoted string"},
}},