]> juplo.de Git - website/commitdiff
Projects: Content Collection + Helper-Bibliothek für Hibernate Maven Plugin
authorKai Moritz <kai.milan.moritz@googlemail.com>
Sun, 14 Jun 2026 11:59:50 +0000 (11:59 +0000)
committerKai Moritz <kai.milan.moritz@googlemail.com>
Sun, 14 Jun 2026 11:59:50 +0000 (11:59 +0000)
- js-yaml als explizite Dev-Dependency hinzugefügt (war transitive Dep)
- Custom Content Layer Loader in content.config.ts: liest HTML+YAML-Frontmatter
  aus src/content/projects/ und stellt sie als 'projects'-Collection bereit
- src/lib/projects.ts: buildNavTree(), getActiveProject(), getVisibleProjectNavTrees()
- Repräsentativer Subset: hibernate-maven-plugin 2.1.1 (sichtbar) + 2.1.2-SNAPSHOT
  (nicht-sichtbar), je 6 Seiten: Index, Configuration, Project Information,
  Project Reports, Plugin Documentation, Goal:create

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
16 files changed:
package-lock.json
package.json
src/content.config.ts
src/content/projects/hibernate-maven-plugin/2.1.1/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.1/configuration.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.1/project-info/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/plugin-info/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/plugin-info/create-mojo.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/plugin-info/_index.html [new file with mode: 0644]
src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/plugin-info/create-mojo.html [new file with mode: 0644]
src/lib/projects.ts [new file with mode: 0644]

index 74795f1fe7a9d133dbb4cd9687e4072bb10c58a3..001519a1d35cadfa79888ebd661e57e1e45251c8 100644 (file)
@@ -12,6 +12,8 @@
         "astro": "^6.4.4"
       },
       "devDependencies": {
+        "@types/js-yaml": "^4.0.9",
+        "js-yaml": "^4.2.0",
         "sass": "^1.100.0"
       },
       "engines": {
         "@types/unist": "*"
       }
     },
+    "node_modules/@types/js-yaml": {
+      "version": "4.0.9",
+      "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
+      "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/@types/mdast": {
       "version": "4.0.4",
       "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
index 6dd8a2e55b79109f9be337baf47ce0948ce65fc2..47e7e9a99bf569c8015cc21183e23258edb739f1 100644 (file)
@@ -19,6 +19,8 @@
     "astro": "^6.4.4"
   },
   "devDependencies": {
+    "@types/js-yaml": "^4.0.9",
+    "js-yaml": "^4.2.0",
     "sass": "^1.100.0"
   }
 }
index 8f780751358334636ab2f51fa6126e62e4de3a69..3896f88a19e679fe451d4257f0b34802f6b106d0 100644 (file)
@@ -1,5 +1,8 @@
 import { defineCollection, z } from 'astro:content';
 import { glob } from 'astro/loaders';
+import { load as yamlLoad } from 'js-yaml';
+import { readFileSync, readdirSync } from 'node:fs';
+import { resolve, relative, dirname, basename } from 'node:path';
 
 const blog = defineCollection({
   loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
@@ -20,4 +23,71 @@ const blog = defineCollection({
   }),
 });
 
-export const collections = { blog };
+const projectPageSchema = z.object({
+  title: z.string(),
+  weight: z.number().default(999),
+  url: z.string(),
+  layout: z.string().optional(),
+  outputs: z.array(z.string()).optional(),
+  params: z.object({
+    current: z.boolean(),
+    canonical: z.string().optional(),
+  }),
+});
+
+function findHtmlFiles(dir: string, baseDir: string): string[] {
+  const results: string[] = [];
+  for (const entry of readdirSync(dir, { withFileTypes: true })) {
+    const fullPath = resolve(dir, entry.name);
+    if (entry.isDirectory()) {
+      results.push(...findHtmlFiles(fullPath, baseDir));
+    } else if (entry.name.endsWith('.html')) {
+      results.push(relative(baseDir, fullPath));
+    }
+  }
+  return results;
+}
+
+function parseHtmlWithFrontmatter(content: string): { data: Record<string, unknown>; body: string } {
+  if (!content.startsWith('---')) return { data: {}, body: content };
+  const end = content.indexOf('\n---', 3);
+  if (end === -1) return { data: {}, body: content };
+  const frontmatter = content.slice(3, end).trim();
+  const body = content.slice(end + 4).trim();
+  return { data: yamlLoad(frontmatter) as Record<string, unknown>, body };
+}
+
+const projects = defineCollection({
+  loader: {
+    name: 'project-pages-loader',
+    load: async ({ store, parseData, logger }) => {
+      const baseDir = resolve('./src/content/projects');
+      let files: string[];
+      try {
+        files = findHtmlFiles(baseDir, baseDir);
+      } catch {
+        logger.warn('No src/content/projects/ directory found — skipping projects loader');
+        return;
+      }
+
+      for (const relPath of files) {
+        const fullPath = resolve(baseDir, relPath);
+        const raw = readFileSync(fullPath, 'utf-8');
+        const { data, body } = parseHtmlWithFrontmatter(raw);
+
+        // Normalise id: use forward slashes, strip leading ./
+        const id = relPath.replace(/\\/g, '/');
+
+        try {
+          const parsed = await parseData({ id, data });
+          store.set({ id, data: parsed, body });
+        } catch (e) {
+          logger.warn(`Skipping ${id}: ${e}`);
+        }
+      }
+    },
+  },
+  schema: projectPageSchema,
+});
+
+export const collections = { blog, projects };
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.1/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.1/_index.html
new file mode 100644 (file)
index 0000000..6c3ce3b
--- /dev/null
@@ -0,0 +1,54 @@
+---
+title: Hibernate Maven Plugin
+weight: 0
+outputs:
+  - html
+url: /hibernate-maven-plugin/
+layout: article
+params:
+  current: true
+---
+<div id="sili-body">
+<h1>Hibernate Maven Plugin</h1><section>
+<h2>A simple plugin for generating a database-schema from Hibernate-Mappings</h2>
+<p>The <b>hibernate-maven-plugin</b> is a plugin for generating a database-schema
+from your Hibernate-Mappings and create or update your database accordingly.
+Its main usage is to automatically create and populate a test-database for
+unit-tests in cooperation with the
+<a class="externalLink" href="http://mojo.codehaus.org/dbunit-maven-plugin">dbunit-maven-plugin</a>.</p>
+<p>The plugin was designed with three main goals in mind:</p>
+<ul>
+<li>It should be easy to use.</li>
+<li>It should be maximal unlikely, to erase a producation-database by accident.</li>
+<li>It should not slow down the development cycle.</li>
+</ul>
+<p>To achieve the first goal, the convention-over-configuration paradigma was applied
+and the plugin was stuffed with usefull logging-messages. So, if in doubt, just turn
+on the <a href="./debugging.html">debugging output</a> with the <code>mvn -X ...</code>.</p>
+<p>To achieve the second goal, the precedence in which the configuration locations are
+consulted was layouted in a way that makes it possible, to prevent overwrites of the
+wrong database by accident.</p>
+<p>Last but not least, in order to not slow down the development cycle, the
+hibernate-maven-plugin only executes the generated SQL, if the mapping or the
+configuration has changed (or if you force it to do so).</p>
+</section><section>
+<h2>Documentation</h2>
+<ul>
+<li>See <a href="./configuration.html">Configuration Examples</a> for Usage-Explanations
+and simple examples of how to use this plugin.</li>
+<li>See <a href="./create-mojo.html">hibernate:create</a>,
+<a href="./update-mojo.html">hibernate:update</a>,
+<a href="./drop-mojo.html">hibernate:drop</a> and
+<a href="./help-mojo.html">hibernate:help</a> and
+<a href="./plugin-info.html">Plugin Documentation</a> for the full autogenerated documentation.</li>
+</ul>
+</section><section>
+<h2>Releases</h2>
+<ul>
+<li><a href="/hibernate-maven-plugin/">current version</a></li>
+<li>2.1.1 (this version)</li>
+<li><a href="/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/">2.1.2-SNAPSHOT</a></li>
+<li><a href="/projects/hibernate-maven-plugin/2.1.0/">2.1.0</a></li>
+</ul>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.1/configuration.html b/src/content/projects/hibernate-maven-plugin/2.1.1/configuration.html
new file mode 100644 (file)
index 0000000..a9f1a36
--- /dev/null
@@ -0,0 +1,32 @@
+---
+title: Configuration Examples
+weight: 20
+outputs:
+  - html
+url: /hibernate-maven-plugin/configuration.html
+layout: article
+params:
+  current: true
+---
+<div id="sili-body">
+<h1>Configuration Examples</h1><section>
+<h2>Configuration Through A Configuration-File</h2>
+<p>The most simple way to configure the plugin is, to put all the hibernate-configuration
+in a <b>hibernate.properties</b>- or a <b>hibernate.cfg.xml</b>-file on your classpath
+or in the <b>persistence.xml</b>-file of your JPA-configuration, just like you would
+do, if you are not using the hibernate-maven-plugin at all.</p>
+<p>In that case, the only configuration needed in the pom.xml is:</p>
+<pre>&lt;plugin&gt;
+  &lt;groupId&gt;de.juplo&lt;/groupId&gt;
+  &lt;artifactId&gt;hibernate-maven-plugin&lt;/artifactId&gt;
+  &lt;version&gt;2.1.1&lt;/version&gt;
+  &lt;executions&gt;
+    &lt;execution&gt;
+      &lt;goals&gt;
+        &lt;goal&gt;create&lt;/goal&gt;
+      &lt;/goals&gt;
+    &lt;/execution&gt;
+  &lt;/executions&gt;
+&lt;/plugin&gt;</pre>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.1/project-info/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.1/project-info/_index.html
new file mode 100644 (file)
index 0000000..a0f906a
--- /dev/null
@@ -0,0 +1,32 @@
+---
+title: Project Information
+weight: 1
+outputs:
+  - html
+url: /hibernate-maven-plugin/project-info.html
+layout: article
+params:
+  current: true
+---
+<div id="sili-body">
+<section>
+<h2>Project Information</h2>
+<p>This document provides an overview of the various documents and links that are part
+of this project's general information. All of this content is automatically generated
+by <a class="externalLink" href="http://maven.apache.org">Maven</a> on behalf of the project.</p>
+<section>
+<h3>Overview</h3>
+<table border="0" class="bodyTable">
+<tr class="a"><th>Document</th><th>Description</th></tr>
+<tr class="b"><td><a href="ci-management.html">CI Management</a></td>
+<td>This document lists the continuous integration management system of this project.</td></tr>
+<tr class="a"><td><a href="dependencies.html">Dependencies</a></td>
+<td>This document lists the project's dependencies and provides information on each dependency.</td></tr>
+<tr class="b"><td><a href="licenses.html">Licenses</a></td>
+<td>This document lists the project license(s).</td></tr>
+<tr class="a"><td><a href="team.html">Team</a></td>
+<td>This document provides information on the members of this project.</td></tr>
+</table>
+</section>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/_index.html
new file mode 100644 (file)
index 0000000..3529051
--- /dev/null
@@ -0,0 +1,29 @@
+---
+title: Project Reports
+weight: 12
+outputs:
+  - html
+url: /hibernate-maven-plugin/project-reports.html
+layout: article
+params:
+  current: true
+---
+<div id="sili-body">
+<section>
+<h2>Generated Reports</h2>
+<p>This document provides an overview of the various reports that are automatically
+generated by <a class="externalLink" href="http://maven.apache.org">Maven</a>.</p>
+<section>
+<h3>Overview</h3>
+<table border="0" class="bodyTable">
+<tr class="a"><th>Document</th><th>Description</th></tr>
+<tr class="b"><td><a href="/projects/hibernate-maven-plugin/2.1.1/apidocs/">JavaDocs</a></td>
+<td>This document contains the JavaDoc API documentation.</td></tr>
+<tr class="a"><td><a href="/projects/hibernate-maven-plugin/2.1.1/testapidocs/">Test JavaDocs</a></td>
+<td>This document contains the test JavaDoc API documentation.</td></tr>
+<tr class="b"><td><a href="plugin-info.html">Plugin Documentation</a></td>
+<td>This document lists the plugins goals and their parameters.</td></tr>
+</table>
+</section>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/plugin-info/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/plugin-info/_index.html
new file mode 100644 (file)
index 0000000..a0d8104
--- /dev/null
@@ -0,0 +1,27 @@
+---
+title: Plugin Documentation
+weight: 19
+outputs:
+  - html
+url: /hibernate-maven-plugin/plugin-info.html
+layout: article
+params:
+  current: true
+---
+<div id="sili-body">
+<section>
+<h2>Plugin Documentation</h2>
+<p>Goals available for this plugin:</p>
+<table border="0" class="bodyTable">
+<tr class="a"><th>Goal</th><th>Description</th></tr>
+<tr class="b"><td><a href="create-mojo.html">hibernate:create</a></td>
+<td>Creates the database schema using Hibernate.</td></tr>
+<tr class="a"><td><a href="drop-mojo.html">hibernate:drop</a></td>
+<td>Drops the database schema using Hibernate.</td></tr>
+<tr class="b"><td><a href="update-mojo.html">hibernate:update</a></td>
+<td>Updates the database schema using Hibernate.</td></tr>
+<tr class="a"><td><a href="help-mojo.html">hibernate:help</a></td>
+<td>Display help information on hibernate-maven-plugin.</td></tr>
+</table>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/plugin-info/create-mojo.html b/src/content/projects/hibernate-maven-plugin/2.1.1/project-reports/plugin-info/create-mojo.html
new file mode 100644 (file)
index 0000000..d241a92
--- /dev/null
@@ -0,0 +1,25 @@
+---
+title: "Goal — hibernate:create"
+weight: 21
+outputs:
+  - html
+url: /hibernate-maven-plugin/create-mojo.html
+layout: article
+params:
+  current: true
+---
+<div id="sili-body">
+<section>
+<h2>hibernate:create</h2>
+<p><b>Full name:</b> de.juplo:hibernate-maven-plugin:2.1.1:create</p>
+<p><b>Description:</b> Creates the database-schema from Hibernate-Mappings.
+This goal executes the generated DDL-SQL, if the mapping or the configuration
+has changed since the last run (or if forced).</p>
+<p><b>Attributes:</b></p>
+<ul>
+<li>Requires a Maven project to be executed.</li>
+<li>Executes as an aggregator goal.</li>
+<li>Binds by default to the lifecycle phase: <code>process-test-resources</code>.</li>
+</ul>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/_index.html
new file mode 100644 (file)
index 0000000..3c4f971
--- /dev/null
@@ -0,0 +1,30 @@
+---
+title: Hibernate Maven Plugin
+weight: 0
+outputs:
+  - html
+url: /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/
+layout: article
+params:
+  current: false
+  canonical: /hibernate-maven-plugin/
+---
+<div id="sili-body">
+<h1>Hibernate Maven Plugin</h1>
+<p><b>This is a development snapshot (2.1.2-SNAPSHOT).</b>
+The current stable release is <a href="/hibernate-maven-plugin/">2.1.1</a>.</p>
+<section>
+<h2>A simple plugin for generating a database-schema from Hibernate-Mappings</h2>
+<p>The <b>hibernate-maven-plugin</b> is a plugin for generating a database-schema
+from your Hibernate-Mappings and create or update your database accordingly.
+Its main usage is to automatically create and populate a test-database for
+unit-tests in cooperation with the
+<a class="externalLink" href="http://mojo.codehaus.org/dbunit-maven-plugin">dbunit-maven-plugin</a>.</p>
+</section><section>
+<h2>Releases</h2>
+<ul>
+<li><a href="/hibernate-maven-plugin/">current version (2.1.1)</a></li>
+<li>2.1.2-SNAPSHOT (this version)</li>
+</ul>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html b/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html
new file mode 100644 (file)
index 0000000..0664763
--- /dev/null
@@ -0,0 +1,33 @@
+---
+title: Configuration Examples
+weight: 20
+outputs:
+  - html
+url: /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/configuration.html
+layout: article
+params:
+  current: false
+  canonical: /hibernate-maven-plugin/configuration.html
+---
+<div id="sili-body">
+<h1>Configuration Examples</h1><section>
+<h2>Configuration Through A Configuration-File</h2>
+<p>The most simple way to configure the plugin is, to put all the hibernate-configuration
+in a <b>hibernate.properties</b>- or a <b>hibernate.cfg.xml</b>-file on your classpath
+or in the <b>persistence.xml</b>-file of your JPA-configuration, just like you would
+do, if you are not using the hibernate-maven-plugin at all.</p>
+<p>In that case, the only configuration needed in the pom.xml is:</p>
+<pre>&lt;plugin&gt;
+  &lt;groupId&gt;de.juplo&lt;/groupId&gt;
+  &lt;artifactId&gt;hibernate-maven-plugin&lt;/artifactId&gt;
+  &lt;version&gt;2.1.2-SNAPSHOT&lt;/version&gt;
+  &lt;executions&gt;
+    &lt;execution&gt;
+      &lt;goals&gt;
+        &lt;goal&gt;create&lt;/goal&gt;
+      &lt;/goals&gt;
+    &lt;/execution&gt;
+  &lt;/executions&gt;
+&lt;/plugin&gt;</pre>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info/_index.html
new file mode 100644 (file)
index 0000000..fd01d86
--- /dev/null
@@ -0,0 +1,33 @@
+---
+title: Project Information
+weight: 1
+outputs:
+  - html
+url: /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-info.html
+layout: article
+params:
+  current: false
+  canonical: /hibernate-maven-plugin/project-info.html
+---
+<div id="sili-body">
+<section>
+<h2>Project Information</h2>
+<p>This document provides an overview of the various documents and links that are part
+of this project's general information. All of this content is automatically generated
+by <a class="externalLink" href="http://maven.apache.org">Maven</a> on behalf of the project.</p>
+<section>
+<h3>Overview</h3>
+<table border="0" class="bodyTable">
+<tr class="a"><th>Document</th><th>Description</th></tr>
+<tr class="b"><td><a href="ci-management.html">CI Management</a></td>
+<td>This document lists the continuous integration management system of this project.</td></tr>
+<tr class="a"><td><a href="dependencies.html">Dependencies</a></td>
+<td>This document lists the project's dependencies and provides information on each dependency.</td></tr>
+<tr class="b"><td><a href="licenses.html">Licenses</a></td>
+<td>This document lists the project license(s).</td></tr>
+<tr class="a"><td><a href="team.html">Team</a></td>
+<td>This document provides information on the members of this project.</td></tr>
+</table>
+</section>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/_index.html
new file mode 100644 (file)
index 0000000..ba8a836
--- /dev/null
@@ -0,0 +1,30 @@
+---
+title: Project Reports
+weight: 12
+outputs:
+  - html
+url: /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports.html
+layout: article
+params:
+  current: false
+  canonical: /hibernate-maven-plugin/project-reports.html
+---
+<div id="sili-body">
+<section>
+<h2>Generated Reports</h2>
+<p>This document provides an overview of the various reports that are automatically
+generated by <a class="externalLink" href="http://maven.apache.org">Maven</a>.</p>
+<section>
+<h3>Overview</h3>
+<table border="0" class="bodyTable">
+<tr class="a"><th>Document</th><th>Description</th></tr>
+<tr class="b"><td><a href="/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/apidocs/">JavaDocs</a></td>
+<td>This document contains the JavaDoc API documentation.</td></tr>
+<tr class="a"><td><a href="/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/testapidocs/">Test JavaDocs</a></td>
+<td>This document contains the test JavaDoc API documentation.</td></tr>
+<tr class="b"><td><a href="plugin-info.html">Plugin Documentation</a></td>
+<td>This document lists the plugins goals and their parameters.</td></tr>
+</table>
+</section>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/plugin-info/_index.html b/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/plugin-info/_index.html
new file mode 100644 (file)
index 0000000..7ec2fe3
--- /dev/null
@@ -0,0 +1,28 @@
+---
+title: Plugin Documentation
+weight: 19
+outputs:
+  - html
+url: /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/plugin-info.html
+layout: article
+params:
+  current: false
+  canonical: /hibernate-maven-plugin/plugin-info.html
+---
+<div id="sili-body">
+<section>
+<h2>Plugin Documentation</h2>
+<p>Goals available for this plugin:</p>
+<table border="0" class="bodyTable">
+<tr class="a"><th>Goal</th><th>Description</th></tr>
+<tr class="b"><td><a href="create-mojo.html">hibernate:create</a></td>
+<td>Creates the database schema using Hibernate.</td></tr>
+<tr class="a"><td><a href="drop-mojo.html">hibernate:drop</a></td>
+<td>Drops the database schema using Hibernate.</td></tr>
+<tr class="b"><td><a href="update-mojo.html">hibernate:update</a></td>
+<td>Updates the database schema using Hibernate.</td></tr>
+<tr class="a"><td><a href="help-mojo.html">hibernate:help</a></td>
+<td>Display help information on hibernate-maven-plugin.</td></tr>
+</table>
+</section>
+</div>
diff --git a/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/plugin-info/create-mojo.html b/src/content/projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/project-reports/plugin-info/create-mojo.html
new file mode 100644 (file)
index 0000000..8d4bd7e
--- /dev/null
@@ -0,0 +1,18 @@
+---
+title: "Goal — hibernate:create"
+weight: 21
+outputs:
+  - html
+url: /projects/hibernate-maven-plugin/2.1.2-SNAPSHOT/create-mojo.html
+layout: article
+params:
+  current: false
+  canonical: /hibernate-maven-plugin/create-mojo.html
+---
+<div id="sili-body">
+<section>
+<h2>hibernate:create</h2>
+<p><b>Full name:</b> de.juplo:hibernate-maven-plugin:2.1.2-SNAPSHOT:create</p>
+<p><b>Description:</b> Creates the database-schema from Hibernate-Mappings.</p>
+</section>
+</div>
diff --git a/src/lib/projects.ts b/src/lib/projects.ts
new file mode 100644 (file)
index 0000000..79abcf9
--- /dev/null
@@ -0,0 +1,175 @@
+import { getCollection, type CollectionEntry } from 'astro:content';
+import { readdirSync } from 'node:fs';
+import { resolve } from 'node:path';
+
+export type ProjectPage = CollectionEntry<'projects'>;
+
+export interface ProjectNavNode {
+  title: string;
+  url: string;
+  weight: number;
+  isNode: boolean;   // true when this entry is a section (_index.html)
+  children: ProjectNavNode[];
+}
+
+export interface ProjectInfo {
+  slug: string;      // e.g. 'hibernate-maven-plugin'
+  version: string;   // e.g. '2.1.1' or '2.1.2-SNAPSHOT'
+  isCurrent: boolean;
+  navRoot: ProjectNavNode;
+}
+
+// Detect generated-content dirs (apidocs, xref, etc.) in public/projects/X/Y/
+const GENERATED_DOC_NAMES: Record<string, string> = {
+  apidocs:    'JavaDocs',
+  testapidocs: 'Test JavaDocs',
+  xref:       'Source Xref',
+  'xref-test': 'Test Source Xref',
+};
+
+function generatedDocNodes(projectSlug: string, version: string, isCurrent: boolean): ProjectNavNode[] {
+  const baseUrl = `/projects/${projectSlug}/${version}/`;
+  const nodes: ProjectNavNode[] = [];
+  const pubDir = resolve(`./public/projects/${projectSlug}/${version}`);
+  let entries: string[] = [];
+  try { entries = readdirSync(pubDir); } catch { return []; }
+  for (const [dirName, title] of Object.entries(GENERATED_DOC_NAMES)) {
+    if (entries.includes(dirName)) {
+      nodes.push({ title, url: `${baseUrl}${dirName}/`, weight: -1, isNode: false, children: [] });
+    }
+  }
+  return nodes;
+}
+
+// Build a nav tree for a single version from the collection entries.
+// The hierarchy is derived from the filesystem path (id):
+//   X/Y/_index.html          → root node
+//   X/Y/page.html            → direct child of root
+//   X/Y/sub/_index.html      → direct child of root (section node)
+//   X/Y/sub/page.html        → child of sub
+function buildNavTree(
+  pages: ProjectPage[],
+  projectSlug: string,
+  version: string,
+): ProjectNavNode | null {
+  // Find the root entry (_index.html at version level)
+  const rootEntry = pages.find(p => p.id === `${projectSlug}/${version}/_index.html`);
+  if (!rootEntry) return null;
+
+  function makeNode(entry: ProjectPage): ProjectNavNode {
+    const idPath = entry.id; // e.g. "hibernate-maven-plugin/2.1.1/project-reports/plugin-info/_index.html"
+    const versionPrefix = `${projectSlug}/${version}/`;
+    const rel = idPath.slice(versionPrefix.length); // e.g. "project-reports/plugin-info/_index.html"
+    const isNode = rel.endsWith('/_index.html') || rel === '_index.html';
+
+    // Find direct children: entries whose path is one level deeper inside the same dir
+    const relDir = isNode
+      ? (rel === '_index.html' ? '' : rel.replace('/_index.html', '/'))
+      : null;
+
+    const children: ProjectNavNode[] = [];
+    if (relDir !== null) {
+      for (const child of pages) {
+        if (child.id === entry.id) continue;
+        const childRel = child.id.slice(versionPrefix.length);
+        if (!childRel.startsWith(relDir)) continue;
+        const remainder = childRel.slice(relDir.length); // e.g. "sub/_index.html" or "page.html"
+        // Direct child: either "page.html" (no slash) or "sub/_index.html" (one slash, ends with _index.html)
+        const isDirectChild =
+          (!remainder.includes('/')) ||
+          (remainder.indexOf('/') === remainder.lastIndexOf('/') && remainder.endsWith('/_index.html'));
+        if (isDirectChild) {
+          children.push(makeNode(child));
+        }
+      }
+      // Add generated-content nodes under root or under project-reports
+      const isReports = rel === 'project-reports/_index.html' || rel === '_index.html';
+      if (rel === 'project-reports/_index.html') {
+        children.push(...generatedDocNodes(projectSlug, version, entry.data.params.current));
+      }
+    }
+
+    children.sort((a, b) => a.weight - b.weight);
+
+    return {
+      title: entry.data.title,
+      url:   entry.data.url,
+      weight: entry.data.weight,
+      isNode,
+      children,
+    };
+  }
+
+  return makeNode(rootEntry);
+}
+
+let _cachedPages: ProjectPage[] | null = null;
+
+export async function getAllProjectPages(): Promise<ProjectPage[]> {
+  if (!_cachedPages) _cachedPages = await getCollection('projects');
+  return _cachedPages;
+}
+
+// Returns ProjectInfo for the version the user is currently browsing,
+// or null if currentUrl is not a project page.
+export async function getActiveProject(currentUrl: string): Promise<ProjectInfo | null> {
+  const pages = await getAllProjectPages();
+
+  // Non-visible: URL matches /projects/X/Y/...
+  const nonVisibleMatch = currentUrl.match(/^\/projects\/([^/]+)\/([^/]+)\//);
+  if (nonVisibleMatch) {
+    const [, projectSlug, version] = nonVisibleMatch;
+    const versionPages = pages.filter(p => p.id.startsWith(`${projectSlug}/${version}/`));
+    if (versionPages.length === 0) return null;
+    const navRoot = buildNavTree(versionPages, projectSlug, version);
+    if (!navRoot) return null;
+    return { slug: projectSlug, version, isCurrent: false, navRoot };
+  }
+
+  // Visible: currentUrl matches the url of a current: true page
+  const visibleRoot = pages.find(
+    p => p.data.params.current && p.id.endsWith('/_index.html') && p.data.url === currentUrl
+  );
+  if (visibleRoot) {
+    const [projectSlug, version] = visibleRoot.id.split('/');
+    const versionPages = pages.filter(p => p.id.startsWith(`${projectSlug}/${version}/`));
+    const navRoot = buildNavTree(versionPages, projectSlug, version);
+    if (!navRoot) return null;
+    return { slug: projectSlug, version, isCurrent: true, navRoot };
+  }
+
+  // Also handle sub-pages of a visible project
+  const visiblePage = pages.find(p => p.data.params.current && p.data.url === currentUrl);
+  if (visiblePage) {
+    const [projectSlug, version] = visiblePage.id.split('/');
+    const versionPages = pages.filter(p => p.id.startsWith(`${projectSlug}/${version}/`));
+    const navRoot = buildNavTree(versionPages, projectSlug, version);
+    if (!navRoot) return null;
+    return { slug: projectSlug, version, isCurrent: true, navRoot };
+  }
+
+  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();
+  const seen = new Set<string>();
+  const result: ProjectInfo[] = [];
+
+  for (const page of pages) {
+    if (!page.data.params.current) continue;
+    if (!page.id.endsWith('/_index.html')) continue;
+    const parts = page.id.split('/');
+    if (parts.length < 3) continue; // must be X/Y/_index.html
+    const [projectSlug, version] = parts;
+    const key = `${projectSlug}/${version}`;
+    if (seen.has(key)) continue;
+    seen.add(key);
+    const versionPages = pages.filter(p => p.id.startsWith(`${key}/`));
+    const navRoot = buildNavTree(versionPages, projectSlug, version);
+    if (navRoot) result.push({ slug: projectSlug, version, isCurrent: true, navRoot });
+  }
+
+  return result;
+}