From 7c48138dad28fbbe92f5e03aaa5eccb00a02f857 Mon Sep 17 00:00:00 2001 From: Oliver Steele Date: Fri, 30 Jun 2017 17:33:36 -0400 Subject: [PATCH] Add RenderContext.ParseTagArgs --- chunks/chunk.go | 6 +++--- chunks/marshal.go | 4 ++-- chunks/parser.go | 4 ++-- chunks/render_context.go | 32 ++++++++++++++++++++++++++------ chunks/scanner.go | 4 ++-- chunks/scanner_test.go | 8 ++++---- tags/loop.go | 2 +- tags/tags.go | 10 +++++----- 8 files changed, 45 insertions(+), 25 deletions(-) diff --git a/chunks/chunk.go b/chunks/chunk.go index 3eb758b..720dafd 100644 --- a/chunks/chunk.go +++ b/chunks/chunk.go @@ -11,7 +11,7 @@ type Chunk struct { Type ChunkType SourceInfo SourceInfo 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. } @@ -38,9 +38,9 @@ func (c Chunk) String() string { case TextChunkType: return fmt.Sprintf("%s{%#v}", c.Type, c.Source) 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: - return fmt.Sprintf("%s{%#v}", c.Type, c.Parameters) + return fmt.Sprintf("%s{%#v}", c.Type, c.Args) default: return fmt.Sprintf("%s{%#v}", c.Type, c.Source) } diff --git a/chunks/marshal.go b/chunks/marshal.go index 5883998..8faa41b 100644 --- a/chunks/marshal.go +++ b/chunks/marshal.go @@ -21,7 +21,7 @@ func (c Chunk) MarshalYAML() (interface{}, error) { case TextChunkType: return map[string]interface{}{"text": c.Source}, nil 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: return map[string]interface{}{"obj": c.Name}, nil default: @@ -33,7 +33,7 @@ func (c Chunk) MarshalYAML() (interface{}, error) { func (n ASTControlTag) MarshalYAML() (interface{}, error) { return map[string]map[string]interface{}{ n.cd.name: { - "args": n.Parameters, + "args": n.Args, "body": n.Body, "branches": n.Branches, }}, nil diff --git a/chunks/parser.go b/chunks/parser.go index fb6a8de..0eb0f02 100644 --- a/chunks/parser.go +++ b/chunks/parser.go @@ -45,7 +45,7 @@ func (s Settings) parseChunks(chunks []Chunk) (ASTNode, error) { rawTag.slices = append(rawTag.slices, c.Source) } case c.Type == ObjChunkType: - expr, err := expressions.Parse(c.Parameters) + expr, err := expressions.Parse(c.Args) if err != nil { return nil, err } @@ -82,7 +82,7 @@ func (s Settings) parseChunks(chunks []Chunk) (ASTNode, error) { ccd, ccn, ap = f.cd, f.cn, f.ap } } else if td, ok := s.FindTagDefinition(c.Name); ok { - f, err := td(c.Parameters) + f, err := td(c.Args) if err != nil { return nil, err } diff --git a/chunks/render_context.go b/chunks/render_context.go index 8de023c..6d3942c 100644 --- a/chunks/render_context.go +++ b/chunks/render_context.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "io" + "strings" "github.com/osteele/liquid/expressions" ) @@ -16,10 +17,10 @@ type RenderContext interface { Evaluate(expr expressions.Expression) (interface{}, error) EvaluateString(source string) (interface{}, error) EvaluateStatement(tag, source string) (interface{}, error) + InnerString() (string, error) + ParseTagArgs() (string, error) RenderChild(io.Writer, *ASTControlTag) error RenderChildren(io.Writer) error - // RenderTemplate(io.Writer, filename string) (string, error) - InnerString() (string, error) } type renderContext struct { @@ -82,10 +83,6 @@ func (c renderContext) RenderChildren(w io.Writer) error { 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. func (c renderContext) InnerString() (string, error) { buf := new(bytes.Buffer) @@ -94,3 +91,26 @@ func (c renderContext) InnerString() (string, error) { } 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 +} diff --git a/chunks/scanner.go b/chunks/scanner.go index 99963b8..d4b3383 100644 --- a/chunks/scanner.go +++ b/chunks/scanner.go @@ -31,7 +31,7 @@ func Scan(data string, pathname string) []Chunk { Type: ObjChunkType, SourceInfo: si, Source: source, - Parameters: data[m[2]:m[3]], + Args: data[m[2]:m[3]], }) case '%': c := Chunk{ @@ -41,7 +41,7 @@ func Scan(data string, pathname string) []Chunk { Name: data[m[4]:m[5]], } if m[6] > 0 { - c.Parameters = data[m[6]:m[7]] + c.Args = data[m[6]:m[7]] } out = append(out, c) } diff --git a/chunks/scanner_test.go b/chunks/scanner_test.go index c67c6b9..cb2dfb9 100644 --- a/chunks/scanner_test.go +++ b/chunks/scanner_test.go @@ -33,27 +33,27 @@ func TestScanner(t *testing.T) { require.NotNil(t, tokens) require.Len(t, tokens, 1) require.Equal(t, ObjChunkType, tokens[0].Type) - require.Equal(t, "obj", tokens[0].Parameters) + require.Equal(t, "obj", tokens[0].Args) tokens = Scan("{{ obj }}", "") require.NotNil(t, tokens) require.Len(t, tokens, 1) 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%}", "") require.NotNil(t, tokens) require.Len(t, tokens, 1) require.Equal(t, TagChunkType, tokens[0].Type) 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 %}", "") require.NotNil(t, tokens) require.Len(t, tokens, 1) require.Equal(t, TagChunkType, tokens[0].Type) 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 { t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) { diff --git a/tags/loop.go b/tags/loop.go index abbbda5..2f92287 100644 --- a/tags/loop.go +++ b/tags/loop.go @@ -33,7 +33,7 @@ func parseLoopExpression(source string) (expressions.Expression, 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 { return nil, err } diff --git a/tags/tags.go b/tags/tags.go index 8b12e05..6243fd2 100644 --- a/tags/tags.go +++ b/tags/tags.go @@ -28,7 +28,7 @@ func AddStandardTags(settings chunks.Settings) { func captureTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderContext) error, error) { // TODO verify syntax - varname := node.Parameters + varname := node.Args return func(w io.Writer, ctx chunks.RenderContext) error { s, err := ctx.InnerString() 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) { // TODO parse error on non-empty node.Body // TODO case can include an else - expr, err := expressions.Parse(node.Parameters) + expr, err := expressions.Parse(node.Args) if err != nil { return nil, err } @@ -52,7 +52,7 @@ func caseTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.RenderCont } cases := []caseRec{} for _, branch := range node.Branches { - bfn, err := expressions.Parse(branch.Parameters) + bfn, err := expressions.Parse(branch.Args) if err != nil { return nil, err } @@ -82,7 +82,7 @@ func ifTagParser(polarity bool) func(chunks.ASTControlTag) (func(io.Writer, chun test expressions.Expression body *chunks.ASTControlTag } - expr, err := expressions.Parse(node.Parameters) + expr, err := expressions.Parse(node.Args) if err != nil { return nil, err } @@ -98,7 +98,7 @@ func ifTagParser(polarity bool) func(chunks.ASTControlTag) (func(io.Writer, chun case "else": // TODO parse error if this isn't the last branch case "elsif": - t, err := expressions.Parse(c.Parameters) + t, err := expressions.Parse(c.Args) if err != nil { return nil, err }