Metadata-Version: 2.4
Name: hiearch
Version: 0.12.0
Summary: Generates multi-view diagrams from textual descriptions
Project-URL: Homepage, https://github.com/asherikov/hiearch
Project-URL: Issues, https://github.com/asherikov/hiearch/issues
Author-email: Alexander Sherikov <asherikov@yandex.com>
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.8
Requires-Dist: importlib-resources
Requires-Dist: pydot
Requires-Dist: pyyaml
Description-Content-Type: text/markdown

- [Introduction](#introduction)
- [Features](#features)
  - [Input files](#input-files)
  - [`hiearch` file format](#hiearch-file-format)
  - [Extras](#extras)
  - [Comparison](#comparison)
- [Installation](#installation)
  - [Command line options](#command-line-options)
- [Examples](#examples)
  - [Trivial](#trivial)
  - [Node relations and graphviz
    attributes](#node-relations-and-graphviz-attributes)
  - [Selection using tags](#selection-using-tags)
  - [Edge labels](#edge-labels)
  - [Edge styles](#edge-styles)
  - [Style inheritance without tags](#style-inheritance-without-tags)
  - [Automatic node selection](#automatic-node-selection)
  - [Edge promotion](#edge-promotion)
  - [View expansion](#view-expansion)
  - [View styles](#view-styles)
  - [Automatic color selection](#automatic-color-selection)
  - [Formatted node labels](#formatted-node-labels)
  - [Multiscoping](#multiscoping)
- [Predefined styles](#predefined-styles)
  - [State machine](#state-machine)
  - [Use Case](#use-case)
  - [Activity diagram](#activity-diagram)
  - [Python diagrams](#python-diagrams)

Introduction
============

`hiearch` is a CLI utility that generates multiple diagrams (views) from a
shared description in `yaml` format. Descriptions provide node hierarchies that
are automatically expanded, collapsed, or hidden, depending on configuration of
a particular view. In this sense the utility is more similar to design tools
such as <https://structurizr.com> and
<https://github.com/soulspace-org/overarch> than to simple generators such as
`graphviz`.

`hiearch` is meant to be more abstract than design frameworks such as UML, C4,
SysML, etc. I believe that the most important aspects of the system are its
decomposition into components and connections between them, `hiearch` provides
just that, so that you can focus on documenting your system rather than fitting
it into a specific framework.

Currently, `hiearch` uses `graphviz` for diagram rendering, other backends may
be added in the future.

Features
========

Input files
-----------

- `hiearch` accepts two kinds of input files: `yaml` files following `hiearch`
  format and files in `graphviz` format with `dot` or `gv` extension.

- The order of inputs is not important – their content gets composed into a
  single description, which, in turn, gets decomposed into views.

- `graphviz` files are internally converted to `hiearch` representation, which
  allows application of `hiearch` views to `graphviz` files generated by other
  tools.

`hiearch` file format
---------------------

- Description files have flat structure without nesting or inclusion and contain
  lists of the following objects: nodes, edges, and views. Hierarchical
  relations between nodes are specified using node parameters.

- The format is stricter than `graphviz`: for example, all nodes must be defined
  explicitly and cannot be deduced from edge definitions.

- `hiearch` allows nodes to have multiple parent nodes, which is referenced here
  as ‘multiscoping’. Different parents are meant to be visualized in different
  views, for example, to outline system from logical or hardware point of view.
  However, it is possible to visualize all parents in the same diagram as well.

- `hiearch` supports label templates, which facilitates automatic generation of
  URLs, tables, icon inclusions, etc.

Extras
------

- Several predefined styles distributed with the utility, e.g., for generation
  of state machine graphs, see examples in this file.

- \[Beta\] Package includes a coding agent skill, which can be installed to a
  given directory by `hiearch`.

Comparison
----------

### `graphviz`

- Unlike `graphviz` `hiearch` has no notion of a cluster/subgraph, which is just
  an expanded representation of a particular node.

- View is not the same thing as `graphviz` layer
  <https://graphviz.org/docs/attrs/layer/>: `graphviz` places all nodes on each
  layer and simply makes some of them invisible, which results in awkward
  placement.

Installation
============

- `pipx install hiearch`

Command line options
--------------------

    usage: hiearch [-h] [-o OUTPUT] [-f FORMAT] [-t TEMP_DIR] [-r RESOURCE_DIRS]
                   [-i [INSTALL_SKILL]] [-l] [-s STYLES]
                   <filename> [<filename> ...]

    Generates diagrams

    positional arguments:
      <filename>            Input files

    optional arguments:
      -h, --help            show this help message and exit
      -o OUTPUT, --output OUTPUT
                            Output directory [./]
      -f FORMAT, --format FORMAT
                            Output format [SVG]
      -t TEMP_DIR, --temp-dir TEMP_DIR
                            Temporary files output directory (defaults to output directory)
      -r RESOURCE_DIRS, --resource-dirs RESOURCE_DIRS
                            Directories to search for graphical resources (can be specified multiple times)
      -i [INSTALL_SKILL], --install-skill [INSTALL_SKILL]
                            Install hiearch skill to coding agent skill directory
      -l, --list-styles     List installed styles
      -s STYLES, --styles STYLES
                            Style names or patterns to include (can be specified
                            multiple times, supports wildcards)

Examples
========

Trivial
-------

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]  # [label, unique id]
edges:
    - link: [test1, test1]   # [from node id, to node id]
views:
    - id: view1              # unique id / output filename
      nodes: [test1]         # nodes to include
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/07_trivial/view1.svg" alt="view1" />
<br /> view1
</td>

</tr>

</table>

Node relations and graphviz attributes
--------------------------------------

<table>

<tr>

<td rowspan="3">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]
      graphviz:  # set graphviz attributes directly
        fillcolor: grey
        style: filled
    - id: ["Test 2", test2]
      graphviz:
        fillcolor: aqua
        style: filled
    - id: ["Test 3", test3]
      scope: test1  # test3 is contained in test1
      style: test2  # test3 inherits all test2 attributes
edges:
    - link: [test3, test3]
views:
    - id: view1
      nodes: [test2, test3]
    - id: view2  # test1 is shown as subgraph
      nodes: [test1, test3]
    - id: view3
      nodes: [test1, test2]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/08_node_realations/view1.svg" alt="view1" />
<br /> view1
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/08_node_realations/view2.svg" alt="view2" />
<br /> view2
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/08_node_realations/view3.svg" alt="view3" />
<br /> view3
</td>

</tr>

</table>

Selection using tags
--------------------

### Nodes

<table>

<tr>

<td rowspan="2">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]
      # tags: ["default"] if not specified
    - id: ["Test 2", test2]
      tags: ["test2_tag"]
edges:
    - link: [test1, test1]
    - link: [test2, test2]
views:
    - id: view1
      tags: ["test2_tag"]
    - id: view2
      tags: ["default"]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/09_tags/view1.svg" alt="view1" />
<br /> view1
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/09_tags/view2.svg" alt="view2" />
<br /> view2
</td>

</tr>

</table>

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]
# if no views are specified explicitly, a default one is
# added with 'tags: ["default"]'
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/10_minimal/default.svg" alt="default" />
<br /> default
</td>

</tr>

</table>

### Edges

<table>

<tr>

<td rowspan="3">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["A", a]
    - id: ["B", b]
    - id: ["C", c]
    - id: ["D", d]
edges:
    - link: [a, b]
      # edges can be tagged too
      tags: ["tag1"]
    - link: [a, c]
      tags: ["tag2"]
    - link: [b, c]
    - link: [a, d]
      tags: ["tag1", "tag2"]
views:
    - id: tag1_view
      edge_tags: ["tag1"]
      neighbours: direct
    - id: default_edges_view
      neighbours: direct
    - id: all_edges_view
      edge_tags: ["tag1", "tag2", "default"]
      neighbours: direct
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/50_edge_tags/tag1_view.svg" alt="tag1_view" />
<br /> tag1_view
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/50_edge_tags/default_edges_view.svg" alt="default_edges_view" />
<br /> default_edges_view
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/50_edge_tags/all_edges_view.svg" alt="all_edges_view" />
<br /> all_edges_view
</td>

</tr>

</table>

Nodes and edges are automatically tagged based on their structural
relationships.

<table>

<tr>

<td rowspan="3">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["A", a]
      # gets hh:scope:g
      scope: g
    - id: ["B", b]
      # gets hh:scope:a and hh:scope:g
      scope: a
    - id: ["C", c]
      # gets hh:style:i and hh:style:h
      style: i
    - id: ["D", d]
      # combined: hh:scope:g
      # and hh:style:i + hh:style:h
      scope: g
      style: i
    - id: ["E", e]
      # multiscoping:
      # hh:scope:a + hh:scope:g
      scope: [a, g]
    - id: ["F", f]
      # inherits style but no tags
      style_notag: i
    - id: ["G", g]
    - id: ["H", h]
      graphviz:
          shape: box
    - id: ["I", i]
      style: h
      graphviz:
          style: filled
          fillcolor: lightblue
edges:
    - link: [a, b]
    - link: [a, c, j]
      graphviz:
          color: red
    - link: [b, c]
      style: j
views:
    - id: scope_parent
      # A, B, D, E
      tags: ["hh:scope:g"]
    - id: style_derived
      # C and D
      tags: ["hh:style:i"]
    - id: combined
      # D only (scope + style)
      # with styled edges
      tags: ["hh:scope:g", "hh:style:h"]
      edge_tags: ["hh:style:j"]
      neighbours: direct
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/53_autotag/scope_parent.svg" alt="scope_parent" />
<br /> scope_parent
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/53_autotag/style_derived.svg" alt="style_derived" />
<br /> style_derived
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/53_autotag/combined.svg" alt="combined" />
<br /> combined
</td>

</tr>

</table>

Edge labels
-----------

<table>

<tr>

<td rowspan="2">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]
    - id: ["Test 2", test2]
edges:
    - link: [test1, test1]
      label: 'test1_edge'
    - link: [test2, test2]
      label: ['tail', 'middle', 'head']
views:
    - id: view1
      nodes: [test1]
    - id: view2
      nodes: [test2]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/13_edge_labels/view1.svg" alt="view1" />
<br /> view1
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/13_edge_labels/view2.svg" alt="view2" />
<br /> view2
</td>

</tr>

</table>

Edge styles
-----------

<table>

<tr>

<td rowspan="3">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]
    - id: ["Test 2", test2]
    - id: ["Test 3", test3]
    # helper node to define "invisible" edges used purely
    # as style templates
    - id: ["StyleNode", stylenode]
      # invisible unless this tag is requested in a view
      # note that tags are inherited too
      tags: ["mystyle"]
edges:
    # "pure" style link
    - link: [stylenode, stylenode, stylelink]
      graphviz:
        color: red
    - link: [test1, test1]
      label: 'test1'
      style: stylelink
    # optional third link parameter introduces an explicit
    # id, which must be unique
    - link: [test2, test2, edge2]
      # style can be referenced by link attribute
      style: [test1, test1]
      graphviz:
        dir: both
    - link: [test3, test3]
      # style can also be an explicit id
      style: edge2
      graphviz:
        color: blue
views:
    - id: view1
      nodes: [test1]
    - id: view2
      nodes: [test2]
    - id: view3
      nodes: [test3]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/14_edge_style/view1.svg" alt="view1" />
<br /> view1
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/14_edge_style/view2.svg" alt="view2" />
<br /> view2
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/14_edge_style/view3.svg" alt="view3" />
<br /> view3
</td>

</tr>

</table>

Style inheritance without tags
------------------------------

### Nodes

<table>

<tr>

<td rowspan="2">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Node A", node_a]
      tags: ["custom_tag"]
      graphviz:
        fillcolor: grey
        style: filled
    - id: ["Node B", node_b]
      style: node_a
    - id: ["Node C", node_c]
      # no need to explicitly override inherited tags,
      # which is useful for dealing with pure style nodes.
      style_notag: node_a
views:
    - id: view_default          # includes node C
    - id: view_custom           # includes nodes A and B
      tags: ["custom_tag"]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/22_style_notag_tag_inheritance/view_default.svg" alt="view_default" />
<br /> view_default
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/22_style_notag_tag_inheritance/view_custom.svg" alt="view_custom" />
<br /> view_custom
</td>

</tr>

</table>

### Edges

<table>

<tr>

<td rowspan="3">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["A", a]
    - id: ["B", b]
    - id: ["C", c]
    - id: ["D", d]
edges:
    - link: [a, b, style_edge]
      tags: ["tag1"]
      graphviz:
        color: red
    - link: [b, c]
      # edge style can also be inherited without tags
      style_notag: style_edge
    - link: [c, d]
      style: style_edge
    - link: [a, d]
      style_notag: style_edge
      tags: ["tag2"]
views:
    - id: view_default
      # no edge_tags -- include edges with default tag only
    - id: view_all
      edge_tags: ["tag1", "tag2", "default"]
    - id: view_tag1
      edge_tags: ["tag1"]
      neighbours: direct
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/52_edge_style_notag/view_default.svg" alt="view_default" />
<br /> view_default
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/52_edge_style_notag/view_all.svg" alt="view_all" />
<br /> view_all
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/52_edge_style_notag/view_tag1.svg" alt="view_tag1" />
<br /> view_tag1
</td>

</tr>

</table>

Automatic node selection
------------------------

There are several types on automated node selection:

- `explicit` – only explicitly specified nodes are selected;
- `direct` – explicitly specified and their direct connections;
- `direct_with_parents` – similar to `direct`, but also includes all parent
  scopes of directly connected nodes;
- `parent` – similar to `direct`, but instead of directly connected nodes their
  top-most parents (scopes) are selected;
- `recursive_in`, `recursive_out`, `recursive_all` – recursively expand
  connections of explicitly selected nodes.

<table>

<tr>

<td rowspan="7">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Node A", node_a]
    - id: ["Node B", node_b]
    - id: ["Node C", node_c]
      scope: [node_b]
    - id: ["Node D", node_d]
edges:
    - link: [node_a, node_c]
    - link: [node_c, node_d]
views:
    - id: explicit
      nodes: [node_a]
      # only node_a
      #neighbours: explicit
    - id: direct
      nodes: [node_a]
      # node_a and node_c (directly connected)
      neighbours: direct
    - id: parent
      nodes: [node_a]
      # node_a and node_b (parent of connected node C)
      neighbours: parent
    - id: recursive_out
      nodes: [node_a]
      # node_a, node_c, node_d (all connected)
      # + node_b -- parent of c
      neighbours: recursive_out
    - id: recursive_in
      nodes: [node_d]
      # node_a, node_c, node_d (all connected)
      # + node_b -- parent of c
      neighbours: recursive_in
    - id: recursive_in_c
      nodes: [node_c]
      # node_a, node_c
      neighbours: recursive_in
    - id: direct_with_parents
      nodes: [node_a]
      # node_a, node_c (direct) + node_b (parent)
      neighbours: direct_with_parents
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/explicit.svg" alt="explicit" />
<br /> explicit
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/direct.svg" alt="direct" />
<br /> direct
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/parent.svg" alt="parent" />
<br /> parent
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/recursive_in.svg" alt="recursive_in" />
<br /> recursive_in
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/recursive_out.svg" alt="recursive_out" />
<br /> recursive_out
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/recursive_in_c.svg" alt="recursive_out" />
<br /> recursive_in_c
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/11_neighbors/direct_with_parents.svg" alt="direct_with_parents" />
<br /> direct_with_parents
</td>

</tr>

</table>

Edge promotion
--------------

When a view shows scope nodes (parent nodes) but not their children, edges
between those (grand)children are automatically promoted to the scope level.
When multiple edges are promoted between two scopes, they merge into a single
edge labeled with the count, e.g., `(2)`. Promotion is performed separately for
“in” and “out” edges.

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: ["A", a]
    - id: ["A1", a1]
      scope: a
    - id: ["A2", a2]
      scope: a
    - id: ["B", b]
    - id: ["B1", b1]
      scope: b
    - id: ["B2", b2]
      scope: b
edges:
    - link: [a1, a2]
    - link: [b1, a1]
    - link: [b2, a1]
    - link: [a2, b2]
views:
    - id: view1
      # not connected directly, edges between childred
      # get promoted
      nodes: ["a", "b"]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/45_scope_edges_mixed/view1.svg" alt="view1" />
<br /> edge promotion
</td>

</tr>

</table>

View expansion
--------------

<table>

<tr>

<td rowspan="3">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Node A", node_a]
      tags: [group1]
    - id: ["Node B", node_b]
      tags: [group1]
    - id: ["Node C", node_c]
      scope: [node_b]
    - id: ["Node D", node_d]
    - id: ["Node E", node_e]
    - id: ["Node F", node_f]
    - id: ["Node H", node_h]
edges:
    - link: [node_a, node_c]
    - link: [node_c, node_d]
    - link: [node_d, node_e]
    - link: [node_e, node_f]
    - link: [node_f, node_h]
    - link: [node_a, node_b]
views:
    - id: tag_based_recursive_out
      tags: [group1]
      # create additional views based on the current one:
      #  - for each node selected in the current view
      #    add a view, where this node is present as well
      #    as its relations specified in expand array;
      #  - note that only nodes present in the original
      #    view are shown in new views;
      #  - original view is preserved;
      #  - expanded views inherit properties of the
      #    original.
      expand: [recursive_out]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/23_expand/tag_based_recursive_out.svg" alt="tag_based_recursive_out" />
<br /> original
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/23_expand/tag_based_recursive_out_node_a_recursive_out.svg" alt="tag_based_recursive_out_node_a_recursive_out" />
<br /> node A expansion
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/23_expand/tag_based_recursive_out_node_b_recursive_out.svg" alt="tag_based_recursive_out_node_b_recursive_out" />
<br /> node B expansion
</td>

</tr>

</table>

View styles
-----------

<table>

<tr>

<td rowspan="2">

<pre>
-----------------------------------------------------------
nodes:
    - id: ["Test 1", test1]
edges:
    - link: [test1, test1]
views:
    - id: style
      nodes: []  # explicitly empty view is not rendered
      # defaults, overriden by node/edge attributes
      graphviz:
          graph:
              style: filled
              bgcolor: coral
          node:
              fontsize: "24"
              fontname: times
          edge:
              dir: both
    - id: styled
      nodes: [test1]
      style: style  # inherit style from another view
    - id: plain
      nodes: [test1]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/12_view_style/styled.svg" alt="styled" />
<br /> styled
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/12_view_style/plain.svg" alt="plain" />
<br /> plain
</td>

</tr>

</table>

Automatic color selection
-------------------------

The keyword `auto` can be used as a color value for any graphviz color attribute
(e.g., `color`, `fillcolor`, `fontcolor`, `edgecolor`, `linecolor`). When
specified, a deterministic random color is generated based on a hash of the node
or edge attributes.

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: [A, node1]
      graphviz:
        shape: rectangle
        style: filled
        fillcolor: auto
    - id: [B, node2]
      graphviz:
        shape: rectangle
        style: filled
        fillcolor: auto
    - id: [C, node3]
      graphviz:
        shape: ellipse
        style: filled
        fillcolor: auto
        color: auto
        fontcolor: auto
edges:
    - link: [node1, node2]
      graphviz:
        color: auto
        style: solid
    - link: [node2, node3]
      graphviz:
        color: auto
        style: solid
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/33_auto_color/default.svg" alt="default" />
<br /> default
</td>

</tr>

</table>

Formatted node labels
---------------------

    nodes:
        - id: ["Test 1", test1]
          # https://www.svgrepo.com/svg/479843/duck-toy-illustration-3
          # https://www.svgrepo.com/svg/479405/casa-pictogram-5
          graphviz:
            node_label_format: '<<table><tr><td><img src="https://raw.githubusercontent.com/asherikov/hiearch/master/icon_{id}.svg"/></td><td>{label}</td></tr></table>>'
            scope_label_format: '<<table><tr><td><img src="https://raw.githubusercontent.com/asherikov/hiearch/master/icon_{id}.svg"/></td><td>Scope: {label}</td></tr></table>>'
        - id: ["Test 2", test2]
          scope: test1
        - id: ["Test 3", test3]
          tags: []
          substitutions:
            suffix: '!'
          graphviz:
            node_label_format: '<<table><tr><td><img src="https://raw.githubusercontent.com/asherikov/hiearch/master/icon_{style}.svg"/></td><td>{label}{suffix}</td></tr></table>>'
        - id: ["Test 4", test4]
          style: test3
    views:
        - id: view1
          nodes: [test1]
        - id: view2
          nodes: [test1, test2]
        - id: view3
          nodes: [test4]

Note that SVG with other embedded SVG is not always rendered properly, and
embedded pictures may get lost during conversion to other formats. The PNG files
below were generated with
`rsvg-convert view1.svg --format=png --output=view1.png`, exporting directly to
PNG using graphviz won’t work. Also, the included images must be present in the
output directory.

<table>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/15_formatted_labels/view1.png" alt="view1" />
<br /> view1
</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/15_formatted_labels/view2.png" alt="view2" />
<br /> view2
</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/15_formatted_labels/view3.png" alt="view3" />
<br /> view3
</td>

</tr>

</table>

Multiscoping
------------

<table>

<tr>

<td rowspan="2">

<pre>
-----------------------------------------------------------
nodes:
    # root nodes
    - id: ["Test 1", test1]
    - id: ["Test 2", test2]
    # child nodes
    - id: ["Test 3", test3]
      # a child of both root nodes: if both scopes are
      # present in a view they are automatically ranked
      # to form a hierarchy
      scope: [test1, test2]
    # Both root nodes also include non-shared nodes.
    # Since is not possible to visualize overlaping
    # subgraphs with graphviz, one of them is going to be
    # divided into two parts.
    - id: ["Test 4", test4]
      scope: test2
    - id: ["Test 5", test5]
      scope: [test1]
views:
    - id: default
      tags: ["default"]
    - id: autoranking
      nodes: [test1, test2, test3]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/06_multiscope/autoranking.svg" alt="autoranking" />
<br /> autoranking
</td>

</tr>

<tr>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/06_multiscope/default.svg" alt="default" />
<br /> default
</td>

</tr>

</table>

Predefined styles
=================

- By default, only one variant of each base style is loaded. Styles with names
  containing a dash (`-`) are treated as variants of a base style (e.g.,
  `hiearch_diagrams-0_vertical` and `hiearch_diagrams-1_horizontal` are variants
  of base style `hiearch_diagrams`). The first variant in sorted order is
  selected by default.
- The `-s`/`--styles` option allows selecting specific styles or variants by
  name or pattern. Multiple styles can be specified using multiple `-s` options
  or comma-separated lists. Wildcards are supported:
  `hiearch -s "diagrams_aws*" input.yaml` or
  `hiearch -s state_machine -s use_case input.yaml`.
- Selecting multiple variants of the same base style simultaneously results in
  an error (e.g.,
  `hiearch -s "hiearch_diagrams-0_vertical,hiearch_diagrams-1_horizontal"` will
  fail).
- The `-l`/`--list-styles` option lists all available style names.
- Generally it is necessary to override tags inherited from style nodes.

State machine
-------------

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: ["", choice1]
      style_notag: hh_state_machine_choice
    - id: [state1, state1]
      style_notag: hh_state_machine_regular
    - id: [state2, state2]
      style_notag: hh_state_machine_regular
    - id: ["", fork1]
      style_notag: hh_state_machine_junction
    - id: ["", join2]
      style_notag: hh_state_machine_junction
    - id: ["", start]
      style_notag: hh_state_machine_initial
    - id: ["", end1]
      style_notag: hh_state_machine_final
    - id: ["", end2]
      style_notag: hh_state_machine_final
edges:
    - link: [start, choice1]
      style_notag: hh_state_machine_edge
      label: "from start\nto choice"
    - link: [choice1, fork1]
      style_notag: hh_state_machine_edge
      label: "from choice\nto fork"
    - link: [choice1, join2]
      style_notag: hh_state_machine_edge
      label: "from choice\nto join"
    - link: [choice1, end2]
      style_notag: hh_state_machine_edge
      label: "from choice\nto end"
    - link: [fork1, state1]
      style_notag: hh_state_machine_edge
      label: "from fork\nto state"
    - link: [fork1, state2]
      style_notag: hh_state_machine_edge
      label: "from fork\nto state"
    - link: [state2, join2]
      style_notag: hh_state_machine_edge
      label: "from state\nto join"
    - link: [state1, end1]
      style_notag: hh_state_machine_edge
      label: "from state\nto end"
    - link: [join2, end1]
      style_notag: hh_state_machine_edge
      label: "from join\nto end"
views:
    - id: state_machine_example
      style: hh_state_machine_view
      # override empty selection inherited from style view
      tags: ["default"]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/16_state_machine/state_machine_example.svg" alt="state_machine_example" />
<br /> state machine example
</td>

</tr>

</table>

Use Case
--------

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: ["User", user]
      style_notag: hh_use_case_actor
    - id: ["Admin", admin]
      style_notag: hh_use_case_actor
    - id: ["Login System", system_boundary]
      style_notag: hh_use_case_system_boundary
    - id: ["Login", login]
      style_notag: hh_use_case_case
      scope: system_boundary
    - id: ["Logout", logout]
      style_notag: hh_use_case_case
      scope: system_boundary
    - id: ["Reset Password", reset_password]
      style_notag: hh_use_case_case
      scope: system_boundary
    - id: ["Register", register]
      style_notag: hh_use_case_case
      scope: system_boundary
    - id: ["Validate Credentials", validate_credentials]
      style_notag: hh_use_case_case
      scope: system_boundary
    - id: ["2FA Authentication", two_factor_auth]
      style_notag: hh_use_case_case
      scope: system_boundary
edges:
    - link: [user, login]
      style_notag: hh_use_case_association
    - link: [user, logout]
      style_notag: hh_use_case_association
    - link: [user, reset_password]
      style_notag: hh_use_case_association
    - link: [user, register]
      style_notag: hh_use_case_association
    - link: [admin, reset_password]
      style_notag: hh_use_case_association
    - link: [login, validate_credentials]
      style_notag: hh_use_case_include
    - link: [two_factor_auth, login]
      style_notag: hh_use_case_extend
views:
    - id: use_case_example
      style: hh_use_case_view
      # override empty selection inherited from style view
      tags: ["default"]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/17_use_case/use_case_example.svg" alt="use_case_example" />
<br /> use case example
</td>

</tr>

</table>

Activity diagram
----------------

Activity diagrams visualize the flow of activities, actions, and operations
within a system. They show the sequence of steps, decision points, and parallel
flows.

<table>

<tr>

<td>

<pre>
-----------------------------------------------------------
nodes:
    - id: ["", start]
      style_notag: hh_activity_initial
    - id: ["Author", author_lane]
      style_notag: hh_activity_swimlane
    - id: ["Create Document", create_doc]
      style_notag: hh_activity_action
      scope: author_lane
    - id: ["Update Document", update_doc]
      style_notag: hh_activity_action
      scope: author_lane
    - id: ["Reviewer", reviewer_lane]
      style_notag: hh_activity_swimlane
    - id: ["Review Document", review_doc]
      style_notag: hh_activity_action
      scope: reviewer_lane
    - id: ["Approver", approver_lane]
      style_notag: hh_activity_swimlane
    - id: ["", approve_decision]
      style_notag: hh_activity_decision
      scope: approver_lane
    - id: ["Owner", owner_lane]
      style_notag: hh_activity_swimlane
    - id: ["Archive Document", archive_doc]
      style_notag: hh_activity_action
      scope: owner_lane
    - id: ["", review_deadline]
      style_notag: hh_activity_time_event
    - id: ["", end1]
      style_notag: hh_activity_final
    - id: ["Review must complete within 48h", deadline_note]
      style_notag: hh_activity_note
edges:
    - link: [start, create_doc]
      style_notag: hh_activity_edge
    - link: [create_doc, review_doc]
      style_notag: hh_activity_edge
      label: "submit"
    - link: [review_doc, approve_decision]
      style_notag: hh_activity_edge
      label: "reviewed"
    - link: [approve_decision, update_doc, approve_reject]
      style_notag: hh_activity_edge
      label: "rejected"
    - link: [update_doc, review_doc]
      style_notag: hh_activity_edge
      label: "resubmit"
    - link: [approve_decision, archive_doc, approve_accept]
      style_notag: hh_activity_edge
      label: "approved"
    - link: [archive_doc, end1]
      style_notag: hh_activity_edge
    - link: [review_deadline, review_doc, deadline_trigger]
      style_notag: hh_activity_edge
      label: "T=48h"
    - link: [deadline_note, review_doc, note_link]
views:
    - id: document_management
      style: hh_activity_view
      tags: ["default"]
</pre>

</td>

<td align="center">

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/39_activity_diagram/document_management.svg" alt="document_management" />
<br /> activity diagram example
</td>

</tr>

</table>

Python diagrams
---------------

The `diagrams` style provides access to icons from the
<https://github.com/mingrammer/diagrams> package
(<http://diagrams.mingrammer.com>), allowing you to create cloud system
architecture diagrams. The `diagrams` package is not a hiearch dependency and
must be installed separately to access the icon files. The icons are located in
the package’s resources directory (typically
`~/.local/lib/python3.X/site-packages/resources` or similar), which can be
passed to `hiearch` like this

``` bash
hiearch -r /path/to/diagrams/resources input.yaml
```

The `hiearch_diagrams` style comes in two variants: -
`hiearch_diagrams-0_vertical` (default) - icon above text -
`hiearch_diagrams-1_horizontal` - icon beside text

To use the horizontal variant:

``` bash
hiearch -s hiearch_diagrams-1_horizontal input.yaml
```

### Example

<pre>
nodes:
    - id: ["Mobile User", mobile_user]
      style_notag: hh_diagrams_generic_device_mobile
    - id: ["Tablet User", tablet_user]
      style_notag: hh_diagrams_generic_device_tablet
    - id: ["CloudFront\nCDN", cloudfront]
      style_notag: hh_diagrams_aws_network_cloudfront
      scope: aws_frontend
    - id: ["Application\nLoad Balancer", elb]
      style_notag: hh_diagrams_aws_network_elb_application_load_balancer
      scope: aws_frontend
    - id: ["EC2 Instances", ec2]
      style_notag: hh_diagrams_aws_compute_ec2
      scope: aws_compute
    - id: ["Lambda\nFunctions", lambda_func]
      style_notag: hh_diagrams_aws_compute_lambda
      scope: aws_compute
    - id: ["Elastic\nContainer", ecs]
      style_notag: hh_diagrams_aws_compute_elastic_container_service
      scope: aws_compute
    - id: ["Prometheus", prometheus]
      style_notag: hh_diagrams_onprem_monitoring_prometheus
    - id: ["Grafana", grafana]
      style_notag: hh_diagrams_onprem_monitoring_grafana
    - id: ["AWS\nFrontend", aws_frontend]
      style_notag: hh_diagrams_scope
    - id: ["AWS\nCompute", aws_compute]
      style_notag: hh_diagrams_scope
edges:
    - link: [mobile_user, cloudfront]
      style_notag: hh_diagrams_link
    - link: [tablet_user, cloudfront]
      style_notag: hh_diagrams_link
    - link: [cloudfront, elb]
      style_notag: hh_diagrams_link
    - link: [elb, ec2]
      style_notag: hh_diagrams_link
    - link: [elb, lambda_func]
      style_notag: hh_diagrams_link
    - link: [elb, ecs]
      style_notag: hh_diagrams_link
    - link: [prometheus, ec2]
      style_notag: hh_diagrams_link
    - link: [prometheus, lambda_func]
      style_notag: hh_diagrams_link
    - link: [grafana, prometheus]
      style_notag: hh_diagrams_link
views:
    - id: cloud_architecture
      style: hh_diagrams_view
      tags: ["default"]
</pre>

<img src="https://raw.githubusercontent.com/asherikov/hiearch/master/test/34_diagrams_style/cloud_architecture.png" alt="cloud_architecture" />
