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

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

A `diagram` with a `.dot` or a `.gv` file calls `draw!/2`. The function runs
`dot -Tsvg` with the layout engine of the `layout` option, through
`Expresso.Element.Diagram.Tool`, and it returns the SVG with a name for each
node, edge and cluster.

Graphviz puts each node, edge and cluster in a `g` element with the class
`node`, `edge` or `cluster`, and the `g` element holds a `<title>` with the
name from the source. An element without an `id` in the source gets an `id`
such as `node1`, `edge2` or `clust1`, and the numbers change when the graph
changes. Therefore `name/1` replaces each such `id` with the text of the
title:

| Element | Title | Name |
| --- | --- | --- |
| A node | `web` | `web` |
| A cluster | `cluster_app` | `cluster_app` |
| An edge of a directed graph | `web->api` | `web->api` |
| An edge of a graph with no direction | `a--b` | `a--b` |
| A second edge between the same ends | `web->api` | `web->api:2` |

An `id` that the source gives stays, unless it has the form of an `id` of
Graphviz, such as `node1`.

Each edge also gets the names of its two ends, in the attributes
`data-graph-from` and `data-graph-to`. An end is the `id` of its node, so
`db [id="store"]` gives the end `store`. `Expresso.Element.Diagram` reads
the ends for the `edges` option. A port of an end, such as `web:out`, is not
a part of the name of the end.

# `draw!`

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

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

The names are the `id` of each node, edge and cluster, in the order of the
file. Graphviz measures each text with the font, and a `fontname` of the
source still applies to its element. The function raises an
`ArgumentError` when Graphviz is not present and when Graphviz fails.

# `layouts`

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

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

# `name`

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

Give each node, edge and cluster of an SVG of Graphviz the name from its title

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

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

# `theme`

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

Give a graph of Graphviz the colors of the theme

Graphviz writes black lines, black text and a white background. The function
removes the polygon of the background, and it changes `black` to
`currentColor`, so the lines take the color of the text of the theme. A
color that the source gives stays. The style sheet gives a text without a
`fill` the color of the text.

    iex> svg = ~s(<svg><g class="graph"><polygon fill="white" stroke="transparent"></polygon><path stroke="black"></path></g></svg>)
    iex> Expresso.Element.Diagram.Graphviz.theme(svg)
    ~s(<svg><g class="graph"><path stroke="currentColor"></path></g></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*
