# `Expresso.Goto`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/goto.ex#L1)

A link from an element to a slide and a step of the deck

The `goto` option of a text area, an image or an item takes a keyword list,
such as `goto: [slide: 5]` or `goto: [slide: 5, step: 2]`. The slide is a
number or the name of a slide, such as `goto: [slide: "summary"]`. The
default step is 1. The render function of the element then puts its content
into a link:

```html
<a class="goto" href="#5.2" data-link="0">
```

`data-link` holds the number of the link in the deck. The renderer writes
the commands of each link one time into the element `expresso-links`, in
the order of these numbers, such as `[[["goto",7]]]`. The number 7 is the
index of step 2 of slide 5 in the list of the steps. A click on the link in
the present view runs the commands of the link with the program of the
presenter, so the presenter goes to that step. The link is an HTML link, so
the keyboard and a screen reader can use it. In the handout view and in the
speaker view, the script does not run the commands.

The link holds no commands itself. Thus raw HTML in a text area can refer to
the commands of a link of the deck, but it cannot give new commands. The
compiler makes each command, and `Expresso.Presenter.Schema` gives the
form of the list.

A name must belong to one slide of the deck. A link by name stays correct
when a slide comes in front of its target, and a link by number does not.

A link can only go to a slide and a step of the deck. Thus the handout view
and the print show each state that a link can give. `Expresso.GotoVerifier`
refuses a slide or a step that the deck does not have, and a name that no
slide or more than one slide has. A deck from the
imperative API can put a struct into the `goto` field of the element, and
`resolve/1` raises for such a slide or step.

# `t`

```elixir
@type t() :: %Expresso.Goto{
  commands: [Expresso.Presenter.Definition.command()] | nil,
  index: non_neg_integer() | nil,
  slide: pos_integer() | String.t(),
  step: pos_integer()
}
```

A link

`index` holds the number of the link in the deck, from 0, and `commands`
holds its commands. `resolve/1` writes the two fields, and they are `nil`
before. `resolve/1` also replaces a name in `slide` with the number of the
slide.

# `check`

```elixir
@spec check(t(), [{String.t() | nil, pos_integer()}]) ::
  {:ok, pos_integer()} | {:error, String.t()}
```

Make sure that a slide and a step of a link are in the deck

`slides` holds the name and the maximum step number of each slide, in slide
order. The function returns the number of the slide of the link.

# `href`

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

Return the fragment of the address of a link, such as `#5.2`

The browser follows this address when the program does not use the click,
such as in the handout view.

# `json`

```elixir
@spec json(Expresso.Deck.t()) :: String.t() | nil
```

Write the commands of the links of a deck as JSON, or return `nil`

The value is a list with the commands of each link, in the order of their
numbers, such as `[[["goto",7]]]`. `resolve/1` must give the numbers first.
The renderer writes the value into the element `expresso-links`, so the
function escapes each `<`. A deck with no link gets `nil`, and the document
then holds no such element.

# `new`

```elixir
@spec new(term()) :: {:ok, t()} | {:error, String.t()}
```

Make a link from the value of the `goto` option

    iex> Expresso.Goto.new(slide: 5, step: 2)
    {:ok, %Expresso.Goto{slide: 5, step: 2}}

    iex> Expresso.Goto.new(slide: "summary")
    {:ok, %Expresso.Goto{slide: "summary", step: 1}}

    iex> Expresso.Goto.new(slide: 0)
    {:error, "goto takes [slide: n] or [slide: n, step: n], with positive integers or the name of a slide"}

# `resolve`

```elixir
@spec resolve(Expresso.Deck.t()) :: Expresso.Deck.t()
```

Give each link of a deck its number and its commands

The number is the position of the link in the deck, in document order, from
0. The commands go to the index of the step in the list of the steps.
`Expresso.Renderer` calls this function before it renders the deck. The
function raises an `ArgumentError` for a link to a slide or a step that the
deck does not have.

# `targets`

```elixir
@spec targets([Expresso.Slide.t()]) :: [{String.t() | nil, pos_integer()}]
```

Return the name and the maximum step number of each slide, in slide order

`check/2` takes this list.

---

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