Rodney
Rodney

Reputation: 3061

Python 3 markdown to html: how to enable code-fencing / syntax highlighting

I'm trying to programatically generate html from .md source files.

If I edit them in the Remarkable editor, which uses python3 markdown it works. By which I mean html exported from the editor is correct. For example the source

~~~~python
import os, sys
~~~~

yields html which is approximately rendered as

import os, sys

However, when my python script tries to render the text this syntax appears not to be supported. The fencing tags just appear in the output instead of being parsed. I basically do this:

html = markdown.markdown(md_text)

Python appears not to recognise the fenced_code extension:

>>> markdown.markdown (markdown_text, extensions=markdown.extensions.fenced_code)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'markdown.extensions' has no attribute 'fenced_code'
>>> dir (markdown.extensions)
['Extension', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'parseBoolValue', 'unicode_literals', 'warnings']

I assume the relevant extension must be there since Remarkable is processing the code correctly.

How do I enable code fencing / syntax highlighting?

Github-style fencing is the same, ie it works in remarkable and not in my script. Block indenting just seems to do block-quote highlighting.

Upvotes: 2

Views: 4791

Answers (1)

larsks
larsks

Reputation: 312630

The first error you're getting...

AttributeError: module 'markdown.extensions' has no attribute 'fenced_code'

...is because you haven't imported markdown.extensions.fenced_code:

>>> import markdown.extensions.fenced_code

But then you have a second problem, which is that the extensions keyword takes a list:

>>> markdown.markdown (markdown_text, extensions=markdown.extensions.fenced_code)
TypeError: 'module' object is not iterable

But actually, the markdown.markdown method isn't expecting a module:

>>> markdown.markdown (markdown_text, extensions=[markdown.extensions.fenced_code])
TypeError: Extension "builtins.module" must be of type: "markdown.Extension"

You can do what the error says and pass in a class instance, or you can just pass in the extension name as a string and let markdown figure it out:

>>> markdown.markdown (markdown_text, extensions=['fenced_code'])

Hopefully it's obvious, but using this model you don't need to import markdown.extensions.fenced_code either using this mechanism, because you're never using the module name. That is, this is a complete example:

#!/usr/bin/python3

import markdown

markdown_text = '''# This is a test

~~~~python
import os, sys
~~~~
'''

print(markdown.markdown(markdown_text,
                        extensions=['fenced_code', 'codehilite']))

Note that code highlighting is provided by a the codehilite extension, which will only work if you also have the pygments library installed.

Upvotes: 6

Related Questions