A program parses its templates into one page.Set.
Each page and each fragment is a block of its own name. So a fragment renders
the same in the page, in the answer to htmx, and in an event of the stream.
{{define "layout"}}<main>{{include .Content .}}</main>{{end}}
{{define "page-hosts"}}<table>{{include "hosts-table" .}}</table>{{end}}
fsys := fstest.MapFS{"ui.html": &fstest.MapFile{Data: []byte(
`{{define "layout"}}<main>{{include .Content .}}</main>{{end}}` +
`{{define "page-hosts"}}<table>{{include "hosts-table" .}}</table>{{end}}` +
`{{define "hosts-table"}}{{range .Hosts}}<tr><td>{{.}}</td></tr>{{end}}{{end}}`)}}
set, err := page.Parse(fsys, page.Options{}, "*.html")
if err != nil {
fmt.Println(err)
return
}
w := httptest.NewRecorder()
data := map[string]any{"Content": "page-hosts", "Hosts": []string{"node1", "<node2>"}}
if err := set.Respond(w, http.StatusOK, "layout", data); err != nil {
fmt.Println(err)
return
}
fmt.Println(w.Code, w.Header().Get("Content-Type"))
fmt.Println(w.Body)200 text/html; charset=utf-8
<main><table><tr><td>node1</td></tr><tr><td><node2></td></tr></table></main>localweb/page/example_test.go. CI runs it and checks its output.| Name | What it does |
|---|---|
page.Parse, page.Set | the templates in one set; include runs a block by name |
page.Set.Respond | renders the whole block before it writes anything |
page.IsHTMX, page.Redirect, page.Retarget | the requests and headers of htmx |
page.MaxIncludeDepth | a block that includes itself fails, and does not overflow the stack |
NOTE
Check at the start of the program that each block it names is there, with
Set.Has.