Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
@@ -1,12 +1,77 @@
import { defineConfig } from "vitepress";
import { generateDocumentationSidebar } from "./sidebar.js";
import { readdir, readFile } from "fs/promises";
import { join } from "path";
import matter from "gray-matter";

// Get base URL from environment variable (for GitHub Pages deployment)
const base = process.env.BASE_URL || "/";

// Generate sidebar dynamically at build time
const documentationSidebar = generateDocumentationSidebar();

// Build a map of URL -> { title, description, url } for all markdown pages
async function buildPageMap(pagesDir: string): Promise<Record<string, { title: string; description: string; url: string }>> {
const map: Record<string, { title: string; description: string; url: string }> = {};
const skipDirs = ['.vitepress', 'node_modules', 'dist', '_build', '.venv'];

async function scanDir(dir: string, basePath: string = "") {
const dirName = dir.split('/').pop() || '';
if (skipDirs.includes(dirName)) {
return;
}

try {
const entries = await readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = join(dir, entry.name);
if (entry.isDirectory()) {
await scanDir(fullPath, basePath + entry.name + "/");
} else if (entry.name.endsWith(".md")) {
try {
const content = await readFile(fullPath, "utf-8");
const { data } = matter(content);
let url = basePath + entry.name.replace(/\.md$/, ".html");
url = url.replace(/\/index\.html$/, "/");
if (!url.startsWith("/")) {
url = "/" + url;
}
map[url] = {
title: data.title || entry.name.replace(/\.md$/, ""),
description: data.description || "",
url,
};
} catch (e) {
// Skip files that can't be read
}
}
}
} catch (e) {
// Skip directories that can't be read
}
}

await scanDir(pagesDir);
return map;
}

// Normalize a related_topics path to a URL
function normalizeUrl(ref: string): string {
// Remove .md extension if present
let url = ref.replace(/\.md$/, "");
// If no extension and no trailing slash, add .html
if (!url.endsWith("/") && !url.includes(".")) {
url = url + ".html";
}
// Handle /index paths
url = url.replace(/\/index\.html$/, "/");
// Ensure leading slash
if (!url.startsWith("/")) {
url = "/" + url;
}
return url;
}

// https://vitepress.dev/reference/site-config
export default defineConfig({
base,
Expand Down Expand Up @@ -147,4 +212,46 @@ export default defineConfig({
provider: "local",
},
},
async transformPageData(pageData, { siteConfig }) {
// Build page map - NOT cached globally due to VitePress config execution issues
const pagesDir = siteConfig.root;
const pageMap = await buildPageMap(pagesDir);

// Resolve related_topics if present
const relatedTopics = pageData.frontmatter?.related_topics;
if (relatedTopics && Array.isArray(relatedTopics)) {
// Get current page URL
let currentPageUrl = "/" + pageData.relativePath.replace(/\.md$/, ".html");
currentPageUrl = currentPageUrl.replace(/\/index\.html$/, "/");

pageData.frontmatter.resolvedRelated = relatedTopics
.map((ref: string) => {
// Normalize the file path to URL
const url = normalizeUrl(ref);
const page = pageMap[url];

// ERROR: File not found
if (!page) {
throw new Error(
`RelatedTopics: File not found "${ref}" (resolved to "${url}") in ${pageData.relativePath}`
);
}

// ERROR: Title missing in frontmatter
if (!page.title) {
throw new Error(
`RelatedTopics: File "${ref}" has no title in frontmatter (in ${pageData.relativePath})`
);
}

// OK: Description is optional
return {
url,
title: page.title,
description: page.description || "",
};
})
.filter((page) => page.url !== currentPageUrl); // Remove self-references
}
},
});
67 changes: 67 additions & 0 deletions docs/.vitepress/theme/components/RelatedTopics.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script setup lang="ts">
import { useData } from 'vitepress'
import { computed } from 'vue'

const { frontmatter } = useData()

const relatedPages = computed(() => {
return frontmatter.value.resolvedRelated || []
})
</script>

<template>
<div v-if="relatedPages.length" class="related-topics">
<ul>
<li v-for="(page, index) in relatedPages" :key="index">
<a :href="page.url" class="topic-link">
<span class="topic-title">{{ page.title }}</span>
<span v-if="page.description" class="topic-description">{{ page.description }}</span>
</a>
</li>
</ul>
</div>
</template>

<style scoped>
.related-topics {
margin-top: 1.25rem;
}

.related-topics h2 {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
}

.related-topics ul {
list-style: disc;
padding-left: 1.25rem;
margin: 0;
}

.related-topics li {
margin-bottom: 0.5rem;
}

.related-topics a.topic-link {
display: block;
color: var(--vp-c-brand-1);
text-decoration: none;
line-height: 1.4;
}

.related-topics a.topic-link:hover {
text-decoration: underline;
}

.related-topics .topic-title {
font-weight: 500;
}

.related-topics .topic-description {
display: block;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.1rem;
}
</style>
2 changes: 2 additions & 0 deletions docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useData } from 'vitepress'
import { createMermaidRenderer } from 'vitepress-mermaid-renderer'
import './style.css'
import SectionIndex from './components/SectionIndex.vue'
import RelatedTopics from './components/RelatedTopics.vue'

export default {
extends: DefaultTheme,
Expand All @@ -31,5 +32,6 @@ export default {
},
enhanceApp({ app }) {
app.component('SectionIndex', SectionIndex)
app.component('RelatedTopics', RelatedTopics)
},
} satisfies Theme
18 changes: 10 additions & 8 deletions docs/contributing/documentation/adding-repos.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
---
title: "Adding Repositories to Documentation Aggregation"
description: "Guide for adding new repositories to the documentation aggregation system"
related_topics:
- /contributing/documentation/documentation_workflow.md
- /contributing/documentation/writing_good_docs.md
- /contributing/documentation/aggregation-architecture.md
- /contributing/documentation/adding-repos.md
- /contributing/documentation/working-locally.md
- /contributing/documentation/technical.md
- /contributing/documentation/testing.md
- /contributing/documentation/vitepress-features.md
---

# Adding Repositories to Documentation Aggregation
Expand Down Expand Up @@ -256,11 +265,4 @@ Here's a complete configuration:

## Related Topics

- [Documentation Workflow](./documentation_workflow.md)
- [Documentation Quality Markers](./writing_good_docs.md)
- [Documentation Aggregator Architecture](./aggregation-architecture.md)
- [How to Documentation - Adding Repos to Aggregate](./adding-repos.md)
- [How to Documentation - Working With the Aggregator Locally](./working-locally.md)
- [Documentation Aggregator Technical Reference](./technical.md)
- [Documentation Aggregator Local Testing Guide](./testing.md)
- [Working with the Documentation Hub on Your Machine](./working-locally.md)
<RelatedTopics />
26 changes: 13 additions & 13 deletions docs/contributing/documentation/aggregation-architecture.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
---
title: "Documentation Aggregation Architecture"
description: "Deep dive into how the documentation aggregation system works"
related_topics:
- /contributing/documentation/documentation_workflow.md
- /contributing/documentation/writing_good_docs.md
- /contributing/documentation/aggregation-architecture.md
- /contributing/documentation/adding-repos.md
- /contributing/documentation/working-locally.md
- /contributing/documentation/technical.md
- /contributing/documentation/testing.md
- /contributing/documentation/vitepress-features.md
---

# Documentation Aggregation Architecture
Expand Down Expand Up @@ -81,13 +90,11 @@ source repositories into a unified VitePress documentation site.

1. **Link Rewriting:** Transform relative links to work across repository
boundaries

- Intra-repo links: Maintained relative to project mirror
- Cross-repo links: Rewritten to absolute paths
- External links: Preserved as-is

2. **Front-matter Handling:** Ensure all documents have proper front-matter

- Add missing front-matter blocks
- Quote YAML values safely
- Preserve existing metadata
Expand Down Expand Up @@ -168,9 +175,9 @@ For reproducible builds, commits can be locked:

```json
{
"name": "repo",
"ref": "main",
"commit": "abc123..."
"name": "repo",
"ref": "main",
"commit": "abc123..."
}
```

Expand Down Expand Up @@ -289,11 +296,4 @@ Temp Directory Docs Output

## Related Topics

- [Documentation Workflow](./documentation_workflow.md)
- [Documentation Quality Markers](./writing_good_docs.md)
- [Documentation Aggregator Architecture](./aggregation-architecture.md)
- [How to Documentation - Adding Repos to Aggregate](./adding-repos.md)
- [How to Documentation - Working With the Aggregator Locally](./working-locally.md)
- [Documentation Aggregator Technical Reference](./technical.md)
- [Documentation Aggregator Local Testing Guide](./testing.md)
- [Working with the Documentation Hub on Your Machine](./working-locally.md)
<RelatedTopics />
44 changes: 21 additions & 23 deletions docs/contributing/documentation/configuration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
---
title: "Documentation Aggregation Configuration Reference"
description: "Complete reference for repos-config.json and repos-config.local.json configuration options"
related_topics:
- /contributing/documentation/documentation_workflow.md
- /contributing/documentation/writing_good_docs.md
- /contributing/documentation/aggregation-architecture.md
- /contributing/documentation/adding-repos.md
- /contributing/documentation/working-locally.md
- /contributing/documentation/technical.md
- /contributing/documentation/testing.md
- /contributing/documentation/vitepress-features.md
---

# Documentation Aggregation Configuration Reference
Expand Down Expand Up @@ -288,35 +297,24 @@ github_target_path: "docs/tutorials/my-tutorial.md"

## Front-Matter Fields

When using `github_target_path`, you can include additional metadata:
### Aggregation-Specific Fields

When using `github_target_path` for aggregated content, you can include additional metadata:

- **`github_org`**: Organization name (e.g., `"gardenlinux"`)
- **`github_repo`**: Repository name (e.g., `"docs-ng"`)
- **`github_source_path`**: Original file path in source repo (e.g.,
`"docs/tutorial.md"`)
- **`github_branch`**: Branch name for edit links (default: `"main"`)

These help create source links in the documentation.
These fields enable "Edit this page on GitHub" links for aggregated content.

### Page Display Fields

- **`description`**: A short summary of the page. Used as the `<meta>`
description by VitePress and shown in section index listings when
`overviewDescriptions` is enabled on the parent page.
- **`overviewDescriptions`**: Boolean controlling whether the `<SectionIndex />`
component displays child page descriptions. Defaults to `true`. Set to `false`
on an index page to hide descriptions for its listing.
- **`order`**: Numeric value for controlling sort order in the sidebar and
section listings. Lower values appear first.
- **`migration_status`**: Status for content migration (e.g., `"new"`,
`"adapt"`, `"aggregate"`).

## See Also

- [Documentation Workflow](./documentation_workflow.md)
- [Documentation Quality Markers](./writing_good_docs.md)
- [Documentation Aggregator Architecture](./aggregation-architecture.md)
- [How to Documentation - Adding Repos to Aggregate](./adding-repos.md)
- [How to Documentation - Working With the Aggregator Locally](./working-locally.md)
- [Documentation Aggregator Technical Reference](./technical.md)
- [Documentation Aggregator Local Testing Guide](./testing.md)
- [Working with the Documentation Hub on Your Machine](./working-locally.md)
For general page display and component configuration fields (such as `title`,
`description`, `order`, `overviewDescriptions`, and `related_topics`), see
[VitePress Features](vitepress-features.md).

## Related Topics

<RelatedTopics />
22 changes: 10 additions & 12 deletions docs/contributing/documentation/documentation_workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
title: Documentation Workflow
description: How to Contribute Documentation to Garden Linux
order: 1
related_topics:
- /contributing/documentation/documentation_workflow.md
- /contributing/documentation/writing_good_docs.md
- /contributing/documentation/aggregation-architecture.md
- /contributing/documentation/adding-repos.md
- /contributing/documentation/working-locally.md
- /contributing/documentation/technical.md
- /contributing/documentation/testing.md
- /contributing/documentation/vitepress-features.md
---

# Documenting Garden Linux
Expand Down Expand Up @@ -138,15 +147,4 @@ The review validates:

## Related Topics

Before you get started, you might want to check out the following docs:

- [Documentation Quality Markers](./writing_good_docs.md)
- [Documentation Aggregator Architecture](./aggregation-architecture.md)
- [How to Documentation - Adding Repos to Aggregate](./adding-repos.md)
- [How to Documentation - Working With the Aggregator Locally](./working-locally.md)
- [Documentation Aggregator Technical Reference](./technical.md)
- [Documentation Aggregator Local Testing Guide](./testing.md)
- [Working with the Documentation Hub on Your Machine](./working-locally.md)

> **Source Repository:**
> [gardenlinux/docs-ng](https://github.com/gardenlinux/docs-ng)
<RelatedTopics />
Loading
Loading