diff --git a/YaeBlog.Core/Models/BlogEssay.cs b/YaeBlog.Core/Models/BlogEssay.cs index b06e887..218c461 100644 --- a/YaeBlog.Core/Models/BlogEssay.cs +++ b/YaeBlog.Core/Models/BlogEssay.cs @@ -4,6 +4,8 @@ public class BlogEssay { public required string Title { get; init; } + public required string FileName { get; init; } + public required DateTime PublishTime { get; init; } public List Tags { get; } = []; diff --git a/YaeBlog.Core/Models/MarkdownMetadata.cs b/YaeBlog.Core/Models/MarkdownMetadata.cs index f276b34..0296f19 100644 --- a/YaeBlog.Core/Models/MarkdownMetadata.cs +++ b/YaeBlog.Core/Models/MarkdownMetadata.cs @@ -6,5 +6,5 @@ public class MarkdownMetadata public DateTime? Date { get; set; } - public List Tags { get; set; } = []; + public List? Tags { get; set; } } diff --git a/YaeBlog.Core/Services/RendererService.cs b/YaeBlog.Core/Services/RendererService.cs index 611edfc..e842ebb 100644 --- a/YaeBlog.Core/Services/RendererService.cs +++ b/YaeBlog.Core/Services/RendererService.cs @@ -1,7 +1,9 @@ -using Markdig; +using System.Diagnostics; +using Markdig; using Microsoft.Extensions.Logging; using YaeBlog.Core.Exceptions; using YaeBlog.Core.Models; +using YamlDotNet.Core; using YamlDotNet.Serialization; namespace YaeBlog.Core.Services; @@ -12,33 +14,61 @@ public class RendererService(ILogger logger, IDeserializer yamlDeserializer, EssayContentService essayContentService) { + private readonly Stopwatch _stopwatch = new(); + public async Task RenderAsync() { + _stopwatch.Start(); + logger.LogInformation("Render essays start."); + List contents = await essayScanService.ScanAsync(); - Parallel.ForEach(contents, content => + List essays = []; + + await Task.Run(() => { - MarkdownMetadata? metadata = TryParseMetadata(content); + foreach (BlogContent content in contents) + { + MarkdownMetadata? metadata = TryParseMetadata(content); + BlogEssay essay = new() + { + Title = metadata?.Title ?? content.FileName, + FileName = content.FileName, + PublishTime = metadata?.Date ?? DateTime.Now, + HtmlContent = content.FileContent + }; - BlogEssay essay = new() - { - Title = metadata?.Title ?? content.FileName, - PublishTime = metadata?.Date ?? DateTime.Now, - HtmlContent = Markdown.ToHtml(content.FileContent, markdownPipeline) - }; - if (metadata is not null) - { - essay.Tags.AddRange(essay.Tags); + if (metadata?.Tags is not null) + { + essay.Tags.AddRange(metadata.Tags); + } + essays.Add(essay); } + }); - if (!essayContentService.TryAdd(essay.Title, essay)) + Parallel.ForEach(essays, essay => + { + + BlogEssay newEssay = new() + { + Title = essay.Title, + FileName = essay.FileName, + PublishTime = essay.PublishTime, + HtmlContent = Markdown.ToHtml(essay.HtmlContent, markdownPipeline) + }; + newEssay.Tags.AddRange(essay.Tags); + + if (!essayContentService.TryAdd(newEssay.FileName, newEssay)) { throw new BlogFileException( - $"There are two essays with the same name: '{content.FileName}'."); + $"There are two essays with the same name: '{newEssay.FileName}'."); } - logger.LogDebug("Render markdown file {}.", essay); - logger.LogDebug("{}", essay.HtmlContent); + logger.LogDebug("Render markdown file {}.", newEssay); }); + + _stopwatch.Stop(); + logger.LogInformation("Render finished, consuming {} s.", + _stopwatch.Elapsed.ToString("s\\.fff")); } private MarkdownMetadata? TryParseMetadata(BlogContent content) @@ -60,14 +90,23 @@ public class RendererService(ILogger logger, } string yamlContent = fileContent[..lastPos]; - MarkdownMetadata metadata = yamlDeserializer.Deserialize(yamlContent); - logger.LogDebug("Title: {}, Publish Date: {}.", - metadata.Title, metadata.Date); - // 返回去掉元数据之后的文本 lastPos += 3; content.FileContent = fileContent[lastPos..]; - return null; + try + { + MarkdownMetadata metadata = + yamlDeserializer.Deserialize(yamlContent); + logger.LogDebug("Title: {}, Publish Date: {}.", + metadata.Title, metadata.Date); + + return metadata; + } + catch (YamlException e) + { + logger.LogWarning("Failed to parse '{}' metadata: {}", yamlContent, e); + return null; + } } }