Am I reinventing reStructuredText with shortcodes? Don't judge me.
I figured out how to write Hugo shortcodes to generate
tables from CSV and other formats. Didn’t even occur to me
that it was possible — or this easy — so I had to share.
This approach only works as-is for uniform, shallow structures: every row has
the same number of fields, and every field translates cleanly to a string. If
you have more complex structures, you need more complex templates.
Most Markdown parsers include some way to handle tables. Usually it involves
drawing your table with ASCII characters. Something like this, from an older
post of mine about elscreen:
I can read it just fine, but I find managing Markdown tables tedious without
editor extensions. I want easy tables. I don’t care if they look like a table
while I’m editing them. If I can copy and paste something into a shortcode?
My shortcode receives that data as a string in the .Inner
variable. How to turn that string into a table?
Just use transform.Unmarshal
Give transform.Unmarshal a formatted string, and it
gives you back a data structure. CSV text becomes an array of arrays, which we
turn into a table by iterating through everything with range.
Voila! Instant table!
Not bad, but it could be better.
that first row provides column names, which works better as table headers
than just another row
I prefer a particular style for numeric columns
what about a summary caption?
Give me a minute.
Fine-tuning the table with parameters
I’ll add a parameter for the caption. Maybe another parameter indicating
whether to expect a header row, since the first row of CSV doesn’t always
contain column names.
Now that I know how I want to use the shortcode, it’s time to implement the details.
if there’s a header row, after lets me skip past it when building the data rows
The regular expression I hand to findRE is a little naive, but it works for today
I still need to fiddle with my styles. This table’s a little wide for these
values. Maybe later.
CSV is great, but transform.Unmarshal supports other formats. What about those?
Digression: data tables
I got a little carried away when I learned how much transform.Unmarshal can
do. You could get a data structure from CSV, JSON,
TOML, or YAML!
What about — what about a data table? Mind you, I’m not talking about Hugo
data files or getJSON. That’s a great idea for
No, I’m talking about something similar to the csv-table case: arrays of JSON
objects you paste in from somewhere else to add a little information to your
Heck, you don’t even need parameters. You could put caption and header details
in the data! Might be a good idea to use a list of desired columns instead of
a simple flag. That way we can pick and choose columns without editing the row
Suppose I extracted details for the US and a couple neighbors from
The logic looks similar to csv-table, with adjustments for data format
These header fields use camel case
names like “TotalRecovered”. Piping them through
title transforms them into distinct
capitalized words: “Total Recovered.” That’s easier for me to read in a
And — sadly, considering that the topic is
cases — lang.NumFmt makes large
numbers more readable.
Wonderful! Wonderful formatting, anyways. The details are pretty sobering.
People! Wash your hands and wear a mask!
There’s really only one slight problem with data-table. I don’t need it.
Not today, anyways.
What I need: list tables
What about that first table I mentioned? You know, the elscreen quick
reference? That is the kind of table I need a shortcode for. Something like a
I tried different approaches with transform.Unmarshal and mashing YAML, TOML,
or JSON lists into something useful. That got frustratingly brittle. Time to
step back and reevaluate. What’s the simplest structure that still does what I
Maybe something line-oriented?
Every line contains one field. Blank lines separate table rows. No special
prefix characters needed, since everything’s already in a shortcode.
I like it. Easy to write, easy to read, and easy to parse with
split. Well — you need to
trim a leading newline because of how
.Inner gets handed off, but that’s the only wrinkle so far.
Perfect. This will keep me going for a while. Time to stop before I get too
Try to keep the original goal in mind when working on a thing. I could try
making a universal data table shortcode. I don’t need a universal data table
shortcode. Not yet, anyways.
Make a universal data table shortcode.
Okay not really, but I can see a few specific conveniences I’d like to add
improve the numeric value handling to recognize and properly format decimal values, including money.
format dates and timestamps
support building a simple table from .Site.Data or getJSON
control column widths
control column alignment
refactor into partials where I can, so there’s less duplication between csv-table, list-table, and data-table
I might steal more ideas from reStructuredText. It’s fun!
Speaking of fun, the dog wants to go outside again.