# `MingaEditor.RenderModel.Window.Builder`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga_editor/render_model/window/builder.ex#L1)

Builds a `RenderWindow` from the same data the Content stage uses.

Called during `build_window_content/2` when the frontend has GUI
capabilities. Captures the pre-resolved semantic data that the GUI
needs, without duplicating the draw logic.

The builder reads from:
- `WindowScroll` (viewport, lines, cursor, fold map, visible_line_map)
- `Context.t()` (visual selection, search matches, highlight, decorations)
- Buffer diagnostics (for inline ranges)

All positions are converted to display coordinates (relative to the
window's content rect, with fold/wrap adjustments applied).

# `build_stats`

```elixir
@type build_stats() :: %{
  rasterized: non_neg_integer(),
  retained_rows: %{
    optional(non_neg_integer()) =&gt;
      {non_neg_integer(), Minga.RenderModel.Window.Row.t()}
  },
  retained_wrap_lines: %{
    optional(non_neg_integer()) =&gt; {non_neg_integer(), [map()]}
  }
}
```

Per-build retained-row statistics (#2287).

* `rasterized` — rows whose text and spans were freshly composed this frame.
* `retained_rows` — the `{row_id => {input_hash, Row.t()}}` map to carry into
  the next frame so unchanged rows can be reused without recomposing.
* `retained_wrap_lines` — the `{buf_line => {input_hash, [entry]}}` map to
  carry into the next frame so unchanged wrapped logical lines can be reused
  without recomposing or re-wrapping.

# `state`

```elixir
@type state() :: MingaEditor.State.t() | MingaEditor.RenderPipeline.Input.t()
```

# `build`

```elixir
@spec build(
  state(),
  MingaEditor.RenderPipeline.Scroll.WindowScroll.t(),
  MingaEditor.Renderer.Context.t(),
  keyword()
) :: Minga.RenderModel.Window.t()
```

Builds a `RenderWindow` for one editor window.

Called from the Content stage with the same `WindowScroll` and
`Context` that drive the draw-based rendering.

# `build_with_stats`

```elixir
@spec build_with_stats(
  state(),
  MingaEditor.RenderPipeline.Scroll.WindowScroll.t(),
  MingaEditor.Renderer.Context.t(),
  keyword()
) :: {Minga.RenderModel.Window.t(), build_stats()}
```

Builds a `RenderWindow` and reports retained-row statistics (#2287).

Identical output to `build/4` but also returns how many rows were freshly
rasterized and the retained-row map to carry into the next frame. Pass the
previous frame's retained rows via the `:retained_rows` option so unchanged
rows are reused verbatim instead of being recomposed.

# `wrapped_source_position`

```elixir
@spec wrapped_source_position(
  [String.t()],
  non_neg_integer(),
  non_neg_integer(),
  non_neg_integer(),
  MingaEditor.Renderer.Context.t(),
  map()
) :: {:ok, non_neg_integer(), non_neg_integer()} | :error
```

Returns the source buffer position for a click in wrapped composed rows.

---

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