uigen

package
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package uigen turns one resolved widget document into the files that make it a running widget: a templ view and a Go scaffold implementing the SDK's widget contract.

In memory, then to disk

Generate returns artifacts — a path and its exact bytes — and writes nothing. Write is a separate call. That split is what makes the determinism claim cheap to check: a spec generates twice and compares two slices, with no temporary directory and no filesystem anywhere in the assertion. It is the shape pkg/gotth/internal/clientcodec already uses, for the same reason.

Determinism is not incidental here. Everything emitted is derived from the IR's ordered sequences, and nothing is derived from a map: the IR is ordered precisely so a render is byte-identical for equal state, and a generator that reintroduced iteration order would hand that property back.

What it emits, and what it refuses

Every block of the dialect reaches the output: state, predicates, bindings, labels, chrome, roles, channels, placements, a scene of nodes, edges and orbits, motion, indicators, controls, events and streams. The three computed records reach it too — an edge's geometry becomes its transform, the legend is walked rather than re-derived from the channels, and the dirty projection becomes the widget's own dirty declaration.

Each generated definition has a default constructor and view, plus NewWidgetAt and WidgetViewAt forms that accept a host-assigned region. The region scopes the live root, accessible title and animated scene identities; the definition's name and event contracts remain shared. Hosts validate region syntax and uniqueness before exposing instances through their live configuration.

What is refused is listed by Refusals and is three shapes of one construct: a control whose trigger is change, input or submit. A control declares a caption, a trigger and an event, and nothing that says what kind of element it is — a click is a button and needs nothing more, while those three need a form control the dialect cannot describe. Binding one of them to a button would emit a binding that can never fire.

Refusing is the whole point of the boundary. A generator that silently omitted a construct, or emitted a plausible-looking approximation of one, would produce a widget that compiles, renders, and is not the widget the author wrote — which is the failure the dialect's validator exists to prevent one layer up, and it would be pointless to enforce there and abandon here.

Index

Constants

This section is empty.

Variables

View Source
var ErrNameCollision = errors.New("uigen: two document identifiers emit one Go identifier")

ErrNameCollision is returned when two document identifiers, distinct in the dialect's flat namespace, would emit one Go identifier.

The dialect's own namespace cannot prevent it: `statusText` and `StatusText` are two names there and one exported name here. Reporting it is what keeps the generator from emitting a file that will not compile and blaming templ for it.

View Source
var ErrPackage = errors.New("uigen: the output package name is not a Go identifier")

ErrPackage is returned for an output package name Go could not compile.

View Source
var ErrUnexportable = errors.New("uigen: a document identifier has no exported Go spelling")

ErrUnexportable is returned for a document identifier with no exported Go spelling — one beginning with an underscore, which the dialect's identifier pattern allows and Go's export rule does not.

View Source
var ErrUnsound = errors.New("uigen: the document is not sound; refuse its findings before generating")

ErrUnsound is returned for a document missing something the interpreter guarantees a sound one has.

It is a refusal rather than a nil dereference. The IR is returned whether or not a document validated, so a caller that generated without reading the findings hands this package a partial document, and saying so is more use than a stack trace naming a field.

Functions

func Refusals

func Refusals() []string

Refusals names every construct this generator refuses, in the order a message lists them. It is exported so that a caller can print what the generator will not do without provoking it into refusing.

func Write

func Write(directory string, artifacts []Artifact) error

Write writes artifacts under directory, creating directories as needed.

Types

type Artifact

type Artifact struct {
	// Path is relative to the output directory and is part of the generated
	// output: gen.sh compares it, so a renamed artifact is a diff rather than a
	// silently orphaned file.
	Path string

	// Data is the file's exact bytes.
	Data []byte
}

Artifact is one generated file: a path relative to the output directory and its exact bytes.

func Generate

func Generate(document *ir.Document, options Options) ([]Artifact, error)

Generate produces every artifact for one resolved document, without writing anything.

The document must be sound: interpreting it must have produced no finding. Generating from an unsound document is generating from a guess, and this package has no way to tell the two apart — the IR is returned either way, so the caller holding the findings is the only one who can refuse.

type Options

type Options struct {
	// Package is the Go package name both emitted files declare.
	Package string
}

Options are the decisions the document does not carry.

A widget document names no path, no package and no import, by construction — that is what makes one publishable — so the one thing generation needs and the document cannot supply is where the emitted Go belongs.

type UnsupportedError

type UnsupportedError struct {
	// Widget is the document's own name.
	Widget string
	// Constructs are the unsupported constructs, in the order [Refusals] lists
	// them.
	Constructs []string
}

UnsupportedError reports the constructs this generator does not yet emit. It names every one of them rather than the first, on the same argument the interpreter's findings are made on: an author who fixes one and re-runs to find the next learns the tool tells them a fraction of the truth.

func (*UnsupportedError) Error

func (unsupportedError *UnsupportedError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL