# `Expresso.Element.Diagram.D2`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/element/diagram/d2.ex#L1)

Draws a graph in the language of D2, and names its elements

A `diagram` with a `.d2` file calls `draw!/2`. The function runs `d2` with
the layout engine of the `layout` option, through
`Expresso.Element.Diagram.Tool`, and it returns the SVG with a name for each
shape, container and connection.

D2 gives no `id` to a shape. It puts each shape, container and connection in
a `g` element with one class: the key of the element in Base64, such as
`YXBwLndlYg==` for `app.web`. The key of a connection holds its two ends and
its index, such as `(app.api -> db)[0]`, and a connection inside a
container has the key of the container in front, such as
`app.(web -> api)[0]`. Therefore `name/1` gives each such `g` element an
`id`:

| Element | Key | Name |
| --- | --- | --- |
| A shape | `app.web` | `app.web` |
| A container | `app` | `app` |
| A connection | `(app.api -> db)[0]` | `app.api->db` |
| A connection in a container | `app.(web -> api)[0]` | `app.web->app.api` |
| A second connection between the same ends | `(app.api -> db)[1]` | `app.api->db:2` |

The name of a connection has no spaces, and each end has its full key, so a
part names a connection as the source names its ends. Each connection also
gets the keys of its two ends, in the attributes `data-graph-from` and
`data-graph-to`, for the `edges` option of `Expresso.Element.Diagram`.

# `draw!`

```elixir
@spec draw!(Path.t(), atom(), Expresso.Element.Diagram.Font.t()) ::
  {String.t(), [String.t()]}
```

Run D2 on a source file, and return the SVG and the names

The names are the `id` of each shape, container and connection, in the
order of the file. The function raises an `ArgumentError` when D2 is not
present and when D2 fails.

# `layouts`

```elixir
@spec layouts() :: [atom()]
```

The layout engines of D2, for the `layout` option

# `name`

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

Give each shape, container and connection of an SVG of D2 the name from its key

The function returns the SVG and the names, in the order of the file.

    iex> svg = ~s(<svg><g class="YXBwLndlYg=="><g class="shape"></g></g></svg>)
    iex> Expresso.Element.Diagram.D2.name(svg)
    {~s(<svg><g id="app.web" class="YXBwLndlYg==" data-graph-kind="node"><g class="shape"></g></g></svg>), ["app.web"]}

# `theme`

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

Give a graph of D2 the colors of the theme

D2 gives each element a class of its palette, such as `fill-B4`, and a rule
of its style sheet gives the class a color. The function writes each color
as `var(--graph-B4, #E3E9FD)`, so the custom property of the style sheet of
the deck gives the color. It also removes the rectangle of the background.

    iex> svg = ~s|<svg><style>.d2-1 .fill-B4{fill:#E3E9FD;}</style></svg>|
    iex> Expresso.Element.Diagram.D2.theme(svg)
    ~s|<svg><style>.d2-1 .fill-B4{fill:var(--graph-B4, #E3E9FD);}</style></svg>|

# `tool`

```elixir
@spec tool() :: Expresso.Element.Diagram.Tool.t()
```

The tool, for `Expresso.Element.Diagram.Tool`

---

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