# `Puck.Prompt`
[🔗](https://github.com/bradleygolden/puck/blob/v0.2.25/lib/puck/prompt.ex#L1)

Behaviour for prompt template engines.

## Example

Using Solid (requires `{:solid, "~> 0.15"}`):

    alias Puck.Prompt.Solid

    {:ok, template} = Solid.parse("Hello {{ name }}!")
    {:ok, result} = Solid.render(template, %{name: "World"})

    # Or in one step
    {:ok, result} = Solid.evaluate("Hello {{ name }}!", %{name: "World"})

## Callbacks

- `parse/1`, `parse!/1` - Parse a template string
- `render/2`, `render!/2` - Render a parsed template
- `evaluate/2`, `evaluate!/2` - Parse and render in one step

# `context`

```elixir
@type context() :: %{optional(atom() | String.t()) =&gt; term()}
```

Context variables for template rendering

# `error`

```elixir
@type error() :: term()
```

Parse or render errors

# `t`

```elixir
@type t() :: term()
```

A parsed template (implementation-specific)

# `evaluate`

```elixir
@callback evaluate(template :: String.t(), context :: context()) ::
  {:ok, String.t()} | {:error, error()}
```

Parses and renders a template in one step.

Convenience function that combines `parse/1` and `render/2`.

## Examples

    {:ok, "Hello World!"} = MyEngine.evaluate("Hello {{ name }}!", %{name: "World"})

# `evaluate!`

```elixir
@callback evaluate!(template :: String.t(), context :: context()) :: String.t()
```

Parses and renders a template in one step, raising on error.

## Examples

    "Hello World!" = MyEngine.evaluate!("Hello {{ name }}!", %{name: "World"})
    # Raises on invalid template or render error

# `parse`

```elixir
@callback parse(template :: String.t()) :: {:ok, t()} | {:error, error()}
```

Parses a template string into an implementation-specific format.

Returns `{:ok, parsed_template}` on success, `{:error, reason}` on failure.

## Examples

    {:ok, template} = MyEngine.parse("Hello {{ name }}!")
    {:error, reason} = MyEngine.parse("Hello {{ unclosed")

# `parse!`

```elixir
@callback parse!(template :: String.t()) :: t()
```

Parses a template string, raising on error.

## Examples

    template = MyEngine.parse!("Hello {{ name }}!")
    # Raises on invalid template

# `render`

```elixir
@callback render(template :: t(), context :: context()) ::
  {:ok, String.t()} | {:error, error()}
```

Renders a parsed template with context variables.

Returns `{:ok, rendered_string}` on success, `{:error, reason}` on failure.

## Examples

    {:ok, template} = MyEngine.parse("Hello {{ name }}!")
    {:ok, "Hello World!"} = MyEngine.render(template, %{name: "World"})

# `render!`

```elixir
@callback render!(template :: t(), context :: context()) :: String.t()
```

Renders a parsed template, raising on error.

## Examples

    {:ok, template} = MyEngine.parse("Hello {{ name }}!")
    "Hello World!" = MyEngine.render!(template, %{name: "World"})

---

*Consult [api-reference.md](api-reference.md) for complete listing*
