Documentation
¶
Overview ¶
Purpose: This file implements the Tempose Ahead-of-Time (AOT) component compilation engine.
Philosophy: GoStack treats frontend components (HTML, CSS, JS) as first-class Go citizens. Rather than parsing template files at runtime (which introduces disk I/O latency and defers syntax errors to production), the compiler transforms all component assets into static Go source code during the build step.
This means the generated file (gostack_components_gen.go) is a standard Go file that is compiled directly into the application binary. The result is:
- Zero disk I/O on every HTTP request for view rendering.
- Compile-time guarantees that all registered components exist.
- A single, portable binary with all assets embedded.
COMPONENT STRUCTURE: Each component lives in its own subdirectory under the components path:
components/
counter/
counter.html ← markup template (supports {{ .Field }} bindings)
counter.css ← component-scoped styles
counter.js ← component-specific client scripts
The compiler scans this directory structure, processes each asset type, and emits a single Go registration file containing all compiled outputs.
Purpose: This file contains the Glide client-side reactive directive engine, embedded as a Go string constant so the entire runtime ships inside the binary — zero HTTP round-trips to load a JS file.
Philosophy: Glide is GoStack's browser-side reactivity layer. Like Alpine.js, it works directly on existing HTML via data attributes. Unlike Alpine, it is purpose-built for GoStack components and carries zero third-party footprint.
Package ui (Tempose + Glide) coordinates AOT component compilation, scoped asset collection, and the Glide client-side reactive directive engine runtime injection.
Index ¶
- Constants
- func ApplyFilter(val any, filterName string, args ...string) string
- func Escape(val any) string
- func Evaluate(data any, field string) any
- func EvaluateBool(data any, field string) bool
- func EvaluateSlice(data any, field string) []any
- func FilterDate(val any, args ...string) string
- func FilterLower(val any, _ ...string) string
- func FilterPlural(val any, args ...string) string
- func FilterSlugify(val any, _ ...string) string
- func FilterTruncate(val any, args ...string) string
- func FilterUpper(val any, _ ...string) string
- func RegisterComponentScript(name, js string)
- func RegisterComponentStyle(name, prefixedCSS string)
- func RegisterFilter(name string, fn any)
- func WriteMasterAssetBlock(w io.Writer)
- type AssetCompiler
- type HotReloadWatcher
- type SafeHTML
Constants ¶
const GlideJS = `` /* 56795-byte string literal not displayed */
GlideJS is the Glide reactive directive engine runtime, injected into every GoStack page via WriteMasterAssetBlock. It is written as a pure JavaScript IIFE with zero external dependencies and works in any modern browser.
const GoStackCoreCSS = `` /* 472513-byte string literal not displayed */
GoStackCoreCSS provides the global semantic styles for elements opting-in via [gs-css].
Variables ¶
This section is empty.
Functions ¶
func ApplyFilter ¶ added in v1.0.2
ApplyFilter invokes a named filter on the given value with optional string arguments. It returns the filtered string, or the original fmt.Sprint value if the filter is not found.
func Escape ¶ added in v1.0.2
Escape sanitizes template output to prevent XSS, unless the value is marked as SafeHTML or template.HTML.
func Evaluate ¶
Evaluate performs a safe runtime reflection lookup of a field name on a given data object. It supports nested dot-notation paths (e.g. "User.Profile.Name").
func EvaluateBool ¶ added in v1.0.2
EvaluateBool inspects the resolved value of a field path and returns its truthiness.
func EvaluateSlice ¶ added in v1.0.2
EvaluateSlice inspects the field path and returns a slice of interfaces.
func FilterDate ¶ added in v1.0.2
FilterDate formats a time.Time or parseable string using Go reference time layout. Format defaults to "2006-01-02" if empty.
func FilterLower ¶ added in v1.0.2
FilterLower converts the value to lowercase.
func FilterPlural ¶ added in v1.0.2
FilterPlural returns the singular or plural form based on the "count" string arg. Usage in template: {{ count | plural("apple", "apples") }}
func FilterSlugify ¶ added in v1.0.2
FilterSlugify converts a string to a URL-safe, dash-separated slug.
func FilterTruncate ¶ added in v1.0.2
FilterTruncate shortens a string to the given character length, appending "…" if cut.
func FilterUpper ¶ added in v1.0.2
FilterUpper converts the value to uppercase.
func RegisterComponentScript ¶
func RegisterComponentScript(name, js string)
RegisterComponentScript registers component-scoped JS scripts during system boot passes.
func RegisterComponentStyle ¶
func RegisterComponentStyle(name, prefixedCSS string)
RegisterComponentStyle saves isolated, prefixed component CSS configurations during system boot passes.
func RegisterFilter ¶ added in v1.0.2
RegisterFilter adds or overrides a named template filter. The fn value must be a function with signature func(val any, args ...string) string.
func WriteMasterAssetBlock ¶
WriteMasterAssetBlock streams the GoStack core styles, the Glide reactive runtime, and all registered component-scoped styles and scripts into the HTTP response writer. It is called once per page render, typically just before the closing </head> tag. No arguments are required — the Glide engine is embedded directly from GlideJS.
Types ¶
type AssetCompiler ¶
AssetCompiler orchestrates the full component compilation pipeline. It scans the components source directory, processes all assets (HTML, CSS, JS), and writes a fully compiled, Go-formatted registration file to the output path.
Fields:
- ComponentsPath: Absolute or relative path to the components source directory.
- OutputPath: Absolute or relative path where the generated Go file will be written.
func NewAssetCompiler ¶
func NewAssetCompiler(componentsPath, outputPath string) *AssetCompiler
NewAssetCompiler returns a pointer to an initialized AssetCompiler.
func (*AssetCompiler) Run ¶
func (c *AssetCompiler) Run() error
Run executes the full compilation sequence.
type HotReloadWatcher ¶ added in v1.0.2
type HotReloadWatcher struct {
// contains filtered or unexported fields
}
HotReloadWatcher polls a components directory for file changes and re-runs the AssetCompiler automatically. On each rebuild it broadcasts a reload signal to all connected SSE clients so the browser refreshes instantly — with zero external dependencies (no inotify, no fsnotify, no CGO).
Usage in your dev server entrypoint:
watcher := ui.NewHotReloadWatcher(compiler, 500*time.Millisecond)
go watcher.Start(ctx)
// Register the SSE endpoint with your router:
router.Get("/__gostack_reload", func(ctx *http.Context) {
watcher.ServeSSE(ctx.Writer, ctx.Request)
})
In your base layout HTML add:
<script>
if (location.hostname === 'localhost') {
const es = new EventSource('/__gostack_reload');
es.onmessage = () => location.reload();
}
</script>
func NewHotReloadWatcher ¶ added in v1.0.2
func NewHotReloadWatcher(compiler *AssetCompiler, interval time.Duration) *HotReloadWatcher
NewHotReloadWatcher creates a watcher that polls the compiler's ComponentsPath. interval controls how often the directory is scanned for changes.
func (*HotReloadWatcher) ServeSSE ¶ added in v1.0.2
func (w *HotReloadWatcher) ServeSSE(writer interface { Header() interface{ Set(string, string) } WriteHeader(int) Write([]byte) (int, error) Flush() }, req interface { Context() interface{ Done() <-chan struct{} } })
ServeSSE writes an HTTP/SSE stream that sends a "reload" event whenever the compiler detects a component change. Connect a browser EventSource to this endpoint to get automatic page refreshes during development.
func (*HotReloadWatcher) Start ¶ added in v1.0.2
func (w *HotReloadWatcher) Start(ctx interface{ Done() <-chan struct{} })
Start begins the polling loop. It blocks until ctx.Done() is closed. Run this in a goroutine: go watcher.Start(ctx)