Use YAML parser
This commit is contained in:
parent
ef1e976eda
commit
49457ff42f
|
@ -153,4 +153,4 @@
|
|||
|
||||
@section postfooter {
|
||||
<img src="/files/help.svg" height="450rem" title="Designed by someone I love, ~fr2">
|
||||
}
|
||||
}
|
|
@ -37,4 +37,4 @@
|
|||
<a href="https://music.apple.com/gb/album/%E3%83%AA%E3%83%95%E3%82%A1%E3%82%AF%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0-%E3%83%88%E3%83%A9%E3%83%99%E3%83%AB/1494424249">Apple Music</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>
|
|
@ -52,4 +52,4 @@
|
|||
</div>
|
||||
<script src="~/js/site.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
|
@ -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<BlogPost> 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<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 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<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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
ViewData["title"] = "blog";
|
||||
ViewData["subtitle"] = post.Shorthand;
|
||||
#if (DEBUG)
|
||||
post.UpdateContent();
|
||||
post.UpdateContentAndMetadata();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -20,4 +20,4 @@
|
|||
<h1 id="post">IPv6-native networking: a project report</h1>
|
||||
<div align="justify">
|
||||
@Html.Raw(post.Content)
|
||||
</div>
|
||||
</div>
|
|
@ -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"*.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -38,4 +38,4 @@ public class LogPlayback : Controller {
|
|||
Response.StatusCode = 403;
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,4 +5,4 @@ public class LogPlaybackRequest {
|
|||
public string? Title { get; set; }
|
||||
public string? Source { get; set; }
|
||||
public string? Link { get; set; }
|
||||
}
|
||||
}
|
|
@ -42,4 +42,4 @@ app.UseAuthorization();
|
|||
app.MapRazorPages();
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
app.Run();
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -6,4 +6,4 @@ namespace zotanpw_web.well_known;
|
|||
public class Pronouns : Controller {
|
||||
[HttpGet]
|
||||
public string Get() => "she/they\n";
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" width="500mm" height="400mm"
|
||||
<svg xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" width="500mm" height="400mm"
|
||||
version="1.1" viewBox="0 0 500 400"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>
|
||||
|
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.1 MiB |
|
@ -66,6 +66,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0"/>
|
||||
<PackageReference Include="System.Data.SQLite" Version="1.0.115"/>
|
||||
<PackageReference Include="YamlDotNet" Version="12.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
Loading…
Reference in a new issue