Skip to content

refactor: Moved reading time into BlogPost #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions src/LinkDotNet.Blog.Domain/BlogPost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,35 @@ private BlogPost()

public string TagsAsString => Tags is null ? string.Empty : string.Join(", ", Tags);

public int ReadingTimeInMinutes { get; private set; }

public string Slug => GenerateSlug();

private string GenerateSlug()
{
// Remove all accents and make the string lower case.
if (string.IsNullOrWhiteSpace(Title))
{
return Title;
}

Title = Title.Normalize(NormalizationForm.FormD);
var chars = Title
.Where(c => CharUnicodeInfo.GetUnicodeCategory(c)
!= UnicodeCategory.NonSpacingMark)
.ToArray();

Title = new string(chars).Normalize(NormalizationForm.FormC);

var slug = Title.ToLower(CultureInfo.CurrentCulture);
var normalizedTitle = Title.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();

// Remove all special characters from the string.
slug = MatchIfSpecialCharactersExist().Replace(slug, "");
foreach (var c in normalizedTitle.Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark))
{
stringBuilder.Append(c);
}

// Remove all additional spaces in favour of just one.
slug= MatchIfAdditionalSpacesExist().Replace(slug," ").Trim();
var cleanTitle = stringBuilder
.ToString()
.Normalize(NormalizationForm.FormC)
.ToLower(CultureInfo.CurrentCulture);

// Replace all spaces with the hyphen.
slug= MatchIfSpaceExist().Replace(slug, "-");
cleanTitle = MatchIfSpecialCharactersExist().Replace(cleanTitle, "");
cleanTitle = MatchIfAdditionalSpacesExist().Replace(cleanTitle, " ");
cleanTitle = MatchIfSpaceExist().Replace(cleanTitle, "-");

return slug;
return cleanTitle.Trim();
}

[GeneratedRegex(
Expand Down Expand Up @@ -114,7 +115,8 @@ public static BlogPost Create(
PreviewImageUrl = previewImageUrl,
PreviewImageUrlFallback = previewImageUrlFallback,
IsPublished = isPublished,
Tags = tags?.Select(t => t.Trim()).ToImmutableArray(),
Tags = tags?.Select(t => t.Trim()).ToImmutableArray() ?? ImmutableArray<string>.Empty,
ReadingTimeInMinutes = ReadingTimeCalculator.CalculateReadingTime(content),
};

return blogPost;
Expand Down Expand Up @@ -144,5 +146,6 @@ public void Update(BlogPost from)
PreviewImageUrlFallback = from.PreviewImageUrlFallback;
IsPublished = from.IsPublished;
Tags = from.Tags;
ReadingTimeInMinutes = from.ReadingTimeInMinutes;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Text.RegularExpressions;

namespace LinkDotNet.Blog.Web.Features.Services;
namespace LinkDotNet.Blog.Domain;

public static partial class ReadingTimeCalculator
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,65 +23,65 @@ public sealed class CreateNewModel
public string Title
{
get => title;
set => SetProperty(ref title, value);
set => SetProperty(out title, value);
}

[Required]
public string ShortDescription
{
get => shortDescription;
set => SetProperty(ref shortDescription, value);
set => SetProperty(out shortDescription, value);
}

[Required]
public string Content
{
get => content;
set => SetProperty(ref content, value);
set => SetProperty(out content, value);
}

[Required]
[MaxLength(1024)]
public string PreviewImageUrl
{
get => previewImageUrl;
set => SetProperty(ref previewImageUrl, value);
set => SetProperty(out previewImageUrl, value);
}

[Required]
[PublishedWithScheduledDateValidation]
public bool IsPublished
{
get => isPublished;
set => SetProperty(ref isPublished, value);
set => SetProperty(out isPublished, value);
}

[Required]
public bool ShouldUpdateDate
{
get => shouldUpdateDate;
set => SetProperty(ref shouldUpdateDate, value);
set => SetProperty(out shouldUpdateDate, value);
}

[FutureDateValidation]
public DateTime? ScheduledPublishDate
{
get => scheduledPublishDate;
set => SetProperty(ref scheduledPublishDate, value);
set => SetProperty(out scheduledPublishDate, value);
}

public string Tags
{
get => tags;
set => SetProperty(ref tags, value);
set => SetProperty(out tags, value);
}

[MaxLength(256)]
[FallbackUrlValidation]
public string PreviewImageUrlFallback
{
get => previewImageUrlFallback;
set => SetProperty(ref previewImageUrlFallback, value);
set => SetProperty(out previewImageUrlFallback, value);
}

public bool IsDirty { get; private set; }
Expand All @@ -108,7 +108,9 @@ public static CreateNewModel FromBlogPost(BlogPost blogPost)

public BlogPost ToBlogPost()
{
var tagList = string.IsNullOrWhiteSpace(Tags) ? ArraySegment<string>.Empty : Tags.Split(",");
var tagList = string.IsNullOrWhiteSpace(Tags)
? Array.Empty<string>()
: Tags.Split(",", StringSplitOptions.RemoveEmptyEntries);
DateTime? updatedDate = ShouldUpdateDate || originalUpdatedDate == default
? null
: originalUpdatedDate;
Expand All @@ -127,7 +129,7 @@ public BlogPost ToBlogPost()
return blogPost;
}

private void SetProperty<T>(ref T backingField, T value)
private void SetProperty<T>(out T backingField, T value)
{
backingField = value;
IsDirty = true;
Expand Down
17 changes: 2 additions & 15 deletions src/LinkDotNet.Blog.Web/Features/Components/ShortBlogPost.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
@using LinkDotNet.Blog.Web.Features.Services
@using Microsoft.Extensions.Caching.Memory

@inject IMemoryCache MemoryCache
<article>
<div class="blog-card @AltCssClass">
<div class="meta">
Expand All @@ -24,7 +23,7 @@
<li class="draft">Draft</li>
}
<li class="date me-4"><span>@BlogPost.UpdatedDate.ToString("dd/MM/yyyy")</span></li>
@if (BlogPost.Tags != null && BlogPost.Tags.Any())
@if (BlogPost.Tags.Any())
{
<li class="tags me-4">
<ul>
Expand All @@ -35,7 +34,7 @@
</ul>
</li>
}
<li class="read-time me-4">@readingTime min</li>
<li class="read-time me-4">@BlogPost.ReadingTimeInMinutes min</li>
</ul>
</div>
<div class="description">
Expand All @@ -50,8 +49,6 @@
</article>

@code {
private int readingTime;

[Parameter]
public BlogPost BlogPost { get; set; }

Expand Down Expand Up @@ -83,14 +80,4 @@

return base.SetParametersAsync(ParameterView.Empty);
}

protected override void OnInitialized()
{
var key = "reading-time-" + BlogPost.Id;
readingTime = MemoryCache.GetOrCreate(key, entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
return ReadingTimeCalculator.CalculateReadingTime(BlogPost.Content);
});
}
}
5 changes: 3 additions & 2 deletions tests/LinkDotNet.Blog.UnitTests/Domain/BlogPostTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ public void ShouldUpdateBlogPost()
{
var blogPostToUpdate = new BlogPostBuilder().Build();
blogPostToUpdate.Id = "random-id";
var blogPost = BlogPost.Create("Title", "Desc", "Content", "Url", true, previewImageUrlFallback: "Url2");
var blogPost = BlogPost.Create("Title", "Desc", "Other Content", "Url", true, previewImageUrlFallback: "Url2");
blogPost.Id = "something else";

blogPostToUpdate.Update(blogPost);

blogPostToUpdate.Title.Should().Be("Title");
blogPostToUpdate.ShortDescription.Should().Be("Desc");
blogPostToUpdate.Content.Should().Be("Content");
blogPostToUpdate.Content.Should().Be("Other Content");
blogPostToUpdate.PreviewImageUrl.Should().Be("Url");
blogPostToUpdate.PreviewImageUrlFallback.Should().Be("Url2");
blogPostToUpdate.IsPublished.Should().BeTrue();
blogPostToUpdate.Tags.Should().BeNullOrEmpty();
blogPostToUpdate.Slug.Should().NotBeNull();
blogPostToUpdate.ReadingTimeInMinutes.Should().Be(1);
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Linq;
using LinkDotNet.Blog.Web.Features.Services;
using LinkDotNet.Blog.Domain;

namespace LinkDotNet.Blog.UnitTests.Web.Features.Services;
namespace LinkDotNet.Blog.UnitTests.Domain;

public class ReadingTimeCalculatorTests
{
Expand Down