Markdown to RST table conversion#

The prebuild.py and postbuild.py scripts enable markdown table rendering when using Sphinx and the recommonmark extension.

  1. Prebuild.py makes temporary copies of markdown files and converts markdown tables fenced by <!--table--> <!--endtable--> comment lines to RST tables fenced by eval_rst code blocks.
  2. Sphinx builds HTML using the markdown files with the converted rst tables.
  3. Postbuild.py returns the markdown files to their original state and removes the temporary files created by prebuild.py.

Formatting markdown tables#

To label a markdown table for conversion, add <!--table--> on the line prior to the table and <!--endtable--> on the line after the table. For example:

<!--table-->
| Tables        | Are           | Cool  |
| ------------- |-------------- | ----- |
| col 3 is      | nifty         | $1600 |
| col 2 is      | awesome       |   $12 |
| zebra stripes | are neat      |    $1 |
<!--endtable-->

Limitations#

The underlying markdown to RST conversion is handled by Pandoc, but there are some limitations to what it can parse.

HTML tags

Pandoc converts HTML tags in markdown tables to raw HTML directives in RST. This breaks the table syntax.

The prebuild.py and postbuild.py scripts can handle <br> and <li> HTML tags. Do not use any other HTML tags within markdown tables.

An alternative to <li> tags is &bull;, which inserts a bullet point character.

If you require other HTML tags, please open an issue in rackerlabs/docs-rackspace to have support added.

Empty cells

The conversion process cannot handle empty cells in tables. If you require a blank cell, use &nbsp; in the cell. Example:

<!--table-->
Correct name | Notes
--- | ---
Apache | This is a good name.
Bash shell | &nbsp;
CentOS | &nbsp;
Git   | We all love Git.
<!--endtable-->

See HTML named special symbols.

Configuration#

The prebuild.py and postbuild.py scripts read configuration settings from the tox.ini file in the [mdsphinx] section. The following settings are available:

docdir
The documentation directory, relative to tools/. This is usually ../doc/.
mdsuffix
The suffix being used for markdown files. This is usually .md.
tempsuffix
The temporary suffix used during the conversion process. This is usually .temp.
ignore
A comma-separated list of files to ignore. Use file names only without paths. Does not accept directories or wildcards (*).
debug

True - show debugging output.

False - hide debugging output.

Sample configuration

[mdsphinx]
docdir = ../doc/
mdsuffix = .md
tempsuffix = .temp
ignore = README.md, draft.md
debug = False

Makefile html target#

The prebuild.py and postbuild.py scripts are integrated into the Makefile html target. They run automatically when the tox -e checkbuild or make html commands are run.

html:
@echo "\nConverting MD tables to RST"
python3 ../tools/prebuild.py
@echo
$(SPHINXBUILD) -E -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo "\nCleaning up from MD table conversion"
python3 ../tools/postbuild.py
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

Prebuild.py#

Convert tables in MD files to RST prior to processing by Sphinx.

Warning

The script does not perform any tests on the conversion nor does it rollback if it encounters an error. Always check the rendered output. It is possible that some errors may occur that require manual fixes, especially when converting complex tables.

prebuild.adjustrow(row)[source]#

Convert a grid row to a list-table row.

Parameters:row (str) – a row of grid table text
Returns:a row of list-table text
Return type:str
prebuild.buildtable(gridtable)[source]#

Build an RST list-table from an RST grid table.

Parameters:gridtable (list) – an RST grid table
Returns:an RST list-table
Return type:str
prebuild.copydocs(files, tempsuffix)[source]#

Copy files for processing and move originals to temp filenames.

Parameters:
  • files (list) – list of filenames
  • temptsuffix – temporary file extension addition
Type:

str

Returns:

0 (Success), 1 (Failure)

Return type:

int

Example:
>>> copydocs(['file1.md.temp','file2.md.temp'], '.temp')
1
prebuild.listfiles(docroot, suffix, ignore)[source]#

List docs with suffix extension in docroot directory.

Parameters:
  • docroot (str) – directory containing documentation files
  • suffix (str) – extension of files to collect
  • ignore (str) – file(s) to ignore
Returns:

list of filenames in docroot with the suffix extension

Return type:

list

Example:
>>> listfiles('./', '.none', 'README.md')
[]
prebuild.listtable(mdstring)[source]#

Process markdown string to convert grid tables to list-tables.

Parameters:mdstring (str) – markdown string with RST grid tables
Returns:markdown string with RST grid tables converted to RST list-tables
Return type:str
prebuild.parsedoc(mdstring)[source]#

Find MD tables and convert them to RST grid tables.

Parameters:mdstring (str) – markdown string with <!--table--> <!--endtable--> fenced tables
Returns:markdown string with MD table converted to RST grid table
Return type:str
Example:
>>> parsedoc('A string of markdown.')
'A string of markdown.'
prebuild.postparse(mdstring)[source]#

Swap HTML substitutes for strings.

Parameters:mdstring (str) – markdown string
Returns:markdown string with parse-safe substitutes converted to strings
Return type:str
Example:
>>> postparse('A string of @br@markdown.')
'A string of \n      markdown.'
prebuild.preparse(mdstring)[source]#

Swap HTML tags for substitutes.

Parameters:mdstring (str) – markdown string
Returns:markdown string with HTML tags converted to parse-safe strings
Return type:str
Example:
>>> preparse('A string of <br />markdown.')
'A string of @br@markdown.'
prebuild.processdocs(files)[source]#

Convert tables in a list of docs using parsedoc() and listtable().

Parameters:files (list) – files to process
Returns:0 (Success), 1 (Failure)
Return type:int
Example:
>>> processdocs(['file1.md.temp','file2.md.temp'])
1
prebuild.readfile(infile)[source]#

Read data from file and return text as a string.

Parameters:infile (str) – file to read
Returns:text (Success), 1 (Failure)
Return type:str or int
Example:
>>> readfile('tools/example.txt')
'Hello world!'
prebuild.writefile(outfile, data)[source]#

Write data to file.

Parameters:outfile – file to write
Returns:0 (Success), 1 (Failure)
Return type:int
Example:
>>> writefile('tools/example.txt', 'Hello world!')
0

Postbuild.py#

Remove temp files created by prebuild and rename original files.

postbuild.cleanup(files, tempsuffix)[source]#

Revert source files and remove temp files.

Parameters:
  • files (list) – files with .temp extension
  • temptsuffix – temporary file extension addition
Type:

str

Returns:

0 (Success), 1 (Failure)

Return type:

int

Example:
>>> cleanup(['file1.md.temp','file2.md.temp'], '.temp')
0

Example input and output#

Prebuild.py converts a markdown file with the following content:

# Heading 1
This is some text

## Heading 2
This is some more text. This is an *emphasized* word.

<!--table-->
| Tables        | Are           | Cool  |
| ------------- |-------------- | ----- |
| col 3 is      | nifty         | $1600 |
| col 2 is      | awesome       |   $12 |
| zebra stripes | are neat      |    $1 |
<!--endtable-->

More paragraphs, tables, and other markdown text.

to a markdown file with the following content:

# Heading 1
This is some text

## Heading 2
This is some more text. This is an *emphasized* word.

```eval_rst
.. list-table::
   :widths: 33 33 33
   :header-rows: 1

   * - Tables
     - Are
     - Cool
   * - col 3 is
     - nifty
     - $1600
   * - col 2 is
     - awesome
     - $12
   * - zebra stripes
     - are neat
     - $1

```

More paragraphs, tables, and other markdown text.