Plugin > Wrap element with another element

I’d like help with writing a plugin to wrap all first level <table> elements generated from markdown with a <div class="customClass">

Below is my markdown

|---
| Default aligned | Left aligned | Center aligned | Right aligned
|-|:-|:-:|-:
| 1st body: row 1, column 1 | row 1, column 2 | row 1, column 3 | row 1, column 4
| row 2, column 1 | row 2, column 2 | **row 2, column 3** | row 2, column 4
| row 3, column 1 | row 3, column 2 | row 3, column 3 | row 3, column 4
|---
| 2nd body: row 1, column 1
| row 2, column 1
|===
| Footer row

In my template/layout (article.liquid), I’d like to wrap the table generated from the markdown with a div that has a class
{{ page.content | wrap_first_level_table: '<div class="customClass">' }}

The final HTML should look exactly like this

<div class="customClass">
<table>
  <thead>
    <tr>
      <th>Default aligned</th>
      <th style="text-align: left">Left aligned</th>
      <th style="text-align: center">Center aligned</th>
      <th style="text-align: right">Right aligned</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1st body: row 1, column 1</td>
      <td style="text-align: left">row 1, column 2</td>
      <td style="text-align: center">row 1, column 3</td>
      <td style="text-align: right">row 1, column 4</td>
    </tr>
    <tr>
      <td>row 2, column 1</td>
      <td style="text-align: left">row 2, column 2</td>
      <td style="text-align: center"><strong>row 2, column 3</strong></td>
      <td style="text-align: right">row 2, column 4</td>
    </tr>
    <tr>
      <td>row 3, column 1</td>
      <td style="text-align: left">row 3, column 2</td>
      <td style="text-align: center">row 3, column 3</td>
      <td style="text-align: right">row 3, column 4</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <td>2nd body: row 1, column 1</td>
      <td style="text-align: left">&nbsp;</td>
      <td style="text-align: center">&nbsp;</td>
      <td style="text-align: right">&nbsp;</td>
    </tr>
    <tr>
      <td>row 2, column 1</td>
      <td style="text-align: left">&nbsp;</td>
      <td style="text-align: center">&nbsp;</td>
      <td style="text-align: right">&nbsp;</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>Footer row</td>
      <td style="text-align: left">&nbsp;</td>
      <td style="text-align: center">&nbsp;</td>
      <td style="text-align: right">&nbsp;</td>
    </tr>
  </tfoot>
</table>
</div>

Does anyone know a plugin that can do something like this? I don’t have a need for more robust plugin and would prefer a very simple; focused execution. Thanks for your help in advance.

Note: When I say first level <table>, I look to avoid wrapping <table>'s embedded in other tables as I don’t need a <div> around those.

Although I don’t know of a plugin, it might be useful to mention other options in case they are useful (both for you and others in the future or past). I realize you must have a specific goal that requires the DIVs, and so none of these may apply.

If your goal is just to mark the tables with a class, then you could add classes via Kramdown’s Block Attribute extension. This assumes you’re using the default Jekyll Markdown processor, based on Kramdown. For example (tested code):

|a|b
|-|-
|1|2
{: .class1 .class2}

Producing:

<table class="class1 class2">
...
</table>

Similarly, you can use Kramdown’s HTML Block extensions to mix HTML and Markdown. For example (tested code):

<div class="customClass" markdown="1">

|a|b
|-|-
|1|2

</div>

Producing:

<div class="customClass">
<table>
...
</table>
</div>

If your goal is just to style non-embedded tables without changing markup, then the CSS :not() selector could be used. For example, something like (untested code):

:not(td) table { color: red }

@chuckhoupt Amazing answers! :grinning: I am currently using the the method above that wraps the markdown table with <div class="customClass" markdown="1"> — which works pretty well.

Background
Without going too off topic here with my CSS+layout…
I have a bunch of tables in a series of articles, and was trying to avoid rewriting (or having to remember) to wrap each instance in a <div>. The wrapping <div> ensures users can scroll tables horizontally on mobile devices. I use CSS 12-column grid with 16px left & right margins and the wrapping div prevents overflow on the X-axis (keeps everything with the grid [grid-column: span 12]).

So my thought was… wouldn’t it be great to find a plugin that just wraps each instance of <table> at compilation time? I haven’t dug too far into plugins as of late.

1 Like

Sometimes one can get tables to scroll properly using variations of the following, but I know the CSS devil is in the details of layouts:

table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
}

Thanks. I have the layout working great. The wrapping div ensures the table stays within the 12-column grid and keep a nice 16px margin from the left and right side of the browser on mobile. CSS grid is fantastic. The padding and font-size always get reduced for mobile… but I do not want to keep the table just 100% width… they have many columns. Going to keep this one live for a bit longer before I close it, but I wanted to say thanks again.

PS: Including the final look to showcase the layout of the table and how it functions.