add: 元数据提取
This commit is contained in:
parent
2d75c5c9a7
commit
cc3e7f1e4b
|
@ -5,6 +5,7 @@ using Microsoft.Extensions.Diagnostics.Metrics;
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using YaeBlog.Core.Extensions;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace YaeBlog.Core.Builder;
|
||||
|
||||
|
@ -12,12 +13,15 @@ public sealed class BlogApplicationBuilder : IHostApplicationBuilder
|
|||
{
|
||||
private readonly HostApplicationBuilder _hostApplicationBuilder;
|
||||
|
||||
public MarkdownPipelineBuilder MarkdigPipelineBuilder { get; set; }
|
||||
public MarkdownPipelineBuilder MarkdigPipelineBuilder { get; }
|
||||
|
||||
public DeserializerBuilder YamlDeserializerBuilder { get; }
|
||||
|
||||
internal BlogApplicationBuilder(BlogApplicationOptions options)
|
||||
{
|
||||
ConfigurationManager configuration = new();
|
||||
MarkdigPipelineBuilder = new MarkdownPipelineBuilder();
|
||||
YamlDeserializerBuilder = new DeserializerBuilder();
|
||||
|
||||
_hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings
|
||||
{
|
||||
|
|
|
@ -4,6 +4,8 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
using YaeBlog.Core.Builder;
|
||||
using YaeBlog.Core.Models;
|
||||
using YaeBlog.Core.Services;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace YaeBlog.Core.Extensions;
|
||||
|
||||
|
@ -19,11 +21,17 @@ internal static class BlogApplicationExtension
|
|||
builder.Services.Configure<BlogOptions>(
|
||||
builder.Configuration.GetSection(BlogOptions.OptionName));
|
||||
|
||||
builder.YamlDeserializerBuilder.WithNamingConvention(CamelCaseNamingConvention.Instance);
|
||||
builder.YamlDeserializerBuilder.IgnoreUnmatchedProperties();
|
||||
|
||||
builder.Services.AddSingleton<MarkdownPipeline>(
|
||||
_ => builder.MarkdigPipelineBuilder.Build());
|
||||
builder.Services.AddSingleton<IDeserializer>(
|
||||
_ => builder.YamlDeserializerBuilder.Build());
|
||||
|
||||
builder.Services.AddHostedService<BlogHostedService>();
|
||||
builder.Services.AddSingleton<EssayScanService>();
|
||||
builder.Services.AddSingleton<RendererService>();
|
||||
builder.Services.AddSingleton<MarkdownPipeline>(
|
||||
_ => builder.MarkdigPipelineBuilder.Build());
|
||||
builder.Services.AddSingleton<EssayContentService>();
|
||||
|
||||
return builder;
|
||||
|
|
|
@ -4,5 +4,5 @@ public class BlogContent
|
|||
{
|
||||
public required string FileName { get; init; }
|
||||
|
||||
public required string FileContent { get; init; }
|
||||
public required string FileContent { get; set; }
|
||||
}
|
||||
|
|
|
@ -6,5 +6,12 @@ public class BlogEssay
|
|||
|
||||
public required DateTime PublishTime { get; init; }
|
||||
|
||||
public List<string> Tags { get; } = [];
|
||||
|
||||
public required string HtmlContent { get; init; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Title}-{PublishTime}";
|
||||
}
|
||||
}
|
||||
|
|
10
YaeBlog.Core/Models/MarkdownMetadata.cs
Normal file
10
YaeBlog.Core/Models/MarkdownMetadata.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace YaeBlog.Core.Models;
|
||||
|
||||
public class MarkdownMetadata
|
||||
{
|
||||
public string? Title { get; set; }
|
||||
|
||||
public DateTime? Date { get; set; }
|
||||
|
||||
public List<string> Tags { get; set; } = [];
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
using System.Collections.Concurrent;
|
||||
using Markdig;
|
||||
using Markdig;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using YaeBlog.Core.Exceptions;
|
||||
using YaeBlog.Core.Models;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace YaeBlog.Core.Services;
|
||||
|
||||
public class RendererService(ILogger<RendererService> logger,
|
||||
EssayScanService essayScanService,
|
||||
MarkdownPipeline markdownPipeline,
|
||||
IDeserializer yamlDeserializer,
|
||||
EssayContentService essayContentService)
|
||||
{
|
||||
public async Task RenderAsync()
|
||||
|
@ -17,19 +18,56 @@ public class RendererService(ILogger<RendererService> logger,
|
|||
|
||||
Parallel.ForEach(contents, content =>
|
||||
{
|
||||
logger.LogDebug("Render markdown file {}.", content.FileName);
|
||||
MarkdownMetadata? metadata = TryParseMetadata(content);
|
||||
|
||||
BlogEssay essay = new()
|
||||
{
|
||||
Title = content.FileName,
|
||||
PublishTime = DateTime.Now,
|
||||
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 (!essayContentService.TryAdd(essay.Title, essay))
|
||||
{
|
||||
throw new BlogFileException(
|
||||
$"There are two essays with the same name: '{content.FileName}'.");
|
||||
}
|
||||
logger.LogDebug("Render markdown file {}.", essay);
|
||||
logger.LogDebug("{}", essay.HtmlContent);
|
||||
});
|
||||
}
|
||||
|
||||
private MarkdownMetadata? TryParseMetadata(BlogContent content)
|
||||
{
|
||||
string fileContent = content.FileContent.Trim();
|
||||
|
||||
if (!fileContent.StartsWith("---"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 移除起始的---
|
||||
fileContent = fileContent[3..];
|
||||
|
||||
int lastPos = fileContent.IndexOf("---", StringComparison.Ordinal);
|
||||
if (lastPos is -1 or 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string yamlContent = fileContent[..lastPos];
|
||||
MarkdownMetadata metadata = yamlDeserializer.Deserialize<MarkdownMetadata>(yamlContent);
|
||||
logger.LogDebug("Title: {}, Publish Date: {}.",
|
||||
metadata.Title, metadata.Date);
|
||||
|
||||
// 返回去掉元数据之后的文本
|
||||
lastPos += 3;
|
||||
content.FileContent = fileContent[lastPos..];
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<PackageReference Include="Markdig" Version="0.34.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="13.7.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue
Block a user