# Health
%%
# Path
```dataviewjs
let startFile = dv.current().file.name; // Start from the current file name
let visited = new Set(); // Track visited files to avoid infinite loops
const hierarchy = ['project', 'effort', 'area', 'marker', 'purpose']; // The upward property chain
// Function to sanitize file names for Mermaid node identifiers
function sanitizeMermaidId(name) {
return name.replace(/[^a-zA-Z0-9]/g, '_'); // Replace all non-alphanumeric characters with underscores
}
// Function to create the Mermaid node with a label and a link
function createMermaidNode(fileName) {
let cleanFileName = fileName.replace('.md', '').split('/').pop(); // Remove .md and path, keep only file name
let nodeId = sanitizeMermaidId(cleanFileName); // Sanitize the file name for the node ID
return `${nodeId}["${cleanFileName}"]`; // Display the readable file name
}
// Function to create a clickable link for the node
function createClickableLink(fileName) {
let cleanFileName = encodeURIComponent(fileName.replace('.md', '').split('/').pop()); // URL encode the file name
let nodeId = sanitizeMermaidId(cleanFileName); // Use the sanitized ID to reference the node
return `click ${nodeId} "obsidian://open?vault=tomcewhite&file=${cleanFileName}"`;
}
// Determine the starting level for the file by checking which properties exist in the file
function findStartingLevel(file) {
let currentFile = dv.page(file);
if (!currentFile) return hierarchy.length;
for (let i = 0; i < hierarchy.length; i++) {
if (currentFile[hierarchy[i]]) return i;
}
return hierarchy.length;
}
// Function to trace paths from the current file upward and build Mermaid chart connections
async function tracePaths(file, level = 0, connections = [], path = [], clickableLinks = []) {
if (visited.has(file)) return; // Prevent loops
visited.add(file); // Mark file as visited
let currentFile = dv.page(file);
if (!currentFile) return; // Page not found
path.unshift(file); // Add current file to the start of the path
if (level >= hierarchy.length) return; // Stop if we've reached the top of the hierarchy
let property = hierarchy[level]; // Get the current property (like 'project')
let linkedFiles = currentFile[property] ?? []; // Get the files linked in this property
// Handle cases where the property is a single link, not an array
if (!Array.isArray(linkedFiles)) linkedFiles = [linkedFiles];
for (let linked of linkedFiles) {
let linkedFileName = linked.path ?? linked; // If the link is an object, get its path
// Create Mermaid nodes and clickable links for the current file and linked file
let fromNode = createMermaidNode(file);
let toNode = createMermaidNode(linkedFileName);
let clickLink = createClickableLink(linkedFileName);
// Add the Mermaid connection between nodes
connections.push(`${fromNode} --> ${toNode}`);
clickableLinks.push(clickLink);
// Recursively trace paths for the linked file
await tracePaths(linkedFileName, level + 1, connections, [...path], clickableLinks); // Clone path to avoid mutation
}
}
// Main logic
let connections = [];
let clickableLinks = [];
let startLevel = findStartingLevel(startFile);
tracePaths(startFile, startLevel, connections, [], clickableLinks).then(() => {
// Remove duplicate connections for Mermaid clarity
let uniqueConnections = Array.from(new Set(connections));
let uniqueClickableLinks = Array.from(new Set(clickableLinks));
// Join the connections and links into Mermaid syntax
let mermaidChart = `graph LR\n ${uniqueConnections.join('\n ')}\n ${uniqueClickableLinks.join('\n ')}`;
// Render the Mermaid chart
dv.paragraph('```mermaid\n' + mermaidChart + '\n```');
});
```
# Reference
```dataview
LIST
FROM [[]] OR # AND !outgoing([[]]) AND -"Templates"
WHERE file.name != this.file.name
SORT file.name ASC
```
# Archive
-
%%