Skip to content

Commit ce3a4d6

Browse files
committed
Rewrite relative links in rendered Markdown HTML
Added the `RewriteRelativeLinks` method to `MarkdownPageService` to adjust relative links in HTML based on the provided `slug`. The method uses a regex to rewrite `<a>` tag `href` attributes, skipping absolute, root, anchor, and `mailto:` links. It also removes `.md` extensions from links and prefixes them with the calculated base path. Updated the Markdown rendering pipeline to call this method after converting Markdown to HTML.
1 parent 817326a commit ce3a4d6

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

src/Downpatch.Web/Services/MarkdownPageService.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public bool TryGetRendered(string? slug, out RenderedPage page)
4848

4949
var title = fm.TryGetValue("title", out var t) && !string.IsNullOrWhiteSpace(t) ? t : entry.Slug;
5050
var htmlBody = Markdown.ToHtml(body, _pipeline);
51+
htmlBody = RewriteRelativeLinks(htmlBody, entry.Slug);
5152

5253
page = new RenderedPage(
5354
Slug: entry.Slug,
@@ -103,6 +104,44 @@ private static (Dictionary<string, string> frontMatter, string body) ParseFrontM
103104
return (fm, body);
104105
}
105106

107+
private static string RewriteRelativeLinks(string html, string slug)
108+
{
109+
// slug example: guide/halo/index
110+
// base path should be /guide/halo/
111+
var lastSlash = slug.LastIndexOf('/');
112+
if (lastSlash < 0)
113+
return html;
114+
115+
var basePath = "/" + slug[..lastSlash] + "/";
116+
117+
return System.Text.RegularExpressions.Regex.Replace(
118+
html,
119+
"<a\\s+([^>]*?)href=\"(.*?)\"",
120+
match =>
121+
{
122+
var before = match.Groups[1].Value;
123+
var href = match.Groups[2].Value;
124+
125+
// skip absolute + root links
126+
if (href.StartsWith("/") ||
127+
href.StartsWith("http", StringComparison.OrdinalIgnoreCase) ||
128+
href.StartsWith("#") ||
129+
href.StartsWith("mailto:"))
130+
return match.Value;
131+
132+
// remove .md if present
133+
if (href.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
134+
href = href[..^3];
135+
136+
var newHref = basePath + href.TrimStart('/');
137+
138+
return $"<a {before}href=\"{newHref}\"";
139+
},
140+
System.Text.RegularExpressions.RegexOptions.IgnoreCase
141+
);
142+
}
143+
144+
106145
public readonly record struct RenderedPage(
107146
string Slug,
108147
string Title,

0 commit comments

Comments
 (0)