gtf

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 22, 2024 License: MIT Imports: 18 Imported by: 0

README

gtf - a useful set of Golang Template Functions

Build Status Coverage Status GoDoc

gtf is a useful set of Golang Template Functions. The goal of this project is implementing all built-in template filters of Django & Jinja2.

Installation

Install module

# specific version
go get go get github.com/QFO6/gtf@vx.x.x
# or get latest
go get github.com/QFO6/gtf@master

Basic usages

Method 1 : Uses gtf.New

gtf.New is a wrapper function of template.New. It automatically adds the gtf functions to the template's function map and returns template.Template.

package main

import (
	"net/http"
	"github.com/leekchan/gtf"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		filesize := 554832114
		tpl, _ := gtf.New("test").Parse("{{ . | filesizeformat }}")
		tpl.Execute(w, filesize)
	})
    http.ListenAndServe(":8080", nil)
}
Method 2 : Adds gtf functions to the existing template.

You can also add the gtf functions to the existing template(html/template package). Just call ".Funcs(gtf.GtfFuncMap)".

package main

import (
	"net/http"
	"html/template"

	"github.com/leekchan/gtf"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		filesize := 554832114
		tpl, _ := template.New("test").Funcs(gtf.GtfFuncMap).Parse("{{ . | filesizeformat }}")
		tpl.Execute(w, filesize)
	})
    http.ListenAndServe(":8080", nil)
}

When you use the "text/template" package, call ".Funcs(gtf.GtfTextFuncMap)".

package main

import (
	"os"
	"text/template"

	"github.com/leekchan/gtf"
)

func main() {
	filesize := 554832114
	tpl, _ := template.New("test").Funcs(gtf.GtfTextFuncMap).Parse("{{ . | filesizeformat }}")
	tpl.Execute(os.Stdout, filesize)
}

Integration

You can use gtf with any web frameworks (revel, beego, martini, gin, etc) which use the Golang's built-in html/template package.

Injection

You can inject gtf functions into your webframework's original FuncMap by calling "gtf.Inject" / "gtf.ForceInject" / "gtf.InjectWithPrefix".

gtf.Inject

gtf.Inject injects gtf functions into the passed FuncMap. It does not overwrite the original function which have same name as a gtf function.

Inject(originalFuncMap)
gtf.ForceInject

gtf.ForceInject injects gtf functions into the passed FuncMap. It overwrites the original function which have same name as a gtf function.

ForceInject(originalFuncMap)
gtf.InjectWithPrefix

gtf.Inject injects gtf functions into the passed FuncMap. It prefixes the gtf functions with the specified prefix. If there are many function which have same names as the gtf functions, you can use this function to prefix the gtf functions.

InjectWithPrefix(originalFuncMap, "gtf_") // prefix : gtf_
Revel integration

Calling "gtf.Inject(revel.TemplateFuncs)" injects gtf functions into revel.TemplateFuncs. Just add this one line in init() of init.go, and use gtf functions in your templates! :)

// init.go

package app

import "github.com/revel/revel"
import "github.com/leekchan/gtf"

func init() {
    gtf.Inject(revel.TemplateFuncs)
}
Beego integration

Add these three lines before "beego.Run()" in your main() function. This code snippet will inject gtf functions into beego's FuncMap.

for k, v := range gtf.GtfFuncMap {
    beego.AddFuncMap(k, v)
}

Full example:

package main

import (
    "github.com/astaxie/beego"
    "github.com/beego/i18n"

    "github.com/beego/samples/WebIM/controllers"

    "github.com/leekchan/gtf"
)

const (
    APP_VER = "0.1.1.0227"
)

func main() {
    beego.Info(beego.AppName, APP_VER)

    // Register routers.
    beego.Router("/", &controllers.AppController{})
    // Indicate AppController.Join method to handle POST requests.
    beego.Router("/join", &controllers.AppController{}, "post:Join")

    // Long polling.
    beego.Router("/lp", &controllers.LongPollingController{}, "get:Join")
    beego.Router("/lp/post", &controllers.LongPollingController{})
    beego.Router("/lp/fetch", &controllers.LongPollingController{}, "get:Fetch")

    // WebSocket.
    beego.Router("/ws", &controllers.WebSocketController{})
    beego.Router("/ws/join", &controllers.WebSocketController{}, "get:Join")

    // Register template functions.
    beego.AddFuncMap("i18n", i18n.Tr)

    // Register gtf functions.
    for k, v := range gtf.GtfFuncMap {
        beego.AddFuncMap(k, v)
    }

    beego.Run()
}
Other web frameworks (TODO)

I will add the detailed integration guides for other web frameworks soon!

Safety

All gtf functions have their own recovery logics. The basic behavior of the recovery logic is silently swallowing all unexpected panics. All gtf functions would not make any panics in runtime. (Production Ready!)

If a panic occurs inside a gtf function, the function will silently swallow the panic and return "" (empty string). If you meet any unexpected empty output, please make an issue! :)

Reference

Index
replace

Removes all values of arg from the given string.

  • supported value types : string
  • supported argument types : string
{{ value | replace " " }}

If value is "The Go Programming Language", the output will be "TheGoProgrammingLanguage".

findreplace

Replaces all instances of the first argument with the second.

  • supported value types : string
  • supported argument types : string
{{ value | findreplace " " "-" }}

If value is "The Go Programming Language", the output will be "The-Go-Programming-Language".

default
  1. If the given string is ""(empty string), uses the given default argument.
  2. If the given array/slice/map is empty, uses the given default argument.
  3. If the given boolean value is false, uses the given default argument.
  • supported value types : string, array, slice, map, boolean
  • supported argument types : all
{{ value | default "default value" }}

If value is ""(the empty string), the output will be "default value".

length

Returns the length of the given string/array/slice/map.

  • supported value types : string, array, slice, map

This function also supports unicode strings.

{{ value | length }}

If value is "The Go Programming Language", the output will be 27.

lower

Converts the given string into all lowercase.

  • supported value types : string
{{ value | lower }}

If value is "The Go Programming Language", the output will be "the go programming language".

upper

Converts the given string into all uppercase.

  • supported value types : string
{{ value | upper }}

If value is "The Go Programming Language", the output will be "THE GO PROGRAMMING LANGUAGE".

truncatechars

Truncates the given string if it is longer than the specified number of characters. Truncated strings will end with a translatable ellipsis sequence ("...")

  • supported value types : string

Argument: Number of characters to truncate to

This function also supports unicode strings.

{{ value | truncatechars 12 }}

Examples

  1. If input is {{ "The Go Programming Language" | truncatechars 12 }}, the output will be "The Go Pr...". (basic string)
  2. If input is {{ "안녕하세요. 반갑습니다." | truncatechars 12 }}, the output will be "안녕하세요. 반갑...". (unicode)
  3. If input is {{ "안녕하세요. The Go Programming Language" | truncatechars 30 }}, the output will be "안녕하세요. The Go Programming L...". (unicode)
  4. If input is {{ "The" | truncatechars 30 }}, the output will be "The". (If the length of the given string is shorter than the argument, the output will be the original string.)
  5. If input is {{ "The Go Programming Language" | truncatechars 3 }}, the output will be "The". (If the argument is less than or equal to 3, the output will not contain "...".)
  6. If input is {{ "The Go" | truncatechars -1 }}, the output will be "The Go". (If the argument is less than 0, the argument will be ignored.)
urlencode

Escapes the given string for use in a URL.

  • supported value types : string
{{ value | urlencode }}

If value is "http://www.example.org/foo?a=b&c=d", the output will be "http%3A%2F%2Fwww.example.org%2Ffoo%3Fa%3Db%26c%3Dd".

wordcount

Returns the number of words.

  • supported value types : string
{{ value | wordcount }}

If value is "The Go Programming Language", the output will be 4.

divisibleby

Returns true if the value is divisible by the argument.

  • supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64
  • supported argument types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64
{{ value | divisibleby 3 }}

Examples

  1. If input is {{ 21 | divisibleby 3 }}, the output will be true.
  2. If input is {{ 21 | divisibleby 4 }}, the output will be false.
  3. If input is {{ 3.0 | divisibleby 1.5 }}, the output will be true.
lengthis

Returns true if the value's length is the argument, or false otherwise.

  • supported value types : string, array, slice, map
  • supported argument types : int
{{ value | lengthis 3 }}

This function also supports unicode strings.

Examples

  1. If input is {{ "Go" | lengthis 2 }}, the output will be true.
  2. If input is {{ "안녕하세요. Go!" | lengthis 10 }}, the output will be true.
trim

Strips leading and trailing whitespace.

  • supported value types : string
{{ value | trim }}
capfirst

Capitalizes the first character of the given string.

  • supported value types : string
{{ value | capfirst }}

If value is "the go programming language", the output will be "The go programming language".

pluralize

Returns a plural suffix if the value is not 1. You can specify both a singular and plural suffix, separated by a comma.

Argument: singular and plural suffix.

  1. "s" --> specify a singular suffix.
  2. "y,ies" --> specify both a singular and plural suffix.
  • supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
  • supported argument types : string
{{ value | pluralize "s" }}
{{ value | pluralize "y,ies" }}

Examples

  1. You have 0 message{{ 0 | pluralize "s" }} --> You have 0 messages
  2. You have 1 message{{ 1 | pluralize "s" }} --> You have 1 message
  3. 0 cand{{ 0 | pluralize "y,ies" }} --> 0 candies
  4. 1 cand{{ 1 | pluralize "y,ies" }} --> 1 candy
  5. 2 cand{{ 2 | pluralize "y,ies" }} --> 2 candies
yesno

Returns argument strings according to the given boolean value.

  • supported value types : boolean
  • supported argument types : string

Argument: any value for true and false

{{ value | yesno "yes!" "no!" }}
rjust

Right-aligns the given string in a field of a given width. This function also supports unicode strings.

  • supported value types : string
{{ value | rjust 10 }}

Examples

  1. If input is {{ "Go" | rjust 10 }}, the output will be "        Go".
  2. If input is {{ "안녕하세요" | rjust 10 }}, the output will be "     안녕하세요".
ljust

Left-aligns the given string in a field of a given width. This function also supports unicode strings.

  • supported value types : string
{{ value | ljust 10 }}

Examples

  1. If input is {{ "Go" | ljust 10 }}, the output will be "Go        ".
  2. If input is {{ "안녕하세요" | ljust 10 }}, the output will be "안녕하세요     ".
center

Centers the given string in a field of a given width. This function also supports unicode strings.

  • supported value types : string
{{ value | center 10 }}

Examples

  1. If input is {{ "Go" | center 10 }}, the output will be "    Go    ".
  2. If input is {{ "안녕하세요" | center 10 }}, the output will be "  안녕하세요   ".
filesizeformat

Formats the value like a human readable file size.

  • supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64
{{ value | filesizeformat }}

Examples

  1. {{ 234 | filesizeformat }} --> "234 bytes"
  2. {{ 12345 | filesizeformat }} --> "12.1 KB"
  3. {{ 12345.35335 | filesizeformat }} --> "12.1 KB"
  4. {{ 1048576 | filesizeformat } --> "1 MB"
  5. {{ 554832114 | filesizeformat }} --> "529.1 MB"
  6. {{ 14868735121 | filesizeformat }} --> "13.8 GB"
  7. {{ 14868735121365 | filesizeformat }} --> "13.5 TB"
  8. {{ 1486873512136523 | filesizeformat }} --> "1.3 PB"
apnumber

For numbers 1-9, returns the number spelled out. Otherwise, returns the number.

  • supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
{{ value | apnumber }}

Examples

  1. {{ 1 | apnumber }} --> one
  2. {{ 2 | apnumber }} --> two
  3. {{ 3 | apnumber }} --> three
  4. {{ 9 | apnumber }} --> nine
  5. {{ 10 | apnumber }} --> 10
  6. {{ 1000 | apnumber }} --> 1000
intcomma

Converts an integer to a string containing commas every three digits.

  • supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
{{ value | intcomma }}

Examples

  1. {{ 1000 | intcomma }} --> 1,000
  2. {{ -1000 | intcomma }} --> -1,000
  3. {{ 1578652313 | intcomma }} --> 1,578,652,313
ordinal

Converts an integer to its ordinal as a string.

  • supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
{{ value | ordinal }}

Examples

  1. {{ 1 | ordinal }} --> 1st
  2. {{ 2 | ordinal }} --> 2nd
  3. {{ 3 | ordinal }} --> 3rd
  4. {{ 11 | ordinal }} --> 11th
  5. {{ 12 | ordinal }} --> 12th
  6. {{ 13 | ordinal }} --> 13th
  7. {{ 14 | ordinal }} --> 14th
first

Returns the first item in the given value.

  • supported value types : string, slice, array

This function also supports unicode strings.

{{ value | first }}

Examples

  1. If value is the string "The go programming language", the output will be the string "T".
  2. If value is the string "안녕하세요", the output will be the string "안". (unicode)
  3. If value is the slice []string{"go", "python", "ruby"}, the output will be the string "go".
  4. If value is the array [3]string{"go", "python", "ruby"}, the output will be the string "go".
last

Returns the last item in the given value.

  • supported value types : string, slice, array

This function also supports unicode strings.

{{ value | last }}

Examples

  1. If value is the string "The go programming language", the output will be the string "e".
  2. If value is the string "안녕하세요", the output will be the string "요". (unicode)
  3. If value is the slice []string{"go", "python", "ruby"}, the output will be the string "ruby".
  4. If value is the array [3]string{"go", "python", "ruby"}, the output will be the string "ruby".
join

Concatenates the given slice to create a single string. The given argument (separator) will be placed between elements in the resulting string.

{{ value | join " " }}

If value is the slice []string{"go", "python", "ruby"}, the output will be the string "go python ruby"

slice

Returns a slice of the given value. The first argument is the start position, and the second argument is the end position.

  • supported value types : string, slice
  • supported argument types : int

This function also supports unicode strings.

{{ value | slice 0 2 }}

Examples

  1. If input is {{ "The go programming language" | slice 0 6 }}, the output will be "The go".
  2. If input is {{ "안녕하세요" | slice 0 2 }}, the output will be "안녕". (unicode)
  3. If input is {{ []string{"go", "python", "ruby"} | slice 0 2 }}, the output will be []string{"go", "python"}.
random

Returns a random item from the given value.

  • supported value types : string, slice, array

This function also supports unicode strings.

{{ value | random }}

Examples

  1. If input is {{ "The go programming language" | random }}, the output could be "T".
  2. If input is {{ "안녕하세요" | random }}, the output could be "안". (unicode)
  3. If input is {{ []string{"go", "python", "ruby"} | random }}, the output could be "go".
  4. If input is {{ [3]string{"go", "python", "ruby"} | random }}, the output could be "go".
randomintrange

Returns a random integer value between the first and second argument

  • supported value types : int
{{ value | randomintrange 0 5}}

Examples

  1. If input is {{ randomintrange 0 5 }}, the output could be "4".
striptags

Makes all possible efforts to strip all [X]HTML tags from given value.

  • supported value types : string

This function also supports unicode strings.

{{ value | striptags }}

Examples

  1. If input is {{ "<strong>text</strong>" | striptags }}, the output will be "text".
  2. If input is {{ "<strong><em>안녕하세요</em></strong>" | striptags }}, the output will be "안녕하세요". (unicode)
  3. If input is {{ "<a href="/link">text <strong>안녕하세요</strong></a>" | striptags }}, the output will be "text 안녕하세요".

Goal

The first goal is implementing all built-in template filters of Django & Jinja2.

The final goal is building a ultimate set which contains hundreds of useful template functions.

Contributing

I love pull requests :) You can add any useful template functions by submitting a pull request!

Documentation

Index

Constants

This section is empty.

Variables

View Source
var GtfTextFuncMap = textTemplate.FuncMap{
	"toValue": func(value interface{}) interface{} {
		defer recover()

		switch value.(type) {
		case primitive.ObjectID:
			return value.(primitive.ObjectID).Hex()
		default:
			return value
		}
	},
	"timeIn": func(t time.Time, locName string) string {
		defer recovery()
		if t.IsZero() {
			return ""
		}

		if locName == "" {
			locName = "Asia/Shanghai"
		}

		loc, err := time.LoadLocation(locName)
		if err == nil && loc != nil {
			t = t.In(loc)
		}
		return t.Format("2006-01-02 15:04 -07")
	},
	"funcMap": func(v ...interface{}) []interface{} {
		defer recovery()
		return v
	},

	"asQuery": func(query string) string {
		defer recovery()
		return url.QueryEscape(query)
	},

	"asURL": func(query string) template.URL {
		defer recovery()
		return template.URL(query)
	},
	"isChecked": func(values interface{}, option interface{}) string {
		defer recovery()
		list := []string{}
		switch values.(type) {
		case string:
			return ""
		case []string:
			list = values.([]string)
		}

		for _, item := range list {
			if item == option.(string) {
				return "checked"
			}
		}
		return ""
	},
	"objectId": func(value interface{}) string {
		defer recovery()
		switch value.(type) {
		case primitive.ObjectID:
			return value.(primitive.ObjectID).Hex()
		default:
			return value.(string)
		}
	},
	"parseUrl": func(path string, r *http.Request) string {
		defer recovery()
		link, _ := url.ParseRequestURI(r.RequestURI)
		link.Path = path
		return link.String()
	},
	"duration": func(start, stop time.Time) float64 {
		defer recovery()
		loading := stop.Sub(start).Seconds()
		return loading
	},
	"existobjectid": func(values []primitive.ObjectID, id string) bool {
		defer recovery()
		for _, value := range values {
			if value.Hex() == id {
				return true
			}
		}
		return false
	},
	"sameobjectid": func(value interface{}, id string) bool {
		defer recovery()
		switch value.(type) {
		case primitive.ObjectID:
			return value.(primitive.ObjectID).Hex() == id
		default:
			return fmt.Sprintf("%v", value) == id
		}
	},
	"minus": func(value interface{}, i int) int {
		defer recovery()
		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			return value.(int) - i
		default:
			return 0
		}
	},

	"delQuery": func(r *http.Request, k string) string {
		defer recovery()
		link, _ := url.ParseRequestURI(r.RequestURI)
		values := link.Query()

		values.Del(k)
		link.RawQuery = values.Encode()
		return link.String()
	},
	"setQuery": func(r *http.Request, k, v string) string {
		defer recovery()
		link, _ := url.ParseRequestURI(r.RequestURI)
		values := link.Query()

		values.Set(k, v)
		link.RawQuery = values.Encode()
		return link.String()
	},
	"getQuery": func(r *http.Request, k string) string {
		defer recovery()
		link, _ := url.ParseRequestURI(r.RequestURI)
		values := link.Query()
		return values.Get(k)
	},
	"repeat": func(count int, str string) string {
		defer recovery()
		return strings.Repeat(str, count)
	},
	"getInt": func(value interface{}) int {
		defer recovery()
		if value == nil {
			return 0
		}
		switch value.(type) {
		case *int:
			return *value.(*int)
		default:
			return value.(int)
		}
	},
	"istrue": func(value interface{}) bool {
		defer recovery()

		v := value.(*bool)
		if v == nil || *v == false {
			return false
		}
		return true
	},
	"humanizeSize": func(size interface{}) string {
		defer recovery()
		switch v := size.(type) {
		case float64:
			out := uint64(int64(v))
			return humanize.Bytes(out)
		case int64:
			return humanize.Bytes(uint64(v))
		}
		return "NA"
	},
	"isblank": func(value string) bool {
		defer recovery()
		s := strings.TrimSpace(value)
		if s == "" {
			return true
		}
		return false
	},
	"renderTime": func(value interface{}) string {
		defer recovery()
		switch value.(type) {
		case time.Time:
			startTime := value.(time.Time)
			loading := time.Now().Sub(startTime).Seconds() * 1000
			return fmt.Sprintf("%.2fms", loading)
		default:
			return ""
		}
	},
	"markdown2": func(value string) template.HTML {
		extensions := parser.CommonExtensions | parser.AutoHeadingIDs
		parser := parser.NewWithExtensions(extensions)

		md := []byte(value)
		output := markdown.ToHTML(md, parser, nil)
		return template.HTML(output)
	},
	"markdown": func(value string) template.HTML {
		defer recovery()

		md := []byte(value)
		output := blackfriday.Run(md)

		return template.HTML(string(output))
	},
	"timeago": func(value time.Time) string {
		defer recovery()
		return timeago.English.Format(value)
	},
	"asHTMLAttr": func(value string) template.HTMLAttr {
		defer recovery()
		return template.HTMLAttr(value)
	},
	"asCSS": func(value string) template.CSS {
		defer recovery()
		return template.CSS(value)
	},
	"asHTML": func(value string) template.HTML {
		defer recovery()
		return template.HTML(value)
	},
	"asJS": func(value string) template.JS {
		defer recovery()
		return template.JS(value)
	},
	"existin": func(list interface{}, value string) bool {
		defer recovery()
		if list == nil {
			return false
		}
		var nlist []string
		switch list.(type) {
		case *[]string:
			nlist = *list.(*[]string)
		default:
			nlist = list.([]string)
		}

		for _, item := range nlist {
			if item == value {
				return true
			}
		}
		return false
	},
	"tojson": func(value interface{}) template.JS {
		defer recovery()
		out, _ := json.Marshal(value)
		return template.JS(string(out))
	},
	"gettitle": func(value string) string {
		defer recovery()
		list := strings.Split(value, ".")
		return list[len(list)-1]
	},
	"replace": func(s1 string, s2 string) string {
		defer recovery()

		return strings.Replace(s2, s1, "", -1)
	},
	"findreplace": func(s1 string, s2 string, s3 string) string {
		defer recovery()

		return strings.Replace(s3, s1, s2, -1)
	},
	"title": func(s string) string {
		defer recovery()
		return strings.Title(s)
	},
	"default": func(arg interface{}, value interface{}) interface{} {
		defer recovery()

		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.String, reflect.Slice, reflect.Array, reflect.Map:
			if v.Len() == 0 {
				return arg
			}
		case reflect.Bool:
			if !v.Bool() {
				return arg
			}
		default:
			return value
		}

		return value
	},
	"length": func(value interface{}) int {
		defer recovery()

		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.Slice, reflect.Array, reflect.Map:
			return v.Len()
		case reflect.String:
			return len([]rune(v.String()))
		case reflect.Ptr:
			return v.Elem().Len()
		}

		return 0
	},
	"lower": func(s string) string {
		defer recovery()

		return strings.ToLower(s)
	},
	"upper": func(s string) string {
		defer recovery()

		return strings.ToUpper(s)
	},
	"truncatechars": func(n int, s string) string {
		defer recovery()

		if n < 0 {
			return s
		}

		r := []rune(s)
		rLength := len(r)

		if n >= rLength {
			return s
		}

		if n > 3 && rLength > 3 {
			return string(r[:n-3]) + "..."
		}

		return string(r[:n])
	},
	"urlencode": func(s string) string {
		defer recovery()

		return url.QueryEscape(s)
	},
	"wordcount": func(s string) int {
		defer recovery()

		return len(strings.Fields(s))
	},
	"divisibleby": func(arg interface{}, value interface{}) bool {
		defer recovery()

		var v float64
		switch value.(type) {
		case int, int8, int16, int32, int64:
			v = float64(reflect.ValueOf(value).Int())
		case uint, uint8, uint16, uint32, uint64:
			v = float64(reflect.ValueOf(value).Uint())
		case float32, float64:
			v = reflect.ValueOf(value).Float()
		default:
			return false
		}

		var a float64
		switch arg.(type) {
		case int, int8, int16, int32, int64:
			a = float64(reflect.ValueOf(arg).Int())
		case uint, uint8, uint16, uint32, uint64:
			a = float64(reflect.ValueOf(arg).Uint())
		case float32, float64:
			a = reflect.ValueOf(arg).Float()
		default:
			return false
		}

		return math.Mod(v, a) == 0
	},
	"lengthis": func(arg int, value interface{}) bool {
		defer recovery()

		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.Slice, reflect.Array, reflect.Map:
			return v.Len() == arg
		case reflect.String:
			return len([]rune(v.String())) == arg
		}

		return false
	},
	"trim": func(s string) string {
		defer recovery()

		return strings.TrimSpace(s)
	},
	"capfirst": func(s string) string {
		defer recovery()

		return strings.ToUpper(string(s[0])) + s[1:]
	},
	"pluralize": func(arg string, value interface{}) string {
		defer recovery()

		flag := false
		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			flag = v.Int() == 1
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			flag = v.Uint() == 1
		default:
			return ""
		}

		if !strings.Contains(arg, ",") {
			arg = "," + arg
		}

		bits := strings.Split(arg, ",")

		if len(bits) > 2 {
			return ""
		}

		if flag {
			return bits[0]
		}

		return bits[1]
	},
	"yesno": func(yes string, no string, value bool) string {
		defer recovery()

		if value {
			return yes
		}

		return no
	},
	"rjust": func(arg int, value string) string {
		defer recovery()

		n := arg - len([]rune(value))

		if n > 0 {
			value = strings.Repeat(" ", n) + value
		}

		return value
	},
	"ljust": func(arg int, value string) string {
		defer recovery()

		n := arg - len([]rune(value))

		if n > 0 {
			value = value + strings.Repeat(" ", n)
		}

		return value
	},
	"center": func(arg int, value string) string {
		defer recovery()

		n := arg - len([]rune(value))

		if n > 0 {
			left := n / 2
			right := n - left
			value = strings.Repeat(" ", left) + value + strings.Repeat(" ", right)
		}

		return value
	},
	"filesizeformat": func(value interface{}) string {
		defer recovery()

		var size float64

		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			size = float64(v.Int())
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			size = float64(v.Uint())
		case reflect.Float32, reflect.Float64:
			size = v.Float()
		default:
			return ""
		}

		var KB float64 = 1 << 10
		var MB float64 = 1 << 20
		var GB float64 = 1 << 30
		var TB float64 = 1 << 40
		var PB float64 = 1 << 50

		filesizeFormat := func(filesize float64, suffix string) string {
			return strings.Replace(fmt.Sprintf("%.1f %s", filesize, suffix), ".0", "", -1)
		}

		var result string
		if size < KB {
			result = filesizeFormat(size, "bytes")
		} else if size < MB {
			result = filesizeFormat(size/KB, "KB")
		} else if size < GB {
			result = filesizeFormat(size/MB, "MB")
		} else if size < TB {
			result = filesizeFormat(size/GB, "GB")
		} else if size < PB {
			result = filesizeFormat(size/TB, "TB")
		} else {
			result = filesizeFormat(size/PB, "PB")
		}

		return result
	},
	"apnumber": func(value interface{}) interface{} {
		defer recovery()

		name := [10]string{"one", "two", "three", "four", "five",
			"six", "seven", "eight", "nine"}

		v := reflect.ValueOf(value)
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.Int() < 10 {
				return name[v.Int()-1]
			}
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			if v.Uint() < 10 {
				return name[v.Uint()-1]
			}
		}

		return value
	},
	"intcomma": func(value interface{}) string {
		defer recovery()

		v := reflect.ValueOf(value)

		var x uint
		minus := false
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.Int() < 0 {
				minus = true
				x = uint(-v.Int())
			} else {
				x = uint(v.Int())
			}
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			x = uint(v.Uint())
		default:
			return ""
		}

		var result string
		for x >= 1000 {
			result = fmt.Sprintf(",%03d%s", x%1000, result)
			x /= 1000
		}
		result = fmt.Sprintf("%d%s", x, result)

		if minus {
			result = "-" + result
		}

		return result
	},
	"ordinal": func(value interface{}) string {
		defer recovery()

		v := reflect.ValueOf(value)

		var x uint
		switch v.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if v.Int() < 0 {
				return ""
			}
			x = uint(v.Int())
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			x = uint(v.Uint())
		default:
			return ""
		}

		suffixes := [10]string{"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"}

		switch x % 100 {
		case 11, 12, 13:
			return fmt.Sprintf("%d%s", x, suffixes[0])
		}

		return fmt.Sprintf("%d%s", x, suffixes[x%10])
	},
	"first": func(value interface{}) interface{} {
		defer recovery()

		v := reflect.ValueOf(value)

		switch v.Kind() {
		case reflect.String:
			return string([]rune(v.String())[0])
		case reflect.Slice, reflect.Array:
			return v.Index(0).Interface()
		}

		return ""
	},
	"last": func(value interface{}) interface{} {
		defer recovery()

		v := reflect.ValueOf(value)

		switch v.Kind() {
		case reflect.String:
			str := []rune(v.String())
			return string(str[len(str)-1])
		case reflect.Slice, reflect.Array:
			return v.Index(v.Len() - 1).Interface()
		}

		return ""
	},
	"join": func(arg string, value []string) string {
		defer recovery()

		return strings.Join(value, arg)
	},
	"slice": func(start int, end int, value interface{}) interface{} {
		defer recovery()

		v := reflect.ValueOf(value)

		if start < 0 {
			start = 0
		}

		switch v.Kind() {
		case reflect.String:
			str := []rune(v.String())

			if end > len(str) {
				end = len(str)
			}

			return string(str[start:end])
		case reflect.Slice:
			return v.Slice(start, end).Interface()
		}
		return ""
	},
	"random": func(value interface{}) interface{} {
		defer recovery()

		rand.Seed(time.Now().UTC().UnixNano())

		v := reflect.ValueOf(value)

		switch v.Kind() {
		case reflect.String:
			str := []rune(v.String())
			return string(str[rand.Intn(len(str))])
		case reflect.Slice, reflect.Array:
			return v.Index(rand.Intn(v.Len())).Interface()
		}

		return ""
	},
	"randomintrange": func(min, max int, value interface{}) int {
		defer recovery()

		rand.Seed(time.Now().UTC().UnixNano())
		return rand.Intn(max-min) + min
	},
	"striptags": func(s string) string {
		return strings.TrimSpace(striptagsRegexp.ReplaceAllString(s, ""))
	},
}

Functions

func ForceInject

func ForceInject(funcs map[string]interface{})

gtf.ForceInject injects gtf functions into the passed FuncMap. It overwrites the original function which have same name as a gtf function.

func Inject

func Inject(funcs map[string]interface{})

gtf.Inject injects gtf functions into the passed FuncMap. It does not overwrite the original function which have same name as a gtf function.

func InjectWithPrefix

func InjectWithPrefix(funcs map[string]interface{}, prefix string)

gtf.Inject injects gtf functions into the passed FuncMap. It prefixes the gtf functions with the specified prefix. If there are many function which have same names as the gtf functions, you can use this function to prefix the gtf functions.

func New

func New(name string) *htmlTemplate.Template

gtf.New is a wrapper function of template.New(https://golang.org/pkg/html/template/#New). It automatically adds the gtf functions to the template's function map and returns template.Template(http://golang.org/pkg/html/template/#Template).

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL