Skip to content

Instantly share code, notes, and snippets.

@laurentkempe
Created October 10, 2020 13:06
Show Gist options
  • Save laurentkempe/6bc27cde6742bb166ab5469032ed9874 to your computer and use it in GitHub Desktop.
Save laurentkempe/6bc27cde6742bb166ab5469032ed9874 to your computer and use it in GitHub Desktop.
Fixing blog permalinks in front matter
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Markdig;
using Markdig.Extensions.Yaml;
using Markdig.Syntax;
using YamlDotNet.Serialization;
namespace blogFix
{
/// <summary>
/// Most code from https://khalidabuhakmeh.com/parse-markdown-front-matter-with-csharp
/// </summary>
internal class Program
{
private static readonly MarkdownPipeline Pipeline
= new MarkdownPipelineBuilder()
// YAML Front Matter extension registered
.UseYamlFrontMatter()
.Build();
private static async Task Main(string[] args)
{
Console.WriteLine("Fixing blog!");
var directory = Directory
.GetFiles(@"C:\Users\laure\projects\blog\source\_posts");
var fileContent = directory.Select(f => new {file = f, fileContent = File.ReadAllText(f)});
var posts = fileContent
.Select(md => new {file = md.file, fileContent = md.fileContent, fileFrontMatter = md.fileContent.GetFrontMatter<BlogFrontMatter>()})
.ToList();
foreach (var post in posts.OrderBy(p => p.fileFrontMatter.Date))
{
Console.WriteLine($"/{post.fileFrontMatter.Date.Year}/{post.fileFrontMatter.Date.Month:00}/{post.fileFrontMatter.Date.Day:00}/{post.fileFrontMatter.Permalink}/");
await ReplacePermalink(post.file, post.fileFrontMatter);
}
}
private static async Task ReplacePermalink(string file, BlogFrontMatter fileFrontMatter)
{
var allLines = await File.ReadAllLinesAsync(file);
var lines = allLines.ToList();
for (var index = 0; index < allLines.ToList().Count; index++)
{
if (lines[index].StartsWith("permalink"))
{
lines[index] = "permalink: " +
$"/{fileFrontMatter.Date.Year}/{fileFrontMatter.Date.Month:00}/{fileFrontMatter.Date.Day:00}/{fileFrontMatter.Permalink}/";
}
}
await File.WriteAllLinesAsync(file, lines);
}
}
public class BlogFrontMatter
{
// [YamlMember(Alias = "tags")]
// public string Tags { get; set; }
[YamlMember(Alias = "title")] public string Title { get; set; }
[YamlMember(Alias = "permalink")] public string Permalink { get; set; }
[YamlMember(Alias = "date")] public DateTime Date { get; set; }
[YamlMember(Alias = "image")] public string Image { get; set; }
[YamlMember(Alias = "image_credit_name")]
public string ImageCreditName { get; set; }
[YamlMember(Alias = "image_credit_url")]
public string ImageCreditUrl { get; set; }
[YamlMember(Alias = "image_alt")] public string ImageAlt { get; set; }
[YamlMember(Alias = "redirect_from")] public string[] RedirectFrom { get; set; }
// [YamlIgnore]
// public IList<string> GetTags => Tags?
// .Split(",", StringSplitOptions.RemoveEmptyEntries)
// .Select(x => x.Trim())
// .ToArray();
}
public static class MarkdownExtensions
{
private static readonly Deserializer YamlDeserializer =
new DeserializerBuilder()
.IgnoreUnmatchedProperties()
.Build();
private static readonly MarkdownPipeline Pipeline
= new MarkdownPipelineBuilder()
.UseYamlFrontMatter()
.Build();
public static T GetFrontMatter<T>(this string markdown)
{
var document = Markdown.Parse(markdown, Pipeline);
var block = document
.Descendants<YamlFrontMatterBlock>()
.FirstOrDefault();
if (block == null)
return default;
var yaml =
block
// this is not a mistake
// we have to call .Lines 2x
.Lines // StringLineGroup[]
.Lines // StringLine[]
.OrderByDescending(x => x.Line)
.Select(x => $"{x}\n")
.ToList()
.Select(x => x.Replace("---", string.Empty))
.Where(x => !string.IsNullOrWhiteSpace(x))
.Aggregate((s, agg) => agg + s);
return YamlDeserializer.Deserialize<T>(yaml);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment