Commit e770b5b3 authored by Daniel Martí's avatar Daniel Martí Committed by Rob Pike

text/template: allow using -}} with many spaces

lexSpace consumed all spaces, even if the last one was part of a right
delimiter like " -}}". Thus, "3  -}}" wouldn't lex as "3" and a right
delimiter, but as "3", "-", and "}}".

To fix that, make lexSpace stop if it encounters a right delimiter.

Fixes #30948.

Change-Id: I80a5546e5809e54f6823e2bf3a57a7e8808329be
Reviewed-on: https://go-review.googlesource.com/c/go/+/168457Reviewed-by: default avatarDaniel Martí <mvdan@mvdan.cc>
parent b434bbf1
...@@ -111,6 +111,7 @@ type lexer struct { ...@@ -111,6 +111,7 @@ type lexer struct {
input string // the string being scanned input string // the string being scanned
leftDelim string // start of action leftDelim string // start of action
rightDelim string // end of action rightDelim string // end of action
trimRightDelim string // end of action with trim marker
pos Pos // current position in the input pos Pos // current position in the input
start Pos // start position of this item start Pos // start position of this item
width Pos // width of last rune read from input width Pos // width of last rune read from input
...@@ -214,6 +215,7 @@ func lex(name, input, left, right string) *lexer { ...@@ -214,6 +215,7 @@ func lex(name, input, left, right string) *lexer {
input: input, input: input,
leftDelim: left, leftDelim: left,
rightDelim: right, rightDelim: right,
trimRightDelim: rightTrimMarker + right,
items: make(chan item), items: make(chan item),
line: 1, line: 1,
startLine: 1, startLine: 1,
...@@ -275,14 +277,12 @@ func rightTrimLength(s string) Pos { ...@@ -275,14 +277,12 @@ func rightTrimLength(s string) Pos {
// atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker. // atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker.
func (l *lexer) atRightDelim() (delim, trimSpaces bool) { func (l *lexer) atRightDelim() (delim, trimSpaces bool) {
if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { if strings.HasPrefix(l.input[l.pos:], l.trimRightDelim) { // With trim marker.
return true, false
}
// The right delim might have the marker before.
if strings.HasPrefix(l.input[l.pos:], rightTrimMarker) &&
strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) {
return true, true return true, true
} }
if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without trim marker.
return true, false
}
return false, false return false, false
} }
...@@ -366,6 +366,7 @@ func lexInsideAction(l *lexer) stateFn { ...@@ -366,6 +366,7 @@ func lexInsideAction(l *lexer) stateFn {
case r == eof || isEndOfLine(r): case r == eof || isEndOfLine(r):
return l.errorf("unclosed action") return l.errorf("unclosed action")
case isSpace(r): case isSpace(r):
l.backup() // Put space back in case we have " -}}".
return lexSpace return lexSpace
case r == '=': case r == '=':
l.emit(itemAssign) l.emit(itemAssign)
...@@ -418,10 +419,26 @@ func lexInsideAction(l *lexer) stateFn { ...@@ -418,10 +419,26 @@ func lexInsideAction(l *lexer) stateFn {
} }
// lexSpace scans a run of space characters. // lexSpace scans a run of space characters.
// One space has already been seen. // We have not consumed the first space, which is known to be present.
// Take care if there is a trim-marked right delimiter, which starts with a space.
func lexSpace(l *lexer) stateFn { func lexSpace(l *lexer) stateFn {
for isSpace(l.peek()) { var r rune
var numSpaces int
for {
r = l.peek()
if !isSpace(r) {
break
}
l.next() l.next()
numSpaces++
}
// Be careful about a trim-marked closing delimiter, which has a minus
// after a space. We know there is a space, so check for the '-' that might follow.
if strings.HasPrefix(l.input[l.pos-1:], l.trimRightDelim) {
l.backup() // Before the space.
if numSpaces == 1 {
return lexRightDelim // On the delim, so go right to that.
}
} }
l.emit(itemSpace) l.emit(itemSpace)
return lexInsideAction return lexInsideAction
......
...@@ -244,6 +244,7 @@ var parseTests = []parseTest{ ...@@ -244,6 +244,7 @@ var parseTests = []parseTest{
{"trim left", "x \r\n\t{{- 3}}", noError, `"x"{{3}}`}, {"trim left", "x \r\n\t{{- 3}}", noError, `"x"{{3}}`},
{"trim right", "{{3 -}}\n\n\ty", noError, `{{3}}"y"`}, {"trim right", "{{3 -}}\n\n\ty", noError, `{{3}}"y"`},
{"trim left and right", "x \r\n\t{{- 3 -}}\n\n\ty", noError, `"x"{{3}}"y"`}, {"trim left and right", "x \r\n\t{{- 3 -}}\n\n\ty", noError, `"x"{{3}}"y"`},
{"trim with extra spaces", "x\n{{- 3 -}}\ny", noError, `"x"{{3}}"y"`},
{"comment trim left", "x \r\n\t{{- /* hi */}}", noError, `"x"`}, {"comment trim left", "x \r\n\t{{- /* hi */}}", noError, `"x"`},
{"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, `"y"`}, {"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, `"y"`},
{"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x""y"`}, {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x""y"`},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment