aboutsummaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
Diffstat (limited to 'static')
-rw-r--r--static/doc.go8
-rwxr-xr-xstatic/templates-noembed.go29
-rwxr-xr-xstatic/templates.go8
3 files changed, 41 insertions, 4 deletions
diff --git a/static/doc.go b/static/doc.go
new file mode 100644
index 0000000..a578372
--- /dev/null
+++ b/static/doc.go
@@ -0,0 +1,8 @@
+// Package static provides the HTML templates, stylesheet and images the
+// frontend serves.
+//
+// It has two implementations selected by the 'embed' build tag. With the tag,
+// the assets are compiled into the binary via go:embed. Without it, they are
+// read from the directory named by StaticPath at startup and held in memory,
+// which is what makes editing templates without a rebuild possible.
+package static
diff --git a/static/templates-noembed.go b/static/templates-noembed.go
index c0dfe7f..ee97ca7 100755
--- a/static/templates-noembed.go
+++ b/static/templates-noembed.go
@@ -1,5 +1,4 @@
//go:build !embed
-// +build !embed
package static
@@ -11,6 +10,7 @@ import (
"time"
)
+// Templates is the in-memory asset filesystem populated by CopyTemplatesToMemory.
var Templates FS
type file struct {
@@ -21,8 +21,12 @@ type file struct {
var templateNames = []string{}
var templates = make(map[string][]file)
+
+// StaticPath is the directory assets are read from at startup.
var StaticPath string
+// CopyTemplatesToMemory reads every asset under StaticPath into memory. It exits
+// the process on failure, since the frontend cannot serve anything without them.
func CopyTemplatesToMemory() {
baseDir, err := os.ReadDir(StaticPath)
try(err)
@@ -53,8 +57,11 @@ func CopyTemplatesToMemory() {
}
}
+// FS serves the in-memory assets. It implements the subset of fs.FS that
+// template.ParseFS requires.
type FS struct{}
+// Open returns the asset stored at name, or an fs.PathError if there is none.
func (FS) Open(name string) (fs.File, error) {
for i, l := 0, len(templateNames); i < l; i++ {
for _, x := range templates[templateNames[i]] {
@@ -69,6 +76,8 @@ func (FS) Open(name string) (fs.File, error) {
return nil, &fs.PathError{}
}
+// Glob returns the paths of every asset in the directory named by pattern's
+// first segment, or an fs.PathError if none match.
func (FS) Glob(pattern string) ([]string, error) {
trimmed := strings.Split(pattern, "/")
var matches = []string{}
@@ -91,47 +100,60 @@ func try(err error) {
}
}
-/* based on https://github.com/psanford/memfs; required for templates.ParseFS to work correctly */
+// fileInfo is a minimal fs.FileInfo. Assets are held in memory and never stat'd
+// for anything but their name, so the remaining fields report fixed values.
+//
+// Based on https://github.com/psanford/memfs; required for templates.ParseFS to
+// work correctly.
type fileInfo struct {
name string
}
+// Name returns the asset's path.
func (fi fileInfo) Name() string {
return fi.name
}
+// Size reports a fixed placeholder size; callers here never use it.
func (fi fileInfo) Size() int64 {
return 4096
}
+// Mode reports no mode bits: in-memory assets have no filesystem permissions.
func (fileInfo) Mode() fs.FileMode {
return 0
}
+// ModTime reports the zero time, as in-memory assets are never modified.
func (fileInfo) ModTime() time.Time {
return time.Time{}
}
+// IsDir always reports false: only files are stored, never directories.
func (fileInfo) IsDir() bool {
return false
}
-func (fileInfo) Sys() interface{} {
+// Sys returns nil, as there is no underlying data source.
+func (fileInfo) Sys() any {
return nil
}
+// File is a read-once handle to an in-memory asset.
type File struct {
name string
content *bytes.Buffer
closed bool
}
+// Stat returns the file's fileInfo. It never fails.
func (f *File) Stat() (fs.FileInfo, error) {
return fileInfo{
name: f.name,
}, nil
}
+// Read consumes the asset's contents, reporting fs.ErrClosed once closed.
func (f *File) Read(b []byte) (int, error) {
if f.closed {
return 0, fs.ErrClosed
@@ -139,6 +161,7 @@ func (f *File) Read(b []byte) (int, error) {
return f.content.Read(b)
}
+// Close marks the file closed. Closing twice reports fs.ErrClosed.
func (f *File) Close() error {
if f.closed {
return fs.ErrClosed
diff --git a/static/templates.go b/static/templates.go
index 28a057a..859f075 100755
--- a/static/templates.go
+++ b/static/templates.go
@@ -1,16 +1,22 @@
//go:build embed
-// +build embed
package static
import "embed"
+// Templates is the asset filesystem compiled into the binary.
+//
//go:embed *
var Templates embed.FS
+
+// Enabled reports that assets are embedded in this build.
var Enabled bool = true
+// StaticPath is accepted for parity with the non-embed build, where it names the
+// directory assets are read from. It is ignored here.
var StaticPath string
+// CopyTemplatesToMemory is a no-op in this build: the assets are already embedded.
func CopyTemplatesToMemory() {
_ = StaticPath
}