zotan.pw-web/Pages/blog/Blog.cshtml.cs

81 lines
2.4 KiB
C#
Raw Normal View History

2022-11-20 22:26:21 +01:00
using System.Diagnostics.CodeAnalysis;
2022-11-20 03:06:41 +01:00
using System.Text.RegularExpressions;
using Markdig;
2022-11-20 22:26:21 +01:00
using Markdig.Extensions.Yaml;
using Markdig.Renderers;
using Markdig.Syntax;
2022-11-20 03:06:41 +01:00
using Microsoft.AspNetCore.Mvc.RazorPages;
2022-11-20 22:26:21 +01:00
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
2022-11-20 03:06:41 +01:00
2022-11-26 13:23:58 +01:00
namespace zotanpw.Pages.blog;
2022-11-20 03:06:41 +01:00
public class BlogModel : PageModel {
2022-11-20 22:26:21 +01:00
public static readonly List<BlogPost> Posts = new();
2022-11-20 03:06:41 +01:00
static BlogModel() {
2022-11-20 22:26:21 +01:00
foreach (var file in Directory.EnumerateFiles("Pages/blog/posts"))
Posts.Add(new BlogPost(Path.GetFileNameWithoutExtension(file)));
2022-11-20 03:06:41 +01:00
Posts = Posts.OrderByDescending(p => p.PublishedOn).ToList();
}
public void OnGet() { }
public class BlogPost {
2022-11-20 22:26:21 +01:00
public readonly string Shorthand;
public string Content = "";
public DateOnly PublishedOn;
public int ReadTimeMinutes;
public string Title = null!;
public BlogPost(string shorthand) {
Shorthand = shorthand;
UpdateContentAndMetadata();
2022-11-20 03:06:41 +01:00
}
2022-11-20 22:26:21 +01:00
public void UpdateContentAndMetadata() {
2022-11-20 03:06:41 +01:00
var markdownText = System.IO.File.ReadAllText($"Pages/blog/posts/{Shorthand}.md");
2022-11-20 22:26:21 +01:00
var parsed = ParseBlogPost(markdownText);
Title = parsed.metadata.Title!;
PublishedOn = parsed.metadata.Date;
2022-11-20 03:06:41 +01:00
ReadTimeMinutes = Regex.Matches(markdownText, @"\b\w+\b").Count / 150;
2022-11-20 22:26:21 +01:00
Content = parsed.html;
}
private static (PostMetadata metadata, string html) ParseBlogPost(string markdown) {
var yaml = "";
var pipeline = new MarkdownPipelineBuilder().UseGenericAttributes().UseYamlFrontMatter().Build();
var writer = new StringWriter();
var renderer = new HtmlRenderer(writer);
pipeline.Setup(renderer);
var document = Markdown.Parse(markdown, pipeline);
var yamlBlock = document.Descendants<YamlFrontMatterBlock>().FirstOrDefault();
if (yamlBlock != null)
yaml = markdown.Substring(yamlBlock.Span.Start, yamlBlock.Span.Length);
renderer.Render(document);
writer.Flush();
var html = writer.ToString();
var yamlDeserializer = new DeserializerBuilder().WithNamingConvention(LowerCaseNamingConvention.Instance).Build();
var metadata = yamlDeserializer.Deserialize<PostMetadata>(yaml);
return (metadata, html);
}
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Local")]
private class PostMetadata {
#pragma warning disable CS0649
public string? Title;
public DateOnly Date;
#pragma warning restore CS0649
2022-11-20 03:06:41 +01:00
}
}
2022-11-20 22:26:21 +01:00
}