deb-python-misaka/misaka/api.py

228 lines
7.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
from ._hoedown import lib, ffi
from .callbacks import python_callbacks, to_string
from .constants import *
from .utils import extension_map, html_flag_map, args_to_int, \
deprecation, to_string
__all__ = [
'html',
'smartypants',
'Markdown',
'BaseRenderer',
'HtmlRenderer',
'HtmlTocRenderer',
'args_to_int',
'extension_map',
'html_flag_map',
'EXT_TABLES',
'EXT_FENCED_CODE',
'EXT_FOOTNOTES',
'EXT_AUTOLINK',
'EXT_STRIKETHROUGH',
'EXT_UNDERLINE',
'EXT_HIGHLIGHT',
'EXT_QUOTE',
'EXT_SUPERSCRIPT',
'EXT_MATH',
'EXT_NO_INTRA_EMPHASIS',
'EXT_SPACE_HEADERS',
'EXT_MATH_EXPLICIT',
'EXT_DISABLE_INDENTED_CODE',
'HTML_SKIP_HTML',
'HTML_ESCAPE',
'HTML_HARD_WRAP',
'HTML_USE_XHTML',
'LIST_ORDERED',
'LI_BLOCK',
'TABLE_ALIGN_LEFT',
'TABLE_ALIGN_RIGHT',
'TABLE_ALIGN_CENTER',
'TABLE_ALIGNMASK',
'TABLE_HEADER',
'AUTOLINK_NORMAL',
'AUTOLINK_EMAIL',
]
IUNIT = 1024
OUNIT = 64
MAX_NESTING = 16
def html(text, extensions=0, render_flags=0):
"""
Convert markdown text to HTML.
``extensions`` can be a list or tuple of extensions (e.g.
``('fenced-code', 'footnotes', 'strikethrough')``) or an integer
(e.g. ``EXT_FENCED_CODE | EXT_FOOTNOTES | EXT_STRIKETHROUGH``).
``render_flags`` can be a list or tuple of flags (e.g.
``('skip-html', 'hard-wrap')``) or an integer
(e.g. ``HTML_SKIP_HTML | HTML_HARD_WRAP``).
"""
extensions = args_to_int(extension_map, extensions)
render_flags = args_to_int(html_flag_map, render_flags)
ib = lib.hoedown_buffer_new(IUNIT)
ob = lib.hoedown_buffer_new(OUNIT)
renderer = lib.hoedown_html_renderer_new(render_flags, 0)
document = lib.hoedown_document_new(renderer, extensions, 16);
lib.hoedown_buffer_puts(ib, text.encode('utf-8'))
lib.hoedown_document_render(document, ob, ib.data, ib.size);
lib.hoedown_buffer_free(ib);
lib.hoedown_document_free(document);
lib.hoedown_html_renderer_free(renderer);
try:
return to_string(ob)
finally:
lib.hoedown_buffer_free(ob);
def smartypants(text):
"""
Transforms sequences of characters into HTML entities.
=================================== ===================== =========
Markdown HTML Result
=================================== ===================== =========
``'s`` (s, t, m, d, re, ll, ve) ’s s
``"Quotes"`` “Quotes” “Quotes”
``---`` — —
``--`` –
``...`` … …
``. . .`` … …
``(c)`` © ©
``(r)`` ® ®
``(tm)`` ™ ™
``3/4`` ¾ ¾
``1/2`` ½ ½
``1/4`` ¼ ¼
=================================== ===================== =========
"""
byte_str = text.encode('utf-8')
ob = lib.hoedown_buffer_new(OUNIT)
lib.hoedown_html_smartypants(ob, byte_str, len(byte_str))
try:
return to_string(ob)
finally:
lib.hoedown_buffer_free(ob);
class Markdown(object):
"""
Parses markdown text and renders it using the given renderer.
``extensions`` can be a list or tuple of extensions (e.g.
``('fenced-code', 'footnotes', 'strikethrough')``) or an integer
(e.g. ``EXT_FENCED_CODE | EXT_FOOTNOTES | EXT_STRIKETHROUGH``).
"""
def __init__(self, renderer, extensions=0):
self.renderer = renderer
self.extensions = args_to_int(extension_map, extensions)
def __call__(self, text):
"""
Parses and renders markdown text.
"""
ib = lib.hoedown_buffer_new(IUNIT)
lib.hoedown_buffer_puts(ib, text.encode('utf-8'))
ob = lib.hoedown_buffer_new(OUNIT)
document = lib.hoedown_document_new(
self.renderer.renderer,
self.extensions,
MAX_NESTING);
lib.hoedown_document_render(document, ob, ib.data, ib.size);
lib.hoedown_buffer_free(ib)
lib.hoedown_document_free(document)
try:
return to_string(ob)
finally:
lib.hoedown_buffer_free(ob);
class BaseRenderer(object):
def __init__(self):
self.renderer = ffi.new('hoedown_renderer *')
self._renderer_handle = ffi.new_handle(self)
for name in python_callbacks.keys():
if hasattr(self, name):
setattr(self.renderer, name, python_callbacks[name])
else:
setattr(self.renderer, name, ffi.NULL)
# Store the render class' handle in the render data.
self._data = ffi.new('hoedown_renderer_data *')
self.renderer.opaque = self._data
ffi.cast('hoedown_renderer_data *', self.renderer.opaque).opaque = \
self._renderer_handle
class HtmlRenderer(BaseRenderer):
"""
A wrapper for the HTML renderer that's included in Hoedown.
``render_flags`` can be a list or tuple of flags (e.g.
``('skip-html', 'hard-wrap')``) or an integer
(e.g. ``HTML_SKIP_HTML | HTML_HARD_WRAP``).
``nesting_level`` limits what's included in the table of contents.
The default value is 0, no headers.
An instance of the ``HtmlRenderer`` can not be shared with multiple
:py:class:`Markdown` instances, because it carries state that's changed
by the ``Markdown`` instance.
"""
def __init__(self, flags=0, nesting_level=0):
flags = args_to_int(html_flag_map, flags)
self.renderer = self._new_renderer(flags, nesting_level)
self._renderer_handle = ffi.new_handle(self)
# Store the render class' handle in the render state.
state = ffi.cast('hoedown_renderer_data *', self.renderer.opaque)
state.opaque = self._renderer_handle
for name in python_callbacks.keys():
if hasattr(self, name):
setattr(self.renderer, name, python_callbacks[name])
def _new_renderer(self, flags, nesting_level):
return lib.hoedown_html_renderer_new(flags, nesting_level)
def __del__(self):
lib.hoedown_html_renderer_free(self.renderer)
class HtmlTocRenderer(HtmlRenderer):
"""
A wrapper for the HTML table of contents renderer that's included in Hoedown.
``nesting_level`` limits what's included in the table of contents.
The default value is 6, all headers.
An instance of the ``HtmlTocRenderer`` can not be shared with multiple
:py:class:`Markdown` instances, because it carries state that's changed
by the ``Markdown`` instance.
"""
def __init__(self, nesting_level=6):
HtmlRenderer.__init__(self, 0, nesting_level)
def _new_renderer(self, flags, nesting_level):
return lib.hoedown_html_toc_renderer_new(nesting_level)