From ac565da1392184df0d38619fd341c190b2d683b2 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Sun, 14 Jun 2026 11:59:59 +0000 Subject: [PATCH] Projects: Routing-Pages, ProjectPage-Komponente und BlogNav-Integration MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit - ProjectPage.astro: wiederverwendbare Komponente für alle Projektseiten (liest Collection-Entry per ID, rendert HTML-Body via set:html, setzt canonical) - 12 statische Routing-Dateien: 6 für 2.1.1 (visible) unter /hibernate-maven-plugin/, 6 für 2.1.2-SNAPSHOT unter /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/ - BlogNav: Projects-Ast zwischen Blog und About eingefügt mit vollständiger off-Logik (tree.html-Analogon); SNAPSHOT-Seiten zeigen SNAPSHOT-NavTree an der Position der sichtbaren Version; off-Logic für Blog/About angepasst Co-Authored-By: Claude Sonnet 4.6 --- src/components/BlogNav.astro | 134 +++++++++++++++++- src/components/ProjectPage.astro | 39 +++++ .../configuration.html.astro | 4 + .../create-mojo.html.astro | 4 + src/pages/hibernate-maven-plugin/index.astro | 4 + .../plugin-info.html.astro | 4 + .../project-info.html.astro | 4 + .../project-reports.html.astro | 4 + .../2.1.2-SNAPSHOT/configuration.html.astro | 4 + .../2.1.2-SNAPSHOT/create-mojo.html.astro | 4 + .../2.1.2-SNAPSHOT/index.astro | 4 + .../2.1.2-SNAPSHOT/plugin-info.html.astro | 4 + .../2.1.2-SNAPSHOT/project-info.html.astro | 4 + .../2.1.2-SNAPSHOT/project-reports.html.astro | 4 + src/pages/projects/index.astro | 31 ++++ 15 files changed, 245 insertions(+), 7 deletions(-) create mode 100644 src/components/ProjectPage.astro create mode 100644 src/pages/hibernate-maven-plugin/configuration.html.astro create mode 100644 src/pages/hibernate-maven-plugin/create-mojo.html.astro create mode 100644 src/pages/hibernate-maven-plugin/index.astro create mode 100644 src/pages/hibernate-maven-plugin/plugin-info.html.astro create mode 100644 src/pages/hibernate-maven-plugin/project-info.html.astro create mode 100644 src/pages/hibernate-maven-plugin/project-reports.html.astro create mode 100644 src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html.astro create mode 100644 src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/create-mojo.html.astro create mode 100644 src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/index.astro create mode 100644 src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/plugin-info.html.astro create mode 100644 src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info.html.astro create mode 100644 src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports.html.astro create mode 100644 src/pages/projects/index.astro diff --git a/src/components/BlogNav.astro b/src/components/BlogNav.astro index c489209c..5c05a463 100644 --- a/src/components/BlogNav.astro +++ b/src/components/BlogNav.astro @@ -1,6 +1,7 @@ --- import type { CollectionEntry } from 'astro:content'; import { getAllPosts, postUrl } from '../lib/posts'; +import { getActiveProject, getVisibleProjectNavTrees, type ProjectNavNode } from '../lib/projects'; interface Props { currentUrl: string; @@ -105,6 +106,59 @@ function aboutPageOff(page: NavPage, parentUrl: string): boolean { return !(isCurrent || isAncestor || isSibling || isChild); } +// ── Projects section ────────────────────────────────────────────────────────── +const activeProject = await getActiveProject(currentUrl); +const onProjectsSection = currentUrl === '/projects/' || activeProject !== null; +// When on a SNAPSHOT page, render that version's tree; otherwise all visible trees. +const projectTrees = onProjectsSection && activeProject && !activeProject.isCurrent + ? [activeProject] + : await getVisibleProjectNavTrees(); + +// Nav helpers for project trees +function inProjectSubtree(node: ProjectNavNode, url: string): boolean { + if (node.url === url) return true; + return node.children.some(c => inProjectSubtree(c, url)); +} + +// Find the parent node of a URL within a tree +function findProjectParent(node: ProjectNavNode, url: string): ProjectNavNode | null { + for (const c of node.children) { + if (c.url === url) return node; + const found = findProjectParent(c, url); + if (found) return found; + } + return null; +} + +// Find a node by URL +function findProjectNode(node: ProjectNavNode, url: string): ProjectNavNode | null { + if (node.url === url) return node; + for (const c of node.children) { + const found = findProjectNode(c, url); + if (found) return found; + } + return null; +} + +// Determine the "active" project URL — either from visible page or SNAPSHOT page +const activeProjectUrl = activeProject?.navRoot.url ?? null; +// The active project's current node and its parent (for off-logic) +const _activeProjectRoot = activeProject?.navRoot ?? null; +const activeProjectCurrentNode = _activeProjectRoot ? findProjectNode(_activeProjectRoot, currentUrl) : null; +const activeProjectCurrentParent = _activeProjectRoot ? findProjectParent(_activeProjectRoot, currentUrl) : null; +const activeProjectCurrentIsNode = activeProjectCurrentNode?.isNode ?? false; + +// off-logic mirroring tree.html for a node within a project tree +function projectNodeOff(node: ProjectNavNode, parentUrl: string): boolean { + const isCurrent = node.url === currentUrl; + const isAncestor = !isCurrent && inProjectSubtree(node, currentUrl); + // Sibling: same parent as current page, and current is NOT a section node + const isSibling = parentUrl === (activeProjectCurrentParent?.url ?? '') && !activeProjectCurrentIsNode; + // Child: this node's parent is the current page + const isChild = parentUrl === currentUrl; + return !(isCurrent || isAncestor || isSibling || isChild); +} + // ── Blog URL classification ──────────────────────────────────────────────────── const mainSections = [ { name: 'blog', url: '/blog/', title: 'Blog' }, @@ -131,16 +185,16 @@ const tagsOff = !blogSelected || onArchive || onCategoryTerm; // Active section for #menu highlight const activeSection = mainSections.find(s => { - if (s.name === 'blog') return blogSelected; - if (s.name === 'about') return onAboutSection; + if (s.name === 'blog') return blogSelected; + if (s.name === 'about') return onAboutSection; + if (s.name === 'projects') return onProjectsSection; return currentUrl.startsWith(s.url); })?.name ?? ''; -// Top-level section off-logic (Hugo blog.html vs default.html + tree.html): -// Blog section hidden when viewing any About-section page (and later: Projects pages). -// About section hidden only when on Blog pages. -const blogSectionOff = onAboutSection; -const aboutOff = blogSelected; +// Top-level section off-logic +const blogSectionOff = onAboutSection || onProjectsSection; +const projectsSectionOff = blogSelected || onAboutSection; +const aboutOff = blogSelected || onProjectsSection; // Active year / taxonomy term helpers function isActiveYear(year: string) { @@ -271,6 +325,72 @@ const activeTagSlug = onTagTerm ? currentUrl.replace(/^\/tags\//, '').repl + {/* ── Projects subtree ─────────────────────────────────────────────────── */} +
  • + + {onProjectsSection ? Projects : 'Projects'} + +
      + {projectTrees.map(info => { + const root = info.navRoot; + const rootOff = projectNodeOff(root, '/projects/'); + const rootInPath = inProjectSubtree(root, currentUrl); + return ( +
    • + + {rootInPath ? {root.title} : root.title} + +
        + {root.children.map(child => { + const childOff = projectNodeOff(child, root.url); + const childInPath = inProjectSubtree(child, currentUrl); + const childIsNode = child.isNode; + return ( +
      • + + {childInPath ? {child.title} : child.title} + + {childIsNode && child.children.length > 0 && ( +
          + {child.children.map(grand => { + const grandOff = projectNodeOff(grand, child.url); + const grandInPath = inProjectSubtree(grand, currentUrl); + const grandIsNode = grand.isNode; + return ( +
        • + + {grandInPath ? {grand.title} : grand.title} + + {grandIsNode && grand.children.length > 0 && ( + + )} +
        • + ); + })} +
        + )} +
      • + ); + })} +
      +
    • + ); + })} +
    +
  • + {/* ── About subtree ────────────────────────────────────────────────────── */}
  • diff --git a/src/components/ProjectPage.astro b/src/components/ProjectPage.astro new file mode 100644 index 00000000..a8526463 --- /dev/null +++ b/src/components/ProjectPage.astro @@ -0,0 +1,39 @@ +--- +import { getEntry } from 'astro:content'; +import BaseLayout from '../layouts/BaseLayout.astro'; +import Breadcrumb from '../components/Breadcrumb.astro'; +import BlogNav from '../components/BlogNav.astro'; + +interface Props { + entryId: string; +} + +const { entryId } = Astro.props; +const entry = await getEntry('projects', entryId); +if (!entry) throw new Error(`Project entry not found: ${entryId}`); + +const { title, url, params } = entry.data; +const canonical = params.canonical + ? new URL(params.canonical, Astro.site).toString() + : undefined; + +const crumbs = [ + { title: 'Home', url: '/' }, + { title: 'Projects', url: '/projects/' }, + { title }, +]; +--- + + + + + + + +
    + + + + + + diff --git a/src/pages/hibernate-maven-plugin/configuration.html.astro b/src/pages/hibernate-maven-plugin/configuration.html.astro new file mode 100644 index 00000000..7560c8e4 --- /dev/null +++ b/src/pages/hibernate-maven-plugin/configuration.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/hibernate-maven-plugin/create-mojo.html.astro b/src/pages/hibernate-maven-plugin/create-mojo.html.astro new file mode 100644 index 00000000..4a827769 --- /dev/null +++ b/src/pages/hibernate-maven-plugin/create-mojo.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/hibernate-maven-plugin/index.astro b/src/pages/hibernate-maven-plugin/index.astro new file mode 100644 index 00000000..9b7098b3 --- /dev/null +++ b/src/pages/hibernate-maven-plugin/index.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/hibernate-maven-plugin/plugin-info.html.astro b/src/pages/hibernate-maven-plugin/plugin-info.html.astro new file mode 100644 index 00000000..6914de2b --- /dev/null +++ b/src/pages/hibernate-maven-plugin/plugin-info.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/hibernate-maven-plugin/project-info.html.astro b/src/pages/hibernate-maven-plugin/project-info.html.astro new file mode 100644 index 00000000..de2067f7 --- /dev/null +++ b/src/pages/hibernate-maven-plugin/project-info.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/hibernate-maven-plugin/project-reports.html.astro b/src/pages/hibernate-maven-plugin/project-reports.html.astro new file mode 100644 index 00000000..eb8585c5 --- /dev/null +++ b/src/pages/hibernate-maven-plugin/project-reports.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html.astro b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html.astro new file mode 100644 index 00000000..a4d65cdc --- /dev/null +++ b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/create-mojo.html.astro b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/create-mojo.html.astro new file mode 100644 index 00000000..e4ce8540 --- /dev/null +++ b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/create-mojo.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/index.astro b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/index.astro new file mode 100644 index 00000000..3c2e0953 --- /dev/null +++ b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/index.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/plugin-info.html.astro b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/plugin-info.html.astro new file mode 100644 index 00000000..32aff094 --- /dev/null +++ b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/plugin-info.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info.html.astro b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info.html.astro new file mode 100644 index 00000000..e0af676c --- /dev/null +++ b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports.html.astro b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports.html.astro new file mode 100644 index 00000000..5021b714 --- /dev/null +++ b/src/pages/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports.html.astro @@ -0,0 +1,4 @@ +--- +import ProjectPage from '../../../../components/ProjectPage.astro'; +--- + diff --git a/src/pages/projects/index.astro b/src/pages/projects/index.astro new file mode 100644 index 00000000..e7930bb6 --- /dev/null +++ b/src/pages/projects/index.astro @@ -0,0 +1,31 @@ +--- +import BaseLayout from '../../layouts/BaseLayout.astro'; +import Breadcrumb from '../../components/Breadcrumb.astro'; +import BlogNav from '../../components/BlogNav.astro'; +import { getVisibleProjectNavTrees } from '../../lib/projects'; + +const projects = await getVisibleProjectNavTrees(); +const crumbs = [{ title: 'Home', url: '/' }, { title: 'Projects' }]; +--- + + + + + + + +

    Projects

    +
    + + + + + + -- 2.39.5