tpls

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

utils.go (2599B)


      1 package tplc
      2 
      3 import (
      4 	"fmt"
      5 	"path"
      6 	"path/filepath"
      7 	"unicode/utf8"
      8 
      9 	"github.com/pkg/errors"
     10 
     11 	"go.lair.cx/go-core/net/htmlx"
     12 )
     13 
     14 func getPackageName(dirName string) (string, error) {
     15 	absPath, err := filepath.Abs(dirName)
     16 	if err != nil {
     17 		return "", err
     18 	}
     19 
     20 	if absPath == "/" {
     21 		return "", errors.New("root directory is not allowed")
     22 	}
     23 
     24 	_, pkg := path.Split(absPath)
     25 	return pkg, nil
     26 }
     27 
     28 func getAttrs(t *htmlx.Tokenizer) map[string]string {
     29 	out := make(map[string]string)
     30 
     31 	for {
     32 		key, val, hasMore := t.TagAttr()
     33 		if key == nil {
     34 			break
     35 		}
     36 
     37 		out[string(key)] = string(val)
     38 
     39 		if !hasMore {
     40 			break
     41 		}
     42 	}
     43 
     44 	return out
     45 }
     46 
     47 func getByteAttrs(t *htmlx.Tokenizer) map[string][]byte {
     48 	out := make(map[string][]byte)
     49 
     50 	for {
     51 		key, val, hasMore := t.TagAttr()
     52 		if key == nil {
     53 			break
     54 		}
     55 
     56 		out[string(key)] = val
     57 
     58 		if !hasMore {
     59 			break
     60 		}
     61 	}
     62 
     63 	return out
     64 }
     65 
     66 func appendBacktickString(buf []byte, s string) ([]byte, error) {
     67 	if cap(buf)-len(buf) < len(s)+2 {
     68 		nbuf := make([]byte, len(buf), len(buf)+len(s)+2)
     69 		copy(nbuf, buf)
     70 		buf = nbuf
     71 	}
     72 	buf = append(buf, '`')
     73 	for width := 0; len(s) > 0; s = s[width:] {
     74 		var r rune
     75 		r, width = utf8.DecodeRuneInString(s)
     76 		if r == '\ufeff' {
     77 			return nil, errors.New("UTF-8 with BOM can not be encoded")
     78 		} else if r == utf8.RuneError {
     79 			return nil, errors.New("invalid utf-8 string")
     80 		} else if r < ' ' && r != '\t' || r == '\u007F' {
     81 			return nil, errors.New("control character can not be encoded")
     82 		} else if r == '`' {
     83 			buf = append(buf, "`+\"`\"+`"...)
     84 		} else {
     85 			buf = append(buf, s[:width]...)
     86 		}
     87 	}
     88 	buf = append(buf, '`')
     89 	return buf, nil
     90 }
     91 
     92 func appendBacktickByteString(buf []byte, s []byte) ([]byte, error) {
     93 	if cap(buf)-len(buf) < len(s)+2 {
     94 		nbuf := make([]byte, len(buf), len(buf)+len(s)+2)
     95 		copy(nbuf, buf)
     96 		buf = nbuf
     97 	}
     98 	buf = append(buf, '`')
     99 	for width := 0; len(s) > 0; s = s[width:] {
    100 		var r rune
    101 		r, width = utf8.DecodeRune(s)
    102 		if r == '\ufeff' {
    103 			return nil, errors.New("UTF-8 with BOM can not be encoded")
    104 		} else if r == utf8.RuneError {
    105 			return nil, errors.New("invalid utf-8 string")
    106 		} else if (r < ' ' && r != '\t' && r != '\r' && r != '\n') || r == '\u007F' {
    107 			return nil, errors.New("control character can not be encoded")
    108 		} else if r == '`' {
    109 			buf = append(buf, "`+\"`\"+`"...)
    110 		} else {
    111 			buf = append(buf, s[:width]...)
    112 		}
    113 	}
    114 	buf = append(buf, '`')
    115 	return buf, nil
    116 }
    117 
    118 func checkTagName(t *htmlx.Tokenizer, name string) error {
    119 	tagName, _ := t.TagName()
    120 	if string(tagName) != name {
    121 		return fmt.Errorf("unexpected closing tag: %s", tagName)
    122 	}
    123 	return nil
    124 }