feat: add <meta> tag creation abstraction
This commit is contained in:
parent
b119861eee
commit
cd6bbec1a5
118
OliverBooth/Extensions/HtmlUtility.cs
Normal file
118
OliverBooth/Extensions/HtmlUtility.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System.Web;
|
||||
using Cysharp.Text;
|
||||
using OliverBooth.Data.Blog;
|
||||
using OliverBooth.Services;
|
||||
|
||||
namespace OliverBooth.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Provides helper methods for generating HTML tags
|
||||
/// </summary>
|
||||
public static class HtmlUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates <c><meta></c> embed tags by pulling data from the specified blog post.
|
||||
/// </summary>
|
||||
/// <param name="post">The blog post whose metadata should be retrieved.</param>
|
||||
/// <param name="blogPostService">The <see cref="IBlogPostService" /> injected by the page.</param>
|
||||
/// <returns>A string containing a collection of <c><meta></c> embed tags.</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <para><paramref name="post" /> is <see langword="null" />.</para>
|
||||
/// -or-
|
||||
/// <para><paramref name="blogPostService" /> is <see langword="null" />.</para>
|
||||
/// </exception>
|
||||
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<string, string>
|
||||
{
|
||||
["title"] = post.Title,
|
||||
["description"] = excerpt,
|
||||
["author"] = post.Author.DisplayName
|
||||
};
|
||||
return CreateMetaTags(tags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates <c><meta></c> embed tags by pulling data from the specified dictionary.
|
||||
/// </summary>
|
||||
/// <param name="tags">
|
||||
/// A dictionary containing the tag values. This dictionary should be in the form:
|
||||
///
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Key</term>
|
||||
/// <description>Description</description>
|
||||
/// </listheader>
|
||||
///
|
||||
/// <item>
|
||||
/// <term>description</term>
|
||||
/// <description>
|
||||
/// The value to apply to the <c>description</c>, <c>og:description</c>, and <c>twitter:description</c>, tags.
|
||||
/// </description>
|
||||
/// </item>
|
||||
///
|
||||
/// <item>
|
||||
/// <term>author</term>
|
||||
/// <description>The value to apply to the <c>og:site_name</c>, and <c>twitter:creator</c>, tags.</description>
|
||||
/// </item>
|
||||
///
|
||||
/// <item>
|
||||
/// <term>title</term>
|
||||
/// <description>
|
||||
/// The value to apply to the <c>title</c>, <c>og:title</c>, and <c>twitter:title</c>, tags.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
///
|
||||
/// Any other values contained with the dictionary are ignored.
|
||||
/// </param>
|
||||
/// <returns>A string containing a collection of <c><meta></c> embed tags.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="tags" /> is <see langword="null" />.</exception>
|
||||
public static string CreateMetaTags(IReadOnlyDictionary<string, string> tags)
|
||||
{
|
||||
if (tags is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tags));
|
||||
}
|
||||
|
||||
using Utf8ValueStringBuilder builder = ZString.CreateUtf8StringBuilder();
|
||||
builder.AppendLine("""<meta property="og:type" content="article">""");
|
||||
|
||||
if (tags.TryGetValue("description", out string? description))
|
||||
{
|
||||
description = HttpUtility.HtmlEncode(description);
|
||||
builder.AppendLine($"""<meta name="description" content="{description}">""");
|
||||
builder.AppendLine($"""<meta property="og:description" content="{description}">""");
|
||||
builder.AppendLine($"""<meta property="twitter:description" content="{description}">""");
|
||||
}
|
||||
|
||||
if (tags.TryGetValue("author", out string? author))
|
||||
{
|
||||
author = HttpUtility.HtmlEncode(author);
|
||||
builder.AppendLine($"""<meta property="og:site_name" content="{author}">""");
|
||||
builder.AppendLine($"""<meta property="twitter:creator" content="{author}">""");
|
||||
}
|
||||
|
||||
if (tags.TryGetValue("title", out string? title))
|
||||
{
|
||||
title = HttpUtility.HtmlEncode(title);
|
||||
builder.AppendLine($"""<meta name="title" content="{title}">""");
|
||||
builder.AppendLine($"""<meta property="og:title" content="{title}">""");
|
||||
builder.AppendLine($"""<meta property="twitter:title" content="{title}">""");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
@ -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);
|
||||
<meta name="title" content="@post.Title">
|
||||
<meta name="description" content="@excerpt">
|
||||
<meta property="og:title" content="@post.Title">
|
||||
<meta property="og:description" content="@excerpt">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="twitter:title" content="@post.Title">
|
||||
<meta property="twitter:creator" content="@post.Author.DisplayName">
|
||||
<meta property="twitter:description" content="@excerpt">
|
||||
@Html.Raw(HtmlUtility.CreateMetaTagsFromPost(post, BlogPostService))
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user