Pelican: Markdown Tables & CSS

Created on 28 Jul 2014  Â·  16Comments  Â·  Source: getpelican/pelican

I've got some tables written in markdown that I'm trying to add bootstrap rendering for.
An example is here: http://crunk.io/understanding-ejuice-and-branching-out.html#blends

I'm currently using a forked copy of the pelican-bootstrap3 theme.

I first asked about this feature on the original theme authors github repo here: https://github.com/DandyDev/pelican-bootstrap3/issues/116.

After a small discussion, I understand I have at least 3 options to make this work:

  1. Write the tables in the markdown document as inline html.
  2. Write a kramdown plugin for pelican.
  3. Add a custom stylesheet to apply a set of styles to all tables.

When the markdown parser renders the table, the generated code is essentially:

<table>
    <thead>
        <tr>
            <th>Heading1</th>
            <th>Heading2</th>
            <th>Heading3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Data1</td>
            <td>Data2</td>
            <td>Data3</td>
        </tr>
    </tbody>
</table>

To improve the rendering, I need to apply the bootstrap attributes to the table tag:

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

... or:

<table class="table table-condensed table-bordered table-hover">
    ...
</table>

With the proper bootstrap attributes applied, it looks like this instead:
Rendered Properly

I'm curious if anyone has any insight with this issue and can suggest a good approach or identify a solution I may not be aware of.

Thanks!

Most helpful comment

Another hack would be to add this to the bottom of the template:

<script>
var tables, i;
tables = document.getElementsByTagName('table');
for (i=0;i<tables.length;i++) {
  tables[i].className = 'table table-striped';
}
</script>

All 16 comments

Pelican hands the content to the specified processor, which in your case is Python-Markdown. That's where I would start looking. If you cannot achieve your desired results within the capabilities of the Python-Markdown library, perhaps one of the alternative options you listed above might be best.

This issue feels ridiculous. Such a simple problem but after several hours I still can't get a working solution.

Per the author of python-markdown:

First, see my position on adding features to the existing table extension as explained in issue #74. My position hasn't changed. In fact, there are a few third-party extensions which implement more feature rich table syntax as listed on the wiki. That said, seems to me like raw html will give you the most power to best meet your needs.

I found a stackoverflow thread in which several solutions are proposed:

  1. Use this fork of python-markdown
  2. Use the third-party Grid Tables extension

Installing third-party extensions for python-markdown is very poorly documented, however after figuring it out, the third-party extension still would not apply the styles correctly - and parsed the tables very poorly.

After replacing python-markdown with the python-markdown fork, the styles were still not applied correctly.

Which leaves basically two solutions:

  1. Stop writing tables in markdown, and write them in inline HTML - which is not so much of a solution as it is just giving up.
  2. Figure out how to do this in CSS/less, which again - is more like giving up than figuring it out.

This is such a basic thing and _should_ be really easy to implement in python.

Markdown itself is a very simple abstraction wasn't really developed with complex needs in mind. In fact, the entire purpose was to fall back to HTML when warranted. That's a core feature — not just a capitulation.

That said, I understand how frustrating it must feel when all you want to do is add a class to the <table> tag. If it were me, I'd be tempted to add a bit of custom CSS to achieve the desired effect.

I don't see either of the above options as "giving up" so much as finding a solution that doesn't require so much frustration. (^_^)

Second option should be pretty doable. Looking at your source, only instances of css selector article table should be the tables coming from Markdown file content. You just need to style that same as .table class.

_Edit_
There is also the option of putting those classes dynamically via JS. Since you have JQuery coming from bootstrap, it should be as easy as adding:

<script>
  $(document).ready(function () {
    $("article table").addClass("table table-condensed table-bordered table-hover");
  });
</script>

Markdown itself is a very simple abstraction wasn't really developed with complex needs in mind. In fact, the entire purpose was to fall back to HTML when warranted. That's a core feature — not just a capitulation.

I understand that's the case, it's just terribly inconvenient. In both vi & sublime text I have support for markdown table editing that acts much like excel, which I would completely lose if I wrote them in inline html.

As far as writing CSS/less rather than getting the parser to simply write the class attribute correctly - these are things I have no skill in. After looking into how to make the dynamic css/less bindings work correctly and failing, I downloaded bootstrap, grepped all the .table attributes out, and dumped them into a custom.css file where they are applied to all tables.

It kind of works, but I'm sure I broke tons of junk in the process. Bah.

/* worse workaround ever */
table {
  border-spacing: 0;
  border-collapse: collapse;
}
td,
th {
  padding: 0;
}
}
table {
  background-color: transparent;
}
th {
  text-align: left;
}
table {
  width: 100%;
  max-width: 100%;
  margin-bottom: 20px;
}
table > thead > tr > th,
table > tbody > tr > th,
table > tfoot > tr > th,
table > thead > tr > td,
table > tbody > tr > td,
table > tfoot > tr > td {
  padding: 8px;
  line-height: 1.42857143;
  vertical-align: top;
  border-top: 1px solid #ddd;
}
table > thead > tr > th {
  vertical-align: bottom;
  border-bottom: 2px solid #ddd;
}
table > caption + thead > tr:first-child > th,
table > colgroup + thead > tr:first-child > th,
table > thead:first-child > tr:first-child > th,
table > caption + thead > tr:first-child > td,
table > colgroup + thead > tr:first-child > td,
table > thead:first-child > tr:first-child > td {
  border-top: 0;
}
table > tbody + tbody {
  border-top: 2px solid #ddd;
}
table table {
  background-color: #fff;
}
table-condensed > thead > tr > th,
table-condensed > tbody > tr > th,
table-condensed > tfoot > tr > th,
table-condensed > thead > tr > td,
table-condensed > tbody > tr > td,
table-condensed > tfoot > tr > td {
  padding: 5px;
}
table-bordered {
  border: 1px solid #ddd;
}
table-bordered > thead > tr > th,
table-bordered > tbody > tr > th,
table-bordered > tfoot > tr > th,
table-bordered > thead > tr > td,
table-bordered > tbody > tr > td,
table-bordered > tfoot > tr > td {
  border: 1px solid #ddd;
}
table-bordered > thead > tr > th,
table-bordered > thead > tr > td {
  border-bottom-width: 2px;
}
table-striped > tbody > tr:nth-child(odd) > td,
table-striped > tbody > tr:nth-child(odd) > th {
  background-color: #f9f9f9;
}
table-hover > tbody > tr:hover > td,
table-hover > tbody > tr:hover > th {
  background-color: #f5f5f5;
}
table col[class*="col-"] {
  position: static;
  display: table-column;
  float: none;
}
table td[class*="col-"],
table th[class*="col-"] {
  position: static;
  display: table-cell;
  float: none;
}

tr.collapse.in {
  display: table-row;
}
tbody.collapse.in {
  display: table-row-group;
}

It is the problem with markdown, it is good for simple use cases but when you need more ... So another alternative is restructuredtext: http://docutils.sourceforge.net/docs/ref/rst/directives.html#table (you can add a :class: attribute).

Hi Nathan. Did you ever come up with a solution that provided some modicum of satisfaction?

Thanks @justinmayer for your concern. I did not find a solution, but I have not spent anymore time investigating. I have however been learning restructedtext (thanks @saimn) which I had been meaning to do for awhile and have found it to be much more robust and feature inclusive.

So, how can I get the markdown table which have black line?

good! but the theme must contain bootstrap? @ingwinlu

@avaris Thanks! Works for me.

Another hack would be to add this to the bottom of the template:

<script>
var tables, i;
tables = document.getElementsByTagName('table');
for (i=0;i<tables.length;i++) {
  tables[i].className = 'table table-striped';
}
</script>

Another workaround - post-process the output via something like:

grep '<table>' output  -r -l --include '*.html' \
 | xargs -r sed -i 's/<table>/<table class="table table-striped">/'

markdown generated tables need to have a class applied and the problem would be solved.

Other plugins may also generate tables so applying a table css style defeats the purpose.

It is a simple fix. If we had a markdown specific css class that always gets applied then we can target it.

What is the issue?

Yet another workaround is to put this into your pelicanconf.py:

# for bootstrap:
# table_css_class = 'table table-striped'

# for m.css:
table_css_class = 'm-table'

import markdown.extensions.tables

class BetterMDTableProcessor(markdown.extensions.tables.TableProcessor):
    def run(self, parent, blocks):
        super().run(parent, blocks)
        for e in parent:
            if e.tag == 'table':
                e.attrib['class'] = table_css_class

class BetterMDTableExtension(markdown.extensions.tables.TableExtension):
    def extendMarkdown(self, md):
        if '|' not in md.ESCAPED_CHARS:
            md.ESCAPED_CHARS.append('|')
        md.parser.blockprocessors.register(BetterMDTableProcessor(md.parser), 'table', 75)

MARKDOWN = {
    'extensions': [ BetterMDTableExtension() ],
    'extension_configs': {
        'markdown.extensions.codehilite': {'css_class': 'm-code'},
        'markdown.extensions.footnotes': {},
        'markdown.extensions.meta': {},
        'markdown.extensions.toc': { 'permalink': True },
    },
    'output_format': 'html5',
}

@Goddard - I think the issue is that the maintainer of the Python markdown package doesn't want to add any features to the table extension. Don't even a trivial css_class configuration item that would work analogously to the css_class item of the codehilite extension.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Lucas-C picture Lucas-C  Â·  4Comments

chenjiandongx picture chenjiandongx  Â·  3Comments

mwcz picture mwcz  Â·  5Comments

soulchainer picture soulchainer  Â·  7Comments

quack1 picture quack1  Â·  6Comments