What it is: an Obsidian plugin to generate hierarchical graphs, with the nodes are from your Obsidian vault
How it does: convert the database from Breadcrumbs to .dot format which Graphviz can understand
Why it is made: to combine the power of Obsidian and Graphviz, which isn't addressed by other plugins at the time of it is made
For a detailed review of why other similar plugins don't cover my needs, as well as the roadmap for the future, read this post on the Obsidian forum.
A cluster of the master graph:
- Auto-wrap node labels to prevent text overflowing
- Detect different node type whether by it being the end node of a particular edge type, or by the index at the beginning of its title
- Support default node and edge styles
- Support subgraphs, and styling for each subgraph
- Support same rank for each subgraph
- Support cluster for each subgraph
- Support pairing nodes (nodes that should be a cluster by themselves)
- Generate a master graph and individual graphs of each cluster (ideal for large graph)
- Support running multiple commands (useful if you want to generate different layouts to know which one looks nicest, use unflatten to distribute nodes on the same rank of a wide graph to different lines, or overlay legend or watermark)
Since I make for myself to serve my need, it doesn't have a nice UI yet. To use it for your need, you will need to get your hand wet 😎
Things you wil need:
- Install and be familiar with Obsidian, Breadcrumbs, and Graphviz. You need to have at least one hierarchy in Breadcrumbs
- Know how to manually install a plugin by following the first 5 minutes of this video
- (Optional) Use VSCode to work on main.ts file, use
npm run dev
to watch for change in the main.ts file and automatically update the main.js file, and Hot-Reload to automatically reload the plugin when the main.js file is changed. (You can directly change the main.js file though, as how I used to do when I was like you: inexperienced and be intimidated with what I just say to you 🤡)
If you also want to have a quick start to learn JavaScript, you can start with this 5 minute video: JavaScript objects explained the visual way
The two most important objects you need to change is the nodeTypeListDeclaration
and edgeTypeListDeclaration
. Both contain the masterGraph
, which contain the default styles and graph declaration. You should not change its key, but you can change its value.
The object looks like this:
const edgeTypeListDeclaration = { //Styles used in final graph for each edge type
masterGraph: {
style: "penwidth=1"
},
edgeType1: {
},
edgeType2: {
},
pairingEdgeType: {
pairing: true,
style: "minlen=0 style=bold penwidth=5 dir=both arrowtype=odiamond"
},
edgeType3: {
},
}
It consists these keys: masterGraph
, edgeType1
, edgeType2
, edgeType3
, pairingEdgeType
. Except the masterGraph
, they are the relationship type that you have used in Breadcrumbs. Replace them with the names you use.
The values of these keys (indicating by the curly brackets after the colons at the ends of the keys) are themselves objects. These objects may or may not have these keys: style
, pairing
. The value of the style
is what you would put into edge [ ]
in Graphviz. If the value of pairing
is false or the key is missing, then the edges are printed normally. If the value is true, then in the output each edge of that type will be in a separate cluster with rank=same
, like this:
subgraph cluster_pairingEdgeType_0{
rank=same
edge [ minlen=0 style=bold penwidth=5 dir=both arrowtype=odiamond ]
"a1" -> "a1"
}
subgraph cluster_pairingEdgeType_1{
rank=same
edge [ minlen=0 style=bold penwidth=5 dir=both arrowtype=odiamond ]
"a2" -> "a3"
}
subgraph cluster_pairingEdgeType_2{
rank=same
edge [ minlen=0 style=bold penwidth=5 dir=both arrowtype=odiamond ]
"b1" -> "b2"
}
This is convenient if you are building an issue tree, and you need to emphasize that two or more solutions need to go together to solve the problem. (E.g.: "Solution a1, a2, and a3 need to be addressed at the same time to solve problem A").
The object looks like this:
const nodeTypeListDeclaration = { //Styles used in final graph for each node type
masterGraph: {
style: "shape=plaintext style=\"filled, rounded\" fontname=\"Lato\" margin=0.2 fillcolor=\"#c6cac3\"",
graphHeader:
`splines=ortho;
style=rounded
label="Graph name";
fontsize = 30
fontname="Lato";`,
},
edgeType1: {
method: "End of edge type",
},
branch_1a: {
method: "Index",
style: "shape=box, penwidth=1.5 fillcolor=\"#D1E4DD\"",
sameRank: true
},
branch_1b: {
method: "Index",
cluster: true,
subgraphSetting: "label = \"foobar\"\ncolor=\"#D1E4DD\"\nstyle=\"filled, rounded\""
},
While the edge types are totally depended on the types you declared in Breadcrumbs, you can have more options with nodes. Two current available methods are: End of edge type
, and Index
. If it's End of edge type
, then the name of the node type should be exactly the same with the name of the edge type. (In the example it's edgeType1
). If it's Index
, then these two conditions must be met:
- The name of the type should have the index at the end, after an underscore. E.g.
blabla_1b
,bloblo_i
- The index of the node should be at the beginning of its title, separate with the name by a space, and splited by dots. E.g.
1b.1 Hello internet
,i.j.k I dream a dream
If sameRank
or cluster
has value true, then the nodes of that type will be contained in a subgraph.
If a node has multiple types, then Graphviz will decide the output based on the order of the types.
To change the output folder to a different location (default is in .obsidian/plguins/dotmaker/graphs), change the value of workingDirectory
:
To change how indexes are detected, change these lines:
To change the Graphviz command (default is unflatten -l 3 graphname.dot | dot -Tpng -o graphname.png
), change the value of command
:
To investigate how Breadcrumbs organize the data, visit the console log and type in app.plugins.plugins.breadcrumbs.mainG.toJSON()
.
lyminhnhat.com (English)
quảcầu.com (Vietnamese)