Home Blog CV Projects Patterns Notes Book Colophon Search

reStructuredText Field Lists

20 Apr, 2009

reStructuredText field lists look like this:

:field1: value1
:field2: value2
... etc ...

They are often used at the start of documents to specify the name of the author and the date of the post. On this page's source code I'm using them to specify the post tags and the posted date like this:

:Posted: 2009-04-20 21:06
:Tags: Python

Here's the code I use to convert this to HTML:

from docutils import core
from docutils.writers.html4css1 import Writer

def rstify(string):
    w = Writer()
    result = core.publish_parts(string, writer=w)['html_body']
    # Strip the first and last lines
    result = '\n'.join(result.split('\n')[1:-2])
    return result

This renders correctly as an HTML table with two columns:

<table class="docinfo" rules="none" frame="void">
<col class="docinfo-name">
<col class="docinfo-content">
<tbody valign="top">
<tr class="field"><th class="docinfo-name">Posted:</th><td class="field-body">2009-04-20 21:06</td>
</tr>
<tr class="field"><th class="docinfo-name">Tags:</th><td class="field-body">Python</a></td>
</tr>
</tbody>
</table>

If the field name is more than 14 characters long though it doesn't render this way, instead rendering the field name and the field value as separate rows, even if the rest of the table is in two columns:

XXX

You can fix this from the command line when running rst2html.py by specifying --field_name_limit=0. Here's a little hack to make it render the same way in code:

from docutils import core
from docutils.writers.html4css1 import Writer, HTMLTranslator

class CustomHTMLTranslator(HTMLTranslator):
    def __init__(self, *k, **p):
        HTMLTranslator.__init__(self, *k, **p)
        # Allow long field names more than 14 characters in reStructuredText field lists
        self.settings.field_name_limit = 0

def rstify(string):
    w = Writer()
    w.translator_class = CustomHTMLTranslator
    result = core.publish_parts(string, writer=w)['html_body']
    # Strip the first and last lines
    result = '\n'.join(result.split('\n')[1:-2])
    return result

Copyright James Gardner 1996-2020 All Rights Reserved. Admin.