diff --git a/zotan.pw-web/Pages/Index.cshtml b/zotan.pw-web/Pages/Index.cshtml index 9361dd1..7117c96 100644 --- a/zotan.pw-web/Pages/Index.cshtml +++ b/zotan.pw-web/Pages/Index.cshtml @@ -153,4 +153,4 @@ @section postfooter { -} +} \ No newline at end of file diff --git a/zotan.pw-web/Pages/NowPlaying.cshtml b/zotan.pw-web/Pages/NowPlaying.cshtml index 9dd54a5..2dbd9d7 100644 --- a/zotan.pw-web/Pages/NowPlaying.cshtml +++ b/zotan.pw-web/Pages/NowPlaying.cshtml @@ -37,4 +37,4 @@ Apple Music - + \ No newline at end of file diff --git a/zotan.pw-web/Pages/Shared/_Layout.cshtml b/zotan.pw-web/Pages/Shared/_Layout.cshtml index dab86b1..d7f268f 100644 --- a/zotan.pw-web/Pages/Shared/_Layout.cshtml +++ b/zotan.pw-web/Pages/Shared/_Layout.cshtml @@ -52,4 +52,4 @@ - + \ No newline at end of file diff --git a/zotan.pw-web/Pages/blog/Blog.cshtml.cs b/zotan.pw-web/Pages/blog/Blog.cshtml.cs index 8ec945b..c73b3c9 100644 --- a/zotan.pw-web/Pages/blog/Blog.cshtml.cs +++ b/zotan.pw-web/Pages/blog/Blog.cshtml.cs @@ -1,40 +1,80 @@ +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_web.Pages.blog; public class BlogModel : PageModel { - public static readonly List Posts = new() { - new BlogPost("adhd-and-notes", "ADHD & Notetaking: an autistic perspective", DateOnly.Parse("2021-08-07")), - new BlogPost("ipv6-networking", "IPv6-native networking: a project report", DateOnly.Parse("2021-08-23")) - }; + public static readonly List 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 DateOnly PublishedOn; - public readonly string Shorthand; - public readonly string Title; - public string Content = ""; - public int ReadTimeMinutes; + public readonly string Shorthand; + public string Content = ""; - public BlogPost(string shorthand, string title, DateOnly publishedOn) { - Title = title; - PublishedOn = publishedOn; - Shorthand = shorthand; - UpdateContent(); + public DateOnly PublishedOn; + public int ReadTimeMinutes; + public string Title = null!; + + public BlogPost(string shorthand) { + Shorthand = shorthand; + UpdateContentAndMetadata(); } - public void UpdateContent() { + public void UpdateContentAndMetadata() { var markdownText = System.IO.File.ReadAllText($"Pages/blog/posts/{Shorthand}.md"); - Content = Markdown.ToHtml(markdownText, new MarkdownPipelineBuilder().UseGenericAttributes().Build()); + 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().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(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 } } -} \ No newline at end of file +} diff --git a/zotan.pw-web/Pages/blog/BlogPost.cshtml b/zotan.pw-web/Pages/blog/BlogPost.cshtml index 35def8d..bf7c761 100644 --- a/zotan.pw-web/Pages/blog/BlogPost.cshtml +++ b/zotan.pw-web/Pages/blog/BlogPost.cshtml @@ -12,7 +12,7 @@ ViewData["title"] = "blog"; ViewData["subtitle"] = post.Shorthand; #if (DEBUG) - post.UpdateContent(); + post.UpdateContentAndMetadata(); #endif } @@ -20,4 +20,4 @@

IPv6-native networking: a project report

@Html.Raw(post.Content) -
+ \ No newline at end of file diff --git a/zotan.pw-web/Pages/blog/posts/adhd-and-notes.md b/zotan.pw-web/Pages/blog/posts/adhd-and-notes.md index 05a4d88..badc92d 100644 --- a/zotan.pw-web/Pages/blog/posts/adhd-and-notes.md +++ b/zotan.pw-web/Pages/blog/posts/adhd-and-notes.md @@ -1,3 +1,7 @@ +--- +title: "ADHD & Notetaking: an autistic perspective" +date: 2021-08-07 +... If you are living with ADHD, diagnosed or not, the following things might sound familiar: *"I forgot to write that down"*, *"I forgot to do that"*, *"I don't remember that"*. diff --git a/zotan.pw-web/Pages/blog/posts/ipv6-networking.md b/zotan.pw-web/Pages/blog/posts/ipv6-networking.md index 8e0d463..2c3b559 100644 --- a/zotan.pw-web/Pages/blog/posts/ipv6-networking.md +++ b/zotan.pw-web/Pages/blog/posts/ipv6-networking.md @@ -1,3 +1,7 @@ +--- +title: "IPv6-native networking: a project report" +date: 2021-08-23 +... If you have reached this post, chances are you already know my [AS211579](https://zotan.network){target="_blank"} project. This post serves as a summary of the things I learnt and the roadblocks diff --git a/zotan.pw-web/PlaybackHistory/LogPlayback.cs b/zotan.pw-web/PlaybackHistory/LogPlayback.cs index 634148b..2f2ce6b 100644 --- a/zotan.pw-web/PlaybackHistory/LogPlayback.cs +++ b/zotan.pw-web/PlaybackHistory/LogPlayback.cs @@ -38,4 +38,4 @@ public class LogPlayback : Controller { Response.StatusCode = 403; return null!; } -} +} \ No newline at end of file diff --git a/zotan.pw-web/PlaybackHistory/LogPlaybackRequest.cs b/zotan.pw-web/PlaybackHistory/LogPlaybackRequest.cs index b442416..2164d8a 100644 --- a/zotan.pw-web/PlaybackHistory/LogPlaybackRequest.cs +++ b/zotan.pw-web/PlaybackHistory/LogPlaybackRequest.cs @@ -5,4 +5,4 @@ public class LogPlaybackRequest { public string? Title { get; set; } public string? Source { get; set; } public string? Link { get; set; } -} +} \ No newline at end of file diff --git a/zotan.pw-web/Program.cs b/zotan.pw-web/Program.cs index ad1f051..5caa607 100644 --- a/zotan.pw-web/Program.cs +++ b/zotan.pw-web/Program.cs @@ -42,4 +42,4 @@ app.UseAuthorization(); app.MapRazorPages(); app.MapControllers(); -app.Run(); +app.Run(); \ No newline at end of file diff --git a/zotan.pw-web/Travelynx/Travelynx.cs b/zotan.pw-web/Travelynx/Travelynx.cs index 622c40d..ac3c9bd 100644 --- a/zotan.pw-web/Travelynx/Travelynx.cs +++ b/zotan.pw-web/Travelynx/Travelynx.cs @@ -18,7 +18,7 @@ public class Travelynx : Controller { db.InsertWithIdentity(new TravelynxInfo { CheckedIn = false }); var status = db.TravelynxInfo.First(); - status.CheckedIn = rq.Status.CheckedIn; + status.CheckedIn = rq.Status!.CheckedIn; status.Train = $"{rq.Status.Train?.Type} {rq.Status.Train?.No}"; status.Destination = rq.Status.ToStation?.Name; db.Update(status); diff --git a/zotan.pw-web/Travelynx/WebhookRequest.cs b/zotan.pw-web/Travelynx/WebhookRequest.cs index c3a924c..4adece8 100644 --- a/zotan.pw-web/Travelynx/WebhookRequest.cs +++ b/zotan.pw-web/Travelynx/WebhookRequest.cs @@ -1,8 +1,8 @@ namespace zotanpw_web.Travelynx; public class WebhookRequest { - public string Reason { get; set; } - public Status Status { get; set; } + public string? Reason { get; set; } + public Status? Status { get; set; } } public class Status { @@ -38,4 +38,4 @@ public class Train { public string? Line { get; set; } public string? No { get; set; } public string? Id { get; set; } -} +} \ No newline at end of file diff --git a/zotan.pw-web/database/Tables/AlbumHistory.cs b/zotan.pw-web/database/Tables/AlbumHistory.cs index 955b556..703635a 100644 --- a/zotan.pw-web/database/Tables/AlbumHistory.cs +++ b/zotan.pw-web/database/Tables/AlbumHistory.cs @@ -12,4 +12,4 @@ public class AlbumHistoryEntry { [Column(Name = "Title"), NotNull] public string Title { get; set; } [Column(Name = "Source"), NotNull] public string Source { get; set; } [Column(Name = "Link")] public string Link { get; set; } -} +} \ No newline at end of file diff --git a/zotan.pw-web/database/Tables/PlaylistHistory.cs b/zotan.pw-web/database/Tables/PlaylistHistory.cs index b44768f..449219b 100644 --- a/zotan.pw-web/database/Tables/PlaylistHistory.cs +++ b/zotan.pw-web/database/Tables/PlaylistHistory.cs @@ -12,4 +12,4 @@ public class PlaylistHistoryEntry { [Column(Name = "Title"), NotNull] public string Title { get; set; } [Column(Name = "Source"), NotNull] public string Source { get; set; } [Column(Name = "Link")] public string Link { get; set; } -} +} \ No newline at end of file diff --git a/zotan.pw-web/database/Tables/TravelynxInfo.cs b/zotan.pw-web/database/Tables/TravelynxInfo.cs index 83695c4..24c2a57 100644 --- a/zotan.pw-web/database/Tables/TravelynxInfo.cs +++ b/zotan.pw-web/database/Tables/TravelynxInfo.cs @@ -8,4 +8,4 @@ public class TravelynxInfo { [Column(Name = "CheckedIn"), NotNull] public bool CheckedIn { get; set; } [Column(Name = "Train")] public string? Train { get; set; } [Column(Name = "Destination")] public string? Destination { get; set; } -} +} \ No newline at end of file diff --git a/zotan.pw-web/well-known/Pronouns.cs b/zotan.pw-web/well-known/Pronouns.cs index dd4359d..9f1432e 100644 --- a/zotan.pw-web/well-known/Pronouns.cs +++ b/zotan.pw-web/well-known/Pronouns.cs @@ -6,4 +6,4 @@ namespace zotanpw_web.well_known; public class Pronouns : Controller { [HttpGet] public string Get() => "she/they\n"; -} +} \ No newline at end of file diff --git a/zotan.pw-web/wwwroot/files/help.svg b/zotan.pw-web/wwwroot/files/help.svg index 2d14a65..a3e8612 100644 --- a/zotan.pw-web/wwwroot/files/help.svg +++ b/zotan.pw-web/wwwroot/files/help.svg @@ -1,5 +1,6 @@ - diff --git a/zotan.pw-web/zotan.pw-web.csproj b/zotan.pw-web/zotan.pw-web.csproj index e41927f..db6cde0 100644 --- a/zotan.pw-web/zotan.pw-web.csproj +++ b/zotan.pw-web/zotan.pw-web.csproj @@ -66,6 +66,7 @@ +