# `Expresso.Presenter.Projection`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/presenter/projection.ex#L1)

Tells how the script writes a state to the document

A **projection** is a rule that writes one part of the state to the document.
`Expresso.Presenter.Default` declares the projections with three entities of
the presenter DSL, and the script applies them after each change of the
state:

  * `attribute` - writes a field of the state into an attribute of the
    `body`. `attribute :view, "data-view"` writes `data-view="present"`. With
    `flag: true`, the attribute is `"true"` while the field is true, and the
    script removes it while the field is false.
  * `property` - writes a value of the current entry of the list of the steps
    into a custom property of the `body`. `property "--fraction", :fraction`
    writes `--fraction: 0.5` at the middle of the deck.
  * `mark` - writes an attribute on each element that a selector finds, when
    a number of the element agrees with a field of the state.
    `mark "data-selected", ".handout-page[data-thumbnail]", :slide,
    [{"", :selected, 0}]` marks the page whose `data-slide` is the selected
    slide. The script removes the attribute from each other element that the
    selector finds.

A mark can have more than one value. The script writes on an element the
first value whose field, plus the offset, agrees with the number of the
element. With `scroll: true`, the script then scrolls the first marked
element into its container, so the cursor of the menu stays in view.

# `t`

```elixir
@type t() :: %{
  attributes: [Expresso.Presenter.Projection.Attribute.t()],
  properties: [Expresso.Presenter.Projection.Property.t()],
  marks: [Expresso.Presenter.Projection.Mark.t()]
}
```

The projections of a definition

# `from`

```elixir
@spec from([struct()]) :: t()
```

Return the projections of the entities of a presenter module, in their order

# `json`

```elixir
@spec json(t()) :: map()
```

Return the projections as the map that `Expresso.Presenter.Program.json/1`
writes

    iex> alias Expresso.Presenter.Projection
    iex> Projection.json(%{
    ...>   attributes: [%Projection.Attribute{field: :blank, name: "data-blank", flag: true}],
    ...>   properties: [%Projection.Property{name: "--fraction", entry: :fraction}],
    ...>   marks: []
    ...> })
    %{
      "attributes" => [["blank", "data-blank", true]],
      "properties" => [["--fraction", "fraction"]],
      "marks" => []
    }

---

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