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
......@@ -107,17 +107,18 @@ type stateFn func(*lexer) stateFn
// lexer holds the state of the scanner.
type lexer struct {
name string // the name of the input; used only for error reports
input string // the string being scanned
leftDelim string // start of action
rightDelim string // end of action
pos Pos // current position in the input
start Pos // start position of this item
width Pos // width of last rune read from input
items chan item // channel of scanned items
parenDepth int // nesting depth of ( ) exprs
line int // 1+number of newlines seen
startLine int // start line of this item
name string // the name of the input; used only for error reports
input string // the string being scanned
leftDelim string // start of action
rightDelim string // end of action
trimRightDelim string // end of action with trim marker
pos Pos // current position in the input
start Pos // start position of this item
width Pos // width of last rune read from input
items chan item // channel of scanned items
parenDepth int // nesting depth of ( ) exprs
line int // 1+number of newlines seen
startLine int // start line of this item
}
// next returns the next rune in the input.
......@@ -210,13 +211,14 @@ func lex(name, input, left, right string) *lexer {
right = rightDelim
}
l := &lexer{
name: name,
input: input,
leftDelim: left,
rightDelim: right,
items: make(chan item),
line: 1,
startLine: 1,
name: name,
input: input,
leftDelim: left,
rightDelim: right,
trimRightDelim: rightTrimMarker + right,
items: make(chan item),
line: 1,
startLine: 1,
}
go l.run()
return l
......@@ -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.
func (l *lexer) atRightDelim() (delim, trimSpaces bool) {
if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
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) {
if strings.HasPrefix(l.input[l.pos:], l.trimRightDelim) { // With trim marker.
return true, true
}
if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without trim marker.
return true, false
}
return false, false
}
......@@ -366,6 +366,7 @@ func lexInsideAction(l *lexer) stateFn {
case r == eof || isEndOfLine(r):
return l.errorf("unclosed action")
case isSpace(r):
l.backup() // Put space back in case we have " -}}".
return lexSpace
case r == '=':
l.emit(itemAssign)
......@@ -418,10 +419,26 @@ func lexInsideAction(l *lexer) stateFn {
}
// 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 {
for isSpace(l.peek()) {
var r rune
var numSpaces int
for {
r = l.peek()
if !isSpace(r) {
break
}
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)
return lexInsideAction
......
......@@ -244,6 +244,7 @@ var parseTests = []parseTest{
{"trim left", "x \r\n\t{{- 3}}", noError, `"x"{{3}}`},
{"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 with extra spaces", "x\n{{- 3 -}}\ny", noError, `"x"{{3}}"y"`},
{"comment trim left", "x \r\n\t{{- /* hi */}}", noError, `"x"`},
{"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, `"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