1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-30 10:19:03 +01:00
liquid/chunks/scanner.go

74 lines
1.5 KiB
Go
Raw Normal View History

2017-06-25 18:36:28 +02:00
//go:generate stringer -type=ChunkType
2017-06-26 15:36:52 +02:00
package chunks
2017-06-25 17:23:20 +02:00
import (
"fmt"
"regexp"
)
type Chunk struct {
Type ChunkType
SourceInfo SourceInfo
Source, Tag, Args string
}
type SourceInfo struct {
Pathname string
lineNo int
}
type ChunkType int
const (
TextChunk ChunkType = iota
TagChunk
ObjChunk
)
var chunkMatcher = regexp.MustCompile(`{{\s*(.+?)\s*}}|{%\s*(\w+)(?:\s+(.+?))?\s*%}`)
// MarshalYAML, for debugging
func (c Chunk) MarshalYAML() (interface{}, error) {
switch c.Type {
case TextChunk:
return map[string]interface{}{"text": c.Source}, nil
case TagChunk:
return map[string]interface{}{"tag": c.Tag, "args": c.Args}, nil
case ObjChunk:
return map[string]interface{}{"obj": c.Tag}, nil
default:
return nil, fmt.Errorf("unknown chunk tag type: %v", c.Type)
}
}
func Scan(data string, pathname string) []Chunk {
2017-06-25 17:23:20 +02:00
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{TextChunk, sourceInfo, data[p:ts], "", ""})
}
switch data[ts+1] {
case '{':
out = append(out, Chunk{ObjChunk, 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{TagChunk, sourceInfo, data[ts:te], data[m[4]:m[5]], args})
}
2017-06-25 23:26:14 +02:00
p = te
2017-06-25 17:23:20 +02:00
}
if p < pe {
out = append(out, Chunk{TextChunk, sourceInfo, data[p:], "", ""})
}
return out
}