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

Runs `mix expresso <input> --check`, and writes a report of the problems of the deck

The check has four levels. Each level runs the checks of the level before
it, and it needs one more tool:

| Level | Option | Checks | Needs |
| --- | --- | --- | --- |
| `:basic` | `--check` | The render, the contrast of the theme, the size of the document, and the text for a screen reader | Nothing |
| `:layout` | `--check=layout` | Each element in the window, each line of code on one line, and the text of each chart and diagram at 1/60 of the window height or more, at each step at 1920 × 1080, or at each size of `--size` | Chrome or Chromium |
| `:a11y` | `--check=a11y` | The rules of axe-core at each step, and in the menu, the list of keys, the overview and the handout view | Chrome or Chromium, and axe-core |
| `:browser` | `--check=browser` | The checks of `:a11y` in Playwright, and the keys of the presenter: each step, each view, the focus and the errors of the script | Node, the npm packages `playwright` and `axe-core`, and the Hex package `playwright_ex` |

`Expresso.Check.Document` gives the checks with no tool, and
`Expresso.Check.Browser` runs the checks in the browser.
`Expresso.Check.Session` runs the browser level in Playwright. A problem makes the
exit status 1. A note does not.

# `level`

```elixir
@type level() :: :basic | :layout | :a11y | :browser
```

A level of the check

# `size`

```elixir
@type size() :: {pos_integer(), pos_integer()}
```

A size of the page in pixels, such as `{1280, 720}`

# `check`

```elixir
@spec check(Path.t(), Path.t() | nil, level(), [size()]) ::
  {:ok, %{text: String.t(), problems: non_neg_integer()}} | {:error, String.t()}
```

Check the deck of an input file, and return the text of the report and the number of problems

The function writes the HTML to `output` when it is not `nil`. It writes
nothing else.

# `named`

```elixir
@spec named([String.t()], Expresso.Deck.t()) :: [String.t()]
```

Put the name of the slide after its number, in each line that starts with a slide

The reports of the checks name a slide by its number, and the deck names it
by its name. A slide with no name keeps its number alone.

    iex> deck = Expresso.Builder.deck([Expresso.Builder.slide("resHit", elements: [])], name: "n")
    iex> Expresso.Check.named(["Slide 1, step 2: a problem", "Slide 1: a note", "The keys: j"], deck)
    ["Slide 1 “resHit”, step 2: a problem", "Slide 1 “resHit”: a note", "The keys: j"]

# `run`

```elixir
@spec run(Path.t(), Path.t() | nil, level(), [size()]) :: 0 | 1
```

Check the deck of an input file, write the report, and return the exit status

With `output`, the function also writes the HTML to that file. The report
goes to the standard output, and an error goes to the standard error. The
exit status is 1 for a problem or an error, and 0 otherwise. `sizes` gives
the sizes of the page for a browser level, and `[]` gives 1920 × 1080.

# `variants`

```elixir
@spec variants([{String.t(), [String.t()]}]) :: [String.t()]
```

Merge the problems of the runs of the checks of the page

Each run has a name, such as `dark` or `1280 × 720`. A problem of each run
gives one line. A problem of some runs names them before the first colon.

    iex> Expresso.Check.variants([{"", ["Slide 1, step 1: a"]}])
    ["Slide 1, step 1: a"]
    iex> Expresso.Check.variants([
    ...>   {"light", ["Slide 1, step 1: a", "Slide 2, step 1: b"]},
    ...>   {"dark", ["Slide 1, step 1: a", "Slide 3, step 2: c"]}
    ...> ])
    ["Slide 1, step 1: a", "Slide 2, step 1 (light): b", "Slide 3, step 2 (dark): c"]
    iex> Expresso.Check.variants([
    ...>   {"1920 × 1080", []},
    ...>   {"1280 × 720", ["Slide 2, step 1: d"]},
    ...>   {"1024 × 768", ["Slide 2, step 1: d"]}
    ...> ])
    ["Slide 2, step 1 (1280 × 720; 1024 × 768): d"]

---

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