HTML Inside Kramdown Table Cells

The question of how to write a list inside of a table cell with Kramdown recently came up in this Jekyll Talk thread — prompting me to look for a solution.

Unfortunately something like this doesn’t work:

| Fruit         | Price         | Advantages         |
| ------------- | ------------- | ------------------ |
| Bananas       | $1.34         | - built-in wrapper |
|               |               | - bright color     |
| ------------- | ------------- | ------------------ |
| Oranges       | $2.10         | - cures scurvy     |
|               |               | - tasty            |

Kramdown treats each new line as a row and doesn’t render the bullet lists properly in the Banana and Oranges rows as can be seen below.

FruitPriceAdvantages
Bananas$1.34- built-in wrapper
- bright color
Oranges$2.10- cures scurvy
- tasty

Throwing HTML at the problem doesn’t quite work either.

| Fruit         | Price         | Advantages         |
| ------------- | ------------- | ------------------ |
| Bananas       | $1.34         | <ul><li>built-in wrapper</li><li>bright color</li></ul> |
| ------------- | ------------- | ------------------ |
| Oranges       | $2.10         | <ul><li>cures scurvy</li><li>tasty</li></ul> |

Instead of rendering the HTML, it is escaped and outputted as a single line of text.

FruitPriceAdvantages
Bananas$1.34<ul><li>built-in wrapper</li><li>bright color</li></ul>
Oranges$2.10<ul><li>cures scurvy</li><li>tasty</li></ul>

What is needed is a way of telling Kramdown to leave the HTML alone and output as is. Thankfully there is such a way using the nomarkdown extension.

Simply wrap the HTML with {::nomarkdown} ... {:/} like so:

| Fruit         | Price         | Advantages         |
| ------------- | ------------- | ------------------ |
| Bananas       | $1.34         | {::nomarkdown}<ul><li>built-in wrapper</li><li>bright color</li></ul>{:/} |
| ------------- | ------------- | ------------------ |
| Oranges       | $2.10         | {::nomarkdown}<ul><li>cures scurvy</li><li>tasty</li></ul>{:/} |

And the table will output as expected1.

FruitPriceAdvantages
Bananas$1.34
  • built-in wrapper
  • bright color
Oranges$2.10
  • cures scurvy
  • tasty

While not as readable as a pure Markdown solution, it gets the job done.

From what I understand Pandoc and RedCarpet have better support for this sort of thing if you want to use their flavor of Markdown.

Since Kramdown is the default renderer used by Jekyll I think I’ll just suck it up and stick with this workaround for now :expressionless:.

  1. Be sure to keep all of your HTML on a single line for this to work properly. 

3 Comments

Willy McAllister

I have the opposite challenge … getting kramdown to process text inside a <details> tag. I would prefer not to drop into html when writing <details>. The solution I’ve come across is http://movb.de/jekyll-details-support.html. This plugin works great, but it is not supported by github pages, so I have to transfer my whole _site to github. Have you come across a kramdown extension that says “hey kramdown, process me!”.

Michael Rose

Have you looked at the markdownify filter? I use it to do something similar to place Markdown text inside of a figcaption element.

There’s several ways to handle this without the need of a plugin. You could do something like this with a Liquid capture:

{% capture your_md %}Here is some Markdown you'd like to **capture**.{% endcapture %}

Then inject the captured variable into whatever you want and add the Markdownify filter so Kramdown processes it like so:

<details>
  {{ your_md | markdownify }}
</details>

Which would give you the following HTML output:

<details>
  <p>Here is some Markdown you'd like to <strong>capture</strong>.</p>
</details>

If you don’t want to bother with all the captures you could build your own Jekyll include that you could pass text through as a parameter to be Markdownified.

Willy McAllister

Captures work nicely! I added a summary, and removed the spurious <p> tags so the summary lines up with the open icon.

{% capture summary %}Here is my Markdown *summary*{% endcapture %}
{% capture details %}Here is my Markdown **captured**.{% endcapture %}

<details>
    <summary>{{ summary | markdownify | remove: '<p>' | remove: '</p>' }}</summary>
    {{ details | markdownify }}
</details>

Leave a Comment