This post describes a method to use a dataviewJS query to scan notes in your vault to generate a clickable Mermaid navigation map.
You might find this useful if:
- you have the dataview plugin installed and enabled.
- you use the folder structure in Obsidian to organize notes with a is a sub-topic of relationship.
- You use files like README to provide instructions and background information for the content of certain important folders.
- you use frontmatter to establish a simple type classification for notes. A single type like ‘type: readme’ to identify the README files is enough to generate usable maps.
Example
The Mermaid map below shows a navigation map of an Obsidian vault that has a handful of type: readme
and type: about
files sprinkled over the vault’s folder structure. These files and their relative position in the folder structure with respect to each other form the backbone of the navigation graph (see snapshot below).
There are also some type: topic
files connected to the graph. These files denote special interest material and are connected as leaf nodes to the navigation graph.
The DataviewJS Query
Note: The bulk of the work is done by the recursive function ‘assembleDiagram’, which forages through the Obsidian vault, collecting notes and establishing connections.
%% Mermaid Content Map (dvjs) v5
Create a mermaid navigation flowchart by starting at the current folder, traversing down the folder tree to collect notes of configured types, and establish connections between them.
Configuration options:
- `mapLimit` the maximum number of connections to include in the graph so that Mermaid does not barf.
- `leafTypes` A list of types to include in the graph as leaf nodes connected to a navigation note.
- `navTypes` A list of node types that form the backbone of the navigation graph (can have child nodes)
%%
~~~dataviewjs
const
mapLimit = 100,
configFile = await app.vault.getFileByPath("Vault Configuration.md"),
config = app.metadataCache.getFileCache(configFile).frontmatter,
navTypes = new Set(["readme", "about"]),
leafTypes = new Set(["topic"]]),
vault = app.vault,
current = dv.current(),
currentFilePath = current.file.path,
currentFolder = (await vault.getFolderByPath(current.file.folder))
?? vault.getRoot(),
nodeDefs = [], // ID[file]
connections = [], // ID -> ID
assembleDiagram = (folder,predIDs) => {
if (connections.length >= mapLimit) {
return
}
const
subFolders = [],
navNodes = [],
leafNodes = [];
for (const chld of folder.children ?? []) {
if (chld.children) {
subFolders.push(chld)
} else {
const
chldType = app
.metadataCache
.getFileCache(chld)
?.frontmatter
?.type,
force = chld.path === currentFilePath;
if (navTypes.has(chldType)) {
navNodes.push(chld);
} else if (leafTypes.has(chldType) || currentFilePath === chld.path) {
leafNodes.push(chld);
}
}
}
let ids = [];
for (const navNode of navNodes) {
const navID = `N${nodeDefs.length}`;
ids.push(navID);
nodeDefs.push(navID+`["${navNode.basename}"]`);
nodeDefs.push(`class ${navID} internal-link;`);
for (const predID of predIDs) {
connections.push(`${predID} --> ${navID}`)
}
}
if (ids.length == 0) {
ids = predIDs;
}
for (const leafNode of leafNodes) {
const leafID = `N${nodeDefs.length}`;
nodeDefs.push(leafID+`["${leafNode.basename}"]`);
nodeDefs.push(`class ${leafID} internal-link;`);
for (const id of ids) { // connecct nodes
connections.push(`${id} --> ${leafID}`)
}
}
for (const subFolder of subFolders) { // recurse
assembleDiagram(subFolder,ids);
}
};
assembleDiagram(currentFolder,[]);
const mermaid = [
"~~~mermaid",
"flowchart LR",
"%%{init: {'flowchart': {'nodeSpacing': 10, 'rankSpacing': 20}}}%%",
…nodeDefs,
…connections,
"~~~"
];
dv.paragraph(mermaid.join("\n"));
~~~
Obsidian Plugins for Note Organization and Structuring
- If you are considering a more sophisticated, concept map type of approach, take a look at the Excalibrain Obsidian plugin. This plugin lets you define and visualize your own ontology.
- To augment the fly-by-the-seat-of-your-pants approach described in this post consider the Smart Connections plugin. It uses AI to establish an additional ‘is similar to’ relationship between notes.
- File organizer 2000 organizes notes and annotates photos with AI.
Note: All mentioned plugins can be found and installed with the Obsidian Community Plugins dialog.
Definition of Terms
Ontology
- Purpose: An ontology used to organize articles and notes provides a structured framework to ensure consistent categorization and discoverability of information.
- Characteristics: Such an ontology includes formal definitions of concepts and their relationships, enabling efficient data interoperability and knowledge management.
Type Readme
- Purpose: Provide instructions and background information about folder content.
- Characteristics: Contains Installation instructions, usage guidelines, troubleshooting tips, and any relevant context or background information.
Type About
- Purpose: Provide an overview and background information for a publication or document (e.g. e-book).