refactor: move document head includes out of via configuration into their own append funcs; update examples

This commit is contained in:
Joao Goncalves
2025-11-09 03:17:03 -01:00
parent 5c80a934e9
commit 9f9e4eb568
7 changed files with 72 additions and 90 deletions

View File

@@ -1,7 +1,5 @@
package via
import "github.com/go-via/via/h"
type LogLevel int
const (
@@ -22,15 +20,6 @@ type Options struct {
// The title of the HTML document.
DocumentTitle string
// Elements to include in the head of the base HTML document.
// Useful for including css stylesheets and JS scripts.
DocumentHeadIncludes []h.H
// Elements to include in the bottom of the body of the base
// HTML document.Useful for including JS scripts or a footer.
DocumentBodyIncludes []h.H
// Plugins to extend the capabilities of the `Via` application.
// Check `https://github.com/go-via/plugins` for a list of available plugins.
Plugins []Plugin
}

View File

@@ -16,11 +16,8 @@ func LiveReloadPlugin(v *via.V) {
<-r.Context().Done()
})
}
func liveReloadScript() h.H {
return h.Script(h.Raw(`
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
v.AppendToFoot(h.Script(h.Raw(`
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
const evtSource = new EventSource('/dev/reload');
let overlay = null;
let showTimer = null;
@@ -52,6 +49,6 @@ if (window.location.hostname === 'localhost' || window.location.hostname === '12
}
})();
};
}
`))
}
`)))
}

View File

@@ -10,13 +10,9 @@ type Counter struct{ Count int }
func main() {
v := via.New()
LiveReloadPlugin(v)
v.Config(via.Options{
DocumentTitle: "Live Reload",
DocumentHeadIncludes: []h.H{
liveReloadScript(),
},
Plugins: []via.Plugin{LiveReloadPlugin},
})
v.Page("/", func(c *via.Context) {
@@ -29,7 +25,7 @@ func main() {
})
c.View(func() h.H {
return h.Div(h.Class("container"),
return h.Div(
h.H1(h.Text("Live Reload")),
h.P(h.Textf("Count: %d", data.Count)),
h.P(h.Span(h.Text("Step: ")), h.Span(step.Text())),

View File

@@ -8,12 +8,7 @@ import (
func main() {
v := via.New()
v.Config(via.Options{
DocumentTitle: "Via",
DocumentHeadIncludes: []h.H{
h.Link(h.Rel("stylesheet"), h.Href("https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css")),
},
})
v.AppendToHead(h.Link(h.Rel("stylesheet"), h.Href("https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css")))
v.Page("/", func(c *via.Context) {
c.View(func() h.H {

View File

@@ -8,8 +8,8 @@ import (
"github.com/go-via/via/h"
)
// In this example we create a Via application with a plugin that adds PicoCSS. The plugin
// is handed to Via in the app Configuration.
// Example of a Via application with a plugin that adds PicoCSS. The plugin
// is handed to Via in the Configuration.
//go:embed pico.yellow.min.css
var picoCSSFile []byte
@@ -41,9 +41,5 @@ func PicoCSSPlugin(v *via.V) {
w.Header().Set("Content-Type", "text/css")
_, _ = w.Write(picoCSSFile)
})
v.Config(via.Options{
DocumentHeadIncludes: []h.H{
h.Link(h.Rel("stylesheet"), h.Href("/_plugins/picocss/assets/style.css")),
},
})
v.AppendToHead(h.Link(h.Rel("stylesheet"), h.Href("/_plugins/picocss/assets/style.css")))
}

View File

@@ -13,13 +13,10 @@ import (
func main() {
v := via.New()
v.Config(via.Options{
DocumentTitle: "Via",
DocumentHeadIncludes: []h.H{
v.AppendToHead(
h.Link(h.Rel("stylesheet"), h.Href("https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css")),
h.Script(h.Src("https://unpkg.com/echarts@6.0.0/dist/echarts.min.js")),
},
})
)
v.Page("/", func(c *via.Context) {
chartComp := c.Component(chartCompFn)

38
via.go
View File

@@ -29,7 +29,8 @@ type V struct {
mux *http.ServeMux
contextRegistry map[string]*Context
contextRegistryMutex sync.RWMutex
baseLayout func(h.HTML5Props) h.H
documentHeadIncludes []h.H
documentFootIncludes []h.H
}
func (v *V) logErr(c *Context, format string, a ...any) {
@@ -78,12 +79,6 @@ func (v *V) Config(cfg Options) {
if cfg.DocumentTitle != "" {
v.cfg.DocumentTitle = cfg.DocumentTitle
}
if cfg.DocumentHeadIncludes != nil {
v.cfg.DocumentHeadIncludes = cfg.DocumentHeadIncludes
}
if cfg.DocumentBodyIncludes != nil {
v.cfg.DocumentBodyIncludes = cfg.DocumentBodyIncludes
}
if cfg.Plugins != nil {
for _, plugin := range cfg.Plugins {
if plugin != nil {
@@ -93,6 +88,27 @@ func (v *V) Config(cfg Options) {
}
}
// AppendToHead appends the given h.H nodes to the head of the base HTML document.
// Useful for including css stylesheets and JS scripts.
func (v *V) AppendToHead(elements ...h.H) {
for _, el := range elements {
if el != nil {
v.documentHeadIncludes = append(v.documentHeadIncludes, el)
}
}
}
// AppendToFoot appends the given h.H nodes to the end of the base HTML document body.
// Useful for including JS scripts.
func (v *V) AppendToFoot(elements ...h.H) {
for _, el := range elements {
if el != nil {
v.documentFootIncludes = append(v.documentFootIncludes, el)
}
}
}
// Page registers a route and its associated page handler.
// The handler receives a *Context to define UI, signals, and actions.
//
@@ -113,13 +129,11 @@ func (v *V) Page(route string, composeContext func(c *Context)) {
v.logDebug(c, "GET %s", route)
composeContext(c)
v.registerCtx(c.id, c)
headElements := v.cfg.DocumentHeadIncludes
headElements := v.documentHeadIncludes
headElements = append(headElements, h.Meta(h.Data("signals", fmt.Sprintf("{'via-ctx':'%s'}", id))))
headElements = append(headElements, h.Meta(h.Data("init", "@get('/_sse')")))
bottomBodyElements := []h.H{c.view()}
for _, el := range v.cfg.DocumentBodyIncludes {
bottomBodyElements = append(bottomBodyElements, el)
}
bottomBodyElements = append(bottomBodyElements, v.documentFootIncludes...)
view := h.HTML5(h.HTML5Props{
Title: v.cfg.DocumentTitle,
Head: headElements,
@@ -174,8 +188,6 @@ func New() *V {
cfg: Options{
LogLvl: LogLevelDebug,
DocumentTitle: "Via Application",
DocumentHeadIncludes: make([]h.H, 0),
DocumentBodyIncludes: make([]h.H, 0),
},
}