Documentation
¶
Overview ¶
Package view renders html/template views with layouts, partials and fragments (single blocks, for htmx), plus request-aware helpers: route, asset, csrfField, old, errors, flash, cspNonce, t and locale.
Layout of the views directory:
layouts/app.html {{block "content" .}}{{end}} inside the page shell
partials/nav.html included with {{template "partials/nav" .}}
components/alert.html same, by convention for reusable widgets
posts/index.html a page: {{define "content"}}...{{end}}
A page uses the default layout ("app") unless its first line is a comment naming another one: {{/* layout: admin */}} or {{/* layout: none */}}.
New parses every view at boot into an Engine, which implements web.Renderer: handlers call c.Render("posts/index", data) for a page and c.Fragment("posts/index", "items", data) for one block (htmx swaps).
See https://github.com/AlexGalhardo/vukem/blob/main/docs/frontend.md.
Example ¶
package main
import (
"context"
"fmt"
"os"
"testing/fstest"
"github.com/AlexGalhardo/vukem/view"
)
func main() {
// Apps use os.DirFS("resources/views") or an embed.FS.
views := fstest.MapFS{
"layouts/app.html": {Data: []byte(`<main>{{block "content" .}}{{end}}</main>`)},
"posts/index.html": {Data: []byte(`{{define "content"}}{{range .}}<p>{{.}}</p>{{end}}{{end}}`)},
}
e, err := view.New(view.Config{FS: views})
if err != nil {
fmt.Println(err)
return
}
// Values are escaped by html/template.
_ = e.Render(context.Background(), os.Stdout, "posts/index", []string{"Hello", "<b>world</b>"})
}
Output: <main><p>Hello</p><p><b>world</b></p></main>
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// FS holds the views (os.DirFS("resources/views") or an embed.FS).
FS fs.FS
// Ext is the view file extension (default ".html").
Ext string
// DefaultLayout is used by pages without a layout comment (default
// "app"; ignored when layouts/app.html does not exist).
DefaultLayout string
// Reload re-parses views on every render (development).
Reload bool
// Funcs adds custom template functions. A name already used by a
// built-in ("route", "csrfField", "cspNonce"...) is an error.
Funcs template.FuncMap
// URLs resolves named routes for the "route" function.
URLs web.URLGenerator
// AssetPrefix is prepended by "asset" (default "/").
AssetPrefix string
// Vite backs the "vite" and "viteReactRefresh" functions; "asset"
// resolves files Vite processed through it first.
Vite *vite.Vite
// I18n backs the "t" and "locale" functions, in the locale that
// i18n.Middleware stored in the request context (the bundle's default
// otherwise). Without it, the bundle in the context is used, and "t"
// returns the key when there is none.
I18n *i18n.Bundle
}
Config configures an Engine.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine renders views; it implements web.Renderer.
func (*Engine) RenderBlock ¶
RenderBlock implements web.Renderer: it renders a single {{block}} or {{define}} of the page, without the layout.
Example ¶
package main
import (
"context"
"os"
"testing/fstest"
"github.com/AlexGalhardo/vukem/view"
)
func main() {
views := fstest.MapFS{
"posts/index.html": {Data: []byte(
`{{/* layout: none */}}<ul>{{block "items" .}}{{range .}}<li>{{.}}</li>{{end}}{{end}}</ul>`,
)},
}
e, _ := view.New(view.Config{FS: views})
// An htmx request gets only the fragment.
_ = e.RenderBlock(context.Background(), os.Stdout, "posts/index", "items", []string{"a", "b"})
}
Output: <li>a</li><li>b</li>