tpls

Extendable, Fast Template Engine for Go
git clone git://git.lair.cx/tpls
Log | Files | Refs | README | LICENSE

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 }