Initial commit

This commit is contained in:
foolin
2019-04-16 19:10:06 +08:00
commit bf08eaab4f
89 changed files with 11504 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea
go.sum

6
.travis.yml Normal file
View File

@@ -0,0 +1,6 @@
language: go
go:
- 1.10.x
- 1.11.x
- 1.12.x

21
LICENSE Normal file
View File

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

753
README.md Normal file
View File

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

202
_examples/.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="ce420b0a-6004-4397-9780-497f5816a9ad" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/README.md" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/main.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/views/index.tpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/views/layouts/footer.tpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/views/layouts/head.tpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/views/layouts/master.tpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/views/page.tpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/advance/views/partials/ad.tpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/basic/README.md" afterDir="false" />
<change afterPath="$PROJECT_DIR$/basic/main.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/basic/views/index.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/basic/views/layouts/footer.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/basic/views/layouts/master.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/basic/views/page.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../supports/ginview/ginview.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../supports/gorice/gorice.go" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/basic/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="272">
<caret line="16" column="13" selection-start-line="16" selection-start-column="13" selection-end-line="16" selection-end-column="13" />
<folding>
<element signature="e#180#271#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/advance/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="237">
<caret line="30" selection-start-line="30" selection-end-line="33" selection-end-column="37" />
<folding>
<element signature="e#180#209#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/go.mod">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="204">
<caret line="12" selection-start-line="12" selection-end-line="12" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="GOROOT" path="C:\Go" />
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="GoLibraries">
<option name="indexEntireGoPath" value="false" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/basic/main.go" />
</list>
</option>
</component>
<component name="ProjectConfigurationFiles">
<option name="files">
<list>
<option value="$PROJECT_DIR$/.idea/_examples.iml" />
<option value="$PROJECT_DIR$/.idea/misc.xml" />
<option value="$PROJECT_DIR$/.idea/vcs.xml" />
<option value="$PROJECT_DIR$/.idea/modules.xml" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="-10" />
<option name="width" value="1940" />
<option name="height" value="1040" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="_examples" type="b2602c69:ProjectViewProjectNode" />
<item name="_examples" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="_examples" type="b2602c69:ProjectViewProjectNode" />
<item name="_examples" type="462c0819:PsiDirectoryNode" />
<item name="basic" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="go.gopath.indexing.explicitly.defined" value="true" />
<property name="go.import.settings.migrated" value="true" />
<property name="go.sdk.automatically.set" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="settings.editor.selected.configurable" value="configurable.group.appearance" />
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="ToolWindowManager">
<frame x="-7" y="-7" width="1550" height="838" extended-state="6" />
<layout>
<window_info id="Favorites" side_tool="true" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.25" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Docker" show_stripe_button="false" />
<window_info anchor="bottom" id="Database Changes" />
<window_info anchor="bottom" id="Version Control" />
<window_info active="true" anchor="bottom" id="Terminal" visible="true" weight="0.3286119" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Run" order="2" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="right" id="Database" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VgoProject">
<integration-enabled>true</integration-enabled>
<proxy>https://goproxy.io</proxy>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/advance/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="237">
<caret line="30" selection-start-line="30" selection-end-line="33" selection-end-column="37" />
<folding>
<element signature="e#180#209#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/go.mod">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="204">
<caret line="12" selection-start-line="12" selection-end-line="12" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/basic/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="272">
<caret line="16" column="13" selection-start-line="16" selection-start-column="13" selection-end-line="16" selection-end-column="13" />
<folding>
<element signature="e#180#271#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

View File

@@ -0,0 +1,14 @@
# Advance
Exmaple for gin template
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

64
_examples/advance/main.go Normal file
View File

@@ -0,0 +1,64 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
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)
}

View File

@@ -0,0 +1,7 @@
{{define "content"}}
<h1 class="hello">This is content!!!!</h1>
<p>123 + 333 = {{call $.add 123 333}}</p>
<p>123 - 100= {{sub 123 100}}</p>
<hr>
<p><a href="/page">Page render</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,17 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{template "ad" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,16 @@
<!-- /views/page.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
<a href="/"><- Back home!</a>
{{template "ad" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,3 @@
{{define "ad"}}
<p>[AD: <a href="https://github.com/foolin" target="_blank">Wellcome to github!</a>]</p>
{{end}}

14
_examples/basic/README.md Normal file
View File

@@ -0,0 +1,14 @@
# Basic
Exmaple for gin template
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

44
_examples/basic/main.go Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
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)
}

View File

@@ -0,0 +1,14 @@
{{define "head"}}
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>
{{end}}
{{define "content"}}
<h1 class="hello">This is content!!!!</h1>
<p>123 + 333 = {{call $.add 123 333}}</p>
<hr>
<p><a href="/page">Page render</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy2018 <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{template "head" .}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,19 @@
<!-- /views/page.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<a href="/"><- Back home!</a>
<hr>
This page not use master, Render code:
<pre>goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})</pre>
<br>
"page.html" - add extension ".html" will render without master.
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,14 @@
# Multiple
Exmaple for gin template, font end and back end.
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
package main
import (
"github.com/foolin/goview"
"github.com/foolin/goview/supports/echoview"
"html/template"
"net/http"
"time"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func main() {
// Echo instance
e := echo.New()
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
//new template engine
e.Renderer = echoview.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,
})
e.GET("/", func(ctx echo.Context) error {
// `HTML()` is a helper func to deal with multiple TemplateEngine's.
// It detects the suitable TemplateEngine for each path automatically.
return echoview.Render(ctx, http.StatusOK, "index", echo.Map{
"title": "Frontend title!",
})
})
//=========== Backend ===========//
//new middleware
mw := echoview.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,
})
// You should use helper func `Middleware()` to set the supplied
// TemplateEngine and make `HTML()` work validly.
backendGroup := e.Group("/admin", mw)
backendGroup.GET("/", func(ctx echo.Context) error {
// With the middleware, `HTML()` can detect the valid TemplateEngine.
return echoview.Render(ctx, http.StatusOK, "index", echo.Map{
"title": "Backend title!",
})
})
// Start server
e.Logger.Fatal(e.Start(":9090"))
}

View File

@@ -0,0 +1,5 @@
{{define "content"}}
<h1 class="hello">This is backend!!!!</h1>
<hr>
<p><a href="/">Go to frontend</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,5 @@
{{define "content"}}
<h1 class="hello">This is frontend!!!!</h1>
<hr>
<p><a href="/admin/">Go to backend</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,17 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{template "ad" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,3 @@
{{define "ad"}}
<p>[AD: <a href="https://github.com/foolin" target="_blank">Wellcome to fontend!</a>]</p>
{{end}}

14
_examples/echo/README.md Normal file
View File

@@ -0,0 +1,14 @@
# Basic
Exmaple for gin template
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

48
_examples/echo/main.go Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
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"))
}

View File

@@ -0,0 +1,14 @@
{{define "head"}}
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>
{{end}}
{{define "content"}}
<h1 class="hello">This is content!!!!</h1>
<p>123 + 333 = {{call $.add 123 333}}</p>
<hr>
<p><a href="/page">Page render</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy2018 <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{template "head" .}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,19 @@
<!-- /views/page.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<a href="/"><- Back home!</a>
<hr>
This page not use master, Render code:
<pre>goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})</pre>
<br>
"page.html" - add extension ".html" will render without master.
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,14 @@
# Multiple
Exmaple for gin template, font end and back end.
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
package main
import (
"github.com/foolin/goview"
"github.com/foolin/goview/supports/ginview"
"github.com/gin-gonic/gin"
"html/template"
"net/http"
"time"
)
func main() {
router := gin.Default()
//new template engine
router.HTMLRender = ginview.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,
})
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.
ginview.HTML(ctx, http.StatusOK, "index", gin.H{
"title": "Frontend title!",
})
})
//=========== Backend ===========//
//new middleware
mw := ginview.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,
})
// 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.
ginview.HTML(ctx, http.StatusOK, "index", gin.H{
"title": "Backend title!",
})
})
router.Run(":9090")
}

View File

@@ -0,0 +1,5 @@
{{define "content"}}
<h1 class="hello">This is backend!!!!</h1>
<hr>
<p><a href="/">Go to frontend</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,5 @@
{{define "content"}}
<h1 class="hello">This is frontend!!!!</h1>
<hr>
<p><a href="/admin/">Go to backend</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,17 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{template "ad" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,3 @@
{{define "ad"}}
<p>[AD: <a href="https://github.com/foolin" target="_blank">Wellcome to fontend!</a>]</p>
{{end}}

14
_examples/gin/README.md Normal file
View File

@@ -0,0 +1,14 @@
# Basic
Exmaple for gin template
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

39
_examples/gin/main.go Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
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")
}

View File

@@ -0,0 +1,14 @@
{{define "head"}}
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>
{{end}}
{{define "content"}}
<h1 class="hello">This is content!!!!</h1>
<p>123 + 333 = {{call $.add 123 333}}</p>
<hr>
<p><a href="/page">Page render</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy2018 <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{template "head" .}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,19 @@
<!-- /views/page.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<a href="/"><- Back home!</a>
<hr>
This page not use master, Render code:
<pre>goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})</pre>
<br>
"page.html" - add extension ".html" will render without master.
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,14 @@
# Basic
Exmaple for gin template
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

44
_examples/go-chi/main.go Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
package main
import (
"fmt"
"github.com/foolin/goview"
"github.com/go-chi/chi"
"net/http"
)
func main() {
r := chi.NewRouter()
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)
}
})
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)
}

View File

@@ -0,0 +1,14 @@
{{define "head"}}
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>
{{end}}
{{define "content"}}
<h1 class="hello">This is content!!!!</h1>
<p>123 + 333 = {{call $.add 123 333}}</p>
<hr>
<p><a href="/page">Page render</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy2018 <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{template "head" .}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,19 @@
<!-- /views/page.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<a href="/"><- Back home!</a>
<hr>
This page not use master, Render code:
<pre>ctx.HTML(200, "page.html", gin.H{})</pre>
<br>
"page.html" - add extension ".html" will render without master.
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,41 @@
# Basic
Exmaple for gin template
# Install
```go
go get github.com/GeertJohan/go.rice
```
# Build & Run
```bash
#build
go build -o bin/gorice
#run
./bin/gorice
```
# Script
```bash
./run.sh
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```
# Links
- [gin template](https://github.com/foolin/gin-template)
- [gin-template support go.rice](https://github.com/foolin/gin-template/tree/master/supports/gorice)
- [gin framework](https://github.com/gin-gonic/gin)
- [go.rice](https://github.com/GeertJohan/go.rice)

BIN
_examples/gorice/bin/gorice Normal file

Binary file not shown.

53
_examples/gorice/main.go Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
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)
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)
}
})
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)
}

10
_examples/gorice/run.sh Normal file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
#rice embed-go
#echo " => rice embed-go"
go build -o bin/gorice
echo " => go build -o bin/gorice"
echo " => ./bin/gorice"
./bin/gorice

8950
_examples/gorice/static/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,13 @@
{{define "head"}}
{{end}}
{{define "content"}}
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<h1 class="display-4">Hello template!</h1>
<img src="/static/img/gopher.png" alt="Gopher">
<p class="py-3">This is example for template support go.rice.</p>
<hr class="my-4">
<a class="btn btn-primary btn-lg" href="/page" role="button">Enter Page</a>
</div>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy2018 <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,26 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<title>{{.title}}</title>
{{template "head" .}}
</head>
<body>
<div class="container py-5">
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</div>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<!-- /views/page.html -->
<!doctype html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<title>{{.title}}</title>
</head>
<body>
<div class="container py-5">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Page</li>
</ol>
</nav>
<hr>
<p class="text-justify">
This page not use master, Render code:
<pre><code>goview.Render(200, "page.html", goview.M{})</code></pre>
<br>
"page.html" - add extension ".html" will render without master.
</p>
<hr>
{{include "layouts/footer"}}
</div>
</body>
</html>

View File

@@ -0,0 +1,14 @@
# Multiple
Exmaple for gin template, font end and back end.
# Run
```go
go run main.go
```
# View
Use the browser to visit the following url
```
http://127.0.0.1:9090
```

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
package main
import (
"fmt"
"github.com/foolin/goview"
"html/template"
"net/http"
"time"
)
func main() {
gvFront := goview.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,
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
err := gvFront.Render(w, http.StatusOK, "index", goview.M{
"title": "Frontend title!",
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}
})
//=========== Backend ===========//
gvBackend := goview.New(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,
})
http.HandleFunc("/admin/", func(w http.ResponseWriter, r *http.Request) {
err := gvBackend.Render(w, http.StatusOK, "index", goview.M{
"title": "Backend title!",
})
if err != nil {
fmt.Fprintf(w, "Render index error: %v!", err)
}
})
fmt.Printf("Server start on :9090")
http.ListenAndServe(":9090", nil)
}

View File

@@ -0,0 +1,5 @@
{{define "content"}}
<h1 class="hello">This is backend!!!!</h1>
<hr>
<p><a href="/">Go to frontend</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,15 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,5 @@
{{define "content"}}
<h1 class="hello">This is frontend!!!!</h1>
<hr>
<p><a href="/admin/">Go to backend</a></p>
{{end}}

View File

@@ -0,0 +1 @@
Copyright &copy {{copy}} <a href="https://github.com/foolin" target="_blank">Foolin</a>

View File

@@ -0,0 +1,4 @@
<style>
.hello{ color: red;}
hr{ border: 1px #ccc dashed;}
</style>

View File

@@ -0,0 +1,17 @@
<!-- /views/admin/master.html -->
<!doctype html>
<html>
<head>
<title>{{.title}}</title>
{{include "layouts/head"}}
</head>
<body>
{{template "content" .}}
<hr>
{{template "ad" .}}
<hr>
{{include "layouts/footer"}}
</body>
</html>

View File

@@ -0,0 +1,3 @@
{{define "ad"}}
<p>[AD: <a href="https://github.com/foolin" target="_blank">Wellcome to fontend!</a>]</p>
{{end}}

20
go.mod Normal file
View File

@@ -0,0 +1,20 @@
module github.com/foolin/goview
go 1.12
require (
github.com/GeertJohan/go.rice v1.0.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 // indirect
github.com/gin-gonic/gin v1.3.0
github.com/go-chi/chi v4.0.2+incompatible // indirect
github.com/golang/protobuf v1.3.1 // indirect
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.2.8 // indirect
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
gopkg.in/yaml.v2 v2.2.2 // indirect
)

21
instance.go Normal file
View File

@@ -0,0 +1,21 @@
package goview
import (
"net/http"
)
var instance *ViewEngine
// Use setting default instance engine
func Use(engine *ViewEngine) {
instance = engine
}
// Render render view template with default instance
func Render(w http.ResponseWriter, status int, name string, data interface{}) error {
if instance == nil {
instance = Default()
//return fmt.Errorf("instance not yet initialized, please call Init() first before Render()")
}
return instance.Render(w, status, name, data)
}

View File

@@ -0,0 +1,52 @@
package echoview
import (
"github.com/foolin/goview"
"github.com/labstack/echo"
"io"
)
const templateEngineKey = "foolin-goview-echoview"
type ViewEngine struct {
*goview.ViewEngine
}
func New(config goview.Config) *ViewEngine {
return &ViewEngine{
ViewEngine: goview.New(config),
}
}
func Default() *ViewEngine {
return New(goview.DefaultConfig)
}
func (e *ViewEngine) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
return e.RenderWriter(w, name, data)
}
// You should use helper func `Middleware()` to set the supplied
// TemplateEngine and make `Render()` work validly.
func Render(ctx echo.Context, code int, name string, data interface{}) error {
if val := ctx.Get(templateEngineKey); val != nil {
if e, ok := val.(*ViewEngine); ok {
return e.Render(ctx.Response().Writer, name, data, ctx)
}
}
return ctx.Render(code, name, data)
}
//New gin middleware for func `goview.Render()`
func NewMiddleware(config goview.Config) echo.MiddlewareFunc {
return Middleware(New(config))
}
func Middleware(e *ViewEngine) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Set(templateEngineKey, e)
return next(c)
}
}
}

View File

@@ -0,0 +1,78 @@
package ginview
import (
"github.com/foolin/goview"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/render"
"net/http"
)
const templateEngineKey = "foolin-goview-ginview"
type ViewEngine struct {
*goview.ViewEngine
}
type ViewRender struct {
Engine *ViewEngine
Name string
Data interface{}
}
func New(config goview.Config) *ViewEngine {
return &ViewEngine{
ViewEngine: goview.New(config),
}
}
func Default() *ViewEngine {
return New(goview.DefaultConfig)
}
func (e *ViewEngine) Instance(name string, data interface{}) render.Render {
return ViewRender{
Engine: e,
Name: name,
Data: data,
}
}
func (e *ViewEngine) HTML(ctx *gin.Context, code int, name string, data interface{}) {
instance := e.Instance(name, data)
ctx.Render(code, instance)
}
// Render (YAML) marshals the given interface object and writes data with custom ContentType.
func (v ViewRender) Render(w http.ResponseWriter) error {
return v.Engine.RenderWriter(w, v.Name, v.Data)
}
func (v ViewRender) WriteContentType(w http.ResponseWriter) {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = goview.HtmlContentType
}
}
//New gin middleware for func `gintemplate.HTML()`
func NewMiddleware(config goview.Config) gin.HandlerFunc {
return Middleware(New(config))
}
func Middleware(e *ViewEngine) gin.HandlerFunc {
return func(c *gin.Context) {
c.Set(templateEngineKey, e)
}
}
// You should use helper func `Middleware()` to set the supplied
// TemplateEngine and make `HTML()` work validly.
func HTML(ctx *gin.Context, code int, name string, data interface{}) {
if val, ok := ctx.Get(templateEngineKey); ok {
if e, ok := val.(*ViewEngine); ok {
e.HTML(ctx, code, name, data)
return
}
}
ctx.HTML(code, name, data)
}

34
supports/gorice/gorice.go Normal file
View File

@@ -0,0 +1,34 @@
package gorice
import (
"github.com/GeertJohan/go.rice"
"github.com/foolin/goview"
)
/**
New gin template engine, default views root.
*/
func New(viewsRootBox *rice.Box) *goview.ViewEngine {
return NewWithConfig(viewsRootBox, goview.DefaultConfig)
}
/**
New gin template engine
Important!!! The viewsRootBox's name and config.Root must be consistent.
*/
func NewWithConfig(viewsRootBox *rice.Box, config goview.Config) *goview.ViewEngine {
config.Root = viewsRootBox.Name()
engine := goview.New(config)
engine.SetFileHandler(FileHandler(viewsRootBox))
return engine
}
/**
Support go.rice file handler
*/
func FileHandler(viewsRootBox *rice.Box) goview.FileHandler {
return func(config goview.Config, tplFile string) (content string, err error) {
// get file contents as string
return viewsRootBox.String(tplFile + config.Extension)
}
}

193
view.go Normal file
View File

@@ -0,0 +1,193 @@
/*
* Copyright 2018 Foolin. All rights reserved.
*
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*
*/
/*
Goview is a lightweight, simple and easy view based on golang html/template for building Go web application.
See https://github.com/foolin/goview for more information.
*/
package goview
import (
"bytes"
"fmt"
"html/template"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
)
//const templateEngineKey = "httpx_templateEngine"
var HtmlContentType = []string{"text/html; charset=utf-8"}
var DefaultConfig = Config{
Root: "views",
Extension: ".html",
Master: "layouts/master",
Partials: []string{},
Funcs: make(template.FuncMap),
DisableCache: false,
Delims: Delims{Left: "{{", Right: "}}"},
}
type ViewEngine struct {
config Config
tplMap map[string]*template.Template
tplMutex sync.RWMutex
fileHandler FileHandler
}
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 M map[string]interface{}
type Delims struct {
Left string
Right string
}
type FileHandler func(config Config, tplFile string) (content string, err error)
func New(config Config) *ViewEngine {
return &ViewEngine{
config: config,
tplMap: make(map[string]*template.Template),
tplMutex: sync.RWMutex{},
fileHandler: DefaultFileHandler(),
}
}
func Default() *ViewEngine {
return New(DefaultConfig)
}
func (e *ViewEngine) Render(w http.ResponseWriter, statusCode int, name string, data interface{}) error {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = HtmlContentType
}
w.WriteHeader(statusCode)
return e.executeRender(w, name, data)
}
func (e *ViewEngine) RenderWriter(w io.Writer, name string, data interface{}) error {
return e.executeRender(w, name, data)
}
func (e *ViewEngine) executeRender(out io.Writer, name string, data interface{}) error {
useMaster := true
if filepath.Ext(name) == e.config.Extension {
useMaster = false
name = strings.TrimSuffix(name, e.config.Extension)
}
return e.executeTemplate(out, name, data, useMaster)
}
func (e *ViewEngine) executeTemplate(out io.Writer, name string, data interface{}, useMaster bool) error {
var tpl *template.Template
var err error
var ok bool
allFuncs := make(template.FuncMap, 0)
allFuncs["include"] = func(layout string) (template.HTML, error) {
buf := new(bytes.Buffer)
err := e.executeTemplate(buf, layout, data, false)
return template.HTML(buf.String()), err
}
// Get the plugin collection
for k, v := range e.config.Funcs {
allFuncs[k] = v
}
e.tplMutex.RLock()
tpl, ok = e.tplMap[name]
e.tplMutex.RUnlock()
exeName := name
if useMaster && e.config.Master != "" {
exeName = e.config.Master
}
if !ok || e.config.DisableCache {
tplList := make([]string, 0)
if useMaster {
//render()
if e.config.Master != "" {
tplList = append(tplList, e.config.Master)
}
}
tplList = append(tplList, name)
tplList = append(tplList, e.config.Partials...)
// Loop through each template and test the full path
tpl = template.New(name).Funcs(allFuncs).Delims(e.config.Delims.Left, e.config.Delims.Right)
for _, v := range tplList {
var data string
data, err = e.fileHandler(e.config, v)
if err != nil {
return err
}
var tmpl *template.Template
if v == name {
tmpl = tpl
} else {
tmpl = tpl.New(v)
}
_, err = tmpl.Parse(data)
if err != nil {
return fmt.Errorf("ViewEngine render parser name:%v, error: %v", v, err)
}
}
e.tplMutex.Lock()
e.tplMap[name] = tpl
e.tplMutex.Unlock()
}
// Display the content to the screen
err = tpl.Funcs(allFuncs).ExecuteTemplate(out, exeName, data)
if err != nil {
return fmt.Errorf("ViewEngine execute template error: %v", err)
}
return nil
}
func (e *ViewEngine) SetFileHandler(handle FileHandler) {
if handle == nil {
panic("FileHandler can't set nil!")
}
e.fileHandler = handle
}
func DefaultFileHandler() FileHandler {
return func(config Config, tplFile string) (content string, err error) {
// Get the absolute path of the root template
path, err := filepath.Abs(config.Root + string(os.PathSeparator) + tplFile + config.Extension)
if err != nil {
return "", fmt.Errorf("ViewEngine path:%v error: %v", path, err)
}
data, err := ioutil.ReadFile(path)
if err != nil {
return "", fmt.Errorf("ViewEngine render read name:%v, path:%v, error: %v", tplFile, path, err)
}
return string(data), nil
}
}