perf: handle content processing in BlogService
This commit is contained in:
parent
983e636635
commit
aaafcaf760
@ -1,6 +1,8 @@
|
|||||||
@page "/blog/{year:int}/{month:int}/{day:int}/{slug}"
|
@page "/blog/{year:int}/{month:int}/{day:int}/{slug}"
|
||||||
@using Humanizer
|
@using Humanizer
|
||||||
|
@using OliverBooth.Services
|
||||||
@model OliverBooth.Pages.Blog.Article
|
@model OliverBooth.Pages.Blog.Article
|
||||||
|
@inject BlogService BlogService
|
||||||
|
|
||||||
@if (Model.Post is not { } post)
|
@if (Model.Post is not { } post)
|
||||||
{
|
{
|
||||||
@ -39,7 +41,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
@Html.Raw(Model.SanitizeContent(post.Body))
|
@Html.Raw(BlogService.GetContent(post))
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using Markdig;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using OliverBooth.Data.Blog;
|
using OliverBooth.Data.Blog;
|
||||||
using OliverBooth.Services;
|
using OliverBooth.Services;
|
||||||
@ -12,17 +11,14 @@ namespace OliverBooth.Pages.Blog;
|
|||||||
public class Article : PageModel
|
public class Article : PageModel
|
||||||
{
|
{
|
||||||
private readonly BlogService _blogService;
|
private readonly BlogService _blogService;
|
||||||
private readonly MarkdownPipeline _markdownPipeline;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Article" /> class.
|
/// Initializes a new instance of the <see cref="Article" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="blogService">The <see cref="BlogService" />.</param>
|
/// <param name="blogService">The <see cref="BlogService" />.</param>
|
||||||
/// <param name="markdownPipeline">The <see cref="MarkdownPipeline" />.</param>
|
public Article(BlogService blogService)
|
||||||
public Article(BlogService blogService, MarkdownPipeline markdownPipeline)
|
|
||||||
{
|
{
|
||||||
_blogService = blogService;
|
_blogService = blogService;
|
||||||
_markdownPipeline = markdownPipeline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -45,23 +41,6 @@ public class Article : PageModel
|
|||||||
/// <value>The requested blog post.</value>
|
/// <value>The requested blog post.</value>
|
||||||
public BlogPost Post { get; private set; } = null!;
|
public BlogPost Post { get; private set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sanitizes the content of the blog post.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content">The content of the blog post.</param>
|
|
||||||
/// <returns>The sanitized content of the blog post.</returns>
|
|
||||||
public string SanitizeContent(string content)
|
|
||||||
{
|
|
||||||
content = content.Replace("<!--more-->", string.Empty);
|
|
||||||
|
|
||||||
while (content.Contains("\n\n"))
|
|
||||||
{
|
|
||||||
content = content.Replace("\n\n", "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Markdown.ToHtml(content.Trim(), _markdownPipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult OnGet(int year, int month, int day, string slug)
|
public IActionResult OnGet(int year, int month, int day, string slug)
|
||||||
{
|
{
|
||||||
if (!_blogService.TryGetBlogPost(year, month, day, slug, out BlogPost? post))
|
if (!_blogService.TryGetBlogPost(year, month, day, slug, out BlogPost? post))
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>@Html.Raw(Model.SanitizeContent(Model.TrimContent(post.Body, out bool trimmed)))</p>
|
<p>@Html.Raw(BlogService.GetExcerpt(post, out bool trimmed))</p>
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
@if (trimmed)
|
@if (trimmed)
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Humanizer;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using OliverBooth.Data.Blog;
|
using OliverBooth.Data.Blog;
|
||||||
using OliverBooth.Services;
|
using OliverBooth.Services;
|
||||||
@ -16,26 +14,6 @@ public class Index : PageModel
|
|||||||
_blogService = blogService;
|
_blogService = blogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SanitizeContent(string content)
|
|
||||||
{
|
|
||||||
content = content.Replace("<!--more-->", string.Empty);
|
|
||||||
|
|
||||||
while (content.Contains("\n\n"))
|
|
||||||
{
|
|
||||||
content = content.Replace("\n\n", "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Markdig.Markdown.ToHtml(content.Trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
public string TrimContent(string content, out bool trimmed)
|
|
||||||
{
|
|
||||||
ReadOnlySpan<char> span = content.AsSpan();
|
|
||||||
int moreIndex = span.IndexOf("<!--more-->", StringComparison.Ordinal);
|
|
||||||
trimmed = moreIndex != -1 || span.Length > 256;
|
|
||||||
return moreIndex != -1 ? span[..moreIndex].Trim().ToString() : content.Truncate(256);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult OnGet([FromQuery(Name = "pid")] int? postId = null,
|
public IActionResult OnGet([FromQuery(Name = "pid")] int? postId = null,
|
||||||
[FromQuery(Name = "p")] int? wpPostId = null)
|
[FromQuery(Name = "p")] int? wpPostId = null)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Humanizer;
|
||||||
|
using Markdig;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using OliverBooth.Data;
|
using OliverBooth.Data;
|
||||||
using OliverBooth.Data.Blog;
|
using OliverBooth.Data.Blog;
|
||||||
@ -8,14 +10,17 @@ namespace OliverBooth.Services;
|
|||||||
public sealed class BlogService
|
public sealed class BlogService
|
||||||
{
|
{
|
||||||
private readonly IDbContextFactory<BlogContext> _dbContextFactory;
|
private readonly IDbContextFactory<BlogContext> _dbContextFactory;
|
||||||
|
private readonly MarkdownPipeline _markdownPipeline;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BlogService" /> class.
|
/// Initializes a new instance of the <see cref="BlogService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dbContextFactory">The <see cref="IDbContextFactory{TContext}" />.</param>
|
/// <param name="dbContextFactory">The <see cref="IDbContextFactory{TContext}" />.</param>
|
||||||
public BlogService(IDbContextFactory<BlogContext> dbContextFactory)
|
/// <param name="markdownPipeline">The <see cref="MarkdownPipeline" />.</param>
|
||||||
|
public BlogService(IDbContextFactory<BlogContext> dbContextFactory, MarkdownPipeline markdownPipeline)
|
||||||
{
|
{
|
||||||
_dbContextFactory = dbContextFactory;
|
_dbContextFactory = dbContextFactory;
|
||||||
|
_markdownPipeline = markdownPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -31,6 +36,34 @@ public sealed class BlogService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the processed content of a blog post.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="post">The blog post.</param>
|
||||||
|
/// <returns>The processed content of the blog post.</returns>
|
||||||
|
public string GetContent(BlogPost post)
|
||||||
|
{
|
||||||
|
return ProcessContent(post.Body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the processed excerpt of a blog post.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="post">The blog post.</param>
|
||||||
|
/// <param name="trimmed">
|
||||||
|
/// When this method returns, contains <see langword="true" /> if the content was trimmed; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The processed excerpt of the blog post.</returns>
|
||||||
|
public string GetExcerpt(BlogPost post, out bool trimmed)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<char> span = post.Body.AsSpan();
|
||||||
|
int moreIndex = span.IndexOf("<!--more-->", StringComparison.Ordinal);
|
||||||
|
trimmed = moreIndex != -1 || span.Length > 256;
|
||||||
|
string result = moreIndex != -1 ? span[..moreIndex].Trim().ToString() : post.Body.Truncate(256);
|
||||||
|
return ProcessContent(result);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to find the author of a blog post.
|
/// Attempts to find the author of a blog post.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -106,4 +139,16 @@ public sealed class BlogService
|
|||||||
post = context.BlogPosts.FirstOrDefault(p => p.WordPressId == postId);
|
post = context.BlogPosts.FirstOrDefault(p => p.WordPressId == postId);
|
||||||
return post is not null;
|
return post is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string ProcessContent(string content)
|
||||||
|
{
|
||||||
|
content = content.Replace("<!--more-->", string.Empty);
|
||||||
|
|
||||||
|
while (content.Contains("\n\n"))
|
||||||
|
{
|
||||||
|
content = content.Replace("\n\n", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Markdown.ToHtml(content.Trim(), _markdownPipeline);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user