Introduction
YAML-flavored Markdown files are pretty self-explanatory - they're Markdown content files containing metadata up top in YAML format. These files are frequently used throughout many projects, from static content generators such as Wyam.io or document generation tools like docfx.
Background
We've got a web app we're trying to upgrade where we've been using LiteDB for storing articles, and while LiteDB is a fantastic database for small apps, it was getting in the way of needing to frequently update articles with new information, so we decided to move all articles to the filesystem where syncing would be much easier. We're also using LazyCache pretty extensively, so having both seemed a bit redundant. To make this work, we needed to combine the article properties with the content, and the need for a YAML-flavored Markdown handler was born.
Antoine Aubry's YamlDotNet package is a great package for parsing YAML content, and Markdig is a great library for parsing CommonMark Markdown files. But nobody had a package putting them together - at least, not until now.
Using the Code
Let's start with an Article
object for our metadata:
public class Article
{
public DateTime dateModified { get; set; }
public DateTime datePublished { get; set; }
public string headline { get; set; }
public string[] ids { get; set; }
public string slug { get; set; }
public string description { get; set; }
public string imageId { get; set; }
public string[] categories { get; set; }
public string author { get; set; }
}
(Side note: If you're not familiar with them, Cloudinary and Algolia are two fantastic products worthy of their own respective articles.)
With this article object in mind, let's build an article in YAML/Markdown format:
---
datePublished: 10/15/2019
headline: Endpoint Systems
ids:
- 12346
- 23467
slug: endpoint-systems
imageId: eps/endpointsystems-logo
categories:
- APIs
- Cloud Migration
- DevOps as a Service
- Web Apps
author: Lucas Vogel
---
## Bacon Ipsum
Bacon ipsum dolor amet kevin turducken t-bone, shankle biltong shank fatback
pork belly kielbasa spare ribs beef tenderloin buffalo. Boudin filet mignon
prosciutto pork loin, andouille fatback beef ribs pork ham hock.
Strip steak shoulder short ribs bacon. Flank cow fatback,
burgdoggen brisket picanha meatloaf pork kevin swine beef meatball chuck hamburger.
## Chuck Capicola
Chuck capicola short ribs fatback burgdoggen, turkey shoulder ball tip bacon tail
shankle drumstick filet mignon pastrami salami. Ribeye jowl filet mignon short loin
doner tail bacon prosciutto. Strip steak picanha andouille pancetta, short ribs
pork chop kielbasa meatball. Pastrami ham hock pork loin ball tip shoulder turkey
ham pork belly burgdoggen. Bacon sausage turkey pastrami.
## Kielbasa
Kielbasa t-bone pork bresaola rump kevin drumstick swine beef. Alcatra filet mignon
meatloaf flank leberkas kevin fatback brisket. Filet mignon pork belly frankfurter
kielbasa leberkas pork jowl pork loin meatball turkey pastrami bacon fatback
porchetta ball tip. Cow shankle shoulder, kielbasa pork chop ground round swine brisket
pancetta bresaola strip steak.
We'll save this to the file system as endpoint-systems.md, though technically, we can name it whatever we want because we're more interested in the slug property in the web app it's being used in.
Let's take a look at some pseudocode for parsing our file:
var articleYaml = new YamlMarkdown<Article>();
var article = articleYaml.Parse("endpoint-systems.md");
var contentMd = articleYaml.Markdown;
var contentHtml = articleYaml.Html;
The code is pretty self-explanatory -- we create a YamlMarkdown
object and initialize our parsers, and when we run the Parse
method, we get a de-serialized Article
object, our Markup content, and our Markup content pre-parsed as HTML.
To save/re-serialize your data, you run the Save
command:
articleYaml.Save(article, markdown, "endpoint-systems.md");
One thing to take note of in the current version of this - the dates come out in their default format, so you'll get something that looks like this:
datePublished: 2019-04-21T00:00:00.0000000
From our perspective, it's a non-issue as it read our incoming format, and we don't care about the timestamp - just getting a date put in there.
Summary and Reference
The EPS.Extensions.YamlMarkdown package is a 'quick and dirty' package for quickly building YAML-flavored Markdown - nothing more, nothing less. The code combines YamlDotNet and Markdig without really using them to their full potential. That being said, if there's any interest in expanding the capabilities, feel free to submit a PR to the codebase!
For more information on the packages:
History
- 10/15/2019: Initial release