import BaseLayout from '../layouts/BaseLayout.astro';
import Breadcrumb from '../components/Breadcrumb.astro';
import BlogNav from '../components/BlogNav.astro';
+import { getActiveProject, findCanonicalPath } from '../lib/projects';
interface Props {
entryId: string;
? new URL(params.canonical, Astro.site).toString()
: undefined;
-const crumbs = [
- { title: 'Home', url: '/' },
- { title: 'Projects', url: '/projects/' },
- { title },
-];
+const activeProject = await getActiveProject(url);
+const navPath = activeProject?.navRoot
+ ? findCanonicalPath(activeProject.navRoot, url)
+ : null;
+
+const crumbs = navPath && navPath.length > 0
+ ? [
+ { title: 'Home', url: '/' },
+ { title: 'Projects', url: '/projects/' },
+ ...navPath.slice(0, -1).map(node => ({ title: node.title, url: node.url })),
+ { title: navPath[navPath.length - 1].title },
+ ]
+ : [
+ { title: 'Home', url: '/' },
+ { title: 'Projects', url: '/projects/' },
+ { title },
+ ];
---
<BaseLayout title={title} canonical={canonical}>
return null;
}
+// Find the path from navRoot to the canonical (non-alias) node matching `url`.
+// Returns [root, ..., target], or null if not found.
+export function findCanonicalPath(
+ node: ProjectNavNode,
+ url: string,
+): ProjectNavNode[] | null {
+ if (node.isAlias) return null;
+ if (node.url === url) return [node];
+ for (const c of node.children) {
+ const sub = findCanonicalPath(c, url);
+ if (sub) return [node, ...sub];
+ }
+ return null;
+}
+
// Returns the nav tree for ALL visible projects (for the normal-case nav).
export async function getVisibleProjectNavTrees(): Promise<ProjectInfo[]> {
const pages = await getAllProjectPages();