81 lines
2.4 KiB
C#
81 lines
2.4 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using System.Text.RegularExpressions;
|
|
using Markdig;
|
|
using Markdig.Extensions.Yaml;
|
|
using Markdig.Renderers;
|
|
using Markdig.Syntax;
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
using YamlDotNet.Serialization;
|
|
using YamlDotNet.Serialization.NamingConventions;
|
|
|
|
namespace zotanpw.Pages.blog;
|
|
|
|
public class BlogModel : PageModel {
|
|
public static readonly List<BlogPost> Posts = new();
|
|
|
|
static BlogModel() {
|
|
foreach (var file in Directory.EnumerateFiles("Pages/blog/posts"))
|
|
Posts.Add(new BlogPost(Path.GetFileNameWithoutExtension(file)));
|
|
|
|
Posts = Posts.OrderByDescending(p => p.PublishedOn).ToList();
|
|
}
|
|
|
|
public void OnGet() { }
|
|
|
|
public class BlogPost {
|
|
public readonly string Shorthand;
|
|
public string Content = "";
|
|
|
|
public DateOnly PublishedOn;
|
|
public int ReadTimeMinutes;
|
|
public string Title = null!;
|
|
|
|
public BlogPost(string shorthand) {
|
|
Shorthand = shorthand;
|
|
UpdateContentAndMetadata();
|
|
}
|
|
|
|
public void UpdateContentAndMetadata() {
|
|
var markdownText = System.IO.File.ReadAllText($"Pages/blog/posts/{Shorthand}.md");
|
|
|
|
var parsed = ParseBlogPost(markdownText);
|
|
Title = parsed.metadata.Title!;
|
|
PublishedOn = parsed.metadata.Date;
|
|
ReadTimeMinutes = Regex.Matches(markdownText, @"\b\w+\b").Count / 150;
|
|
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
|
|
}
|
|
}
|
|
}
|