# `StarView.Template.Node`
[🔗](https://github.com/Neophen/star_view/blob/v0.7.0/lib/star_view/template/node.ex#L1)

One node of a `StarView.Template` tree.

| Kind | Fields | Rendering |
| --- | --- | --- |
| `:text` | `value` | Trusted static HTML source, emitted verbatim |
| `:value` | `value` | HTML-escaped with `Phoenix.HTML`; a nested `StarView.Template` renders structurally |
| `:element` | `tag`, `attrs`, `children` | A normal HTML element |
| `:branch` | `key`, `children` | The chosen branch; `key` identifies which one |
| `:keyed` | `children` | `:fragment` items, each with a unique `key` |
| `:fragment` | `children`, optional `key` | Its children |
| `:component` | `value` | A native `StarView.Template`; legacy HEEx results are rejected |

`:text` values and `{:static, ...}` attribute values are compiler output and
must already be entity-escaped source. They are never escaped again.

Compiled branch/collection children may hold internal programs before
materialization. `StarView.Template.nodes/1` expands those into ordinary nodes.

## Element meta

  * `:void?` - `true` for void elements such as `<br>`; they render no
    closing tag and must have no children.
  * `:namespace` - `:svg` or `:mathml` for foreign elements; defaults to HTML.
  * `:browser_owned?` - `true` when browser code (a Rocket host, an editor)
    manages the element's descendants. Diffs never target those descendants.

Other meta (dependencies, source location) is free-form and ignored by
rendering. Do not store a conn in meta.

## Attributes

  * `{:static, name, raw_value, delimiter}` - `raw_value` is entity-escaped
    source and `delimiter` is `"\""` or `"'"`. A `nil` value renders a bare
    boolean attribute.
  * `{:dynamic, name, value}` - escaped like HEEx `name={value}`: `true`
    renders a bare attribute, `nil` and `false` omit it, `class` accepts
    lists, and `class`/`style` are always emitted.
  * `{:spread, list_or_map}` - escaped like HEEx `{@rest}`.

Dynamic and spread names are validated before rendering. Names containing
whitespace, quotes, `<`, `>`, `/`, `=`, `&` or backticks raise.

# `attr`

```elixir
@type attr() ::
  {:static, String.t(), String.t() | nil, String.t() | nil}
  | {:dynamic, String.t(), term()}
  | {:spread, keyword() | map()}
```

# `child`

```elixir
@type child() :: t() | StarView.Template.Program.t()
```

# `kind`

```elixir
@type kind() :: :text | :value | :element | :branch | :keyed | :fragment | :component
```

# `t`

```elixir
@type t() :: %StarView.Template.Node{
  attrs: [attr()],
  children: [child()],
  key: term(),
  kind: kind(),
  meta: map(),
  tag: String.t() | nil,
  value: term()
}
```

# `branch`

```elixir
@spec branch(term(), [child()], map()) :: t()
```

Builds a `:branch` node for the chosen branch `key`.

# `component`

```elixir
@spec component(StarView.Template.t(), map()) :: t()
```

Builds a `:component` node.

# `element`

```elixir
@spec element(String.t(), [attr()], [child()], map()) :: t()
```

Builds an `:element` node.

# `fragment`

```elixir
@spec fragment([child()], term(), map()) :: t()
```

Builds a `:fragment` node, optionally keyed for item identity.

# `keyed`

```elixir
@spec keyed([child()], map()) :: t()
```

Builds a `:keyed` node from `:fragment` items.

# `text`

```elixir
@spec text(String.t()) :: t()
```

Builds a `:text` node from trusted, already-escaped HTML source.

# `value`

```elixir
@spec value(term(), map()) :: t()
```

Builds a `:value` node.
