Skip to content

Commit

Permalink
Merge pull request #29 from acoshift/config/template
Browse files Browse the repository at this point in the history
add template config
  • Loading branch information
acoshift committed May 18, 2018
2 parents 0586f7f + b27d2d7 commit 014a2e6
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 42 deletions.
4 changes: 2 additions & 2 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ type App struct {
globals Globals
beforeRender middleware.Middleware

template map[string]*tmpl
templateFunc []template.FuncMap
template map[string]*tmpl
templateFuncs []template.FuncMap

gracefulShutdown *gracefulShutdown
}
Expand Down
46 changes: 35 additions & 11 deletions app_internal_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package hime

import (
"crypto/tls"
"html/template"
"log"
"net"
"net/http"
"os"
"reflect"
"testing"
"time"
Expand All @@ -23,18 +28,16 @@ func TestApp(t *testing.T) {
assert.Equal(t, reflect.ValueOf(m).Pointer(), reflect.ValueOf(app.beforeRender).Pointer())
})

t.Run("Routes", func(t *testing.T) {
app.Routes(Routes{"a": "/b", "b": "/cd"})
assert.Len(t, app.routes, 2)
assert.Equal(t, "/b", app.Route("a"))
assert.Equal(t, "/cd", app.Route("b"))
})
t.Run("TemplateFuncs", func(t *testing.T) {
app.TemplateFunc("a", func() {})
assert.Len(t, app.templateFuncs, 1)

t.Run("Globals", func(t *testing.T) {
app.Globals(Globals{"a": 12, "b": "34"})
assert.Len(t, app.globals, 2)
assert.Equal(t, 12, app.Global("a"))
assert.Equal(t, "34", app.Global("b"))
app.TemplateFuncs(template.FuncMap{
"a": func() {},
"b": func() {},
"c": func() {},
})
assert.Len(t, app.templateFuncs, 2)
})

t.Run("GracefulShutdown", func(t *testing.T) {
Expand All @@ -59,3 +62,24 @@ func TestApp(t *testing.T) {
assert.Len(t, gs.notiFns, 3)
})
}

func TestConfigServer(t *testing.T) {
t.Parallel()

app := &App{
TLSConfig: &tls.Config{},
ReadTimeout: 5 * time.Second,
ReadHeaderTimeout: 6 * time.Second,
WriteTimeout: 7 * time.Second,
IdleTimeout: 2 * time.Minute,
MaxHeaderBytes: 1024,
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
ConnState: func(net.Conn, http.ConnState) {},
ErrorLog: log.New(os.Stderr, "", log.LstdFlags),
}

assert.Empty(t, &app.srv)
app.configServer(":8080")
assert.NotEmpty(t, &app.srv)
assert.Equal(t, ":8080", app.srv.Addr)
}
34 changes: 7 additions & 27 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,12 @@ import (
yaml "gopkg.in/yaml.v2"
)

// Config is app's config
type Config struct {
// AppConfig is hime app's config
type AppConfig struct {
Globals map[interface{}]interface{} `yaml:"globals" json:"globals"`
Routes map[string]string `yaml:"routes" json:"routes"`
Templates []struct {
Dir string `yaml:"dir" json:"dir"`
Root string `yaml:"root" json:"root"`
Minify bool `yaml:"minify" json:"minify"`
Components []string `yaml:"components" json:"components"`
List map[string][]string `yaml:"list" json:"list"`
Delims []string `yaml:"delims" json:"delims"`
} `yaml:"templates" json:"templates"`
Server struct {
Templates []TemplateConfig `yaml:"templates" json:"templates"`
Server struct {
ReadTimeout string `yaml:"readTimeout" json:"readTimeout"`
ReadHeaderTimeout string `yaml:"readHeaderTimeout" json:"readHeaderTimeout"`
WriteTimeout string `yaml:"writeTimeout" json:"writeTimeout"`
Expand Down Expand Up @@ -72,24 +65,12 @@ func parseDuration(s string, t *time.Duration) {
// gracefulShutdown:
// timeout: 1m
// wait: 5s
func (app *App) Config(config Config) *App {
func (app *App) Config(config AppConfig) *App {
app.Globals(config.Globals)
app.Routes(config.Routes)

for _, cfg := range config.Templates {
tp := app.Template()
tp.Dir(cfg.Dir)
tp.Root(cfg.Root)
if len(cfg.Delims) == 2 {
tp.Delims(cfg.Delims[0], cfg.Delims[1])
}
tp.Component(cfg.Components...)
for name, filenames := range cfg.List {
tp.Parse(name, filenames...)
}
if cfg.Minify {
tp.Minify()
}
app.Template().Config(cfg)
}

// load server config
Expand All @@ -112,12 +93,11 @@ func (app *App) Config(config Config) *App {

// ParseConfig parses config data
func (app *App) ParseConfig(data []byte) *App {
var config Config
var config AppConfig
err := yaml.Unmarshal(data, &config)
if err != nil {
panic(err)
}

return app.Config(config)
}

Expand Down
26 changes: 26 additions & 0 deletions request_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package hime

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestTrimComma(t *testing.T) {
t.Parallel()

cases := []struct {
Input string
Output string
}{
{"", ""},
{"123", "123"},
{"12,345", "12345"},
{" 12, ,, 34,5, ,,", " 12 345 "},
{"12,345.67", "12345.67"},
}

for _, c := range cases {
assert.Equal(t, c.Output, trimComma(c.Input))
}
}
24 changes: 24 additions & 0 deletions route_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package hime

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestRoute(t *testing.T) {
t.Parallel()

app := New()
assert.Panics(t, func() { app.Route("empty") })

app.Routes(Routes{"a": "/b", "b": "/cd"})
assert.Len(t, app.routes, 2)
assert.Equal(t, "/b", app.Route("a"))
assert.Equal(t, "/cd", app.Route("b"))

assert.Panics(t, func() { app.Route("notexists") })

ctx := appContext{app: app}
assert.Equal(t, "/b", ctx.Route("a"))
}
63 changes: 61 additions & 2 deletions template.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@ import (
"bytes"
"html/template"
"io"
"io/ioutil"
"path/filepath"

"github.com/tdewolff/minify"
"github.com/tdewolff/minify/css"
"github.com/tdewolff/minify/html"
"github.com/tdewolff/minify/js"
yaml "gopkg.in/yaml.v2"
)

// TemplateConfig is template config
type TemplateConfig struct {
Dir string `yaml:"dir" json:"dir"`
Root string `yaml:"root" json:"root"`
Minify bool `yaml:"minify" json:"minify"`
Components []string `yaml:"components" json:"components"`
List map[string][]string `yaml:"list" json:"list"`
Delims []string `yaml:"delims" json:"delims"`
}

// Template creates new template loader
func (app *App) Template() *Template {
if app.template == nil {
Expand All @@ -22,16 +34,21 @@ func (app *App) Template() *Template {
funcs: append([]template.FuncMap{template.FuncMap{
"route": app.Route,
"global": app.Global,
}}, app.templateFunc...),
}}, app.templateFuncs...),
}
}

// TemplateFuncs registers app's level template funcs
func (app *App) TemplateFuncs(funcs ...template.FuncMap) *App {
app.templateFunc = append(app.templateFunc, funcs...)
app.templateFuncs = append(app.templateFuncs, funcs...)
return app
}

// TemplateFunc registers an app's level template func
func (app *App) TemplateFunc(name string, f interface{}) *App {
return app.TemplateFuncs(template.FuncMap{name: f})
}

type tmpl struct {
template.Template
m *minify.M
Expand Down Expand Up @@ -65,6 +82,43 @@ type Template struct {
minifier *minify.M
}

// Config loads template config
func (tp *Template) Config(cfg TemplateConfig) *Template {
tp.Dir(cfg.Dir)
tp.Root(cfg.Root)
if len(cfg.Delims) == 2 {
tp.Delims(cfg.Delims[0], cfg.Delims[1])
}
tp.Component(cfg.Components...)
for name, filenames := range cfg.List {
tp.Parse(name, filenames...)
}
if cfg.Minify {
tp.Minify()
}

return tp
}

// ParseConfig parses template config data
func (tp *Template) ParseConfig(data []byte) *Template {
var config TemplateConfig
err := yaml.Unmarshal(data, &config)
if err != nil {
panic(err)
}
return tp.Config(config)
}

// ParseConfigFile parses template config from file
func (tp *Template) ParseConfigFile(filename string) *Template {
data, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
return tp.ParseConfig(data)
}

// Minify enables minify when render html, css, js
func (tp *Template) Minify() *Template {
tp.minifier = minify.New()
Expand Down Expand Up @@ -110,6 +164,11 @@ func (tp *Template) Funcs(funcs ...template.FuncMap) *Template {
return tp
}

// Func adds a template func while load template
func (tp *Template) Func(name string, f interface{}) *Template {
return tp.Funcs(template.FuncMap{name: f})
}

// Component adds given templates to every templates
func (tp *Template) Component(filename ...string) *Template {
tp.components = append(tp.components, filename...)
Expand Down

0 comments on commit 014a2e6

Please sign in to comment.