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:
parent
54b9f137ad
commit
c09652bed8
@ -29,11 +29,13 @@
|
||||
- [ ] loop variables
|
||||
- [ ] tablerow
|
||||
- [ ] cycle
|
||||
- [ ] Raw
|
||||
- [x] Raw
|
||||
- [ ] Variable
|
||||
- [x] Assign
|
||||
- [ ] Capture
|
||||
- [ ] Filters
|
||||
- [x] some
|
||||
- [ ] all
|
||||
|
||||
## Install
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
15
tags/tags.go
15
tags/tags.go
@ -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 {
|
||||
|
@ -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{}{
|
||||
|
Loading…
x
Reference in New Issue
Block a user