goview

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 16, 2019 License: MIT Imports: 10 Imported by: 93

README

goview

GoDoc Widget Travis Widget

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

Contents

Install

go get -u 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/Echo/Chi - Support gin framework,echo framework, go-chi framework.

Docs

See https://www.godoc.org/github.com/foolin/goview

Supports

Usage

Overview

Project structure:

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

Use default instance:

    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)
        }
    
    })

Use new instance with config:


    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 `.tpl` 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)
        }
    
    })

Use multiple instance with config:


    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,
    })
    
    //render index use `index` without `.tpl` extension, that will render with master layout.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := gvFrontend.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)
        }
    
    })
    
    //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,
    })
    
    //render index use `index` without `.tpl` extension, that will render with master layout.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := gvBackend.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)
        }
    
    })

Config
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.
}
Include syntax
//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

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

The w is instance of http.ResponseWriter

Render only file(not use master layout)

//use full name with extension `.html`
goview.Render(w, http.StatusOK, "page.html", gin.H{})

Examples

See _examples/ for a variety of examples.

Basic example

package main

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

func main() {

	//render index use `index` without `.tpl` 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 '.tpl' 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:

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

See in "examples/basic" folder

Basic example

Gin example
go get -u github.com/foolin/goview/supports/ginview

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:

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

See in "examples/basic" folder

Gin example

Echo example
go get -u github.com/foolin/goview/supports/echoview

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:

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

See in "examples/basic" folder

Echo example

Go-chi example

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 `.tpl` 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 '.tpl' 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:

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

See in "examples/basic" folder

Chi example

Advance example

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 `.tpl` 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 '.tpl' 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:

|-- app/views/
    |--- index.tpl          
    |--- page.tpl
    |-- layouts/
        |--- footer.tpl
        |--- head.tpl
        |--- master.tpl
    |-- partials/
        |--- ad.tpl
    

See in "examples/advance" folder

Advance example

Multiple example

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:

|-- 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

go.rice example
go get -u github.com/foolin/goview/supports/gorice

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 `.tpl` 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 '.tpl' 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:

|-- 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

More examples

See _examples/ for a variety of examples.

Documentation

Overview

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

Example:

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.html` 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:

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

Learn more at https://github.com/foolin/goview

================== Supports ==================

Ginview for Gin framework: https://godoc.org/github.com/foolin/goview/supports/ginview

Echoview for Echo framework: https://godoc.org/github.com/foolin/goview/supports/echoview

Gorice for Go.rice: https://godoc.org/github.com/foolin/goview/supports/gorice

Examples: https://github.com/foolin/goview/_examples

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultConfig = Config{
	Root:         "views",
	Extension:    ".html",
	Master:       "layouts/master",
	Partials:     []string{},
	Funcs:        make(template.FuncMap),
	DisableCache: false,
	Delims:       Delims{Left: "{{", Right: "}}"},
}
View Source
var HtmlContentType = []string{"text/html; charset=utf-8"}

const templateEngineKey = "httpx_templateEngine"

Functions

func Render

func Render(w http.ResponseWriter, status int, name string, data interface{}) error

Render render view template with default instance

func Use

func Use(engine *ViewEngine)

Use setting default instance engine

Types

type Config

type Config struct {
	Root         string           //view root
	Extension    string           //template extension
	Master       string           //template master
	Partials     []string         //template partial, such as head, foot
	Funcs        template.FuncMap //template functions
	DisableCache bool             //disable cache, debug mode
	Delims       Delims           //delimeters
}

type Delims

type Delims struct {
	Left  string
	Right string
}

type FileHandler

type FileHandler func(config Config, tplFile string) (content string, err error)

func DefaultFileHandler

func DefaultFileHandler() FileHandler

type M

type M map[string]interface{}

type ViewEngine

type ViewEngine struct {
	// contains filtered or unexported fields
}

func Default

func Default() *ViewEngine
Example
/*
	   Project structure:

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

*/

//render index use `index` without `.html` extension, that will render with master layout.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	err := Render(w, http.StatusOK, "index", 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.html` with '.html' will only file template without master layout.
http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
	err := Render(w, http.StatusOK, "page.html", 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)
Output:

func New

func New(config Config) *ViewEngine
Example
/*
	Project structure:

	|-- app/views/
	    |--- index.tpl
	    |--- page.tpl
	    |-- layouts/
	        |--- footer.tpl
	        |--- head.tpl
	        |--- master.tpl
	    |-- partials/
	        |--- ad.tpl
*/

//config
gv := New(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
Use(gv)

//render index use `index` without `.tpl` extension, that will render with master layout.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	err := Render(w, http.StatusOK, "index", 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 '.tpl' will only file template without master layout.
http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
	err := Render(w, http.StatusOK, "page.tpl", 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)
Output:

func (*ViewEngine) Render

func (e *ViewEngine) Render(w http.ResponseWriter, statusCode int, name string, data interface{}) error

func (*ViewEngine) RenderWriter

func (e *ViewEngine) RenderWriter(w io.Writer, name string, data interface{}) error

func (*ViewEngine) SetFileHandler

func (e *ViewEngine) SetFileHandler(handle FileHandler)

Directories

Path Synopsis
_examples
gin
supports

Jump to

Keyboard shortcuts

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