Skip to content

Commit

Permalink
templates: Offically make templates extensible
Browse files Browse the repository at this point in the history
This supercedes #4757 (and #4568) by making template extensions
configurable.

The previous implementation was never documented AFAIK and had only
1 consumer, which I'll notify as a courtesy.
  • Loading branch information
mholt committed Nov 13, 2023
1 parent 3b3d678 commit 2d19702
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 10 deletions.
26 changes: 26 additions & 0 deletions modules/caddyhttp/templates/caddyfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package templates

import (
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
Expand Down Expand Up @@ -49,6 +52,29 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
if !h.Args(&t.FileRoot) {
return nil, h.ArgErr()
}
case "extensions":
if h.NextArg() {
return nil, h.ArgErr()
}
if t.ExtensionsRaw != nil {
return nil, h.Err("extensions already specified")
}
for nesting := h.Nesting(); h.NextBlock(nesting); {
extensionModuleName := h.Val()
modID := "http.handlers.templates.functions." + extensionModuleName
unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
if err != nil {
return nil, err
}
cf, ok := unm.(CustomFunctions)
if !ok {
return nil, h.Errf("module %s (%T) does not provide template functions", modID, unm)
}
if t.ExtensionsRaw == nil {
t.ExtensionsRaw = make(caddy.ModuleMap)
}
t.ExtensionsRaw[extensionModuleName] = caddyconfig.JSON(cf, nil)
}
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions modules/caddyhttp/templates/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ type Templates struct {
// the opening and closing delimiters. Default: `["{{", "}}"]`
Delimiters []string `json:"delimiters,omitempty"`

// Extensions adds functions to the template's func map. These often
// act as components on web pages, for example.
ExtensionsRaw caddy.ModuleMap `json:"match,omitempty" caddy:"namespace=http.handlers.templates.functions"`

customFuncs []template.FuncMap
}

Expand All @@ -338,17 +342,13 @@ func (Templates) CaddyModule() caddy.ModuleInfo {

// Provision provisions t.
func (t *Templates) Provision(ctx caddy.Context) error {
fnModInfos := caddy.GetModules("http.handlers.templates.functions")
customFuncs := make([]template.FuncMap, 0, len(fnModInfos))
for _, modInfo := range fnModInfos {
mod := modInfo.New()
fnMod, ok := mod.(CustomFunctions)
if !ok {
return fmt.Errorf("module %q does not satisfy the CustomFunctions interface", modInfo.ID)
}
customFuncs = append(customFuncs, fnMod.CustomTemplateFunctions())
mods, err := ctx.LoadModule(t, "ExtensionsRaw")
if err != nil {
return fmt.Errorf("loading template extensions: %v", err)
}
for _, modIface := range mods.(map[string]any) {
t.customFuncs = append(t.customFuncs, modIface.(CustomFunctions).CustomTemplateFunctions())
}
t.customFuncs = customFuncs

if t.MIMETypes == nil {
t.MIMETypes = defaultMIMETypes
Expand Down

0 comments on commit 2d19702

Please sign in to comment.