Browse Source

:)

tags/v12.2.0-alpha2
Gerasimos (Makis) Maropoulos 6 months ago
parent
commit
8aedf6bc32
No known key found for this signature in database GPG Key ID: 5DBE766BD26A54E7
36 changed files with 99 additions and 130 deletions
  1. +1
    -1
      _examples/file-server/embedding-files-into-app/bindata.go
  2. +2
    -2
      _examples/file-server/embedding-files-into-app/main_test.go
  3. +1
    -1
      _examples/file-server/embedding-gzipped-files-into-app/main_test.go
  4. +2
    -2
      _examples/file-server/single-page-application/embedded-single-page-application/main_test.go
  5. +2
    -2
      _examples/file-server/upload-files/main.go
  6. +1
    -1
      cli.go
  7. +1
    -1
      context/accept_header.go
  8. +1
    -1
      context/compress.go
  9. +7
    -9
      context/context.go
  10. +1
    -1
      core/host/proxy.go
  11. +1
    -1
      core/host/supervisor_task_example_test.go
  12. +0
    -18
      core/memstore/memstore.go
  13. +4
    -4
      core/router/fs.go
  14. +1
    -1
      core/router/path.go
  15. +2
    -2
      core/router/route.go
  16. +1
    -4
      core/router/router.go
  17. +0
    -2
      hero/func_result.go
  18. +1
    -1
      httptest/httptest.go
  19. +2
    -4
      i18n/internal/locale.go
  20. +3
    -4
      i18n/internal/var.go
  21. +1
    -1
      iris.go
  22. +1
    -1
      macro/interpreter/parser/parser.go
  23. +2
    -2
      middleware/accesslog/accesslog.go
  24. +26
    -34
      middleware/accesslog/accesslog_test.go
  25. +1
    -3
      middleware/accesslog/csv.go
  26. +3
    -3
      middleware/accesslog/csv_test.go
  27. +1
    -5
      middleware/basicauth/basicauth.go
  28. +2
    -2
      middleware/requestid/requestid.go
  29. +6
    -8
      mvc/grpc.go
  30. +0
    -4
      sessions/session.go
  31. +1
    -1
      view/ace.go
  32. +4
    -0
      view/amber.go
  33. +4
    -0
      view/django.go
  34. +4
    -3
      view/handlebars.go
  35. +5
    -1
      view/html.go
  36. +4
    -0
      view/jet.go

+ 1
- 1
_examples/file-server/embedding-files-into-app/bindata.go View File

@@ -231,7 +231,7 @@ func jsJquery211Js() (*asset, error) {
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
cannonicalName := strings.ReplaceAll(name, "\\", "/")
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {


+ 2
- 2
_examples/file-server/embedding-files-into-app/main_test.go View File

@@ -54,8 +54,8 @@ func (r resource) loadFromBase(dir string) string {
result := string(b)

if runtime.GOOS != "windows" {
result = strings.Replace(result, "\n", "\r\n", -1)
result = strings.Replace(result, "\r\r", "", -1)
result = strings.ReplaceAll(result, "\n", "\r\n")
result = strings.ReplaceAll(result, "\r\r", "")
}
return result
}


+ 1
- 1
_examples/file-server/embedding-gzipped-files-into-app/main_test.go View File

@@ -55,7 +55,7 @@ func (r resource) loadFromBase(dir string) string {
result := string(b)

if runtime.GOOS != "windows" {
result = strings.Replace(result, "\n", "\r\n", -1)
result = strings.ReplaceAll(result, "\n", "\r\n")
}
return result
}


+ 2
- 2
_examples/file-server/single-page-application/embedded-single-page-application/main_test.go View File

@@ -47,8 +47,8 @@ func (r resource) loadFromBase(dir string) string {
}
result := string(b)
if runtime.GOOS != "windows" {
result = strings.Replace(result, "\n", "\r\n", -1)
result = strings.Replace(result, "\r\r", "", -1)
result = strings.ReplaceAll(result, "\n", "\r\n")
result = strings.ReplaceAll(result, "\r\r", "")
}
return result
}


+ 2
- 2
_examples/file-server/upload-files/main.go View File

@@ -80,8 +80,8 @@ func beforeSave(ctx iris.Context, file *multipart.FileHeader) bool {
ip := ctx.RemoteAddr()
// make sure you format the ip in a way
// that can be used for a file name (simple case):
ip = strings.Replace(ip, ".", "_", -1)
ip = strings.Replace(ip, ":", "_", -1)
ip = strings.ReplaceAll(ip, ".", "_")
ip = strings.ReplaceAll(ip, ":", "_")

// you can use the time.Now, to prefix or suffix the files
// based on the current time as well, as an exercise.


+ 1
- 1
cli.go View File

@@ -47,7 +47,7 @@ func injectLiveReload(r Party) (bool, error) {
path = filepath.Join(wd, path)

if _, err := os.Stat(path); err == nil {
inFile, err := os.OpenFile(path, os.O_RDONLY, 0644)
inFile, err := os.OpenFile(path, os.O_RDONLY, 0600)
if err != nil {
return false, err
}


+ 1
- 1
context/accept_header.go View File

@@ -135,7 +135,7 @@ func expectTokenSlash(s string) (token, rest string) {

func expectQuality(s string) (q float64, rest string) {
switch {
case len(s) == 0:
case s == "":
return -1, ""
case s[0] == '0':
q = 0


+ 1
- 1
context/compress.go View File

@@ -102,7 +102,7 @@ func NewCompressWriter(w io.Writer, encoding string, level int) (cw CompressWrit
}
cw = brotli.NewWriterLevel(w, level)
case SNAPPY:
cw = snappy.NewWriter(w)
cw = snappy.NewBufferedWriter(w)
case S2:
cw = s2.NewWriter(w)
default:


+ 7
- 9
context/context.go View File

@@ -1979,8 +1979,8 @@ func (ctx *Context) UploadFormFiles(destDirectory string, before ...func(*Contex
// which could lead to override existing system files
// by ../../$file.
// Reported by Frank through security reports.
file.Filename = strings.TrimLeft(file.Filename, "../")
file.Filename = strings.TrimLeft(file.Filename, "..\\")
file.Filename = strings.ReplaceAll(file.Filename, "../", "")
file.Filename = strings.ReplaceAll(file.Filename, "..\\", "")

for _, b := range before {
if !b(ctx, file) {
@@ -2859,10 +2859,8 @@ func (ctx *Context) CompressReader(enable bool) error {
return err
}
ctx.request.Body = r
} else {
if ok {
ctx.request.Body = cr.Src
}
} else if ok {
ctx.request.Body = cr.Src
}

return nil
@@ -3208,9 +3206,9 @@ func WriteJSON(writer io.Writer, v interface{}, options JSON, optimize bool) (in
}

if options.UnescapeHTML {
result = bytes.Replace(result, ltHex, lt, -1)
result = bytes.Replace(result, gtHex, gt, -1)
result = bytes.Replace(result, andHex, and, -1)
result = bytes.ReplaceAll(result, ltHex, lt)
result = bytes.ReplaceAll(result, gtHex, gt)
result = bytes.ReplaceAll(result, andHex, and)
}

if prependSecure {


+ 1
- 1
core/host/proxy.go View File

@@ -41,7 +41,7 @@ func ProxyHandler(target *url.URL) *httputil.ReverseProxy {

if netutil.IsLoopbackHost(target.Host) {
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // lint:ignore
}
p.Transport = transport
}


+ 1
- 1
core/host/supervisor_task_example_test.go View File

@@ -56,9 +56,9 @@ func (m myTestTask) OnServe(host TaskHost) {
if rans == exitAfterXRestarts {
m.logger.Println("exit")
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
defer cancel()
_ = host.Supervisor.Shutdown(ctx) // total shutdown
host.Supervisor.RestoreFlow() // free to exit (if shutdown)
cancel()
return
}



+ 0
- 18
core/memstore/memstore.go View File

@@ -363,9 +363,6 @@ func (e Entry) UintDefault(def uint) (uint, error) {
if err != nil {
return def, err
}
if val > uint64(maxValue) {
return def, e.notFound(reflect.Uint)
}
return uint(val), nil
case uint:
return vv, nil
@@ -412,9 +409,6 @@ func (e Entry) Uint8Default(def uint8) (uint8, error) {
if err != nil {
return def, err
}
if val > math.MaxUint8 {
return def, e.notFound(reflect.Uint8)
}
return uint8(val), nil
case uint:
if vv > math.MaxUint8 {
@@ -462,9 +456,6 @@ func (e Entry) Uint16Default(def uint16) (uint16, error) {
if err != nil {
return def, err
}
if val > math.MaxUint16 {
return def, e.notFound(reflect.Uint16)
}
return uint16(val), nil
case uint:
if vv > math.MaxUint16 {
@@ -509,9 +500,6 @@ func (e Entry) Uint32Default(def uint32) (uint32, error) {
if err != nil {
return def, err
}
if val > math.MaxUint32 {
return def, e.notFound(reflect.Uint32)
}
return uint32(val), nil
case uint:
if vv > math.MaxUint32 {
@@ -555,9 +543,6 @@ func (e Entry) Uint64Default(def uint64) (uint64, error) {
if err != nil {
return def, err
}
if val > math.MaxUint64 {
return def, e.notFound(reflect.Uint64)
}
return uint64(val), nil
case uint8:
return uint64(vv), nil
@@ -590,9 +575,6 @@ func (e Entry) Float32Default(key string, def float32) (float32, error) {
if err != nil {
return def, err
}
if val > math.MaxFloat32 {
return def, e.notFound(reflect.Float32)
}
return float32(val), nil
case float32:
return vv, nil


+ 4
- 4
core/router/fs.go View File

@@ -442,9 +442,9 @@ func StripPrefix(prefix string, h context.Handler) context.Handler {

func toWebPath(systemPath string) string {
// winos slash to slash
webpath := strings.Replace(systemPath, "\\", "/", -1)
webpath := strings.ReplaceAll(systemPath, "\\", "/")
// double slashes to single
webpath = strings.Replace(webpath, "//", "/", -1)
webpath = strings.ReplaceAll(webpath, "//", "/")
return webpath
}

@@ -1013,7 +1013,7 @@ func cacheFiles(ctx stdContext.Context, fs http.FileSystem, names []string, comp
case <-ctx.Done():
return ctx.Err()
default:
break
break // lint:ignore
}

if alg == "brotli" {
@@ -1218,7 +1218,7 @@ var _ http.File = (*dir)(nil)

// returns unorderded map of directories both reclusive and flat.
func findDirs(fs http.FileSystem, names []string) (map[string]*dir, error) {
dirs := make(map[string]*dir, 0)
dirs := make(map[string]*dir)

for _, name := range names {
f, err := fs.Open(name)


+ 1
- 1
core/router/path.go View File

@@ -19,7 +19,7 @@ func Param(name string) string {

// WildcardParam receives a parameter name prefixed with the WildcardParamStart symbol.
func WildcardParam(name string) string {
if len(name) == 0 {
if name == "" {
return ""
}
return prefix(name, WildcardParamStart)


+ 2
- 2
core/router/route.go View File

@@ -378,7 +378,7 @@ func formatPath(path string) string {
var formattedParts []string
parts := strings.Split(path, "/")
for _, part := range parts {
if len(part) == 0 {
if part == "" {
continue
}
if part[0] == startRune || part[0] == wildcardStartRune {
@@ -566,7 +566,7 @@ func (r *Route) Trace(w io.Writer, stoppedIndex int) {
if stoppedIndex != -1 && stoppedIndex <= len(r.Handlers) {
if i <= stoppedIndex {
pio.WriteRich(w, " ✓", pio.Green)
} else {
// } else {
// pio.WriteRich(w, " ✕", pio.Red, pio.Underline)
}
}


+ 1
- 4
core/router/router.go View File

@@ -136,10 +136,7 @@ func (router *Router) buildMainHandlerWithFilters(routerFilters map[Party]*Filte
}

if leftSlashLen == rightSlashLen {
if len(left.Path) > len(right.Path) {
return true
}
return false
return len(left.Path) > len(right.Path)
}

return len(left.Path) > len(right.Path)


+ 0
- 2
hero/func_result.go View File

@@ -480,8 +480,6 @@ type View struct {

var _ Result = View{}

const dotB = byte('.')

// Dispatch writes the template filename, template layout and (any) data to the client.
// Completes the `Result` interface.
func (r View) Dispatch(ctx *context.Context) { // r as Response view.


+ 1
- 1
httptest/httptest.go View File

@@ -125,7 +125,7 @@ func NewInsecure(t *testing.T, setters ...OptionSetter) *httpexpect.Expect {
setter.Set(conf)
}
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // lint:ignore
}

testConfiguration := httpexpect.Config{


+ 2
- 4
i18n/internal/locale.go View File

@@ -115,12 +115,10 @@ func (loc *Locale) setString(c *Catalog, key string, value string, vars []Var, f
if err != nil {
return fmt.Errorf("<%s = %s>: %w", key, value, err)
}
} else {
} else if err = c.Set(loc.tag, key, msgs...); err != nil {
// let's make normal keys direct fire:
// renderer = &simpleRenderer{key, loc.Printer}
if err = c.Set(loc.tag, key, msgs...); err != nil {
return fmt.Errorf("<%s = %s>: %w", key, value, err)
}
return fmt.Errorf("<%s = %s>: %w", key, value, err)
}

}


+ 3
- 4
i18n/internal/var.go View File

@@ -1,11 +1,8 @@
package internal

import (
"reflect"
"regexp"
"sort"

"golang.org/x/text/message/catalog"
)

// Var represents a message variable.
@@ -84,7 +81,7 @@ func getVars(loc *Locale, key string, src map[string]interface{}) []Var {
return vars
}

var unescapeVariableRegex = regexp.MustCompile("\\$\\{(.*?)}")
var unescapeVariableRegex = regexp.MustCompile(`\$\{(.*?)}`)

func sortVars(text string, vars []Var) (newVars []Var) {
argth := 1
@@ -122,6 +119,7 @@ func removeVarsDuplicates(elements []Var) (result []Var) {
return result
}

/*
func removeMsgVarsDuplicates(elements []catalog.Message) (result []catalog.Message) {
seen := make(map[string]struct{})

@@ -141,6 +139,7 @@ func removeMsgVarsDuplicates(elements []catalog.Message) (result []catalog.Messa

return
}
*/

func getCases(loc *Locale, src map[string]interface{}) []interface{} {
type PluralCase struct {


+ 1
- 1
iris.go View File

@@ -142,7 +142,7 @@ func Default() *Application {
app.logger.Debugf(`Log level set to "debug"`)

// Register the accesslog middleware.
logFile, err := os.OpenFile("./access.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
logFile, err := os.OpenFile("./access.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if err == nil {
// Close the file on shutdown.
app.ConfigureHost(func(su *Supervisor) {


+ 1
- 1
macro/interpreter/parser/parser.go View File

@@ -18,7 +18,7 @@ func Parse(fullpath string, paramTypes []ast.ParamType) ([]*ast.ParamStatement,
return nil, fmt.Errorf("empty parameter types")
}

pathParts := strings.SplitN(fullpath, "/", -1)
pathParts := strings.Split(fullpath, "/")
p := new(ParamParser)
statements := make([]*ast.ParamStatement, 0)
for i, s := range pathParts {


+ 2
- 2
middleware/accesslog/accesslog.go View File

@@ -337,7 +337,7 @@ func FileUnbuffered(path string) *AccessLog {
func mustOpenFile(path string) *os.File {
// Note: we add os.RDWR in order to be able to read from it,
// some formatters (e.g. CSV) needs that.
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
if err != nil {
panic(err)
}
@@ -1027,7 +1027,7 @@ func (ac *AccessLog) Print(ctx *context.Context,
// but let's don't coplicate things so much
// as the end-developer can use a custom template.
func (ac *AccessLog) writeText(buf *bytes.Buffer, s string) {
if len(s) == 0 {
if s == "" {
if len(ac.Blank) == 0 {
return
}


+ 26
- 34
middleware/accesslog/accesslog_test.go View File

@@ -104,34 +104,29 @@ func TestAccessLogBroker(t *testing.T) {
go func() {
i := 0
ln := broker.NewListener()
for {
select {
case log, ok := <-ln:
if !ok {
if i != n {
for i < n {
wg.Done()
i++
}
}

t.Log("Log Listener Closed: interrupted")
return
}
for log := range ln {
lat := log.Latency
t.Log(lat.String())
wg.Done()
if expected := time.Duration(i) * time.Second; expected != lat {
panic(fmt.Sprintf("expected latency: %s but got: %s", expected, lat))
}
time.Sleep(1350 * time.Millisecond)
if log.Latency != lat {
panic("expected logger to wait for notifier before release the log")
}
i++
}

lat := log.Latency
t.Log(lat.String())
if i != n {
for i < n {
wg.Done()
if expected := time.Duration(i) * time.Second; expected != lat {
panic(fmt.Sprintf("expected latency: %s but got: %s", expected, lat))
}
time.Sleep(1350 * time.Millisecond)
if log.Latency != lat {
panic("expected logger to wait for notifier before release the log")
}
i++
}
}

t.Log("Log Listener Closed: interrupted")
}()

time.Sleep(time.Second)
@@ -258,18 +253,15 @@ func TestAccessLogSetOutput(t *testing.T) {
time.Sleep(10 * time.Millisecond)
}

switch i {
case 5:
if w == nil {
break
}

now := time.Now()
ac.SetOutput(w)
if withSlowClose {
end := time.Since(now)
if end < time.Second {
panic(fmt.Sprintf("[%s] [%d]: SetOutput should wait for previous Close. Expected to return a bit after %s but %s", name, i, time.Second, end))
if i == 5 {
if w != nil {
now := time.Now()
ac.SetOutput(w)
if withSlowClose {
end := time.Since(now)
if end < time.Second {
panic(fmt.Sprintf("[%s] [%d]: SetOutput should wait for previous Close. Expected to return a bit after %s but %s", name, i, time.Second, end))
}
}
}
}


+ 1
- 3
middleware/accesslog/csv.go View File

@@ -8,9 +8,7 @@ import (
)

// CSV is a Formatter type for csv encoded logs.
type CSV struct { // TODO: change it to use csvutil.
writer *csv.Writer

type CSV struct {
writerPool *sync.Pool
ac *AccessLog



+ 3
- 3
middleware/accesslog/csv_test.go View File

@@ -20,7 +20,7 @@ func TestCSV(t *testing.T) {

lat, _ := time.ParseDuration("1s")

print := func() {
printFunc := func() {
ac.Print(
nil,
lat,
@@ -39,8 +39,8 @@ func TestCSV(t *testing.T) {
}

// print twice, the header should only be written once.
print()
print()
printFunc()
printFunc()

expected := `Timestamp,Latency,Code,Method,Path,IP,Req Values,In,Out
725864400000,1s,200,GET,/,::1,sleep=1s,573,81


+ 1
- 5
middleware/basicauth/basicauth.go View File

@@ -28,10 +28,6 @@ const (
DefaultCookieMaxAge = time.Hour
)

// cookieExpireDelete may be set on Cookie.Expire for expiring the given cookie.
// Note that the MaxAge is set but we set Expires field in order to support very old browsers too.
var cookieExpireDelete = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)

const (
authorizationType = "Basic Authentication"
authenticateHeaderKey = "WWW-Authenticate"
@@ -480,7 +476,7 @@ func (b *BasicAuth) logout(ctx *context.Context) {
// If the custom user does
// not implement the User interface, then extract from the request header (most common scenario):
header := ctx.GetHeader(b.authorizationHeader)
fullUser, username, password, ok = decodeHeader(header)
fullUser, _, _, ok = decodeHeader(header)
}

if ok { // If it's authorized then try to lock and delete.


+ 2
- 2
middleware/requestid/requestid.go View File

@@ -1,7 +1,7 @@
package requestid

import (
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"net/http/httputil"

@@ -102,7 +102,7 @@ func Get(ctx *context.Context) string {
// Hash returns the sha1 hash of the request.
// It does not capture error, instead it returns an empty string.
func Hash(ctx *context.Context, includeBody bool) string {
h := sha1.New()
h := sha256.New() // sha1 fits here as well.
b, err := httputil.DumpRequest(ctx.Request(), includeBody)
if err != nil {
return ""


+ 6
- 8
mvc/grpc.go View File

@@ -56,15 +56,13 @@ func (g GRPC) Apply(c *ControllerActivator) {
path := path.Join(g.ServiceName, m.Name)
if g.Strict {
c.app.Router.HandleMany(http.MethodPost, path, pre)
} else {
if route := c.Handle(http.MethodPost, path, m.Name, pre); route != nil {
bckp := route.Description
route.Description = "gRPC"
if g.Strict {
route.Description += "-only"
}
route.Description += " " + bckp // e.g. "gRPC controller"
} else if route := c.Handle(http.MethodPost, path, m.Name, pre); route != nil {
bckp := route.Description
route.Description = "gRPC"
if g.Strict {
route.Description += "-only"
}
route.Description += " " + bckp // e.g. "gRPC controller"
}

}


+ 0
- 4
sessions/session.go View File

@@ -1,7 +1,6 @@
package sessions

import (
"math"
"reflect"
"strconv"
"sync"
@@ -327,9 +326,6 @@ func (s *Session) GetUint64(key string) (uint64, error) {
if err != nil {
return 0, err
}
if val > math.MaxUint64 {
break
}
return uint64(val), nil
case uint8:
return uint64(vv), nil


+ 1
- 1
view/ace.go View File

@@ -39,7 +39,7 @@ func Ace(fs interface{}, extension string) *AceEngine {
s := &AceEngine{HTMLEngine: HTML(fs, extension), indent: ""}
s.name = "Ace"

funcs := make(map[string]interface{}, 0)
funcs := make(map[string]interface{})

once := new(sync.Once)



+ 4
- 0
view/amber.go View File

@@ -143,6 +143,10 @@ func (s *AmberEngine) AddFunc(funcName string, funcBody interface{}) {
// Returns an error if something bad happens, user is responsible to catch it.
func (s *AmberEngine) Load() error {
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info == nil || info.IsDir() {
return nil
}


+ 4
- 0
view/django.go View File

@@ -213,6 +213,10 @@ func (s *DjangoEngine) RegisterTag(tagName string, fn TagParser) error {
// Returns an error if something bad happens, user is responsible to catch it.
func (s *DjangoEngine) Load() error {
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info == nil || info.IsDir() {
return nil
}


+ 4
- 3
view/handlebars.go View File

@@ -19,9 +19,10 @@ type HandlebarsEngine struct {
// files configuration
rootDir string
extension string
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
namesFn func() []string // for embedded, in combination with directory & extension
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded.
// Not used anymore.
// assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
// namesFn func() []string // for embedded, in combination with directory & extension
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded.
// parser configuration
layout string
rmu sync.RWMutex


+ 5
- 1
view/html.go View File

@@ -246,6 +246,10 @@ func (s *HTMLEngine) load() error {
}

return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info == nil || info.IsDir() {
return nil
}
@@ -357,7 +361,7 @@ func (s *HTMLEngine) layoutFuncsFor(lt *template.Template, name string, binding
func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding interface{}) {
funcs := template.FuncMap{
"part": func(partName string) (template.HTML, error) {
nameTemp := strings.Replace(name, s.extension, "", -1)
nameTemp := strings.ReplaceAll(name, s.extension, "")
fullPartName := fmt.Sprintf("%s-%s", nameTemp, partName)
result, err := s.executeTemplateBuf(fullPartName, binding)
if err != nil {


+ 4
- 0
view/jet.go View File

@@ -222,6 +222,10 @@ func (l *jetLoader) Exists(name string) (string, bool) {
// Load should load the templates from a physical system directory or by an embedded one (assets/go-bindata).
func (s *JetEngine) Load() error {
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info == nil || info.IsDir() {
return nil
}


Loading…
Cancel
Save