Add breadcrumbs function, docs and tests

This commit is contained in:
Ruben 2026-05-20 23:23:01 +02:00
parent 4448798bf5
commit 2bdb432a9f
12 changed files with 451 additions and 0 deletions

View file

@ -44,6 +44,10 @@ class Context {
get => buildNavigation($this);
}
public array $breadcrumbs {
get => buildBreadcrumbs($this);
}
public string $homeLabel {
get => loadMetadata($this->contentDir)["slug"] ?? "Home";
}

View file

@ -161,6 +161,59 @@ function findPageJs(string $dirPath, string $contentDir): ?array {
];
}
// Build breadcrumbs for the current path.
// Returns empty array for frontpage and level 1-2 paths.
function buildBreadcrumbs(Context $ctx): array {
$requestPath = $ctx->requestPath;
// Empty path = frontpage, no breadcrumbs
if (empty($requestPath)) return [];
$pathParts = explode('/', trim($requestPath, '/'));
// Only show breadcrumbs on level 3+ (e.g. /nyheter/riksrevisjonen/artikkel/)
// Level 1 (/nyheter/) and level 2 (/nyheter/riksrevisjonen/) have no breadcrumbs by default
if (count($pathParts) < 3) return [];
$breadcrumbs = [];
$accumulatedPath = $ctx->contentDir;
$langPrefix = $ctx->get('langPrefix', '');
// Exclude last part (current page)
$maxIndex = count($pathParts) - 2;
foreach ($pathParts as $index => $part) {
// Skip the last part (current page title)
if ($index > $maxIndex) continue;
// Security: skip path traversal attempts
if (str_contains($part, '..')) continue;
$accumulatedPath .= '/' . $part;
// Skip if directory doesn't exist
if (!is_dir($accumulatedPath)) continue;
// Load metadata for this level
$metadata = loadMetadata($accumulatedPath);
$title = $metadata['title'] ?? extractTitle($accumulatedPath) ?? ucfirst($part);
// Get slug for URL (either from metadata or use folder name)
$urlSlug = $metadata['slug'] ?? $part;
// Build URL with trailing slash, use rawurlencode for safety
$url = $langPrefix . '/' . rawurlencode($urlSlug) . '/';
$breadcrumbs[] = [
'title' => $title,
'url' => $url,
'isCurrent' => false
];
}
return $breadcrumbs;
}
function extractMetaDescription(string $dirPath, ?array $metadata): ?string {
// 1. Check for search_description in metadata
if ($metadata && isset($metadata['search_description'])) {