Skip to content

Commit 7aeff99

Browse files
committed
Fixed breadcrumb links
1 parent 02c4429 commit 7aeff99

File tree

2 files changed

+95
-8
lines changed

2 files changed

+95
-8
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
@using System.Globalization
2+
@using Downpatch.Web.Services
3+
@inject MarkdownPageService Pages
4+
5+
<nav class="docs-breadcrumb" aria-label="Breadcrumb">
6+
<a href="/guide">Guide</a>
7+
8+
@foreach (var crumb in _crumbs)
9+
{
10+
<span class="docs-breadcrumb-sep">/</span>
11+
@if (crumb.IsCurrent || string.IsNullOrWhiteSpace(crumb.Href))
12+
{
13+
<span aria-current="page">@crumb.Label</span>
14+
}
15+
else
16+
{
17+
<a href="@crumb.Href">@crumb.Label</a>
18+
}
19+
}
20+
</nav>
21+
22+
@code {
23+
[Parameter] public string? ResolvedEntrySlug { get; set; }
24+
[Parameter] public string? CurrentTitle { get; set; }
25+
26+
private List<BreadcrumbItem> _crumbs = new();
27+
28+
protected override void OnParametersSet()
29+
{
30+
_crumbs = BuildCrumbs(ResolvedEntrySlug, CurrentTitle);
31+
}
32+
33+
private List<BreadcrumbItem> BuildCrumbs(string? resolvedEntrySlug, string? currentTitle)
34+
{
35+
var crumbs = new List<BreadcrumbItem>();
36+
37+
var path = (resolvedEntrySlug ?? "").Replace('\\', '/').Trim('/');
38+
if (path.StartsWith("guide/", StringComparison.OrdinalIgnoreCase))
39+
path = path["guide/".Length..];
40+
41+
if (path.EndsWith("/index", StringComparison.OrdinalIgnoreCase))
42+
path = path[..^"/index".Length];
43+
44+
if (string.IsNullOrWhiteSpace(path))
45+
return crumbs;
46+
47+
var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
48+
for (var i = 0; i < segments.Length; i++)
49+
{
50+
var segPath = string.Join('/', segments.Take(i + 1));
51+
var isCurrent = i == segments.Length - 1;
52+
53+
var label = isCurrent && !string.IsNullOrWhiteSpace(currentTitle)
54+
? currentTitle!
55+
: ResolveCrumbLabel(segPath, segments[i]);
56+
57+
crumbs.Add(new BreadcrumbItem(
58+
Label: label,
59+
Href: isCurrent ? null : "/guide/" + segPath,
60+
IsCurrent: isCurrent));
61+
}
62+
63+
return crumbs;
64+
}
65+
66+
private string ResolveCrumbLabel(string routeSlug, string fallbackSegment)
67+
{
68+
if (Pages.TryGetRendered(routeSlug, out var page))
69+
{
70+
if (page.FrontMatter.TryGetValue("nav_title", out var navTitle) &&
71+
!string.IsNullOrWhiteSpace(navTitle))
72+
{
73+
return navTitle;
74+
}
75+
76+
if (!string.IsNullOrWhiteSpace(page.Title))
77+
return page.Title;
78+
}
79+
80+
return HumanizeSegment(fallbackSegment);
81+
}
82+
83+
private static string HumanizeSegment(string value)
84+
{
85+
value = (value ?? "").Trim().Replace('-', ' ').Replace('_', ' ');
86+
if (value.Length == 0)
87+
return "Untitled";
88+
89+
var textInfo = CultureInfo.CurrentCulture.TextInfo;
90+
return textInfo.ToTitleCase(value.ToLowerInvariant());
91+
}
92+
93+
private sealed record BreadcrumbItem(string Label, string? Href, bool IsCurrent);
94+
}

src/Downpatch.Web/Components/Pages/Guide.razor

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,7 @@ else
5353
</aside>
5454

5555
<main id="doc-content" class="docs-main" tabindex="-1" aria-label="Document content">
56-
<nav class="docs-breadcrumb" aria-label="Breadcrumb">
57-
<a href="/guide">Guide</a>
58-
@if (!string.IsNullOrWhiteSpace(Slug))
59-
{
60-
<span class="docs-breadcrumb-sep">/</span>
61-
<span>@_title</span>
62-
}
63-
</nav>
56+
<GuideBreadcrumb ResolvedEntrySlug="@_resolvedEntrySlug" CurrentTitle="@_title" />
6457

6558
<header class="docs-header">
6659
<h1 class="docs-h1">@_title</h1>

0 commit comments

Comments
 (0)