rich_diagram/lib.rs
1//! Graph diagrams for the `rich` Rust port: a graph model, a layered layout,
2//! and a renderable that draws it with box-drawing characters.
3//!
4//! Not a port of anything upstream: an rs-rich addition. It depends on core
5//! `rich` only, so any crate (Mermaid flowcharts among them) can draw graphs
6//! without pulling in `rs-rich-ext`.
7//!
8//! - [`Graph`]: nodes with labels and [`Shape`]s, edges with labels,
9//! [`Stroke`]s and [`Head`]s, flowing in a [`Direction`]. Build one in code
10//! with its chaining builder, or from parts as a parser does.
11//! - [`draw`]: the layered (Sugiyama-style) layout, giving a [`Drawing`]:
12//! plain lines of text. See [`layout`] for how it works.
13//! - [`Diagram`]: the drawing as a renderable that measures itself and crops
14//! to the width it is given, in Unicode box drawing or ASCII.
15//!
16//! ```
17//! use rich::Console;
18//! use rich_diagram::{Diagram, Direction, Graph, Shape};
19//!
20//! let graph = Graph::new(Direction::TopDown)
21//! .node("start", "Start").shape(Shape::Round)
22//! .node("ok", "Tests pass?").shape(Shape::Rhombus)
23//! .edge("start", "ok")
24//! .edge("ok", "ship").label("yes");
25//! let console = Console::builder().width(40).color_system(None).build();
26//! let out = console.render_export(&Diagram::new(graph));
27//! assert!(out.contains("Tests pass?"), "{out}");
28//! assert!(out.lines().all(|line| rich::cells::cell_len(line) <= 40));
29//! ```
30//!
31//! Sources:
32//!
33//! - [`dot`]: DOT (Graphviz) sources, parsed natively ([`dot::parse`]) and
34//! drawn by the [`Dot`] renderable. With the `plugin` feature,
35//! [`plugin::DotPlugin`] registers a `dot` fence renderer and source
36//! renderer; with the `graphviz` feature, [`graphviz::render_svg`] runs
37//! Graphviz's own `dot` for SVG.
38//! - [`er`]: entity-relationship diagrams. An [`ErModel`] of entities,
39//! columns and keys, relationships and groups, built in code (a schema
40//! reader fills it), drawn by the [`ErDiagram`] renderable.
41//!
42//! Groupings: a [`Cluster`] is drawn as a dashed frame around its nodes, its
43//! label in the top border, nested clusters inside it; a same-rank group
44//! ([`Graph::same_rank`]) puts its nodes side by side where the layered
45//! layout can. What a drawing could not show is in [`Drawing::notes`].
46
47// A builder method that returns `Self` is `#[must_use]`: dropping its
48// result drops the value (CONTRIBUTING.md, "API conventions").
49#![warn(clippy::return_self_not_must_use)]
50
51mod cluster;
52pub mod diagram;
53pub mod dot;
54pub mod er;
55pub mod graph;
56#[cfg(feature = "graphviz")]
57pub mod graphviz;
58pub mod layout;
59#[cfg(feature = "plugin")]
60pub mod plugin;
61
62pub use diagram::Diagram;
63pub use dot::{Dot, DotError, DotGraph};
64pub use er::{ErDiagram, ErModel};
65pub use graph::{
66 Cluster, Direction, Edge, Graph, Head, MAX_EDGE_LENGTH, MAX_EDGES, MAX_NODES, MAX_SOURCE, Node,
67 Shape, Stroke,
68};
69pub use layout::{DrawError, Drawing, draw};