1
0
mirror of https://github.com/danog/liquid.git synced 2025-01-22 23:11:25 +01:00

Implement raw tag

This commit is contained in:
Oliver Steele 2017-06-27 17:40:15 -04:00
parent 54b9f137ad
commit c09652bed8
6 changed files with 50 additions and 13 deletions

View File

@ -29,11 +29,13 @@
- [ ] loop variables
- [ ] tablerow
- [ ] cycle
- [ ] Raw
- [x] Raw
- [ ] Variable
- [x] Assign
- [ ] Capture
- [ ] Filters
- [x] some
- [ ] all
## Install

View File

@ -9,6 +9,11 @@ type ASTNode interface {
Render(io.Writer, Context) error
}
// ASTRaw holds the text between the start and end of a raw tag.
type ASTRaw struct {
slices []string
}
// ASTSeq is a sequence of nodes.
type ASTSeq struct {
Children []ASTNode

View File

@ -17,7 +17,9 @@ func Parse(chunks []Chunk) (ASTNode, error) {
ccd *controlTagDefinition
ccn *ASTControlTag
stack []frame // stack of control structures
rawTag *ASTRaw
inComment = false
inRaw = false
)
for _, c := range chunks {
switch {
@ -25,6 +27,12 @@ func Parse(chunks []Chunk) (ASTNode, error) {
if c.Type == TagChunkType && c.Tag == "endcomment" {
inComment = false
}
case inRaw:
if c.Type == TagChunkType && c.Tag == "endraw" {
inComment = false
} else {
rawTag.slices = append(rawTag.slices, c.Source)
}
case c.Type == ObjChunkType:
*ap = append(*ap, &ASTObject{Chunk: c})
case c.Type == TextChunkType:
@ -34,6 +42,10 @@ func Parse(chunks []Chunk) (ASTNode, error) {
switch {
case c.Tag == "comment":
inComment = true
case c.Tag == "raw":
inRaw = true
rawTag = &ASTRaw{}
*ap = append(*ap, rawTag)
case cd.requiresParent() && !cd.compatibleParent(ccd):
suffix := ""
if ccd != nil {

View File

@ -35,6 +35,17 @@ func (n *ASTText) Render(w io.Writer, _ Context) error {
return err
}
// Render evaluates an AST node and writes the result to an io.Writer.
func (n *ASTRaw) Render(w io.Writer, _ Context) error {
for _, s := range n.slices {
_, err := w.Write([]byte(s))
if err != nil {
return err
}
}
return nil
}
// RenderASTSequence renders a sequence of nodes.
func (ctx Context) RenderASTSequence(w io.Writer, seq []ASTNode) error {
for _, n := range seq {

View File

@ -9,14 +9,17 @@ import (
// DefineStandardTags defines the standard Liquid tags.
func DefineStandardTags() {
// The parser only recognize the comment and raw tags if they've been defined,
// but it ignores any syntax specified here.
loopTags := []string{"break", "continue", "cycle"}
chunks.DefineControlTag("comment")
chunks.DefineControlTag("if").Branch("else").Branch("elsif").Action(ifTagAction(true))
chunks.DefineControlTag("unless").SameSyntaxAs("if").Action(ifTagAction(false))
chunks.DefineControlTag("case").Branch("when")
chunks.DefineControlTag("for").Governs(loopTags).Action(loopTag)
chunks.DefineControlTag("tablerow").Governs(loopTags)
chunks.DefineControlTag("capture")
chunks.DefineControlTag("case").Branch("when")
chunks.DefineControlTag("comment")
chunks.DefineControlTag("for").Governs(loopTags).Action(loopTag)
chunks.DefineControlTag("if").Branch("else").Branch("elsif").Action(ifTagAction(true))
chunks.DefineControlTag("raw")
chunks.DefineControlTag("tablerow").Governs(loopTags)
chunks.DefineControlTag("unless").SameSyntaxAs("if").Action(ifTagAction(false))
}
func ifTagAction(polarity bool) func(chunks.ASTControlTag) func(io.Writer, chunks.Context) error {

View File

@ -18,9 +18,15 @@ var parseErrorTests = []struct{ in, expected string }{
}
var tagTests = []struct{ in, expected string }{
{"{%assign av = 1%}{{av}}", "1"},
{"{%assign av = obj.a%}{{av}}", "1"},
// TODO test whether this requires matching interior tags
{"{%comment%}{{a}}{%unknown%}{%endcomment%}", ""},
{"{%for a in ar%}{{a}} {%endfor%}", "first second third "},
{"{%for a in ar reversed%}{{a}} {%endfor%}", "third second first "},
{"{%if true%}true{%endif%}", "true"},
{"{%if false%}false{%endif%}", ""},
{"{%if 0%}true{%endif%}", "true"},
@ -35,6 +41,10 @@ var tagTests = []struct{ in, expected string }{
{"{%if false%}0{%elsif true%}1{%else%}2{%endif%}", "1"},
{"{%if false%}0{%elsif false%}1{%else%}2{%endif%}", "2"},
// TODO test whether this requires matching interior tags
{"pre{%raw%}{{a}}{%unknown%}{%endraw%}post", "pre{{a}}{%unknown%}post"},
{"pre{%raw%}{%if false%}anyway-{%endraw%}post", "pre{%if false%}anyway-post"},
{"{%unless true%}false{%endif%}", ""},
{"{%unless false%}true{%endif%}", "true"},
{"{%unless true%}false{%else%}true{%endif%}", "true"},
@ -42,12 +52,6 @@ var tagTests = []struct{ in, expected string }{
{"{%unless false%}0{%elsif true%}1{%else%}2{%endif%}", "0"},
{"{%unless true%}0{%elsif true%}1{%else%}2{%endif%}", "1"},
{"{%unless true%}0{%elsif false%}1{%else%}2{%endif%}", "2"},
{"{%assign av = 1%}{{av}}", "1"},
{"{%assign av = obj.a%}{{av}}", "1"},
{"{%for a in ar%}{{a}} {%endfor%}", "first second third "},
{"{%for a in ar reversed%}{{a}} {%endfor%}", "third second first "},
}
var tagTestContext = chunks.NewContext(map[string]interface{}{