flowchart

package
v0.0.0-...-93f61ce Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2024 License: GPL-3.0 Imports: 9 Imported by: 1

Documentation

Overview

Package flowchart is an object oriented approach to define mermaid flowcharts as defined at https://mermaidjs.github.io/flowchart.html and render them to mermaid code.

You use the constructor NewFlowchart to create a new Flowchart object.

chart := flowchart.NewFlowchart()

This object is used to construct a graph using various class methods, such as:

node1 := chart.AddNode("myNodeId1")
node2 := chart.AddNode("myNodeId2")
edge1 := chart.AddEdge(node1, node2)

Once the graph is completely defined, it can be "rendered" to mermaid code by stringifying the Flowchart object.

fmt.Print(chart)

Which then creates:

graph TB
myNodeId1["myNodeId1"]
myNodeId2["myNodeId2"]
myNodeId1 --> myNodeId2

The package supports defining CSS styles, that can be assigned to Nodes and Edges.

ns1 := chart.NodeStyle("myStyleId1")
ns1.StrokeWidth = 3
ns1.StrokeDash = 5
es1 := chart.EdgeStyle("myStyleId1")
es1.Stroke = "#f00"
es1.StrokeWidth = 2
node1.Style = ns1
node2.Style = chart.NodeStyle("myStyleId1")
edge1.Style = es1

There are various useful constants and further styling options, too.

es1.Stroke = flowchart.ColorRed
node1.Shape = flowchart.NShapeRoundRect
node2.Shape = flowchart.NShapeCircle
edge1.Shape = flowchart.EShapeThickLine

Let's add some text and maybe a link.

node1.AddLines("my body text")
node1.Link = "http://www.example.com"
node1.LinkText = "go to example"

What we have by now is:

graph TB
classDef myStyleId1 stroke-width:3px,stroke-dasharray:5px
myNodeId1("my body text")
class myNodeId1 myStyleId1
click myNodeId1 "http://www.example.com" "go to example"
myNodeId2(("myNodeId2"))
class myNodeId2 myStyleId1
myNodeId1 === myNodeId2
linkStyle 0 stroke-width:2px,stroke:#f00

And there is more. Just explore the package. Start at Flowchart and proceed to Subgraph.

Index

Examples

Constants

View Source
const (
	EShapeArrow       edgeShape = `-->`
	EShapeDottedArrow edgeShape = `-.->`
	EShapeThickArrow  edgeShape = `==>`
	EShapeLine        edgeShape = `---`
	EShapeDottedLine  edgeShape = `-.-`
	EShapeThickLine   edgeShape = `===`
)

Shape definitions for Edges as described at https://mermaidjs.github.io/flowchart.html#links-between-nodes. When added to a Flowchart, Edges get the EShapeArrow shape as the default.

View Source
const (
	InterpolationBasis  edgeInterpolation = `basis`
	InterpolationLinear edgeInterpolation = `linear`
)

Interpolation definitions for Edges as described at https://github.com/knsv/mermaid/issues/580#issuecomment-373929046. The default behaviour if no interpolation is given at all is InterpolationLinear.

View Source
const (
	DirectionTopDown   chartDirection = `TB`
	DirectionBottomUp  chartDirection = `BT`
	DirectionRightLeft chartDirection = `RL`
	DirectionLeftRight chartDirection = `LR`
)

Direction definitions for Flowcharts as described at https://mermaidjs.github.io/flowchart.html#graph. New Flowcharts get DirectionTopDown as the default.

View Source
const (
	ColorBlack   htmlColor = `#000`
	ColorBlue    htmlColor = `#00f`
	ColorGreen   htmlColor = `#0f0`
	ColorCyan    htmlColor = `#0ff`
	ColorRed     htmlColor = `#f00`
	ColorMagenta htmlColor = `#f0f`
	ColorYellow  htmlColor = `#ff0`
	ColorWhite   htmlColor = `#fff`
)

Color definitions for use with NodeStyles and EdgeStyles.

View Source
const (
	NShapeRect      nodeShape = `["%s"]`
	NShapeRoundRect nodeShape = `("%s")`
	NShapeCircle    nodeShape = `(("%s"))`
	NShapeRhombus   nodeShape = `{"%s"}`
	NShapeFlagLeft  nodeShape = `>"%s"]`
)

Shape definitions for Nodes as described at https://mermaidjs.github.io/flowchart.html#nodes--shapes. When added to a Flowchart or Subgraph, Nodes get the NShapeRect shape as the default.

Variables

This section is empty.

Functions

This section is empty.

Types

type Edge

type Edge struct {
	From  *Node      // Pointer to the Node where the Edge starts.
	To    *Node      // Pointer to the Node where the Edge ends.
	Shape edgeShape  // The shape of this Edge.
	Text  []string   // Optional text lines to be added along the Edge.
	Style *EdgeStyle // Optional CSS style.
	// contains filtered or unexported fields
}

Edge represents a connection between 2 Nodes. Create an instance of Edge via Flowchart's AddEdge method, do not create instances directly. Already defined IDs (indices) can be looked up via Flowchart's GetEdge method or iterated over via its ListEdges method.

Example

Working with Edges

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	n1 := f.AddNode("n1")
	n2 := f.AddNode("n2")
	// define some Edges
	e1 := f.AddEdge(n1, n2)
	e2 := f.AddEdge(n1, n2)
	// you can access and modify the Node members afterwards
	e2.From = n2
	e2.To = n1
	// define the Edge shape (EdgeStyles may override the shape)
	e1.Shape = flowchart.EShapeDottedLine
	// add text (you can also directly access e1.Text slice)
	e1.AddLines("first line", "second line")
	e1.AddLines("third line")
	// CSS styling (see EdgeStyle for more details)
	e2.Style = f.EdgeStyle("es1")
	// Previously defined Edges can be looked up
	f.GetEdge(1).Style.Stroke = flowchart.ColorCyan
	fmt.Print(f)
}
Output:

graph TB
n1["n1"]
n2["n2"]
n1 -.-|"first line<br/>second line<br/>third line"| n2
n2 --> n1
linkStyle 1 stroke:#0ff
Example (PrivateFields)

Accessing the readonly fields of an Edge

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	n1 := f.AddNode("n1")
	n2 := f.AddNode("n2")
	e1 := f.AddEdge(n1, n2)
	e2 := f.AddEdge(n1, n2)
	// the ID of an Edge is actually the order of the Edge creation
	fmt.Println(e2.ID(), e1.ID())
}
Output:

1 0

func (*Edge) AddLines

func (e *Edge) AddLines(lines ...string)

AddLines adds one or more lines of text to the Text member. This text gets rendered along the Edge, separated by <br/>'s.

func (*Edge) ID

func (e *Edge) ID() (id int)

ID provides access to the Edge's readonly field id. Since Edges don't really have IDs, this actually is the index when the Edge was added, which is used for linkStyle lines.

func (*Edge) String

func (e *Edge) String() (renderedElement string)

String renders this graph element to an edge definition line. If Style member is set an additional linkStyle line will be created.

type EdgeStyle

type EdgeStyle struct {
	Stroke        htmlColor         // Renders to stroke:#333
	StrokeWidth   uint8             // Renders to stroke-width:2px
	StrokeDash    uint8             // Renders to stroke-dasharray:5px
	More          string            // More styles, e.g.: stroke:#333,stroke-width:1px
	Interpolation edgeInterpolation // Edge curve definition
	// contains filtered or unexported fields
}

An EdgeStyle is used to add CSS to an Edge. It renders to a linkStyle line for each Edge it is associated with. Note that linkStyles will override any effect from the Edge's shape defintion. Retrieve an instance of EdgeStyle via Flowchart's EdgeStyle method, do not create instances directly.

Example

Working with EdgeStyles

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	n1 := f.AddNode("n1")
	n2 := f.AddNode("n2")
	e1 := f.AddEdge(n1, n2)
	e2 := f.AddEdge(n1, n2)
	// create one or more styles
	es1 := f.EdgeStyle("es1")
	es2 := f.EdgeStyle("es2")
	// and assign them to Edges
	e1.Style = es1
	// you can also lookup previously defined EdgeStyles
	e2.Style = f.EdgeStyle("es2")
	// there are some CSS shortcuts
	es2.Stroke = flowchart.ColorRed
	es2.StrokeWidth = 2
	es2.StrokeDash = 5
	// but you can also add additional styles, just in case
	es2.More = "font-size:20px"
	fmt.Print(f)
}
Output:

graph TB
n1["n1"]
n2["n2"]
n1 --> n2
linkStyle 0 stroke-width:1px
n1 --> n2
linkStyle 1 stroke:#f00,stroke-width:2px,stroke-dasharray:5px,font-size:20px
Example (DefaultStyle)

Defining default linkStyles and curve interpolation

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	f.DefaultEdgeStyle = f.EdgeStyle("my_style_1")
	f.DefaultEdgeStyle.Interpolation = flowchart.InterpolationBasis
	fmt.Print(f)
}
Output:

graph TB
linkStyle default interpolate basis
Example (PrivateFields)

Accessing the readonly fields of an EdgeStyle

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	es := f.EdgeStyle("this_is_my_id")
	// get a copy of the id field
	fmt.Println(es.ID())
}
Output:

this_is_my_id

func (*EdgeStyle) ID

func (es *EdgeStyle) ID() (id string)

ID provides access to the EdgeStyle's readonly field id.

func (*EdgeStyle) String

func (es *EdgeStyle) String() (renderedElement string)

String renders this graph element to a linkStyle line.

type Flowchart

type Flowchart struct {
	Direction        chartDirection // The direction used to render the graph.
	DefaultEdgeStyle *EdgeStyle     // Define a default linkStyle element.
	// contains filtered or unexported fields
}

Flowchart objects are the entrypoints to this package, the whole graph is constructed around a Flowchart object. Create an instance of Flowchart via Flowchart's constructor NewFlowchart, do not create instances directly.

Example

Working with Flowcharts

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	// define some Subgraphs
	// see Subgraph for details about what you can do with them
	sg1 := f.AddSubgraph("sg1")
	sg1.Title = "Generating Flowchart graphs"
	// define some Nodes
	// see Node and NodeStyle for details about what you can do with them
	n1 := sg1.AddNode("n1")
	n2 := sg1.AddNode("n2")
	// define some Edges
	// see Edge and EdgeStyle for details about what you can do with them
	f.AddEdge(n1, n2)
	// you can lookup already defined entities
	// but if the ID is not found nil is returned
	sgX := f.GetSubgraph("sg2")
	nX := f.GetNode("n3")
	eX := f.GetEdge(2)
	fmt.Println(sgX, nX, eX)
	// same way you get nil if you try to add an existing ID
	sgY := f.AddSubgraph("sg1")
	nY := f.AddNode("n1")
	// actually this works, since Edges don't have a real ID
	eY := f.AddEdge(n1, n2)
	fmt.Println(sgY, nY, eY)
	// you can iterate over all entities defined in the Flowcharts
	// and all of its Subgraphs
	for _, item := range f.ListSubgraphs() {
		fmt.Printf("%s\n", item.ID())
	}
	for _, item := range f.ListNodes() {
		fmt.Printf("%s\n", item.ID())
	}
	for _, item := range f.ListEdges() {
		fmt.Printf("%d\n", item.ID())
	}
}
Output:

<nil> <nil> <nil>
<nil> <nil> n1 --> n2

sg1
n1
n2
0
1

func NewFlowchart

func NewFlowchart() (newFlowchart *Flowchart)

NewFlowchart is the constructor used to create a new Flowchart object. This object is the entrypoint for any further interactions with your graph. Always use the constructor, don't create Flowchart objects directly.

func (*Flowchart) AddEdge

func (fc *Flowchart) AddEdge(from *Node, to *Node) (newEdge *Edge)

AddEdge is used to add a new Edge to the Flowchart. Since Edges have no IDs this will always succeed. The (pseudo) ID is the index that defines the order of all Edges and is used to define linkStyles. The ID can later be used to lookup the created Edge using Flowchart's GetEdge method.

func (*Flowchart) AddNode

func (fc *Flowchart) AddNode(id string) (newNode *Node)

AddNode is used to add a new Node to the Flowchart. If the provided ID already exists, no new Node is created and nil is returned. The ID can later be used to lookup the created Node using Flowchart's GetNode method. If you want to add a Node to a Subgraph, use that Subgraph's AddNode method.

func (*Flowchart) AddSubgraph

func (fc *Flowchart) AddSubgraph(id string) (newSubgraph *Subgraph)

AddSubgraph is used to add a nested Subgraph to the Flowchart. If the provided ID already exists, no new Subgraph is created and nil is returned. The ID can later be used to lookup the created Subgraph using Flowchart's GetSubgraph method. If you want to add a Subgraph to a Subgraph, use that Subgraph's AddSubgraph method.

func (*Flowchart) EdgeStyle

func (fc *Flowchart) EdgeStyle(id string) (style *EdgeStyle)

EdgeStyle is used to create new or lookup existing EdgeStyles by ID. The returned object pointers can be assigned to any number of Edges to style them using CSS. Note that EdgeStyles override the shape of an Edge, e.g. if you color an Edge that uses EShapeDottedArrow it looses its dotted nature unless you define a dotted line using the EdgeStyle.

func (*Flowchart) GetEdge

func (fc *Flowchart) GetEdge(index int) (existingEdge *Edge)

GetEdge looks up a previously defined Edge by its ID (index). If this index doesn't exist, nil is returned. Use Flowchart's AddEdge to create new Edges.

func (*Flowchart) GetNode

func (fc *Flowchart) GetNode(id string) (existingNode *Node)

GetNode looks up a previously defined Node by its ID. If this ID doesn't exist, nil is returned. Use Flowchart's or Subgraph's AddNode to create new Nodes.

func (*Flowchart) GetSubgraph

func (fc *Flowchart) GetSubgraph(id string) (existingSubgraph *Subgraph)

GetSubgraph looks up a previously defined Subgraph by its ID. If this ID doesn't exist, nil is returned. Use Flowchart's or Subgraph's AddSubgraph to create new Subgraphs.

func (*Flowchart) ListEdges

func (fc *Flowchart) ListEdges() (allEdges []*Edge)

ListEdges returns a slice of all previously defined Edges in the order they were added.

func (*Flowchart) ListNodes

func (fc *Flowchart) ListNodes() (allNodes []*Node)

ListNodes returns a slice of all previously defined Nodes. The order is not well-defined.

func (*Flowchart) ListSubgraphs

func (fc *Flowchart) ListSubgraphs() (allSubgraphs []*Subgraph)

ListSubgraphs returns a slice of all previously defined Subgraphs. The order is not well-defined.

func (*Flowchart) LiveURL

func (fc *Flowchart) LiveURL() (url string)

LiveURL renders the Flowchart and generates a view URL for https://mermaidjs.github.io/mermaid-live-editor from it.

func (*Flowchart) NodeStyle

func (fc *Flowchart) NodeStyle(id string) (style *NodeStyle)

NodeStyle is used to create new or lookup existing NodeStyles by ID. The returned object pointers can be assigned to any number of Nodes to style them using CSS.

func (*Flowchart) String

func (fc *Flowchart) String() (renderedElement string)

String recursively renders the whole graph to mermaid code lines.

func (*Flowchart) ViewInBrowser

func (fc *Flowchart) ViewInBrowser() (err error)

ViewInBrowser uses the URL generated by Flowchart's LiveURL method and opens that URL in the OS's default browser. It starts the browser command non-blocking and eventually returns any error occured.

type Node

type Node struct {
	Shape    nodeShape  // The shape of this Node.
	Text     []string   // The body text, ID if no text is added.
	Link     string     // Optional URL for a click-hook.
	LinkText string     // Optional tooltip for the link.
	Style    *NodeStyle // Optional CSS style.
	// contains filtered or unexported fields
}

Node represents a single, unique node of the Flowchart graph. Create an instance of Node via Flowchart's or Subgraph's AddNode method, do not create instances directly. Already defined IDs can be looked up via Flowchart's GetNode method or iterated over via its ListNodes method.

Example

Working with Nodes

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	// define some Nodes
	n1 := f.AddNode("n1")
	n2 := f.AddNode("n2")
	// define the Node shape
	n1.Shape = flowchart.NShapeRoundRect
	// add text (you can also directly access n1.Text slice)
	n1.AddLines("first line", "second line")
	n1.AddLines("third line")
	// you may add a link
	n2.Link = "http://www.example.com"
	n2.LinkText = "tooltip"
	// CSS styling (see NodeStyle for more details)
	n2.Style = f.NodeStyle("ns1")
	// Previously defined Nodes can be looked up
	f.GetNode("n2").Style.Fill = flowchart.ColorCyan
	fmt.Print(f)
}
Output:

graph TB
classDef ns1 fill:#0ff
n1("first line<br/>second line<br/>third line")
n2["n2"]
class n2 ns1
click n2 "http://www.example.com" "tooltip"
Example (PrivateFields)

Accessing the readonly fields of a Node

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	n1 := f.AddNode("this_is_my_id")
	// get a copy of the id field
	fmt.Println(n1.ID())
}
Output:

this_is_my_id

func (*Node) AddLines

func (n *Node) AddLines(lines ...string)

AddLines adds one or more lines of text to the Text member. This text gets rendered to the Node's body, separated by <br/>'s. If no text is added, the Node's ID is rendered to its body.

func (*Node) ID

func (n *Node) ID() (id string)

ID provides access to the Node's readonly field id.

func (*Node) String

func (n *Node) String() (renderedElement string)

String renders this graph element to a node definition line. If Style member is set an additional class line will be created. If Link member is set an additional click line will be created.

type NodeStyle

type NodeStyle struct {
	Fill        htmlColor // renders to something like fill:#f9f
	Stroke      htmlColor // renders to something like stroke:#333
	StrokeWidth uint8     // renders to something like stroke-width:2px
	StrokeDash  uint8     // renders to something like stroke-dasharray:5px
	More        string    // more styles, e.g.: stroke:#333,stroke-width:1px
	// contains filtered or unexported fields
}

A NodeStyle is used to add CSS to a Node. It renders to a classDef line. Retrieve an instance of NodeStyle via Flowchart's NodeStyle method, do not create instances directly.

Example

Working with NodeStyles

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	n1 := f.AddNode("n1")
	n2 := f.AddNode("n2")
	// create one or more styles
	ns1 := f.NodeStyle("ns1")
	ns2 := f.NodeStyle("ns2")
	// and assign them to Nodes
	n1.Style = ns1
	// you can also lookup previously defined NodeStyles
	n2.Style = f.NodeStyle("ns2")
	// there are some CSS shortcuts
	ns2.Fill = flowchart.ColorYellow
	ns2.Stroke = flowchart.ColorBlue
	ns2.StrokeWidth = 2
	ns2.StrokeDash = 5
	// but you can also add additional styles, just in case
	ns2.More = "font-size:20px"
	fmt.Print(f)
}
Output:

graph TB
classDef ns1 stroke-width:1px
classDef ns2 fill:#ff0,stroke:#00f,stroke-width:2px,stroke-dasharray:5px,font-size:20px
n1["n1"]
class n1 ns1
n2["n2"]
class n2 ns2
Example (PrivateFields)

Accessing the readonly fields of a NodeStyle

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	ns := f.NodeStyle("this_is_my_id")
	// get a copy of the id field
	fmt.Println(ns.ID())
}
Output:

this_is_my_id

func (*NodeStyle) ID

func (ns *NodeStyle) ID() (id string)

ID provides access to the NodeStyle's readonly field id.

func (*NodeStyle) String

func (ns *NodeStyle) String() (renderedElement string)

String renders this graph element to a classDef line.

type Subgraph

type Subgraph struct {
	Title string // The title of this Subgraph.
	// contains filtered or unexported fields
}

Subgraph represents a subgraph block on the Flowchart graph where nested Subgraphs and Nodes can be added. Create an instance of Subgraph via Flowchart's or Subgraph's AddSubgraph method, do not create instances directly. Already defined IDs can be looked up via Flowchart's GetSubgraph method or iterated over via its ListSubgraphs method.

Example

Working with Subgraphs

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	// add some Subgraphs
	sg1 := f.AddSubgraph("sg1")
	sg1.Title = "vpc-123"
	sg2 := sg1.AddSubgraph("sg2")
	sg2.Title = "AZ a"
	// oops we forgot to get the reference ...
	sg1.AddSubgraph("sg3")
	// ... but we can also look it up
	sg3 := f.GetSubgraph("sg3")
	sg3.Title = "AZ b"
	// add some Nodes to different Subgraphs
	f.AddEdge(sg2.AddNode("i-123"), sg2.AddNode("mydb"))
	f.AddEdge(sg3.AddNode("i-456"), f.GetNode("mydb"))
	fmt.Print(f)
}
Output:

graph TB
subgraph vpc-123
subgraph AZ a
i-123["i-123"]
mydb["mydb"]
end
subgraph AZ b
i-456["i-456"]
end
end
i-123 --> mydb
i-456 --> mydb
Example (AddDuplicate)

Adding the same ID multiple times won't work

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	f.AddNode("myid1")
	// myid1 can be used since we deal with a different type
	sg := f.AddSubgraph("myid1")
	// myid1 can't be used since for both types it was already defined
	n := sg.AddNode("myid1")
	s := sg.AddSubgraph("myid1")
	fmt.Println(n, s)
}
Output:

<nil> <nil>
Example (PrivateFields)

Accessing the readonly fields of a Subgraph

package main

import (
	"fmt"

	"github.com/Heiko-san/mermaidgen/flowchart"
)

func main() {
	f := flowchart.NewFlowchart()
	sg := f.AddSubgraph("this_is_my_id")
	sg.Title = "this is my title"
	// get a copy of the id field
	id := sg.ID()
	// get a pointer to the top level Flowchart
	fx := sg.Flowchart()
	fmt.Println(id, f == fx)
}
Output:

this_is_my_id true

func (*Subgraph) AddNode

func (sg *Subgraph) AddNode(id string) (newNode *Node)

AddNode is used to add a new Node to this Subgraph layer. If the provided ID already exists, no new Node is created and nil is returned. The ID can later be used to lookup the created Node using Flowchart's GetNode method.

func (*Subgraph) AddSubgraph

func (sg *Subgraph) AddSubgraph(id string) (newSubgraph *Subgraph)

AddSubgraph is used to add another nested Subgraph below this Subgraph layer. If the provided ID already exists, no new Subgraph is created and nil is returned. The ID can later be used to lookup the created Subgraph using Flowchart's GetSubgraph method.

func (*Subgraph) Flowchart

func (sg *Subgraph) Flowchart() (topLevel *Flowchart)

Flowchart provides access to the Subgraph's underlying Flowchart to be able to access Adder, Getter and Lister methods or to lookup Styles.

func (*Subgraph) ID

func (sg *Subgraph) ID() (id string)

ID provides access to the Subgraph's readonly field id.

func (*Subgraph) String

func (sg *Subgraph) String() (renderedElement string)

String renders this graph element to a subgraph block.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL