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.Data.Blog
|
||||||
|
@using OliverBooth.Extensions
|
||||||
@using OliverBooth.Services
|
@using OliverBooth.Services
|
||||||
@inject IBlogPostService BlogPostService
|
@inject IBlogPostService BlogPostService
|
||||||
@{
|
@{
|
||||||
@ -28,15 +29,7 @@
|
|||||||
}
|
}
|
||||||
@if (ViewData["Post"] is IBlogPost post)
|
@if (ViewData["Post"] is IBlogPost post)
|
||||||
{
|
{
|
||||||
string excerpt = BlogPostService.RenderExcerpt(post, out bool trimmed);
|
@Html.Raw(HtmlUtility.CreateMetaTagsFromPost(post, BlogPostService))
|
||||||
<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">
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user