From bf08eaab4f96f58c3d16ee4bf6cf633e303b94d8 Mon Sep 17 00:00:00 2001 From: foolin Date: Tue, 16 Apr 2019 19:10:06 +0800 Subject: [PATCH] Initial commit --- .gitignore | 2 + .travis.yml | 6 + LICENSE | 21 + README.md | 753 ++ _examples/.idea/workspace.xml | 202 + _examples/advance/README.md | 14 + _examples/advance/main.go | 64 + _examples/advance/views/index.tpl | 7 + _examples/advance/views/layouts/footer.tpl | 1 + _examples/advance/views/layouts/head.tpl | 4 + _examples/advance/views/layouts/master.tpl | 17 + _examples/advance/views/page.tpl | 16 + _examples/advance/views/partials/ad.tpl | 3 + _examples/basic/README.md | 14 + _examples/basic/main.go | 44 + _examples/basic/views/index.html | 14 + _examples/basic/views/layouts/footer.html | 1 + _examples/basic/views/layouts/master.html | 15 + _examples/basic/views/page.html | 19 + _examples/echo-multiple/README.md | 14 + _examples/echo-multiple/main.go | 82 + .../echo-multiple/views/backend/index.html | 5 + .../views/backend/layouts/footer.html | 1 + .../views/backend/layouts/head.html | 4 + .../views/backend/layouts/master.html | 15 + .../echo-multiple/views/frontend/index.html | 5 + .../views/frontend/layouts/footer.html | 1 + .../views/frontend/layouts/head.html | 4 + .../views/frontend/layouts/master.html | 17 + .../views/frontend/partials/ad.html | 3 + _examples/echo/README.md | 14 + _examples/echo/main.go | 48 + _examples/echo/views/index.html | 14 + _examples/echo/views/layouts/footer.html | 1 + _examples/echo/views/layouts/master.html | 15 + _examples/echo/views/page.html | 19 + _examples/gin-multiple/README.md | 14 + _examples/gin-multiple/main.go | 73 + .../gin-multiple/views/backend/index.html | 5 + .../views/backend/layouts/footer.html | 1 + .../views/backend/layouts/head.html | 4 + .../views/backend/layouts/master.html | 15 + .../gin-multiple/views/frontend/index.html | 5 + .../views/frontend/layouts/footer.html | 1 + .../views/frontend/layouts/head.html | 4 + .../views/frontend/layouts/master.html | 17 + .../views/frontend/partials/ad.html | 3 + _examples/gin/README.md | 14 + _examples/gin/main.go | 39 + _examples/gin/views/index.html | 14 + _examples/gin/views/layouts/footer.html | 1 + _examples/gin/views/layouts/master.html | 15 + _examples/gin/views/page.html | 19 + _examples/go-chi/README.md | 14 + _examples/go-chi/main.go | 44 + _examples/go-chi/views/index.html | 14 + _examples/go-chi/views/layouts/footer.html | 1 + _examples/go-chi/views/layouts/master.html | 15 + _examples/go-chi/views/page.html | 19 + _examples/gorice/README.md | 41 + _examples/gorice/bin/gorice | Bin 0 -> 10548224 bytes _examples/gorice/main.go | 53 + _examples/gorice/run.sh | 10 + _examples/gorice/static/css/bootstrap.css | 8950 +++++++++++++++++ _examples/gorice/static/css/bootstrap.css.map | 1 + _examples/gorice/static/css/bootstrap.min.css | 7 + .../gorice/static/css/bootstrap.min.css.map | 1 + _examples/gorice/static/img/gopher.png | Bin 0 -> 17668 bytes _examples/gorice/views/index.html | 13 + _examples/gorice/views/layouts/footer.html | 1 + _examples/gorice/views/layouts/master.html | 26 + _examples/gorice/views/page.html | 35 + _examples/multiple/README.md | 14 + _examples/multiple/main.go | 69 + _examples/multiple/views/backend/index.html | 5 + .../views/backend/layouts/footer.html | 1 + .../multiple/views/backend/layouts/head.html | 4 + .../views/backend/layouts/master.html | 15 + _examples/multiple/views/frontend/index.html | 5 + .../views/frontend/layouts/footer.html | 1 + .../multiple/views/frontend/layouts/head.html | 4 + .../views/frontend/layouts/master.html | 17 + .../multiple/views/frontend/partials/ad.html | 3 + go.mod | 20 + instance.go | 21 + supports/echoview/echoview.go | 52 + supports/ginview/ginview.go | 78 + supports/gorice/gorice.go | 34 + view.go | 193 + 89 files changed, 11504 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 _examples/.idea/workspace.xml create mode 100644 _examples/advance/README.md create mode 100644 _examples/advance/main.go create mode 100644 _examples/advance/views/index.tpl create mode 100644 _examples/advance/views/layouts/footer.tpl create mode 100644 _examples/advance/views/layouts/head.tpl create mode 100644 _examples/advance/views/layouts/master.tpl create mode 100644 _examples/advance/views/page.tpl create mode 100644 _examples/advance/views/partials/ad.tpl create mode 100644 _examples/basic/README.md create mode 100644 _examples/basic/main.go create mode 100644 _examples/basic/views/index.html create mode 100644 _examples/basic/views/layouts/footer.html create mode 100644 _examples/basic/views/layouts/master.html create mode 100644 _examples/basic/views/page.html create mode 100644 _examples/echo-multiple/README.md create mode 100644 _examples/echo-multiple/main.go create mode 100644 _examples/echo-multiple/views/backend/index.html create mode 100644 _examples/echo-multiple/views/backend/layouts/footer.html create mode 100644 _examples/echo-multiple/views/backend/layouts/head.html create mode 100644 _examples/echo-multiple/views/backend/layouts/master.html create mode 100644 _examples/echo-multiple/views/frontend/index.html create mode 100644 _examples/echo-multiple/views/frontend/layouts/footer.html create mode 100644 _examples/echo-multiple/views/frontend/layouts/head.html create mode 100644 _examples/echo-multiple/views/frontend/layouts/master.html create mode 100644 _examples/echo-multiple/views/frontend/partials/ad.html create mode 100644 _examples/echo/README.md create mode 100644 _examples/echo/main.go create mode 100644 _examples/echo/views/index.html create mode 100644 _examples/echo/views/layouts/footer.html create mode 100644 _examples/echo/views/layouts/master.html create mode 100644 _examples/echo/views/page.html create mode 100644 _examples/gin-multiple/README.md create mode 100644 _examples/gin-multiple/main.go create mode 100644 _examples/gin-multiple/views/backend/index.html create mode 100644 _examples/gin-multiple/views/backend/layouts/footer.html create mode 100644 _examples/gin-multiple/views/backend/layouts/head.html create mode 100644 _examples/gin-multiple/views/backend/layouts/master.html create mode 100644 _examples/gin-multiple/views/frontend/index.html create mode 100644 _examples/gin-multiple/views/frontend/layouts/footer.html create mode 100644 _examples/gin-multiple/views/frontend/layouts/head.html create mode 100644 _examples/gin-multiple/views/frontend/layouts/master.html create mode 100644 _examples/gin-multiple/views/frontend/partials/ad.html create mode 100644 _examples/gin/README.md create mode 100644 _examples/gin/main.go create mode 100644 _examples/gin/views/index.html create mode 100644 _examples/gin/views/layouts/footer.html create mode 100644 _examples/gin/views/layouts/master.html create mode 100644 _examples/gin/views/page.html create mode 100644 _examples/go-chi/README.md create mode 100644 _examples/go-chi/main.go create mode 100644 _examples/go-chi/views/index.html create mode 100644 _examples/go-chi/views/layouts/footer.html create mode 100644 _examples/go-chi/views/layouts/master.html create mode 100644 _examples/go-chi/views/page.html create mode 100644 _examples/gorice/README.md create mode 100644 _examples/gorice/bin/gorice create mode 100644 _examples/gorice/main.go create mode 100644 _examples/gorice/run.sh create mode 100644 _examples/gorice/static/css/bootstrap.css create mode 100644 _examples/gorice/static/css/bootstrap.css.map create mode 100644 _examples/gorice/static/css/bootstrap.min.css create mode 100644 _examples/gorice/static/css/bootstrap.min.css.map create mode 100644 _examples/gorice/static/img/gopher.png create mode 100644 _examples/gorice/views/index.html create mode 100644 _examples/gorice/views/layouts/footer.html create mode 100644 _examples/gorice/views/layouts/master.html create mode 100644 _examples/gorice/views/page.html create mode 100644 _examples/multiple/README.md create mode 100644 _examples/multiple/main.go create mode 100644 _examples/multiple/views/backend/index.html create mode 100644 _examples/multiple/views/backend/layouts/footer.html create mode 100644 _examples/multiple/views/backend/layouts/head.html create mode 100644 _examples/multiple/views/backend/layouts/master.html create mode 100644 _examples/multiple/views/frontend/index.html create mode 100644 _examples/multiple/views/frontend/layouts/footer.html create mode 100644 _examples/multiple/views/frontend/layouts/head.html create mode 100644 _examples/multiple/views/frontend/layouts/master.html create mode 100644 _examples/multiple/views/frontend/partials/ad.html create mode 100644 go.mod create mode 100644 instance.go create mode 100644 supports/echoview/echoview.go create mode 100644 supports/ginview/ginview.go create mode 100644 supports/gorice/gorice.go create mode 100644 view.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6e6b069 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +go.sum \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..28ffabd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.10.x + - 1.11.x + - 1.12.x diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..28d8122 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Foolin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..503db01 --- /dev/null +++ b/README.md @@ -0,0 +1,753 @@ +# goview + +[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis] + +Goview is a lightweight, simple and easy template library based on golang html/template for building Go web application. + +## Contents + +- [Install](#install) +- [Features](#features) +- [Docs](#docs) +- [Usage](#usage) + - [Overview](#overview) + - [Config](#config) + - [Include syntax](#include-syntax) + - [Render name](#render-name) +- [Examples](#examples) + - [Basic example](#basic-example) + - [Gin example](#gin-example) + - [Echo example](#echo-example) + - [Go-chi example](#go-chi-example) + - [Advance example](#advance-example) + - [Multiple example](#multiple-example) + - [go.rice example](#gorice-example) +- [Supports](#supports) + + +## Install +```bash +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 + + +## Usage + +### Overview + +Project structure: + +```go +|-- app/views/ + |--- index.html + |--- page.html + |-- layouts/ + |--- footer.html + |--- master.html + +``` + +Use default instance: + +```go + 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: + +```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, + }) + + //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: + +```go + + 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 + +```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. +} +``` + +### 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", gin.H{}) +``` + +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", gin.H{}) +``` + + + + + + +## 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 `.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: +```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 +```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) + + + +### Echo example +```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) + + + +### 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 `.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: +```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 `.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: +```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 + +```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 `.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: +```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) + +## Supports +- go-chi The same as golang http +- [ginview](https://github.com/foolin/goview/tree/master/supports/ginview) goview for gin framework +- [echoview](https://github.com/foolin/goview/tree/master/supports/echoview) goview for echo framework +- [go.rice](https://github.com/foolin/goview/tree/master/supports/gorice) goview for go.rice + + +[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 diff --git a/_examples/.idea/workspace.xml b/_examples/.idea/workspace.xml new file mode 100644 index 0000000..4f891d7 --- /dev/null +++ b/_examples/.idea/workspace.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + s in some browsers, due to the limited stylability of ``s in IE10+.\n &::-ms-expand {\n background-color: transparent;\n border: 0;\n }\n\n // Customize the `:focus` state to imitate native WebKit styles.\n @include form-control-focus();\n\n // Placeholder\n &::placeholder {\n color: $input-placeholder-color;\n // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.\n opacity: 1;\n }\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &:disabled,\n &[readonly] {\n background-color: $input-disabled-bg;\n // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.\n opacity: 1;\n }\n}\n\nselect.form-control {\n &:not([size]):not([multiple]) {\n height: $input-height;\n }\n\n &:focus::-ms-value {\n // Suppress the nested default white text on blue background highlight given to\n // the selected option text when the (still closed) receives focus\n // in IE and (under certain conditions) Edge.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n }\n\n &[multiple],\n &[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: $custom-select-padding-x;\n background-image: none;\n }\n\n &:disabled {\n color: $custom-select-disabled-color;\n background-color: $custom-select-disabled-bg;\n }\n\n // Hides the default caret in IE11\n &::-ms-expand {\n opacity: 0;\n }\n}\n\n.custom-select-sm {\n height: $custom-select-height-sm;\n padding-top: $custom-select-padding-y;\n padding-bottom: $custom-select-padding-y;\n font-size: $custom-select-font-size-sm;\n}\n\n.custom-select-lg {\n height: $custom-select-height-lg;\n padding-top: $custom-select-padding-y;\n padding-bottom: $custom-select-padding-y;\n font-size: $custom-select-font-size-lg;\n}\n\n\n// File\n//\n// Custom file input.\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: $custom-file-height;\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: $custom-file-height;\n margin: 0;\n opacity: 0;\n\n &:focus ~ .custom-file-label {\n border-color: $custom-file-focus-border-color;\n box-shadow: $custom-file-focus-box-shadow;\n\n &::after {\n border-color: $custom-file-focus-border-color;\n }\n }\n\n @each $lang, $value in $custom-file-text {\n &:lang(#{$lang}) ~ .custom-file-label::after {\n content: $value;\n }\n }\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: $custom-file-height;\n padding: $custom-file-padding-y $custom-file-padding-x;\n line-height: $custom-file-line-height;\n color: $custom-file-color;\n background-color: $custom-file-bg;\n border: $custom-file-border-width solid $custom-file-border-color;\n @include border-radius($custom-file-border-radius);\n @include box-shadow($custom-file-box-shadow);\n\n &::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: calc(#{$custom-file-height} - #{$custom-file-border-width} * 2);\n padding: $custom-file-padding-y $custom-file-padding-x;\n line-height: $custom-file-line-height;\n color: $custom-file-button-color;\n content: \"Browse\";\n @include gradient-bg($custom-file-button-bg);\n border-left: $custom-file-border-width solid $custom-file-border-color;\n @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);\n }\n}\n\n// Range\n//\n// Style range inputs the same across browsers. Vendor-specific rules for psuedo\n// elements cannot be mixed. As such, there are no shared styles for focus or\n// active states on prefixed selectors.\n\n.custom-range {\n width: 100%;\n padding-left: 0; // Firefox specific\n background-color: transparent;\n appearance: none;\n\n &:focus {\n outline: none;\n }\n\n &::-moz-focus-outer {\n border: 0;\n }\n\n &::-webkit-slider-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n margin-top: -($custom-range-thumb-width * .25); // Webkit specific?\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n appearance: none;\n\n &:focus {\n outline: none;\n box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility\n }\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-webkit-slider-runnable-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent; // Why?\n cursor: $custom-range-track-cursor;\n background-color: $custom-range-track-bg;\n border-color: transparent;\n @include border-radius($custom-range-track-border-radius);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-moz-range-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n appearance: none;\n\n &:focus {\n outline: none;\n box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility\n }\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-moz-range-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent;\n cursor: $custom-range-track-cursor;\n background-color: $custom-range-track-bg;\n border-color: transparent; // Firefox specific?\n @include border-radius($custom-range-track-border-radius);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-ms-thumb {\n width: $custom-range-thumb-width;\n height: $custom-range-thumb-height;\n @include gradient-bg($custom-range-thumb-bg);\n border: $custom-range-thumb-border;\n @include border-radius($custom-range-thumb-border-radius);\n @include box-shadow($custom-range-thumb-box-shadow);\n appearance: none;\n\n &:focus {\n outline: none;\n box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility\n }\n\n &:active {\n @include gradient-bg($custom-range-thumb-active-bg);\n }\n }\n\n &::-ms-track {\n width: $custom-range-track-width;\n height: $custom-range-track-height;\n color: transparent;\n cursor: $custom-range-track-cursor;\n background-color: transparent;\n border-color: transparent;\n border-width: ($custom-range-thumb-height * .5);\n @include box-shadow($custom-range-track-box-shadow);\n }\n\n &::-ms-fill-lower {\n background-color: $custom-range-track-bg;\n @include border-radius($custom-range-track-border-radius);\n }\n\n &::-ms-fill-upper {\n margin-right: 15px; // arbitrary?\n background-color: $custom-range-track-bg;\n @include border-radius($custom-range-track-border-radius);\n }\n}\n","// Base class\n//\n// Kickstart any navigation component with a set of style resets. Works with\n// `