Documentation ¶
Overview ¶
*
- tmplfn are a collection of functions useful to add to the default Go template/text and template/html template definitions *
- @author R. S. Doiel *
- Copyright (c) 2017, Caltech
- All rights not granted herein are expressly reserved by Caltech. *
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: *
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. *
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. *
- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
Index ¶
Constants ¶
const Version = "0.0.21"
Variables ¶
var ( // Time provides a common set of time/date related functions for use in text/template or html/template Time = template.FuncMap{ "year": func(s string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format("2006") }, "timefmt": func(s string, fmt string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format(fmt) }, "rfc3339": func(s string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format(time.RFC3339) }, "rfc1123": func(s string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format(time.RFC1123) }, "rfc1123z": func(s string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format(time.RFC1123Z) }, "rfc822z": func(s string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format(time.RFC822Z) }, "rfc822": func(s string) string { var ( dt time.Time err error ) if s == "now" { dt = time.Now() } else { dt, err = time.Parse("2006-01-02", normalizeDate(s)) if err != nil { return "" } } return dt.Format(time.RFC822) }, "datefmt": func(dt, outputFmtYMD, outputFmtYM, outputFmtY string) string { var ( inputFmt string outputFmt string ) switch { case len(dt) == 4: inputFmt = "2006" outputFmt = outputFmtY case len(dt) > 4 && len(dt) <= 7: inputFmt = "2006-01" outputFmt = outputFmtYM default: inputFmt = "2006-01-02" outputFmt = outputFmtYMD } d, err := time.Parse(inputFmt, dt) if err != nil { return fmt.Sprintf("%s, %s", dt, err.Error()) } return d.Format(outputFmt) }, } Math = template.FuncMap{ "int": numbers.Int, "int64": numbers.Int64, "float32": numbers.Float32, "float64": numbers.Float64, "add": numbers.Add, "sub": numbers.Subtract, "multiply": numbers.Multiply, "divide": numbers.Divide, "modulo": numbers.Modulo, "addi": numbers.Addi, "subi": numbers.Subtract, "typeof": func(t interface{}) string { if t == nil { return "<nil>" } return fmt.Sprintf("%T", t) }, } Strings = template.FuncMap{ "concat": func(strs ...string) string { return strings.Join(strs, "") }, "has_prefix": strings.HasPrefix, "has_suffix": strings.HasSuffix, "contains": strings.Contains, "trim_prefix": strings.TrimPrefix, "trim_suffix": strings.TrimSuffix, "trimspace": strings.TrimSpace, "trim": strings.Trim, "trim_left": strings.TrimLeft, "trim_right": strings.TrimRight, "lowercase": strings.ToLower, "uppercase": strings.ToUpper, "title": strings.Title, "replace": strings.Replace, "join": func(li []interface{}, sep string) string { var l []string for _, item := range li { if item == nil { l = append(l, "") } else { l = append(l, fmt.Sprintf("%s", item)) } } return strings.Join(l, sep) }, "split": func(s string, delimiter string) []string { return strings.Split(s, delimiter) }, "splitN": func(s string, delimiter string, count int) []string { return strings.SplitN(s, delimiter, count) }, } Page = template.FuncMap{ "nl2p": func(s string) string { return strings.Replace(strings.Replace(s, "\n\n", "<p>", -1), "\n", "<br />", -1) }, "previ": func(pos, move_size, min_pos, max_pos int, wrap bool) int { prev := pos - move_size if prev < min_pos { if wrap == false { return min_pos } return max_pos } return prev }, "nexti": func(pos, move_size, min_pos, max_pos int, wrap bool) int { next := pos + move_size if next > max_pos { if wrap == false { return pos } return min_pos } return next }, "synopsis": func(s string) string { return doc.Synopsis(s) }, "urldecode": func(s string) string { sDecoded, err := url.QueryUnescape(s) if err != nil { log.Printf("Bad encoding request: %q, %s\n", s, err) return "" } return sDecoded }, "urlencode": func(s string) string { return url.QueryEscape(s) }, "url_path_escape": func(s string) string { return url.PathEscape(s) }, "url_path_unescape": func(s string) string { sDecoded, err := url.PathUnescape(s) if err != nil { log.Printf("Bad encoding request: %q, %s\n", s, err) return "" } return sDecoded }, "stringify": func(data interface{}, prettyPrint bool) string { if prettyPrint == true { if buf, err := json.MarshalIndent(data, "", "\t"); err == nil { return string(buf) } } else if buf, err := json.Marshal(data); err == nil { return string(buf) } return "" }, "codeblock": func(src string, start int, end int, hint string) string { result := []string{} lines := strings.Split(src, "\n") if start < 1 { start = 0 } if end < 1 { end = len(lines) } if (end - start) > 0 { result = append(result, fmt.Sprintf("```%s", hint)) } for i, line := range lines[start:end] { if len(line) > 0 { result = append(result, fmt.Sprintf(" %s", line)) } else if i > 0 && i < (end-1) { result = append(result, "") } } if len(result) > 0 { result = append(result, "```") } return strings.Join(result, "\n") }, } // Iterables produces lists that then can supply the template range function with values Iterables = template.FuncMap{ "ints": func(start, end, inc int) []int { var result []int if start == end { return []int{start} } else if start < end { for i := start; i <= end; i = i + inc { result = append(result, i) } } else { for i := end; i >= start; i = i - inc { result = append(result, i) } } return result }, "int64s": func(start, end, inc int64) []int64 { var result []int64 if start == end { return []int64{start} } else if start < end { for i := start; i <= end; i = i + inc { result = append(result, i) } } else { for i := end; i >= start; i = i - inc { result = append(result, i) } } return result }, "float32s": func(start, end, inc float32) []float32 { var result []float32 if start == end { return []float32{start} } else if start < end { for i := start; i <= end; i = i + inc { result = append(result, i) } } else { for i := end; i >= start; i = i - inc { result = append(result, i) } } return result }, "float64s": func(start, end, inc float64) []float64 { var result []float64 if start == end { return []float64{start} } else if start < end { for i := start; i <= end; i = i + inc { result = append(result, i) } } else { for i := end; i >= start; i = i - inc { result = append(result, i) } } return result }, "cols2rows": func(cols ...[]interface{}) [][]interface{} { var ( row []interface{} rows [][]interface{} maxRows int ) for _, col := range cols { if len(col) >= maxRows { maxRows = len(col) } } for i := 0; i < maxRows; i++ { row = []interface{}{} for _, col := range cols { if i < len(col) { row = append(row, col[i]) } else { row = append(row, "") } } rows = append(rows, row) } return rows }, "length": func(arg interface{}) int { switch arg.(type) { case string: return len(arg.(string)) case []byte: return len(arg.([]byte)) case []rune: return len(arg.([]rune)) case []int: return len(arg.([]int)) case []int64: return len(arg.([]int64)) case []float64: return len(arg.([]float64)) case []bool: return len(arg.([]float64)) } return 0 }, } //Booleans provides a set of functions working with Boolean data Booleans = template.FuncMap{ "count_true": func(booleans ...bool) int { cnt := 0 for _, val := range booleans { if val == true { cnt++ } } return cnt }, } //Path methods for working with paths (E.g. path.Base(), path.Ext() and path.Dir() in Go path package) Path = template.FuncMap{ "basename": func(args ...string) string { p := path.Base(args[0]) if len(args) > 1 { for _, ext := range args[1:] { if strings.HasSuffix(p, ext) { p = strings.TrimSuffix(p, ext) } } } return p }, "base": path.Base, "ext": path.Ext, "dir": path.Dir, } //Url methods are for working with URLs and extracting useful parts Url = template.FuncMap{ "url_scheme": func(args ...string) string { if u, err := url.Parse(args[0]); err == nil { return u.Scheme } return "" }, "url_host": func(args ...string) string { if u, err := url.Parse(args[0]); err == nil { return u.Host } return "" }, "url_path": func(args ...string) string { if u, err := url.Parse(args[0]); err == nil { return u.Path } return "" }, } //Dotpath methods from datatools/dotpath in templates Dotpath = template.FuncMap{ "dotpath": func(data interface{}, p string, defaultVal interface{}) interface{} { if val, err := dotpath.Eval(p, data); err == nil { return val } return defaultVal }, "has_dotpath": func(data interface{}, p string, existsVal interface{}, notExistsVal interface{}) interface{} { if _, err := dotpath.Eval(p, data); err == nil { return existsVal } return notExistsVal }, } // Console holds functions that interact with the console where // the template processing is happening (e.g. for a web service // writing to the console log of the web server). Console = template.FuncMap{ "version": func() string { return Version }, "writelog": func(v ...interface{}) string { log.Println(v...) return "" }, } // RegExp holds function that work off of Go's (not pcre) regular expression library. RegExp = template.FuncMap{ "match": func(expr, val string) bool { re := regexp.MustCompile(expr) return re.MatchString(val) }, } )
var (
TextTools = template.FuncMap{
"slug": slug,
"unslug": unslug,
"english_title": englishTitle,
}
)
Functions ¶
Types ¶
type Filter ¶ added in v0.0.18
type Filter struct {
// contains filtered or unexported fields
}
Filter holds the parsed filter source that can be applied to a JSON record to determine if the record is included or exluded NOTE: We're riding on the back of a text template to render true or false
func ParseFilter ¶ added in v0.0.18
ParseFilter parses a byte slice and returns a Filter struct and error
type Tmpl ¶ added in v0.0.18
type Tmpl struct { // Holds the function map for templates FuncMap template.FuncMap // Code holds a map of names to byte arrays, the byte arrays hold the template source code // the names can be either filename or other names defined by the implementor Code map[string][]byte }
Src is a mapping of template source to names and byte arrays. It is useful to create a series of defaults templates that can be overwritten by user supplied template files.
func New ¶ added in v0.0.18
New creates a pointer to a template.Template and empty map of names to byte arrays pointing at an empty byte array
func (Tmpl) Add ¶ added in v0.0.18
Add takes a name and source (byte array) and updates t.Code with it. It is like Merge but for a single file. The name provided in Add is used as the key to the template source code map.
func (Tmpl) Assemble ¶ added in v0.0.18
Assemble mimics template.ParseFiles() but works with the properties of a Tmpl struct.
func (*Tmpl) ReadFiles ¶ added in v0.0.18
ReadFiles takes the given file, filenames or directory name(s) and reads the byte array(s) into the Code map. If a filename is a directory then the directory is scanned for files ending in ".tmpl" and those are loaded into the Code map. It does NOT parse/assemble templates. The basename in the path is used as the name of the template (e.g. templates/page.tmpl would be stored as page.tmpl.
func (Tmpl) ReadMap ¶ added in v0.0.18
ReadMap works like ReadFiles but takes the name/source pairs from a map rather than the file system. It expected template names to end in ".tmpl" like ReadFiles() Note the basename of the key provided in the sourceMap is used as the key in the Code source code map (e.g. /templates/page.tmpl is stored as page.tmpl)