From db387ad28b84ba2b22ba9375c6b0b937a159605c Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Sat, 7 Feb 2026 17:38:49 +0000 Subject: [PATCH] Update embedded template system Just trying to get forward motion. Currently getting a nil Tree inside the shared template holder. --- html/embed.go | 137 +++++++++++++----- html/filesystem.go | 9 +- .../sync/{ => layout}/authenticated.html | 0 html/template/sync/{ => layout}/base.html | 0 4 files changed, 102 insertions(+), 44 deletions(-) rename html/template/sync/{ => layout}/authenticated.html (100%) rename html/template/sync/{ => layout}/base.html (100%) diff --git a/html/embed.go b/html/embed.go index 4faac68b..03ba01f5 100644 --- a/html/embed.go +++ b/html/embed.go @@ -25,62 +25,121 @@ import ( var embeddedFiles embed.FS type templateSystemEmbed struct { - allTemplates *template.Template nameToTemplate map[string]*template.Template sourceFS fs.FS } +func newTemplateSystemEmbed() (templateSystemEmbed, error) { + ts := templateSystemEmbed{ + sourceFS: embeddedFiles, + nameToTemplate: make(map[string]*template.Template), + } + + // Load all templates + if err := ts.loadAll(); err != nil { + return ts, err + } + + return ts, nil +} func (ts templateSystemEmbed) loadAll() error { - ts.nameToTemplate = make(map[string]*template.Template, 0) - err := fs.WalkDir(ts.sourceFS, "template", func(path string, d fs.DirEntry, err error) error { + // Then, parse all remaining templates into their named slots, adding the shared stuff + page_subdirs := []string{"template/sync"} + for _, subdir := range page_subdirs { + err := ts.loadTemplateSubdir(subdir) if err != nil { - return err + return fmt.Errorf("Failed to load subdir '%s': %w", subdir, err) } - - if d.IsDir() { - return nil - } - short_path := removeLeadingDir(path) - - new_t, err := loadTemplateEmbedded(ts.sourceFS, short_path) - if err != nil { - return fmt.Errorf("Failed to add load template '%s': %w", short_path, err) - } - _, err = ts.allTemplates.AddParseTree(new_t.Name(), new_t.Tree) - if err != nil { - return fmt.Errorf("Failed to add parsed template '%s': %w", path, err) - } - ts.nameToTemplate[short_path] = new_t - log.Debug().Str("path", path).Str("short_path", short_path).Msg("Loaded template") - return nil - }) - if err != nil { - return fmt.Errorf("failed to load embeded templates: %w", err) } return nil } + +func (ts templateSystemEmbed) loadTemplateSubdir(subdir string) error { + err := fs.WalkDir(ts.sourceFS, subdir, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() { + return err + } + + content, err := fs.ReadFile(ts.sourceFS, path) + if err != nil { + return fmt.Errorf("error reading template %s: %w", path, err) + } + + new_t := template.New(path) + addFuncMap(new_t) + _, err = new_t.Parse(string(content)) + if err != nil { + return fmt.Errorf("error parsing '%s': %w", path, err) + } + short_path := removeLeadingDir(path) + shared_template_holder := template.New("shared") + shared_subdirs := []string{"template/sync/component", "template/sync/layout"} + for _, shared_subdir := range shared_subdirs { + err := ts.addSubdirTemplates(shared_template_holder, shared_subdir) + if err != nil { + return fmt.Errorf("Failed to add subdir '%s' templates: %w", shared_subdir, err) + } + } + if shared_template_holder.Tree == nil { + return fmt.Errorf("shared template holder tree is nil") + } + _, err = new_t.AddParseTree(short_path, shared_template_holder.Tree) + if err != nil { + return fmt.Errorf("error adding shared parse tree to '%s': %w", path, err) + } + log.Debug().Str("path", short_path).Msg("Loaded page template") + return nil + }) + return err +} + +func (ts templateSystemEmbed) addSubdirTemplates(t *template.Template, subdir string) error { + var err error + log.Debug().Msg("Adding subdir templates") + err = fs.WalkDir(ts.sourceFS, subdir, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() { + return err + } + + content, err := fs.ReadFile(ts.sourceFS, path) + if err != nil { + return fmt.Errorf("error reading template %s: %w", path, err) + } + + new_t := template.New(path) + addFuncMap(new_t) + _, err = new_t.Parse(string(content)) + if err != nil { + return fmt.Errorf("error parsing '%s': %w", path, err) + } + short_path := removeLeadingDir(path) + _, err = t.AddParseTree(short_path, new_t.Tree) + if err != nil { + return fmt.Errorf("error adding parse tree '%s': %w", path, err) + } + ts.nameToTemplate[short_path] = new_t + //log.Debug().Str("path", short_path).Msg("Loaded shared component template") + return nil + }) + return err +} + func (ts templateSystemEmbed) renderOrError(w http.ResponseWriter, template_name string, context interface{}) { buf := &bytes.Buffer{} - t, err := loadTemplateEmbedded(ts.sourceFS, template_name) - if err != nil { - log.Error().Err(err).Str("template_name", template_name).Msg("Failed to load embedded template") - RespondError(w, "Failed to load template", err, http.StatusInternalServerError) - return + + // Execute the template directly from the pre-parsed set + templ, ok := ts.nameToTemplate[template_name] + if !ok { + log.Error().Str("template_name", template_name).Msg("Can't find template") + RespondError(w, "Failed to render template", nil, http.StatusInternalServerError) } - for name, templ := range ts.nameToTemplate { - _, err := t.AddParseTree(name, templ.Tree) - if err != nil { - log.Error().Err(err).Str("name", name).Msg("Failed to add parse tree") - RespondError(w, "Failed to add template", err, http.StatusInternalServerError) - return - } - } - err = t.ExecuteTemplate(buf, template_name, context) + err := templ.Execute(buf, context) if err != nil { - log.Error().Err(err).Str("template_name", template_name).Msg("Failed to render embedded template") + log.Error().Err(err).Str("template_name", template_name).Msg("Failed to render template") RespondError(w, "Failed to render template", err, http.StatusInternalServerError) return } + buf.WriteTo(w) } func loadTemplateEmbedded(sourceFS fs.FS, path string) (*template.Template, error) { diff --git a/html/filesystem.go b/html/filesystem.go index 0862c0df..dcc76835 100644 --- a/html/filesystem.go +++ b/html/filesystem.go @@ -36,16 +36,15 @@ type templateSystemDisk struct { func LoadTemplates() error { _, err := os.Stat("html/template") - if err == nil { + if err != nil { templates = templateSystemDisk{ sourceFS: os.DirFS("./html/template"), } } else { - templates = templateSystemEmbed{ - allTemplates: template.New("all"), - sourceFS: embeddedFiles, + templates, err = newTemplateSystemEmbed() + if err != nil { + return fmt.Errorf("Failed to load embedded templates: %w", err) } - templates.loadAll() } return nil } diff --git a/html/template/sync/authenticated.html b/html/template/sync/layout/authenticated.html similarity index 100% rename from html/template/sync/authenticated.html rename to html/template/sync/layout/authenticated.html diff --git a/html/template/sync/base.html b/html/template/sync/layout/base.html similarity index 100% rename from html/template/sync/base.html rename to html/template/sync/layout/base.html