1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-27 06:44:42 +01:00

Add RenderContext.ParseTagArgs

This commit is contained in:
Oliver Steele 2017-06-30 17:33:36 -04:00
parent af95c44a25
commit 7c48138dad
8 changed files with 45 additions and 25 deletions

View File

@ -11,7 +11,7 @@ type Chunk struct {
Type ChunkType Type ChunkType
SourceInfo SourceInfo SourceInfo SourceInfo
Name string // Name is the tag name of a tag Chunk. E.g. the tag name of "{% if 1 %}" is "if". Name string // Name is the tag name of a tag Chunk. E.g. the tag name of "{% if 1 %}" is "if".
Parameters string // Parameters is the tag arguments of a tag Chunk. E.g. the tag arguments of "{% if 1 %}" is "1". Args string // Parameters is the tag arguments of a tag Chunk. E.g. the tag arguments of "{% if 1 %}" is "1".
Source string // Source is the entirety of the chunk, including the "{{", "{%", etc. markers. Source string // Source is the entirety of the chunk, including the "{{", "{%", etc. markers.
} }
@ -38,9 +38,9 @@ func (c Chunk) String() string {
case TextChunkType: case TextChunkType:
return fmt.Sprintf("%s{%#v}", c.Type, c.Source) return fmt.Sprintf("%s{%#v}", c.Type, c.Source)
case TagChunkType: case TagChunkType:
return fmt.Sprintf("%s{Tag:%#v, Args:%#v}", c.Type, c.Name, c.Parameters) return fmt.Sprintf("%s{Tag:%#v, Args:%#v}", c.Type, c.Name, c.Args)
case ObjChunkType: case ObjChunkType:
return fmt.Sprintf("%s{%#v}", c.Type, c.Parameters) return fmt.Sprintf("%s{%#v}", c.Type, c.Args)
default: default:
return fmt.Sprintf("%s{%#v}", c.Type, c.Source) return fmt.Sprintf("%s{%#v}", c.Type, c.Source)
} }

View File

@ -21,7 +21,7 @@ func (c Chunk) MarshalYAML() (interface{}, error) {
case TextChunkType: case TextChunkType:
return map[string]interface{}{"text": c.Source}, nil return map[string]interface{}{"text": c.Source}, nil
case TagChunkType: case TagChunkType:
return map[string]interface{}{"tag": c.Name, "args": c.Parameters}, nil return map[string]interface{}{"tag": c.Name, "args": c.Args}, nil
case ObjChunkType: case ObjChunkType:
return map[string]interface{}{"obj": c.Name}, nil return map[string]interface{}{"obj": c.Name}, nil
default: default:
@ -33,7 +33,7 @@ func (c Chunk) MarshalYAML() (interface{}, error) {
func (n ASTControlTag) MarshalYAML() (interface{}, error) { func (n ASTControlTag) MarshalYAML() (interface{}, error) {
return map[string]map[string]interface{}{ return map[string]map[string]interface{}{
n.cd.name: { n.cd.name: {
"args": n.Parameters, "args": n.Args,
"body": n.Body, "body": n.Body,
"branches": n.Branches, "branches": n.Branches,
}}, nil }}, nil

View File

@ -45,7 +45,7 @@ func (s Settings) parseChunks(chunks []Chunk) (ASTNode, error) {
rawTag.slices = append(rawTag.slices, c.Source) rawTag.slices = append(rawTag.slices, c.Source)
} }
case c.Type == ObjChunkType: case c.Type == ObjChunkType:
expr, err := expressions.Parse(c.Parameters) expr, err := expressions.Parse(c.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -82,7 +82,7 @@ func (s Settings) parseChunks(chunks []Chunk) (ASTNode, error) {
ccd, ccn, ap = f.cd, f.cn, f.ap ccd, ccn, ap = f.cd, f.cn, f.ap
} }
} else if td, ok := s.FindTagDefinition(c.Name); ok { } else if td, ok := s.FindTagDefinition(c.Name); ok {
f, err := td(c.Parameters) f, err := td(c.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"strings"
"github.com/osteele/liquid/expressions" "github.com/osteele/liquid/expressions"
) )
@ -16,10 +17,10 @@ type RenderContext interface {
Evaluate(expr expressions.Expression) (interface{}, error) Evaluate(expr expressions.Expression) (interface{}, error)
EvaluateString(source string) (interface{}, error) EvaluateString(source string) (interface{}, error)
EvaluateStatement(tag, source string) (interface{}, error) EvaluateStatement(tag, source string) (interface{}, error)
InnerString() (string, error)
ParseTagArgs() (string, error)
RenderChild(io.Writer, *ASTControlTag) error RenderChild(io.Writer, *ASTControlTag) error
RenderChildren(io.Writer) error RenderChildren(io.Writer) error
// RenderTemplate(io.Writer, filename string) (string, error)
InnerString() (string, error)
} }
type renderContext struct { type renderContext struct {
@ -82,10 +83,6 @@ func (c renderContext) RenderChildren(w io.Writer) error {
return c.ctx.RenderASTSequence(w, c.cn.Body) return c.ctx.RenderASTSequence(w, c.cn.Body)
} }
// func (c renderContext) RenderTemplate(w io.Writer, filename string) (string, error) {
// // TODO use the tags and filters from the current context
// }
// InnerString renders the children to a string. // InnerString renders the children to a string.
func (c renderContext) InnerString() (string, error) { func (c renderContext) InnerString() (string, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
@ -94,3 +91,26 @@ func (c renderContext) InnerString() (string, error) {
} }
return buf.String(), nil return buf.String(), nil
} }
func (c renderContext) ParseTagArgs() (string, error) {
var args string
switch {
case c.node != nil:
args = c.node.Chunk.Args
case c.cn != nil:
args = c.cn.Chunk.Args
}
if strings.Contains(args, "{{") {
p, err := c.ctx.settings.Parse(args)
if err != nil {
return "", err
}
buf := new(bytes.Buffer)
err = p.Render(buf, c.ctx)
if err != nil {
return "", err
}
return buf.String(), nil
}
return args, nil
}

View File

@ -31,7 +31,7 @@ func Scan(data string, pathname string) []Chunk {
Type: ObjChunkType, Type: ObjChunkType,
SourceInfo: si, SourceInfo: si,
Source: source, Source: source,
Parameters: data[m[2]:m[3]], Args: data[m[2]:m[3]],
}) })
case '%': case '%':
c := Chunk{ c := Chunk{
@ -41,7 +41,7 @@ func Scan(data string, pathname string) []Chunk {
Name: data[m[4]:m[5]], Name: data[m[4]:m[5]],
} }
if m[6] > 0 { if m[6] > 0 {
c.Parameters = data[m[6]:m[7]] c.Args = data[m[6]:m[7]]
} }
out = append(out, c) out = append(out, c)
} }

View File

@ -33,27 +33,27 @@ func TestScanner(t *testing.T) {
require.NotNil(t, tokens) require.NotNil(t, tokens)
require.Len(t, tokens, 1) require.Len(t, tokens, 1)
require.Equal(t, ObjChunkType, tokens[0].Type) require.Equal(t, ObjChunkType, tokens[0].Type)
require.Equal(t, "obj", tokens[0].Parameters) require.Equal(t, "obj", tokens[0].Args)
tokens = Scan("{{ obj }}", "") tokens = Scan("{{ obj }}", "")
require.NotNil(t, tokens) require.NotNil(t, tokens)
require.Len(t, tokens, 1) require.Len(t, tokens, 1)
require.Equal(t, ObjChunkType, tokens[0].Type) require.Equal(t, ObjChunkType, tokens[0].Type)
require.Equal(t, "obj", tokens[0].Parameters) require.Equal(t, "obj", tokens[0].Args)
tokens = Scan("{%tag args%}", "") tokens = Scan("{%tag args%}", "")
require.NotNil(t, tokens) require.NotNil(t, tokens)
require.Len(t, tokens, 1) require.Len(t, tokens, 1)
require.Equal(t, TagChunkType, tokens[0].Type) require.Equal(t, TagChunkType, tokens[0].Type)
require.Equal(t, "tag", tokens[0].Name) require.Equal(t, "tag", tokens[0].Name)
require.Equal(t, "args", tokens[0].Parameters) require.Equal(t, "args", tokens[0].Args)
tokens = Scan("{% tag args %}", "") tokens = Scan("{% tag args %}", "")
require.NotNil(t, tokens) require.NotNil(t, tokens)
require.Len(t, tokens, 1) require.Len(t, tokens, 1)
require.Equal(t, TagChunkType, tokens[0].Type) require.Equal(t, TagChunkType, tokens[0].Type)
require.Equal(t, "tag", tokens[0].Name) require.Equal(t, "tag", tokens[0].Name)
require.Equal(t, "args", tokens[0].Parameters) require.Equal(t, "args", tokens[0].Args)
for i, test := range scannerCountTests { for i, test := range scannerCountTests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) { t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {

View File

@ -33,7 +33,7 @@ func parseLoopExpression(source string) (expressions.Expression, error) {
} }
func loopTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) { func loopTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) {
expr, err := parseLoopExpression(node.Parameters) expr, err := parseLoopExpression(node.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -28,7 +28,7 @@ func AddStandardTags(settings chunks.Settings) {
func captureTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) { func captureTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) {
// TODO verify syntax // TODO verify syntax
varname := node.Parameters varname := node.Args
return func(w io.Writer, ctx chunks.RenderContext) error { return func(w io.Writer, ctx chunks.RenderContext) error {
s, err := ctx.InnerString() s, err := ctx.InnerString()
if err != nil { if err != nil {
@ -42,7 +42,7 @@ func captureTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderC
func caseTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) { func caseTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) {
// TODO parse error on non-empty node.Body // TODO parse error on non-empty node.Body
// TODO case can include an else // TODO case can include an else
expr, err := expressions.Parse(node.Parameters) expr, err := expressions.Parse(node.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -52,7 +52,7 @@ func caseTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderCont
} }
cases := []caseRec{} cases := []caseRec{}
for _, branch := range node.Branches { for _, branch := range node.Branches {
bfn, err := expressions.Parse(branch.Parameters) bfn, err := expressions.Parse(branch.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -82,7 +82,7 @@ func ifTagParser(polarity bool) func(chunks.ASTControlTag) (func(io.Writer, chun
test expressions.Expression test expressions.Expression
body *chunks.ASTControlTag body *chunks.ASTControlTag
} }
expr, err := expressions.Parse(node.Parameters) expr, err := expressions.Parse(node.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -98,7 +98,7 @@ func ifTagParser(polarity bool) func(chunks.ASTControlTag) (func(io.Writer, chun
case "else": case "else":
// TODO parse error if this isn't the last branch // TODO parse error if this isn't the last branch
case "elsif": case "elsif":
t, err := expressions.Parse(c.Parameters) t, err := expressions.Parse(c.Args)
if err != nil { if err != nil {
return nil, err return nil, err
} }