# Sandwich Hime language specification Status: v1 development draft. Implemented behavior and this document must change together. ## Source unit A `.sando` file defines exactly one component. After optional UTF-8 BOM and whitespace, it starts with a target header and ends at EOF: ```sando

``` The v1 target is `go`. Other target names are rejected. The explicit target is an architectural seam for a possible future San backend; it is not a promise that such a backend exists. The header permits one package clause, ordinary Go imports, and one bodyless, receiverless function declaration. The component name is the function name and its parameters form the generated typed API. A Go type-parameter list is part of the v1 grammar and is preserved after `go/format` normalization: ```sando ``` Constraints, inference, and instantiation use ordinary Go rules; Sandwich Hime does not add a second generic type system. Multiple components, methods, global declarations, and executable initialization in the header are errors. ## Template tags | Form | Meaning | | --- | --- | | `` | Trusted Go statements inside the component renderer | | `` | Render a value escaped for the statically determined output context | | `` | Render a `sando.Component` and propagate its error | | `` | Template-only comment; emits no output | EOF closes the component. There is no inheritance DSL, implicit request, reflection registry, dynamic component lookup, or raw-output intrinsic. ## Generated API For `func Card(card model.Card)`, generation emits: ```go func Card(card model.Card) sando.Component ``` For the generic example above, generation emits: ```go func List[T ~string](values []T) sando.Component ``` The component captures its typed parameters and renders later with a context and writer. All static writes, escaping operations, nested component renders, and application-provided writers propagate errors. Generated files are adjacent to their source (`card.sando.go`), formatted with `go/format`, and contain the compiler version, runtime ABI, source digest, and source mappings. Hime-san does not inject the compiler's AGPL license identifier or copyright claim. An application rightsholder remains free to select AGPL intentionally through the application's own license policy. ## Trust and output contexts Template files and embedded Go are trusted application source. Values rendered by the application are untrusted. V1 recognizes: - HTML text; - quoted attribute values; - quoted values of recognized URL attributes; - script and style data only when the Go expression has the conspicuous trusted runtime type; - component boundaries in ordinary HTML content. `` is illegal inside an attribute, script, style, tag, or comment. Dynamic tag names, attribute names, event-handler attributes, and unquoted dynamic attributes are rejected. Unsupported, malformed, or ambiguous contexts fail compilation. Static markup must return to the same neutral parser context at EOF and must be structurally balanced under the v1 HTML model. Ordinary URL values are attribute-escaped and rejected at render time when their normalized scheme is dangerous. Only `sando.TrustedURL`, made by an explicit `sando.TrustURL` call in trusted Go code, may bypass that scheme policy. The analogous trusted HTML, JavaScript, and CSS types are opaque and have conspicuous constructors. ### V1 output matrix | Template position | Ordinary value | Explicit trusted value | Unsupported or rejected | | --- | --- | --- | --- | | HTML text | HTML-escaped by `WriteText` | `TrustedHTML` is written verbatim | Dynamic markup structure remains the caller's capability boundary | | `title`/`textarea` RCDATA | HTML-escaped by `WriteRCDATA` | Trusted wrappers are still escaped | Closing the element through a value | | Quoted ordinary attribute | HTML-escaped by `WriteAttr` | Trusted wrappers stringify, then escape | Unquoted values, dynamic names, and event-handler attributes | | Quoted URL attribute | Scheme-checked, normalized, then attribute-escaped by `WriteURL` | `TrustedURL` bypasses only the scheme check | Ambiguous schemes, controls, and non-allowlisted schemes | | `script` data | Not accepted | `TrustedJS` is written verbatim | Plain strings and ambiguous escaped-script parser states | | `style` data | Not accepted | `TrustedCSS` is written verbatim | Plain strings and dynamic style attributes | | Ordinary HTML content | `