Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/foolin/goview

Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application.
https://github.com/foolin/goview

chi echo framework gin go golang gorice html library template view

Last synced: about 1 month ago
JSON representation

Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application.

Lists

README

        

# goview

[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis] [![GoReportCard Widget]][GoReportCard]

Goview is a lightweight, minimalist and idiomatic template library based on golang [html/template](https://golang.org/pkg/html/template/) for building Go web application.

## Contents

- [Install](#install)
- [Features](#features)
- [Docs](#docs)
- [Supports](#supports)
- [Gin Framework](https://github.com/foolin/goview/tree/master/supports/ginview)
- [Iris Framework](https://github.com/foolin/goview/tree/master/supports/irisview)
- [Echo Framework](https://github.com/foolin/goview/tree/master/supports/echoview)
- [Go.Rice](https://github.com/foolin/goview/tree/master/supports/gorice)
- [Usage](#usage)
- [Overview](#overview)
- [Config](#config)
- [Include syntax](#include-syntax)
- [Render name](#render-name)
- [Custom template functions](#custom-template-functions)
- [Examples](#examples)
- [Basic example](#basic-example)
- [Gin example](#gin-example)
- [Iris example](#iris-example)
- [Iris multiple example](#iris-multiple-example)
- [Echo example](#echo-example)
- [Go-chi example](#go-chi-example)
- [Advance example](#advance-example)
- [Multiple example](#multiple-example)
- [go.rice example](#gorice-example)
- [more examples](#more-examples)

## Install
```bash
go get github.com/foolin/goview
```

## Features

* **Lightweight** - use golang html/template syntax.
* **Easy** - easy use for your web application.
* **Fast** - Support configure cache template.
* **Include syntax** - Support include file.
* **Master layout** - Support configure master layout file.
* **Extension** - Support configure template file extension.
* **Easy** - Support configure templates directory.
* **Auto reload** - Support dynamic reload template(disable cache mode).
* **Multiple Engine** - Support multiple templates for frontend and backend.
* **No external dependencies** - plain ol' Go html/template.
* **Gorice** - Support gorice for package resources.
* **Gin/Iris/Echo/Chi** - Support gin framework, Iris framework, echo framework, go-chi framework.

## Docs
See

## Supports
- **[ginview](https://github.com/foolin/goview/tree/master/supports/ginview)** goview for gin framework
- **[irisview](https://github.com/foolin/goview/tree/master/supports/irisview)** goview for Iris framework
- **[echoview](https://github.com/foolin/goview/tree/master/supports/echoview)** goview for echo framework
- **[gorice](https://github.com/foolin/goview/tree/master/supports/gorice)** goview for go.rice

## Usage

### Overview

Project structure:

```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html

```

Use default instance:

```go
//write http.ResponseWriter
//"index" -> index.html
goview.Render(writer, http.StatusOK, "index", goview.M{})
```

Use new instance with config:

```go

gv := goview.New(goview.Config{
Root: "views",
Extension: ".tpl",
Master: "layouts/master",
Partials: []string{"partials/ad"},
Funcs: template.FuncMap{
"sub": func(a, b int) int {
return a - b
},
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
Delims: Delims{Left: "{{", Right: "}}"},
})

//Set new instance
goview.Use(gv)

//write http.ResponseWriter
goview.Render(writer, http.StatusOK, "index", goview.M{})

```

Use multiple instance with config:

```go
//============== Frontend ============== //
gvFrontend := goview.New(goview.Config{
Root: "views/frontend",
Extension: ".tpl",
Master: "layouts/master",
Partials: []string{"partials/ad"},
Funcs: template.FuncMap{
"sub": func(a, b int) int {
return a - b
},
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
Delims: Delims{Left: "{{", Right: "}}"},
})

//write http.ResponseWriter
gvFrontend.Render(writer, http.StatusOK, "index", goview.M{})

//============== Backend ============== //
gvBackend := goview.New(goview.Config{
Root: "views/backend",
Extension: ".tpl",
Master: "layouts/master",
Partials: []string{"partials/ad"},
Funcs: template.FuncMap{
"sub": func(a, b int) int {
return a - b
},
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
Delims: Delims{Left: "{{", Right: "}}"},
})

//write http.ResponseWriter
gvBackend.Render(writer, http.StatusOK, "index", goview.M{})

```

### Config

```go
goview.Config{
Root: "views", //template root path
Extension: ".tpl", //file extension
Master: "layouts/master", //master layout file
Partials: []string{"partials/head"}, //partial files
Funcs: template.FuncMap{
"sub": func(a, b int) int {
return a - b
},
// more funcs
},
DisableCache: false, //if disable cache, auto reload template file for debug.
Delims: Delims{Left: "{{", Right: "}}"},
}
```

### Include syntax

```go
//template file
{{include "layouts/footer"}}
```

### Render name:

Render name use `index` without `.html` extension, that will render with master layout.

- **"index"** - Render with master layout.
- **"index.html"** - Not render with master layout.

```
Notice: `.html` is default template extension, you can change with config
```

Render with master

```go
//use name without extension `.html`
goview.Render(w, http.StatusOK, "index", goview.M{})
```

The `w` is instance of `http.ResponseWriter`

Render only file(not use master layout)
```go
//use full name with extension `.html`
goview.Render(w, http.StatusOK, "page.html", goview.M{})
```

### Custom template functions

We have two type of functions `global functions`, and `temporary functions`.

`Global functions` are set within the `config`.

```go
goview.Config{
Funcs: template.FuncMap{
"reverse": e.Reverse,
},
}
```

```go
//template file
{{ reverse "route-name" }}
```

`Temporary functions` are set inside the handler.

```go
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "index", goview.M{
"reverse": e.Reverse,
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}
})
```
```go
//template file
{{ call $.reverse "route-name" }}
```

## Examples

See [_examples/](https://github.com/foolin/goview/blob/master/_examples/) for a variety of examples.

### Basic example
```go

package main

import (
"fmt"
"github.com/foolin/goview"
"net/http"
)

func main() {

//render index use `index` without `.html` extension, that will render with master layout.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "index", goview.M{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}

})

//render page use `page.tpl` with '.html' will only file template without master layout.
http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})
if err != nil {
fmt.Fprintf(w, "Render page.html error: %v!", err)
}
})

fmt.Println("Listening and serving HTTP on :9090")
http.ListenAndServe(":9090", nil)

}

```

Project structure:
```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html

See in "examples/basic" folder
```

[Basic example](https://github.com/foolin/goview/tree/master/_examples/basic)

### Gin example

```bash
go get github.com/foolin/goview/supports/ginview
```

```go

package main

import (
"github.com/foolin/goview/supports/ginview"
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
router := gin.Default()

//new template engine
router.HTMLRender = ginview.Default()

router.GET("/", func(ctx *gin.Context) {
//render with master
ctx.HTML(http.StatusOK, "index", gin.H{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
})

router.GET("/page", func(ctx *gin.Context) {
//render only file, must full name with extension
ctx.HTML(http.StatusOK, "page.html", gin.H{"title": "Page file title!!"})
})

router.Run(":9090")
}

```

Project structure:
```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html

See in "examples/basic" folder
```

[Gin example](https://github.com/foolin/goview/tree/master/_examples/gin)

### Iris example

```bash
$ go get github.com/foolin/goview/supports/irisview
```

```go
package main

import (
"github.com/foolin/goview/supports/irisview"
"github.com/kataras/iris/v12"
)

func main() {
app := iris.New()

// Register the goview template engine.
app.RegisterView(irisview.Default())

app.Get("/", func(ctx iris.Context) {
// Render with master.
ctx.View("index", iris.Map{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
})

app.Get("/page", func(ctx iris.Context) {
// Render only file, must full name with extension.
ctx.View("page.html", iris.Map{"title": "Page file title!!"})
})

app.Listen(":9090")
}
```

Project structure:
```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html

See in "examples/iris" folder
```

[Iris example](https://github.com/foolin/goview/tree/master/_examples/iris)

### Iris multiple example

```go
package main

import (
"html/template"
"time"

"github.com/foolin/goview"
"github.com/foolin/goview/supports/irisview"
"github.com/kataras/iris/v12"
)

func main() {
app := iris.New()

// Register a new template engine.
app.RegisterView(irisview.New(goview.Config{
Root: "views/frontend",
Extension: ".html",
Master: "layouts/master",
Partials: []string{"partials/ad"},
Funcs: template.FuncMap{
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
}))

app.Get("/", func(ctx iris.Context) {
ctx.View("index", iris.Map{
"title": "Frontend title!",
})
})

//=========== Backend ===========//

// Assign a new template middleware.
mw := irisview.NewMiddleware(goview.Config{
Root: "views/backend",
Extension: ".html",
Master: "layouts/master",
Partials: []string{},
Funcs: template.FuncMap{
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
})

backendGroup := app.Party("/admin", mw)

backendGroup.Get("/", func(ctx iris.Context) {
// Use the ctx.View as you used to. Zero changes to your codebase,
// even if you use multiple templates.
ctx.View("index", iris.Map{
"title": "Backend title!",
})
})

app.Listen(":9090")
}
```

Project structure:
```go
|-- app/views/
|-- fontend/
|--- index.html
|-- layouts/
|--- footer.html
|--- head.html
|--- master.html
|-- partials/
|--- ad.html
|-- backend/
|--- index.html
|-- layouts/
|--- footer.html
|--- head.html
|--- master.html

See in "examples/iris-multiple" folder
```

[Iris multiple example](https://github.com/foolin/goview/tree/master/_examples/iris-multiple)

### Echo example

Echo <=v3 version:
```bash
go get github.com/foolin/goview/supports/echoview
```

Echo v4 version:

```bash
go get github.com/foolin/goview/supports/echoview-v4
```

```go

package main

import (
"github.com/foolin/goview/supports/echoview"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"net/http"
)

func main() {

// Echo instance
e := echo.New()

// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())

//Set Renderer
e.Renderer = echoview.Default()

// Routes
e.GET("/", func(c echo.Context) error {
//render with master
return c.Render(http.StatusOK, "index", echo.Map{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
})

e.GET("/page", func(c echo.Context) error {
//render only file, must full name with extension
return c.Render(http.StatusOK, "page.html", echo.Map{"title": "Page file title!!"})
})

// Start server
e.Logger.Fatal(e.Start(":9090"))
}

```

Project structure:
```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html

See in "examples/basic" folder
```

[Echo example](https://github.com/foolin/goview/tree/master/_examples/echo)
[Echo v4 example](https://github.com/foolin/goview/tree/master/_examples/echo-v4)

### Go-chi example
```go

package main

import (
"fmt"
"github.com/foolin/goview"
"github.com/go-chi/chi"
"net/http"
)

func main() {

r := chi.NewRouter()

//render index use `index` without `.html` extension, that will render with master layout.
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "index", goview.M{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}
})

//render page use `page.tpl` with '.html' will only file template without master layout.
r.Get("/page", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})
if err != nil {
fmt.Fprintf(w, "Render page.html error: %v!", err)
}
})

fmt.Println("Listening and serving HTTP on :9090")
http.ListenAndServe(":9090", r)

}

```

Project structure:
```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html

See in "examples/basic" folder
```

[Chi example](https://github.com/foolin/goview/tree/master/_examples/go-chi)

### Advance example
```go

package main

import (
"fmt"
"github.com/foolin/goview"
"html/template"
"net/http"
"time"
)

func main() {

gv := goview.New(goview.Config{
Root: "views",
Extension: ".tpl",
Master: "layouts/master",
Partials: []string{"partials/ad"},
Funcs: template.FuncMap{
"sub": func(a, b int) int {
return a - b
},
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
})

//Set new instance
goview.Use(gv)

//render index use `index` without `.html` extension, that will render with master layout.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "index", goview.M{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}

})

//render page use `page.tpl` with '.html' will only file template without master layout.
http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "page.tpl", goview.M{"title": "Page file title!!"})
if err != nil {
fmt.Fprintf(w, "Render page.html error: %v!", err)
}
})

fmt.Println("Listening and serving HTTP on :9090")
http.ListenAndServe(":9090", nil)
}

```

Project structure:
```go
|-- app/views/
|--- index.tpl
|--- page.tpl
|-- layouts/
|--- footer.tpl
|--- head.tpl
|--- master.tpl
|-- partials/
|--- ad.tpl

See in "examples/advance" folder
```

[Advance example](https://github.com/foolin/goview/tree/master/_examples/advance)

### Multiple example
```go

package main

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

"github.com/foolin/goview"
"github.com/gin-gonic/gin"
)

func main() {
router := gin.Default()

//new template engine
router.HTMLRender = gintemplate.New(gintemplate.TemplateConfig{
Root: "views/fontend",
Extension: ".html",
Master: "layouts/master",
Partials: []string{"partials/ad"},
Funcs: template.FuncMap{
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
})

router.GET("/", func(ctx *gin.Context) {
// `HTML()` is a helper func to deal with multiple TemplateEngine's.
// It detects the suitable TemplateEngine for each path automatically.
gintemplate.HTML(ctx, http.StatusOK, "index", gin.H{
"title": "Fontend title!",
})
})

//=========== Backend ===========//

//new middleware
mw := gintemplate.NewMiddleware(gintemplate.TemplateConfig{
Root: "views/backend",
Extension: ".html",
Master: "layouts/master",
Partials: []string{},
Funcs: template.FuncMap{
"copy": func() string {
return time.Now().Format("2006")
},
},
DisableCache: true,
})

// You should use helper func `Middleware()` to set the supplied
// TemplateEngine and make `HTML()` work validly.
backendGroup := router.Group("/admin", mw)

backendGroup.GET("/", func(ctx *gin.Context) {
// With the middleware, `HTML()` can detect the valid TemplateEngine.
gintemplate.HTML(ctx, http.StatusOK, "index", gin.H{
"title": "Backend title!",
})
})

router.Run(":9090")
}

```

Project structure:
```go
|-- app/views/
|-- fontend/
|--- index.html
|-- layouts/
|--- footer.html
|--- head.html
|--- master.html
|-- partials/
|--- ad.html
|-- backend/
|--- index.html
|-- layouts/
|--- footer.html
|--- head.html
|--- master.html

See in "examples/multiple" folder
```

[Multiple example](https://github.com/foolin/goview/tree/master/_examples/multiple)

### go.rice example

```bash
go get github.com/foolin/goview/supports/gorice
```

```go

package main

import (
"fmt"
"github.com/GeertJohan/go.rice"
"github.com/foolin/goview"
"github.com/foolin/goview/supports/gorice"
"net/http"
)

func main() {

//static
staticBox := rice.MustFindBox("static")
staticFileServer := http.StripPrefix("/static/", http.FileServer(staticBox.HTTPBox()))
http.Handle("/static/", staticFileServer)

//new view engine
gv := gorice.New(rice.MustFindBox("views"))
//set engine for default instance
goview.Use(gv)

//render index use `index` without `.html` extension, that will render with master layout.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "index", goview.M{
"title": "Index title!",
"add": func(a int, b int) int {
return a + b
},
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}

})

//render page use `page.tpl` with '.html' will only file template without master layout.
http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
err := goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})
if err != nil {
fmt.Fprintf(w, "Render page.html error: %v!", err)
}
})

fmt.Println("Listening and serving HTTP on :9090")
http.ListenAndServe(":9090", nil)
}

```

Project structure:
```go
|-- app/views/
|--- index.html
|--- page.html
|-- layouts/
|--- footer.html
|--- master.html
|-- app/static/
|-- css/
|--- bootstrap.css
|-- img/
|--- gopher.png

See in "examples/gorice" folder
```

[gorice example](https://github.com/foolin/goview/tree/master/_examples/gorice)

### More examples

See [_examples/](https://github.com/foolin/goview/blob/master/_examples/) for a variety of examples.

[GoDoc]: https://godoc.org/github.com/foolin/goview
[GoDoc Widget]: https://godoc.org/github.com/foolin/goview?status.svg
[Travis]: https://travis-ci.org/foolin/goview
[Travis Widget]: https://travis-ci.org/foolin/goview.svg?branch=master
[GoReportCard]: https://goreportcard.com/report/github.com/foolin/goview
[GoReportCard Widget]: https://goreportcard.com/badge/github.com/foolin/goview
[GoCover]: https://goreportcard.com/report/github.com/foolin/goview
[GoCover Widget]: https://goreportcard.com/badge/github.com/foolin/goview

### Todo
[ ] Add Partials support directory or glob
[ ] Add functions support.