From cd6bbec1a52045ed4c2d0e1f5cf21b286eb42e97 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 27 Apr 2024 15:36:13 +0100 Subject: [PATCH] feat: add tag creation abstraction --- OliverBooth/Extensions/HtmlUtility.cs | 118 ++++++++++++++++++++++++ OliverBooth/Pages/Shared/_Layout.cshtml | 11 +-- 2 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 OliverBooth/Extensions/HtmlUtility.cs diff --git a/OliverBooth/Extensions/HtmlUtility.cs b/OliverBooth/Extensions/HtmlUtility.cs new file mode 100644 index 0000000..7139ac5 --- /dev/null +++ b/OliverBooth/Extensions/HtmlUtility.cs @@ -0,0 +1,118 @@ +using System.Web; +using Cysharp.Text; +using OliverBooth.Data.Blog; +using OliverBooth.Services; + +namespace OliverBooth.Extensions; + +/// +/// Provides helper methods for generating HTML tags +/// +public static class HtmlUtility +{ + /// + /// Creates <meta> embed tags by pulling data from the specified blog post. + /// + /// The blog post whose metadata should be retrieved. + /// The injected by the page. + /// A string containing a collection of <meta> embed tags. + /// + /// is . + /// -or- + /// is . + /// + public static string CreateMetaTagsFromPost(IBlogPost post, IBlogPostService blogPostService) + { + if (post is null) + { + throw new ArgumentNullException(nameof(post)); + } + + if (blogPostService is null) + { + throw new ArgumentNullException(nameof(blogPostService)); + } + + + string excerpt = blogPostService.RenderExcerpt(post, out _); + var tags = new Dictionary + { + ["title"] = post.Title, + ["description"] = excerpt, + ["author"] = post.Author.DisplayName + }; + return CreateMetaTags(tags); + } + + /// + /// Creates <meta> embed tags by pulling data from the specified dictionary. + /// + /// + /// A dictionary containing the tag values. This dictionary should be in the form: + /// + /// + /// + /// Key + /// Description + /// + /// + /// + /// description + /// + /// The value to apply to the description, og:description, and twitter:description, tags. + /// + /// + /// + /// + /// author + /// The value to apply to the og:site_name, and twitter:creator, tags. + /// + /// + /// + /// title + /// + /// The value to apply to the title, og:title, and twitter:title, tags. + /// + /// + /// + /// + /// Any other values contained with the dictionary are ignored. + /// + /// A string containing a collection of <meta> embed tags. + /// is . + public static string CreateMetaTags(IReadOnlyDictionary tags) + { + if (tags is null) + { + throw new ArgumentNullException(nameof(tags)); + } + + using Utf8ValueStringBuilder builder = ZString.CreateUtf8StringBuilder(); + builder.AppendLine(""""""); + + if (tags.TryGetValue("description", out string? description)) + { + description = HttpUtility.HtmlEncode(description); + builder.AppendLine($""""""); + builder.AppendLine($""""""); + builder.AppendLine($""""""); + } + + if (tags.TryGetValue("author", out string? author)) + { + author = HttpUtility.HtmlEncode(author); + builder.AppendLine($""""""); + builder.AppendLine($""""""); + } + + if (tags.TryGetValue("title", out string? title)) + { + title = HttpUtility.HtmlEncode(title); + builder.AppendLine($""""""); + builder.AppendLine($""""""); + builder.AppendLine($""""""); + } + + return builder.ToString(); + } +} diff --git a/OliverBooth/Pages/Shared/_Layout.cshtml b/OliverBooth/Pages/Shared/_Layout.cshtml index 2ee6fe0..4ed9767 100644 --- a/OliverBooth/Pages/Shared/_Layout.cshtml +++ b/OliverBooth/Pages/Shared/_Layout.cshtml @@ -1,4 +1,5 @@ @using OliverBooth.Data.Blog +@using OliverBooth.Extensions @using OliverBooth.Services @inject IBlogPostService BlogPostService @{ @@ -28,15 +29,7 @@ } @if (ViewData["Post"] is IBlogPost post) { - string excerpt = BlogPostService.RenderExcerpt(post, out bool trimmed); - - - - - - - - + @Html.Raw(HtmlUtility.CreateMetaTagsFromPost(post, BlogPostService)) } else {