1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-27 08:34:42 +01:00
liquid/chunks/scanner.go
Oliver Steele 803fbbcd61 Docs
2017-06-26 12:41:41 -04:00

67 lines
2.0 KiB
Go

//go:generate stringer -type=ChunkType
package chunks
import (
"regexp"
)
// Chunk is a chunk of a template source. It is one of an object "{{…}}", a tag "{%…%}", or the text between objects and tags.
type Chunk struct {
Type ChunkType
SourceInfo SourceInfo
Source string // Source is the entirety of the chunk, including the "{{", "{%", etc. markers.
Tag string // Tag is the tag name of a tag Chunk. E.g. the tag name of "{% if 1 %}" is "if".
Args string // Args is the tag arguments of a tag Chunk. E.g. the tag arguments of "{% if 1 %}" is "1".
}
// SourceInfo contains a Chunk's source information
type SourceInfo struct {
Pathname string
lineNo int
}
// ChunkType is the type of a Chunk
type ChunkType int
const (
TextChunkType ChunkType = iota // TextChunkType is the type of a text Chunk
TagChunkType // TagChunkType is the type of a tag Chunk "{%…%}"
ObjChunkType // TextChunkType is the type of an object Chunk "{{…}}"
)
var chunkMatcher = regexp.MustCompile(`{{\s*(.+?)\s*}}|{%\s*(\w+)(?:\s+(.+?))?\s*%}`)
// Scan breaks a string into a sequence of Chunks.
func Scan(data string, pathname string) []Chunk {
// TODO error on unterminated {{ and {%
// TODO probably an error when a tag contains a {{ or {%, at least outside of a string
var (
sourceInfo = SourceInfo{pathname, 0}
out = make([]Chunk, 0)
p, pe = 0, len(data)
matches = chunkMatcher.FindAllStringSubmatchIndex(data, -1)
)
for _, m := range matches {
ts, te := m[0], m[1]
if p < ts {
out = append(out, Chunk{TextChunkType, sourceInfo, data[p:ts], "", ""})
}
switch data[ts+1] {
case '{':
out = append(out, Chunk{ObjChunkType, sourceInfo, data[ts:te], "", data[m[2]:m[3]]})
case '%':
var args string
if m[6] > 0 {
args = data[m[6]:m[7]]
}
out = append(out, Chunk{TagChunkType, sourceInfo, data[ts:te], data[m[4]:m[5]], args})
}
p = te
}
if p < pe {
out = append(out, Chunk{TextChunkType, sourceInfo, data[p:], "", ""})
}
return out
}