Aug 2022

Markdown is a popular markup language used to format text. It's great for documentation, blog posts, and other types of written content. Frontmatter is a feature of Markdown that allows you to store metadata such as the title, author, date, tags, and other information in a YAML block at the top of the file. YAML itself is yet another markup language -- literally what the acronym stands for -- and a superset of JSON that supports comments, multi-line strings, arrays, and other features.

.NET has two popular and well-supported libraries to help parse frontmatter:

  • Markdig to parse Markdown into structured blocks.
  • YamlDotNet to deserialize YAML content into a dictionary or object.

With the following sample markdown content:

---
title: How to Parse Markdown Frontmatter
desc: Article describing how to parse YAML frontmatter from a Markdown file.
posted: 2020-01-01
tags: [software, dotnet]
---

# Document Title

With some text

This is a code sample to parse and extract frontmatter:

using System;
using System.Linq;
using System.Collections.Generic;
using Markdig;
using Markdig.Extensions.Yaml;
using Markdig.Syntax;
using YamlDotNet.Serialization;

var markdown = "...";

// create a markdown parsing pipeline (with YAML frontmatter support)
// and parse the markdown text into blocks
var pipeline = new MarkdownPipelineBuilder().UseYamlFrontMatter().Build();
var document = Markdown.Parse(markdown, pipeline);

// extract the first YAML frontmatter block
// and assemble it into a string
var yamlBlock = document.Descendants<YamlFrontMatterBlock>().FirstOrDefault();
var yaml = yamlBlock?.Lines.ToString() ?? "";

// create a YAML deserializer
// and deserialize YAML into a dictionary (or object)
var deserializer = new DeserializerBuilder().Build();
var frontmatter = deserializer.Deserialize<Dictionary<string, object>>(yaml);

Console.WriteLine(frontmatter["title"]);

YamlDotNet can also deserialize into a strongly typed object:

public class PostFrontMatter
{
    [YamlMember(Alias = "title")]
    public string? Title { get; set; }

    [YamlMember(Alias = "desc")]
    public string? Description { get; set; }

    [YamlMember(Alias = "posted")]
    public DateTime Posted { get; set; }

    [YamlMember(Alias = "tags")]
    public List<string> Tags { get; set; } = new();
}

var frontmatter = deserializer.Deserialize<PostFrontMatter>(yaml);
Console.WriteLine(frontmatter.Title);

Working example on .NET Fiddle: https://dotnetfiddle.net/aV9TZL

Comments

No comments posted.