👩‍💻 chrismanbrown.gitlab.io

templating markdown+yaml frontmatter with rec and awk

smol templating

2024-03-19

This is a really small deal, but I’ve been really tickled since figuring it out this week.

Sometimes I have a markdown document with yaml frontmatter, and in the document body I sometimes want to refer to that frontmatter metadata.

---
title: templating markdown+yaml frontmatter with rec and awk
subtitle: smol templating
created: 2024-03-19
keywords: rec awk markdown yaml
---
# {{title}}

{{subtitle}}

{{created}}

This is a really small deal ...
example markdown file with template slots

The thing about rec (https://www.gnu.org/software/recutils/) is that it’s basically a superset of yaml. So if I can isolate that yaml block and then pipe it into recfmt, then it’ll fill out the templates.

Here is a small line of awk that prints all the content between the two --- lines.

awk '/^---$/{a=!a;next;}a' document.md

First, /^---$/ checks whether the current line matches ---. If it does, it toggles a. a can be anything. It’s just a variable. Call it foo or call it printme.

Because every variable in awk has an implicit value, you never need to initialize that variable. You can just start using it. Which is really cool! So in this case, the first time awk matches ---, it flips a on. Then next skips the rest of the evaluation so it doesn’t print the current line.

On the next line(s), until it matches --- again and toggles a back off, it evaluates a which is true, and performs the default action, which is printing the line.

That’s it!

> awk '/^---$/{a=!a;next;}a' document.md

title: templating markdown+yaml frontmatter with rec and awk
subtitle: smol templating
created: 2024-03-19
keywords: rec awk markdown yaml
awk and output

That is a valid rec record. And you can just pipe it into recfmt:

> awk '/^---$/{a=!a;next;}a' document.md \
  | recfmt -f document.md

---
title: templating markdown+yaml frontmatter with rec and awk
subtitle: smol templating
created: 2024-03-19
keywords: rec awk markdown yaml
---
# templating markdown+yaml frontmatter with rec and awk

smol templating

2024-03-19

This is a really small deal ...
example markdown file after template expansion

That’s it! Neat!

BONUS CONTENT: RESTRICTING MATCHES

So this particular document has a lot of --- in it which messes with my awk matching. You can ignore all of the inline --- by making sure your regex only matches instances that exist on a line by themselves: /^---$/ good, /---/ bad.

But I still have a bunch of (4) extra lines that match /^---$/ because of the markdown examples I included.

Now I could do something silly and add a whitespace at the end of those lines but that would be quite silly. And I would have to remember to pad the line every time I wrote it.

No, let’s do it the right way and have awk only match the 1st two lines.

awk '/^---$/{if (times < 2) { a=!a;times++;next;} } a' document.md

There we go. Easy as pie.

This is yet another example of getting to use variables before they are initialized. What a wonderful feature. awk is so cute.

EDIT:

acdw (https://www.acdw.net/) makes the following suggestions:

awk '/^---$/{if (times++ < 2) { a=!a;next;} } a' document.md

I think this is a great change. Love it.

awk '$0 ~ /^---$/ && times++ > 2 { a=!a;next; } a' document.md

This is acceptable. But let’s not get carried away.