I think I’ve mentioned it once (or twice) before, but one of the things which drives me when solving stuff, is personal interest. And whilst doing it the “normal” way is interesting enough, doing it using a mermaid graph, just peaked my interest. A lot.
So no matter what you feel , the first solution to this request is the mermaid variant. It works for me, and I’m hoping it’ll work for you, as well. I built the data set matching my example in the previous reply, and lo and behold, here is the script actually doing this!
Script to build the mermaid graph
function toLetters(num) {
let mod = num % 26,
pow = num / 26 | 0,
out = mod ? String.fromCharCode(64 + mod) : (--pow, 'Z')
return pow ? toLetters(pow) + out : out;
}
const result = await dv.query(`
LIST directive
WHERE type AND type = [[Directive]]
SORT file.name
`)
console.log(result)
if (result.successful) {
let linkCounter = 0
let linkSet = {}
const nodes = result.value.values
const mFront = "```mermaid\ngraph LR\n"
let mNodes = []
for (let node of nodes) {
let leftIdx, leftLink, rightIdx, rightLink
if ( !node.value?.length)
node.value = [node.value]
for (let connection of node.value) {
if ( !connection )
continue; // Bail out if it doesn't link anywhere
leftLink = node.key.path.match(/\/([^\/]+)\.md/)[1]
rightLink = connection.path.match(/\/([^\/]+)\.md/)[1]
if ( leftLink in linkSet )
leftIdx = linkSet[leftLink]
else {
linkCounter += 1
leftIdx = toLetters( linkCounter )
linkSet[leftLink] = leftIdx
}
if ( rightLink && rightLink in linkSet )
rightIdx = linkSet[rightLink]
else {
linkCounter += 1
rightIdx = toLetters( linkCounter )
linkSet[rightLink] = rightIdx
}
mNodes.push(` ${ leftIdx }[${ leftLink }] --> ${ rightIdx }[${ rightLink }]`)
}
}
let classList = []
for (let i = 1; i<= linkCounter; i++) {
classList.push( toLetters(i) )
}
const mEnd = "\nclass " + classList.join(",") + " internal-link\n```\n"
dv.span(mFront + mNodes.join("\n") + mEnd)
} else
dv.paragraph("~~~~\n" + result.error + "\n~~~~")
Explanation of script
This is going to be a cursory explanation. It’s getting late, and it’s kind of complex script, so if you don’t know javascript at all, it’s hard to explain it…
- The first function
toLetters
is a helper function, which converts number to a letter combination, in the sequence: A, B, C, … Y, Z, AA, AB, … These are later on used to name the nodes internally in the graph, and to build aclassList ... internal-link
at the end - The query is pretty basic, but it finds all files having the
type
of[[Directive]]
, and lists the correspondingdirective
field of that file. If this field is not a link, things will go astray… - A random
console.log(result)
just to check the result of the query. This line could be removed, but I forgot - Given a successful result, lets do the magic
-
Reset
linkCounter
andlinkSet
. ThelinkSet
will hold all links found in the query, and return the corresponding name when using the link as key into the set -
Fetch the actual nodes from the query into
nodes
-
Define
mFront
which is the front of the mermaid block -
Define
mNode
as an empty array to hold all of the nodes to come -
Loop through each of the files (or nodes) of the result, and do:
- Define some helper variables, and if the
node.value
(aka thedirective
being singular) is not a list, then make it into a list of one element, just to ease the logic later on - Now loop through each of the connections (aka the
directive
fields) of a given file to create the mermaid link:- First of all, if there is no
connection
(akadirective
field), then bail out, as there is nothing to link to - Pull out the unique(!) name from the file name and the connection into
leftLink
andrightLink
- For each of these, check if it exists in the
linkSet
. If it does exist use the letter from thelinkSet
, and if it doesn’t exists get a new letter, and insert the new link into thelinkSet
. Store the letter into eitherleftIdx
orrightIdx
- Push the new link connection into
mNodes
, using theA[note]
syntax for both sides. Thenote
is used for display, whilst theA
is used by mermaid to keep track of the nodes internally
- First of all, if there is no
- Define some helper variables, and if the
-
Back out after the for loop, we need to retrack how many nodes we’ve created and add them into a classList, and we also need to end the mermaid script. All this is stored into
mEnd
. Part of what makes this tick is the concept of doing theclass A,B,C,...,K internal-link
line. This enables the mermaid engine to actually turn our nodes into the links. -
Final action is simply to output the mermaid script using
dv.span()
and let the magic unfold
-
- If however the result of the query failed, print a suitable error message
Below is an attached zip file to a folder containing all the needed files to showcase this script:
f54538.zip (3.4 KB)
There is one caveat with the script as of now, and that is if your files don’t have a unique name, it’s kind of random which file you’re getting. I haven’t found a way to add aliases to mermaid links.
Update: Credit to Hassle free linking in mermaid graphs - #9 by WhiteNoise for giving me the idea to use mermaid for this