diff --git a/src/Elastic.Markdown/Helpers/Markdown.cs b/src/Elastic.Markdown/Helpers/Markdown.cs new file mode 100644 index 0000000..9ab56ea --- /dev/null +++ b/src/Elastic.Markdown/Helpers/Markdown.cs @@ -0,0 +1,15 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +namespace Elastic.Markdown.Helpers; + +public static class MarkdownStringExtensions +{ + public static string StripMarkdown(this string markdown) + { + using var writer = new StringWriter(); + Markdig.Markdown.ToPlainText(markdown, writer); + return writer.ToString().TrimEnd('\n'); + } +} diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index 03cdc01..230fcbe 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -42,11 +42,21 @@ public DocumentationGroup? Parent public string? UrlPathPrefix { get; } private MarkdownParser MarkdownParser { get; } public YamlFrontMatter? YamlFrontMatter { get; private set; } - public string? Title { get; private set; } + public string? TitleRaw { get; private set; } + + public string? Title + { + get => _title; + private set + { + _title = value?.StripMarkdown(); + TitleRaw = value; + } + } public string? NavigationTitle { get => !string.IsNullOrEmpty(_navigationTitle) ? _navigationTitle : Title; - private set => _navigationTitle = value; + private set => _navigationTitle = value?.StripMarkdown(); } //indexed by slug @@ -64,6 +74,7 @@ public string? NavigationTitle private bool _instructionsParsed; private DocumentationGroup? _parent; + private string? _title; public MarkdownFile[] YieldParents() { @@ -156,7 +167,7 @@ private void ReadDocumentInstructions(MarkdownDocument document) .Select(h => (h.GetData("header") as string, h.GetData("anchor") as string)) .Select(h => new PageTocItem { - Heading = h.Item1!.Replace("`", "").Replace("*", ""), + Heading = h.Item1!.StripMarkdown(), Slug = (h.Item2 ?? h.Item1).Slugify() }) .ToList(); diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index aac30ed..23ef8ae 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -56,6 +56,7 @@ public async Task RenderLayout(MarkdownFile markdown, Cancel ctx = defau var slice = Index.Create(new IndexViewModel { Title = markdown.Title ?? "[TITLE NOT SET]", + TitleRaw = markdown.TitleRaw ?? "[TITLE NOT SET]", MarkdownHtml = html, PageTocItems = markdown.TableOfContents.Values.ToList(), Tree = DocumentationSet.Tree, diff --git a/src/Elastic.Markdown/Slices/Index.cshtml b/src/Elastic.Markdown/Slices/Index.cshtml index 0a03dbc..3abb070 100644 --- a/src/Elastic.Markdown/Slices/Index.cshtml +++ b/src/Elastic.Markdown/Slices/Index.cshtml @@ -1,3 +1,4 @@ +@using Markdig @inherits RazorSliceHttpResult @implements IUsesLayout @functions { @@ -16,7 +17,8 @@ }; }
-

@(Model.Title)

+ @* This way it's correctly rendered as

text

instead of

text

*@ + @(new HtmlString(Markdown.ToHtml("# " + Model.TitleRaw))) @if (Model.Applies is not null) { await RenderPartialAsync(Applies.Create(Model.Applies)); diff --git a/src/Elastic.Markdown/Slices/_ViewModels.cs b/src/Elastic.Markdown/Slices/_ViewModels.cs index 3e89a70..987f5f6 100644 --- a/src/Elastic.Markdown/Slices/_ViewModels.cs +++ b/src/Elastic.Markdown/Slices/_ViewModels.cs @@ -10,6 +10,7 @@ namespace Elastic.Markdown.Slices; public class IndexViewModel { public required string Title { get; init; } + public required string TitleRaw { get; init; } public required string MarkdownHtml { get; init; } public required DocumentationGroup Tree { get; init; } public required IReadOnlyCollection PageTocItems { get; init; } @@ -26,6 +27,7 @@ public class IndexViewModel public class LayoutViewModel { public string Title { get; set; } = "Elastic Documentation"; + public string RawTitle { get; set; } = "Elastic Documentation"; public required IReadOnlyCollection PageTocItems { get; init; } public required DocumentationGroup Tree { get; init; } public required MarkdownFile CurrentDocument { get; init; }