using System.Web; using Cysharp.Text; using OliverBooth.Common.Data.Blog; using OliverBooth.Common.Data.Web; using OliverBooth.Common.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 article. /// /// The article 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 CreateMetaTagsFromTutorialArticle(ITutorialArticle article, ITutorialService tutorialService) { if (article is null) { throw new ArgumentNullException(nameof(article)); } if (tutorialService is null) { throw new ArgumentNullException(nameof(tutorialService)); } string excerpt = tutorialService.RenderExcerpt(article, out _); var tags = new Dictionary { ["title"] = article.Title, ["description"] = excerpt, ["author"] = "Oliver Booth" // TODO add article author support? }; 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(); } }