feat: add update time.
All checks were successful
Build blog docker image / Build-Blog-Image (push) Successful in 3m57s
All checks were successful
Build blog docker image / Build-Blog-Image (push) Successful in 3m57s
Make the link in blog blue.
This commit is contained in:
@@ -6,5 +6,11 @@ public interface IEssayScanService
|
||||
{
|
||||
public Task<BlogContents> ScanContents();
|
||||
|
||||
/// <summary>
|
||||
/// 将对应的博客文章保存在磁盘上
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="isDraft">指定对应博客文章是否为草稿。因为BlogContent是不可变对象,因此提供该参数以方便publish的实现。</param>
|
||||
/// <returns></returns>
|
||||
public Task SaveBlogContent(BlogContent content, bool isDraft = true);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public sealed class YaeBlogCommand
|
||||
AddWatchCommand(_rootCommand);
|
||||
AddListCommand(_rootCommand);
|
||||
AddNewCommand(_rootCommand);
|
||||
AddUpdateCommand(_rootCommand);
|
||||
AddPublishCommand(_rootCommand);
|
||||
AddScanCommand(_rootCommand);
|
||||
AddCompressCommand(_rootCommand);
|
||||
@@ -46,7 +47,7 @@ public sealed class YaeBlogCommand
|
||||
|
||||
WebApplication application = builder.Build();
|
||||
|
||||
application.UseStaticFiles();
|
||||
application.MapStaticAssets();
|
||||
application.UseAntiforgery();
|
||||
application.UseYaeBlog();
|
||||
|
||||
@@ -76,7 +77,7 @@ public sealed class YaeBlogCommand
|
||||
|
||||
WebApplication application = builder.Build();
|
||||
|
||||
application.UseStaticFiles();
|
||||
application.MapStaticAssets();
|
||||
application.UseAntiforgery();
|
||||
application.UseYaeBlog();
|
||||
|
||||
@@ -109,7 +110,7 @@ public sealed class YaeBlogCommand
|
||||
|
||||
await essayScanService.SaveBlogContent(new BlogContent(
|
||||
new FileInfo(Path.Combine(blogOption.Value.Root, "drafts", file + ".md")),
|
||||
new MarkdownMetadata { Title = file, Date = DateTime.Now },
|
||||
new MarkdownMetadata { Title = file, Date = DateTimeOffset.Now, UpdateTime = DateTimeOffset.Now },
|
||||
string.Empty, true, [], []));
|
||||
|
||||
Console.WriteLine($"Created new blog '{file}.");
|
||||
@@ -117,6 +118,33 @@ public sealed class YaeBlogCommand
|
||||
new EssayScanServiceBinder());
|
||||
}
|
||||
|
||||
private static void AddUpdateCommand(RootCommand rootCommand)
|
||||
{
|
||||
Command newCommand = new("update", "Update the blog essay.");
|
||||
rootCommand.AddCommand(newCommand);
|
||||
|
||||
Argument<string> filenameArgument = new(name: "blog name", description: "The blog filename to update.");
|
||||
newCommand.AddArgument(filenameArgument);
|
||||
|
||||
newCommand.SetHandler(async (file, _, _, essayScanService) =>
|
||||
{
|
||||
Console.WriteLine("HINT: The update command only consider published blogs.");
|
||||
BlogContents contents = await essayScanService.ScanContents();
|
||||
|
||||
BlogContent? content = contents.Posts.FirstOrDefault(c => c.BlogName == file);
|
||||
if (content is null)
|
||||
{
|
||||
Console.WriteLine($"Target essay {file} is not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
content.Metadata.UpdateTime = DateTimeOffset.Now;
|
||||
await essayScanService.SaveBlogContent(content, content.IsDraft);
|
||||
|
||||
}, filenameArgument,
|
||||
new BlogOptionsBinder(), new LoggerBinder<EssayScanService>(), new EssayScanServiceBinder());
|
||||
}
|
||||
|
||||
private static void AddListCommand(RootCommand rootCommand)
|
||||
{
|
||||
Command command = new("list", "List all blogs");
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
<div class="flex flex-row gap-4">
|
||||
<div class="font-light">
|
||||
@(_essay!.PublishTime.ToString("yyyy-MM-dd"))
|
||||
</div>
|
||||
|
||||
@foreach (string tag in _essay!.Tags)
|
||||
{
|
||||
<div class="text-sky-500">
|
||||
@@ -32,10 +28,19 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-6 pt-2 pb-4">
|
||||
<div class="font-light">
|
||||
<div class="font-light py-1">
|
||||
发布于: @(_essay.PublishTime.ToString("yyyy年MM月dd日 hh:mm:ss"))
|
||||
</div>
|
||||
|
||||
@if (_essay.UpdateTime != _essay.PublishTime)
|
||||
{
|
||||
<div class="font-light pb-1">
|
||||
更新于: @(_essay.UpdateTime.ToString("yyyy年MM月dd日 hh:mm:ss"))
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="font-light pb-1">
|
||||
总字数:@(_essay!.WordCount)字,预计阅读时间 @(_essay!.ReadTime)。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,9 @@ public class BlogEssay : IComparable<BlogEssay>
|
||||
|
||||
public required bool IsDraft { get; init; }
|
||||
|
||||
public required DateTime PublishTime { get; init; }
|
||||
public required DateTimeOffset PublishTime { get; init; }
|
||||
|
||||
public required DateTimeOffset UpdateTime { get; init; }
|
||||
|
||||
public required string Description { get; init; }
|
||||
|
||||
@@ -28,6 +30,7 @@ public class BlogEssay : IComparable<BlogEssay>
|
||||
FileName = FileName,
|
||||
IsDraft = IsDraft,
|
||||
PublishTime = PublishTime,
|
||||
UpdateTime = UpdateTime,
|
||||
Description = Description,
|
||||
WordCount = WordCount,
|
||||
ReadTime = ReadTime,
|
||||
|
||||
@@ -4,7 +4,9 @@ public class MarkdownMetadata
|
||||
{
|
||||
public string? Title { get; set; }
|
||||
|
||||
public DateTime? Date { get; set; }
|
||||
public DateTimeOffset Date { get; set; }
|
||||
|
||||
public DateTimeOffset UpdateTime { get; set; }
|
||||
|
||||
public List<string>? Tags { get; set; }
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@ public sealed class EssayStylesPostRenderProcessor : IPostRenderProcessor
|
||||
public async Task<BlogEssay> ProcessAsync(BlogEssay essay)
|
||||
{
|
||||
BrowsingContext context = new(Configuration.Default);
|
||||
IDocument document = await context.OpenAsync(
|
||||
req => req.Content(essay.HtmlContent));
|
||||
IDocument document = await context.OpenAsync(req => req.Content(essay.HtmlContent));
|
||||
|
||||
ApplyGlobalCssStyles(document);
|
||||
BeatifyTable(document);
|
||||
@@ -36,6 +35,7 @@ public sealed class EssayStylesPostRenderProcessor : IPostRenderProcessor
|
||||
{ "h5", "text-lg font-bold py-1" },
|
||||
{ "p", "p-2" },
|
||||
{ "img", "w-11/12 block mx-auto my-2 rounded-md shadow-md" },
|
||||
{ "a", "text-blue-600" }
|
||||
};
|
||||
|
||||
private void ApplyGlobalCssStyles(IDocument document)
|
||||
|
||||
@@ -47,7 +47,10 @@ public partial class RendererService(
|
||||
Description = GetDescription(content),
|
||||
WordCount = wordCount,
|
||||
ReadTime = CalculateReadTime(wordCount),
|
||||
PublishTime = content.Metadata.Date ?? DateTime.Now,
|
||||
PublishTime = content.Metadata.Date == default ? DateTimeOffset.Now : content.Metadata.Date,
|
||||
// 如果不存在最后的更新时间,就把更新时间设置为发布时间
|
||||
UpdateTime =
|
||||
content.Metadata.UpdateTime == default ? content.Metadata.Date : content.Metadata.UpdateTime,
|
||||
HtmlContent = content.Content
|
||||
};
|
||||
|
||||
@@ -182,7 +185,7 @@ public partial class RendererService(
|
||||
|
||||
string description = builder.ToString();
|
||||
|
||||
logger.LogDebug("Description of {} is {}.", content.BlogName,
|
||||
logger.LogDebug("Description of {name} is {desc}.", content.BlogName,
|
||||
description);
|
||||
return description;
|
||||
}
|
||||
@@ -193,7 +196,7 @@ public partial class RendererService(
|
||||
where char.IsLetterOrDigit(c)
|
||||
select c).Count();
|
||||
|
||||
logger.LogDebug("Word count of {} is {}", content.BlogName,
|
||||
logger.LogDebug("Word count of {blog} is {count}", content.BlogName,
|
||||
count);
|
||||
return (uint)count;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user