tplc_commons_test.go (1734B)
1 package tplc 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "strconv" 8 9 "github.com/valyala/bytebufferpool" 10 11 "go.lair.cx/go-core/net/htmlx" 12 "go.lair.cx/tpls/internal/stacks" 13 ) 14 15 func NewTestWriter() *Writer { 16 return &Writer{ 17 builder: New().UseBuiltin(), 18 } 19 } 20 21 func NewTestBuilder(useBuiltin bool, tags map[string]TagHandler) *Builder { 22 b := New() 23 if useBuiltin { 24 b = b.UseBuiltin() 25 } 26 for key, tag := range tags { 27 b = b.AddTag(key, tag) 28 } 29 return b 30 } 31 32 func TagTestTransparent(name string) TagHandler { 33 return func(b *Builder, w *Writer, t *htmlx.Tokenizer) error { 34 if t.CurrentType() == htmlx.SelfClosingTagToken { 35 return nil 36 } 37 38 buf := bytebufferpool.Get() 39 defer bytebufferpool.Put(buf) 40 41 stackBuf := bytebufferpool.Get() 42 defer bytebufferpool.Put(stackBuf) 43 44 stack := stacks.NewByteStack(stackBuf.B) 45 46 loop: 47 for { 48 switch t.Next() { 49 case htmlx.StartTagToken: 50 tagName, _ := t.TagName() 51 stack.Put(tagName) 52 53 case htmlx.EndTagToken: 54 tagName, _ := t.TagName() 55 56 // Remove items in stack until the matched starting tag is found. 57 // If the tag is not exists in stack, 58 // - Root tag's closing. 59 // - Unexpected closing tag. 60 for { 61 item, ok := stack.Pop() 62 if !ok { // Tag is not found: 63 if string(tagName) == name { 64 break loop 65 } 66 return fmt.Errorf( 67 "unexpected closing tag: %s", 68 strconv.Quote(string(tagName)), 69 ) 70 } 71 if bytes.Equal(item, tagName) { 72 break 73 } 74 } 75 76 case htmlx.ErrorToken: 77 err := t.Err() 78 if err == io.EOF { 79 if len(name) == 0 && stack.Len() == 0 { 80 return nil 81 } 82 return io.ErrUnexpectedEOF 83 } 84 return err 85 } 86 87 w.WriteGoCodeBytes(t.Raw()) 88 } 89 90 return nil 91 } 92 }