Move callbacks, utils and constants into their own modules.
This commit is contained in:
parent
cbd9834466
commit
aac40ee755
|
@ -36,24 +36,42 @@ class benchmark(object):
|
|||
print('{0} is not available'.format(name))
|
||||
|
||||
|
||||
@benchmark('mistune')
|
||||
def benchmark_mistune(text):
|
||||
import mistune
|
||||
mistune.markdown(text)
|
||||
# @benchmark('mistune')
|
||||
# def benchmark_mistune(text):
|
||||
# import mistune
|
||||
# mistune.markdown(text)
|
||||
|
||||
|
||||
@benchmark('misaka')
|
||||
def benchmark_misaka(text):
|
||||
import misaka as m
|
||||
# mistune has all these features
|
||||
extensions = (
|
||||
m.EXT_NO_INTRA_EMPHASIS | m.EXT_FENCED_CODE | m.EXT_AUTOLINK |
|
||||
m.EXT_TABLES | m.EXT_STRIKETHROUGH
|
||||
)
|
||||
# extensions = (
|
||||
# m.EXT_NO_INTRA_EMPHASIS | m.EXT_FENCED_CODE | m.EXT_AUTOLINK |
|
||||
# m.EXT_TABLES | m.EXT_STRIKETHROUGH
|
||||
# )
|
||||
# md = m.Markdown(m.HtmlRenderer(), extensions=extensions)
|
||||
# md.render(text)
|
||||
|
||||
m.html(text, extensions)
|
||||
m.html(text, ('no-intra-emphasis', 'fenced=code', 'autolink', 'tables', 'strikethrough'))
|
||||
|
||||
|
||||
@benchmark('misaka_classes')
|
||||
def benchmark_misaka_classes(text):
|
||||
import misaka as m
|
||||
# mistune has all these features
|
||||
# extensions = (
|
||||
# m.EXT_NO_INTRA_EMPHASIS | m.EXT_FENCED_CODE | m.EXT_AUTOLINK |
|
||||
# m.EXT_TABLES | m.EXT_STRIKETHROUGH
|
||||
# )
|
||||
# # md = m.Markdown(m.HtmlRenderer(), extensions=extensions)
|
||||
# # md.render(text)
|
||||
|
||||
# m.html(text, extensions)
|
||||
|
||||
r = m.HtmlRenderer()
|
||||
p = m.Markdown(r, ('no-intra-emphasis', 'fenced=code', 'autolink', 'tables', 'strikethrough'))
|
||||
p(text)
|
||||
|
||||
|
||||
# @benchmark('markdown2')
|
||||
|
@ -90,7 +108,7 @@ def benchmark_hoep(text):
|
|||
m.EXT_TABLES | m.EXT_STRIKETHROUGH | m.EXT_FOOTNOTES
|
||||
)
|
||||
md = m.Hoep(extensions=extensions)
|
||||
md.render(text.decode('utf-8'))
|
||||
md.render(text)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -56,6 +56,7 @@ ffi.set_source(
|
|||
#include "hoedown/buffer.h"
|
||||
#include "hoedown/document.h"
|
||||
#include "hoedown/html.h"
|
||||
#include "extra.h"
|
||||
""",
|
||||
sources=(
|
||||
'misaka/hoedown/version.c',
|
||||
|
@ -67,6 +68,7 @@ ffi.set_source(
|
|||
'misaka/hoedown/document.c',
|
||||
'misaka/hoedown/buffer.c',
|
||||
'misaka/hoedown/autolink.c',
|
||||
'misaka/extra.c',
|
||||
),
|
||||
include_dirs=('misaka',))
|
||||
|
||||
|
@ -274,6 +276,12 @@ hoedown_renderer *hoedown_html_toc_renderer_new(
|
|||
);
|
||||
void hoedown_html_renderer_free(hoedown_renderer *renderer);
|
||||
void hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *data, size_t size);
|
||||
|
||||
// ---------------
|
||||
// --- extra.h ---
|
||||
// ---------------
|
||||
|
||||
void *misaka_get_renderer(const hoedown_renderer_data *data);
|
||||
""")
|
||||
|
||||
|
||||
|
|
450
misaka/api.py
450
misaka/api.py
|
@ -1,16 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import operator as op
|
||||
import warnings
|
||||
from inspect import getmembers, ismethod
|
||||
|
||||
from ._hoedown import lib, ffi
|
||||
|
||||
try:
|
||||
reduce
|
||||
except NameError:
|
||||
from functools import reduce
|
||||
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__ = [
|
||||
|
@ -21,7 +15,7 @@ __all__ = [
|
|||
'HtmlRenderer',
|
||||
'HtmlTocRenderer',
|
||||
|
||||
'_args_to_int',
|
||||
'args_to_int',
|
||||
'extension_map',
|
||||
'html_flag_map',
|
||||
|
||||
|
@ -59,81 +53,17 @@ __all__ = [
|
|||
]
|
||||
|
||||
|
||||
def _set_constants():
|
||||
is_int = lambda n: isinstance(n, int)
|
||||
|
||||
for name, value in getmembers(lib, is_int):
|
||||
if not name.startswith('HOEDOWN_'):
|
||||
continue
|
||||
setattr(sys.modules[__name__], name[8:], value)
|
||||
|
||||
|
||||
if not hasattr(sys.modules[__name__], 'EXT_TABLES'):
|
||||
_set_constants()
|
||||
|
||||
|
||||
extension_map = {
|
||||
'tables': EXT_TABLES,
|
||||
'fenced-code': EXT_FENCED_CODE,
|
||||
'footnotes': EXT_FOOTNOTES,
|
||||
'autolink': EXT_AUTOLINK,
|
||||
'strikethrough': EXT_STRIKETHROUGH,
|
||||
'underline': EXT_UNDERLINE,
|
||||
'highlight': EXT_HIGHLIGHT,
|
||||
'quote': EXT_QUOTE,
|
||||
'superscript': EXT_SUPERSCRIPT,
|
||||
'math': EXT_MATH,
|
||||
'no-intra-emphasis': EXT_NO_INTRA_EMPHASIS,
|
||||
'space-headers': EXT_SPACE_HEADERS,
|
||||
'math-explicit': EXT_MATH_EXPLICIT,
|
||||
'disable-indented-code': EXT_DISABLE_INDENTED_CODE,
|
||||
}
|
||||
|
||||
html_flag_map = {
|
||||
'skip-html': HTML_SKIP_HTML,
|
||||
'escape': HTML_ESCAPE,
|
||||
'hard-wrap': HTML_HARD_WRAP,
|
||||
'use-xhtml': HTML_USE_XHTML,
|
||||
}
|
||||
|
||||
|
||||
IUNIT = 1024
|
||||
OUNIT = 64
|
||||
MAX_NESTING = 16
|
||||
|
||||
|
||||
def deprecation(message):
|
||||
warnings.warn(message, DeprecationWarning, stacklevel=3)
|
||||
|
||||
|
||||
def to_string(buffer):
|
||||
if buffer == ffi.NULL or buffer.size == 0:
|
||||
return ''
|
||||
return ffi.string(buffer.data, buffer.size).decode('utf-8')
|
||||
|
||||
|
||||
def _args_to_int(mapping, argument):
|
||||
"""
|
||||
Convert list of strings to an int using a mapping.
|
||||
"""
|
||||
if isinstance(argument, int):
|
||||
if argument == 0:
|
||||
return 0
|
||||
|
||||
deprecation('passing extensions and flags as constants is deprecated')
|
||||
return argument
|
||||
elif isinstance(argument, (tuple, list)):
|
||||
return reduce(op.or_, [mapping[n] for n in argument if n in mapping], 0)
|
||||
|
||||
raise TypeError('argument must be a list of strings or an int')
|
||||
|
||||
|
||||
def html(text, extensions=0, render_flags=0):
|
||||
"""
|
||||
Convert markdown text to HTML.
|
||||
"""
|
||||
extensions = _args_to_int(extension_map, extensions)
|
||||
render_flags = _args_to_int(html_flag_map, render_flags)
|
||||
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)
|
||||
|
@ -183,13 +113,13 @@ def smartypants(text):
|
|||
lib.hoedown_buffer_free(ob);
|
||||
|
||||
|
||||
class Markdown:
|
||||
class Markdown(object):
|
||||
"""
|
||||
Parses markdown text and renders it using the given renderer.
|
||||
"""
|
||||
def __init__(self, renderer, extensions=0):
|
||||
self.renderer = renderer
|
||||
self.extensions = _args_to_int(extension_map, extensions)
|
||||
self.extensions = args_to_int(extension_map, extensions)
|
||||
|
||||
def __call__(self, text):
|
||||
"""
|
||||
|
@ -214,340 +144,21 @@ class Markdown:
|
|||
lib.hoedown_buffer_free(ob);
|
||||
|
||||
|
||||
_callback_signatures = {
|
||||
# block level callbacks - NULL skips the block
|
||||
'blockcode': 'void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data)',
|
||||
'blockquote': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'header': 'void(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)',
|
||||
'hrule': 'void(hoedown_buffer *ob, const hoedown_renderer_data *data)',
|
||||
'list': 'void(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)',
|
||||
'listitem': 'void(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)',
|
||||
'paragraph': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'table': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'table_header': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'table_body': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'table_row': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'table_cell': 'void(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data)',
|
||||
'footnotes': 'void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'footnote_def': 'void(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data)',
|
||||
'blockhtml': 'void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)',
|
||||
|
||||
# span level callbacks - NULL or return 0 prints the span verbatim
|
||||
'autolink': 'int(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data)',
|
||||
'codespan': 'int(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)',
|
||||
'double_emphasis': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'emphasis': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'underline': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'highlight': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'quote': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'image': 'int(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data)',
|
||||
'linebreak': 'int(hoedown_buffer *ob, const hoedown_renderer_data *data)',
|
||||
'link': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)',
|
||||
'triple_emphasis': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'strikethrough': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'superscript': 'int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)',
|
||||
'footnote_ref': 'int(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data)',
|
||||
'math': 'int(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data)',
|
||||
'raw_html': 'int(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)',
|
||||
|
||||
# low level callbacks - NULL copies input directly into the output
|
||||
'entity': 'void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)',
|
||||
'normal_text': 'void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)',
|
||||
|
||||
# miscellaneous callbacks
|
||||
'doc_header': 'void(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)',
|
||||
'doc_footer': 'void(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)',
|
||||
}
|
||||
|
||||
|
||||
class BaseRenderer:
|
||||
class BaseRenderer(object):
|
||||
def __init__(self):
|
||||
# Use a noop method as a placeholder for render methods that are
|
||||
# implemented so there's no need to check if a render method exists
|
||||
# in a callback.
|
||||
for attr in _callback_signatures.keys():
|
||||
if not hasattr(self, attr):
|
||||
setattr(self, attr, self.noop)
|
||||
self.renderer = ffi.new('hoedown_renderer *')
|
||||
|
||||
self._callbacks = {k: ffi.callback(v, getattr(self, '_w_' + k))
|
||||
for k, v in _callback_signatures.items()}
|
||||
self.renderer = ffi.new('hoedown_renderer *', self._callbacks)
|
||||
for name in python_callbacks.keys():
|
||||
if hasattr(self, name):
|
||||
setattr(self.renderer, name, python_callbacks[name])
|
||||
else:
|
||||
setattr(self.renderer, name, ffi.NULL)
|
||||
|
||||
def noop(self, *args, **kwargs):
|
||||
return None
|
||||
|
||||
def _w_blockcode(self, ob, text, lang, data):
|
||||
text = to_string(text)
|
||||
lang = to_string(lang)
|
||||
|
||||
result = self.blockcode(text, lang)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_blockquote(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.blockquote(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_header(self, ob, content, level, data):
|
||||
content = to_string(content)
|
||||
level = int(level)
|
||||
result = self.header(content, level)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_hrule(self, ob, data):
|
||||
result = self.hrule()
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
# flags: LIST_ORDERED, LI_BLOCK.
|
||||
def _w_list(self, ob, content, flags, data):
|
||||
content = to_string(content)
|
||||
flags = int(flags)
|
||||
is_ordered = flags & LIST_ORDERED != 0
|
||||
is_block = flags & LI_BLOCK != 0
|
||||
result = self.list(content, is_ordered, is_block)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
# flags: LIST_ORDERED, LI_BLOCK.
|
||||
def _w_listitem(self, ob, content, flags, data):
|
||||
content = to_string(content)
|
||||
flags = int(flags)
|
||||
is_ordered = flags & LIST_ORDERED != 0
|
||||
is_block = flags & LI_BLOCK != 0
|
||||
result = self.listitem(content, is_ordered, is_block)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_paragraph(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.paragraph(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_table(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.table(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_table_header(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.table_header(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_table_body(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.table_body(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_table_row(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.table_row(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
# flags: TABLE_ALIGNMASK, TABLE_ALIGN_LEFT, TABLE_ALIGN_RIGHT,
|
||||
# TABLE_ALIGN_CENTER, TABLE_HEADER
|
||||
def _w_table_cell(self, ob, content, flags, data):
|
||||
content = to_string(content)
|
||||
flags = int(flags)
|
||||
is_header = flags & TABLE_HEADER != 0
|
||||
align_bit = flags & TABLE_ALIGNMASK
|
||||
|
||||
if align_bit == TABLE_ALIGN_CENTER:
|
||||
align = 'center'
|
||||
elif align_bit == TABLE_ALIGN_LEFT:
|
||||
align = 'left'
|
||||
elif align_bit == TABLE_ALIGN_RIGHT:
|
||||
align = 'right'
|
||||
else:
|
||||
align = ''
|
||||
|
||||
result = self.table_cell(content, align, is_header)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_footnotes(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.footnotes(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_footnote_def(self, ob, content, num, data):
|
||||
content = to_string(content)
|
||||
num = int(num)
|
||||
result = self.footnote_def(content, num)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_blockhtml(self, ob, text, data):
|
||||
text = ffi.string(text.data, text.size).decode('utf-8')
|
||||
result = self.blockhtml(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_autolink(self, ob, link, type, data):
|
||||
link = ffi.string(link.data, link.size).decode('utf-8')
|
||||
is_email = int(type) & AUTOLINK_EMAIL != 0
|
||||
result = self.autolink(link, is_email)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_codespan(self, ob, text, data):
|
||||
text = ffi.string(text.data, text.size).decode('utf-8')
|
||||
result = self.codespan(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_double_emphasis(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.double_emphasis(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_emphasis(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.emphasis(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_underline(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.underline(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_highlight(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.highlight(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_quote(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.quote(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_image(self, ob, link, title, alt, data):
|
||||
link = to_string(link)
|
||||
title = to_string(title)
|
||||
alt = to_string(alt)
|
||||
result = self.image(link, title, alt)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_linebreak(self, ob, data):
|
||||
result = self.linebreak()
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_link(self, ob, content, link, title, data):
|
||||
content = to_string(content)
|
||||
link = to_string(link)
|
||||
title = to_string(title)
|
||||
result = self.link(content, link, title)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_triple_emphasis(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.triple_emphasis(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_strikethrough(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.strikethrough(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_superscript(self, ob, content, data):
|
||||
content = to_string(content)
|
||||
result = self.superscript(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_footnote_ref(self, ob, num, data):
|
||||
num = int(num)
|
||||
result = self.footnote_ref(num)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_math(self, ob, text, displaymode, data):
|
||||
text = to_string(text)
|
||||
displaymode = int(displaymode)
|
||||
result = self.math(text, displaymode)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_raw_html(self, ob, text, data):
|
||||
text = to_string(text)
|
||||
result = self.raw_html(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _w_entity(self, ob, text, data):
|
||||
text = to_string(text)
|
||||
result = self.entity(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_normal_text(self, ob, text, data):
|
||||
text = to_string(text)
|
||||
result = self.normal_text(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_doc_header(self, ob, inline_render, data):
|
||||
inline_render = int(inline_render)
|
||||
result = self.doc_header(inline_render)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
def _w_doc_footer(self, ob, inline_render, data):
|
||||
inline_render = int(inline_render)
|
||||
result = self.doc_footer(inline_render)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
# 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 = \
|
||||
ffi.new_handle(self)
|
||||
|
||||
|
||||
class HtmlRenderer(BaseRenderer):
|
||||
|
@ -562,21 +173,16 @@ class HtmlRenderer(BaseRenderer):
|
|||
by the ``Markdown`` instance.
|
||||
"""
|
||||
def __init__(self, flags=0, nesting_level=0):
|
||||
flags = _args_to_int(html_flag_map, flags)
|
||||
flags = args_to_int(html_flag_map, flags)
|
||||
self.renderer = self._new_renderer(flags, nesting_level)
|
||||
callbacks = []
|
||||
|
||||
for name, signature in _callback_signatures.items():
|
||||
if not hasattr(self, name):
|
||||
continue
|
||||
# Store the render class' handle in the render state.
|
||||
state = ffi.cast('hoedown_renderer_data *', self.renderer.opaque)
|
||||
state.opaque = ffi.new_handle(self)
|
||||
|
||||
wrapper = getattr(self, '_w_' + name)
|
||||
callback = ffi.callback(signature, wrapper)
|
||||
callbacks.append(callback)
|
||||
setattr(self.renderer, name, callback)
|
||||
|
||||
# Prevent garbage collection of callbacks.
|
||||
self._callbacks = callbacks
|
||||
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)
|
||||
|
|
|
@ -0,0 +1,429 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from ._hoedown import lib, ffi
|
||||
from .constants import *
|
||||
from .utils import to_string
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data)')
|
||||
def cb_blockcode(ob, text, lang, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = to_string(text)
|
||||
lang = to_string(lang)
|
||||
|
||||
result = renderer.blockcode(text, lang)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_blockquote(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.blockquote(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)')
|
||||
def cb_header(ob, content, level, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
level = int(level)
|
||||
result = renderer.header(content, level)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_renderer_data *data)')
|
||||
def cb_hrule(ob, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
result = renderer.hrule()
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
# flags: LIST_ORDERED, LI_BLOCK.
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)')
|
||||
def cb_list(ob, content, flags, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
flags = int(flags)
|
||||
is_ordered = flags & LIST_ORDERED != 0
|
||||
is_block = flags & LI_BLOCK != 0
|
||||
result = renderer.list(content, is_ordered, is_block)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
# flags: LIST_ORDERED, LI_BLOCK.
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)')
|
||||
def cb_listitem(ob, content, flags, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
flags = int(flags)
|
||||
is_ordered = flags & LIST_ORDERED != 0
|
||||
is_block = flags & LI_BLOCK != 0
|
||||
result = renderer.listitem(content, is_ordered, is_block)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_paragraph(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.paragraph(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_table(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.table(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_table_header(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.table_header(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_table_body(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.table_body(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_table_row(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.table_row(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
# flags: TABLE_ALIGNMASK, TABLE_ALIGN_LEFT, TABLE_ALIGN_RIGHT,
|
||||
# TABLE_ALIGN_CENTER, TABLE_HEADER
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data)')
|
||||
def cb_table_cell(ob, content, flags, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
flags = int(flags)
|
||||
is_header = flags & TABLE_HEADER != 0
|
||||
align_bit = flags & TABLE_ALIGNMASK
|
||||
|
||||
if align_bit == TABLE_ALIGN_CENTER:
|
||||
align = 'center'
|
||||
elif align_bit == TABLE_ALIGN_LEFT:
|
||||
align = 'left'
|
||||
elif align_bit == TABLE_ALIGN_RIGHT:
|
||||
align = 'right'
|
||||
else:
|
||||
align = ''
|
||||
|
||||
result = renderer.table_cell(content, align, is_header)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_footnotes(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.footnotes(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data)')
|
||||
def cb_footnote_def(ob, content, num, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
num = int(num)
|
||||
result = renderer.footnote_def(content, num)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)')
|
||||
def cb_blockhtml(ob, text, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = ffi.string(text.data, text.size).decode('utf-8')
|
||||
result = renderer.blockhtml(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data)')
|
||||
def cb_autolink(ob, link, type, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
link = ffi.string(link.data, link.size).decode('utf-8')
|
||||
is_email = int(type) & AUTOLINK_EMAIL != 0
|
||||
result = renderer.autolink(link, is_email)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)')
|
||||
def cb_codespan(ob, text, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = ffi.string(text.data, text.size).decode('utf-8')
|
||||
result = renderer.codespan(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_double_emphasis(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.double_emphasis(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_emphasis(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.emphasis(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_underline(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.underline(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_highlight(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.highlight(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_quote(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.quote(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data)')
|
||||
def cb_image(ob, link, title, alt, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
link = to_string(link)
|
||||
title = to_string(title)
|
||||
alt = to_string(alt)
|
||||
result = renderer.image(link, title, alt)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_renderer_data *data)')
|
||||
def cb_linebreak(ob, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
result = renderer.linebreak()
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)')
|
||||
def cb_link(ob, content, link, title, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
link = to_string(link)
|
||||
title = to_string(title)
|
||||
result = renderer.link(content, link, title)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_triple_emphasis(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.triple_emphasis(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_strikethrough(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.strikethrough(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)')
|
||||
def cb_superscript(ob, content, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
content = to_string(content)
|
||||
result = renderer.superscript(content)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data)')
|
||||
def cb_footnote_ref(ob, num, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
num = int(num)
|
||||
result = renderer.footnote_ref(num)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data)')
|
||||
def cb_math(ob, text, displaymode, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = to_string(text)
|
||||
displaymode = int(displaymode)
|
||||
result = renderer.math(text, displaymode)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('int(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)')
|
||||
def cb_raw_html(ob, text, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = to_string(text)
|
||||
result = renderer.raw_html(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)')
|
||||
def cb_entity(ob, text, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = to_string(text)
|
||||
result = renderer.entity(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)')
|
||||
def cb_normal_text(ob, text, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
text = to_string(text)
|
||||
result = renderer.normal_text(text)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)')
|
||||
def cb_doc_header(ob, inline_render, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
inline_render = int(inline_render)
|
||||
result = renderer.doc_header(inline_render)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
@ffi.callback('void(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)')
|
||||
def cb_doc_footer(ob, inline_render, data):
|
||||
renderer = ffi.from_handle(lib.misaka_get_renderer(data))
|
||||
inline_render = int(inline_render)
|
||||
result = renderer.doc_footer(inline_render)
|
||||
if result:
|
||||
lib.hoedown_buffer_puts(ob, result.encode('utf-8'))
|
||||
|
||||
|
||||
python_callbacks = {
|
||||
# block level callbacks - NULL skips the block
|
||||
'blockcode': cb_blockcode,
|
||||
'blockquote': cb_blockquote,
|
||||
'header': cb_header,
|
||||
'hrule': cb_hrule,
|
||||
'list': cb_list,
|
||||
'listitem': cb_listitem,
|
||||
'paragraph': cb_paragraph,
|
||||
'table': cb_table,
|
||||
'table_header': cb_table_header,
|
||||
'table_body': cb_table_body,
|
||||
'table_row': cb_table_row,
|
||||
'table_cell': cb_table_cell,
|
||||
'footnotes': cb_footnotes,
|
||||
'footnote_def': cb_footnote_def,
|
||||
'blockhtml': cb_blockhtml,
|
||||
|
||||
# span level callbacks - NULL or return 0 prints the span verbatim
|
||||
'autolink': cb_autolink,
|
||||
'codespan': cb_codespan,
|
||||
'double_emphasis': cb_double_emphasis,
|
||||
'emphasis': cb_emphasis,
|
||||
'underline': cb_underline,
|
||||
'highlight': cb_highlight,
|
||||
'quote': cb_quote,
|
||||
'image': cb_image,
|
||||
'linebreak': cb_linebreak,
|
||||
'link': cb_link,
|
||||
'triple_emphasis': cb_triple_emphasis,
|
||||
'strikethrough': cb_strikethrough,
|
||||
'superscript': cb_superscript,
|
||||
'footnote_ref': cb_footnote_ref,
|
||||
'math': cb_math,
|
||||
'raw_html': cb_raw_html,
|
||||
|
||||
# low level callbacks - NULL copies input directly into the output
|
||||
'entity': cb_entity,
|
||||
'normal_text': cb_normal_text,
|
||||
|
||||
# miscellaneous callbacks
|
||||
'doc_header': cb_doc_header,
|
||||
'doc_footer': cb_doc_footer,
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
from inspect import getmembers
|
||||
|
||||
from ._hoedown import lib
|
||||
|
||||
|
||||
def _set_constants():
|
||||
is_int = lambda n: isinstance(n, int)
|
||||
|
||||
for name, value in getmembers(lib, is_int):
|
||||
if not name.startswith('HOEDOWN_'):
|
||||
continue
|
||||
setattr(sys.modules[__name__], name[8:], value)
|
||||
|
||||
|
||||
if not hasattr(sys.modules[__name__], 'EXT_TABLES'):
|
||||
_set_constants()
|
|
@ -0,0 +1,9 @@
|
|||
#include "hoedown/document.h"
|
||||
#include "hoedown/html.h"
|
||||
|
||||
void *misaka_get_renderer(const hoedown_renderer_data *data) {
|
||||
// NOTE: Cast to a "hoedown_renderer_data *", because
|
||||
// the structure is assumed to have an "opaque" field.
|
||||
// Otherwise this doesn't work.
|
||||
return ((hoedown_renderer_data *) data->opaque)->opaque;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
/* extra.h - extra stuff in C */
|
||||
|
||||
void *misaka_get_renderer(const hoedown_renderer_data *data);
|
|
@ -0,0 +1,61 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import operator as op
|
||||
import warnings
|
||||
|
||||
try:
|
||||
reduce
|
||||
except NameError:
|
||||
from functools import reduce
|
||||
|
||||
from ._hoedown import ffi
|
||||
from .constants import *
|
||||
|
||||
|
||||
extension_map = {
|
||||
'tables': EXT_TABLES,
|
||||
'fenced-code': EXT_FENCED_CODE,
|
||||
'footnotes': EXT_FOOTNOTES,
|
||||
'autolink': EXT_AUTOLINK,
|
||||
'strikethrough': EXT_STRIKETHROUGH,
|
||||
'underline': EXT_UNDERLINE,
|
||||
'highlight': EXT_HIGHLIGHT,
|
||||
'quote': EXT_QUOTE,
|
||||
'superscript': EXT_SUPERSCRIPT,
|
||||
'math': EXT_MATH,
|
||||
'no-intra-emphasis': EXT_NO_INTRA_EMPHASIS,
|
||||
'space-headers': EXT_SPACE_HEADERS,
|
||||
'math-explicit': EXT_MATH_EXPLICIT,
|
||||
'disable-indented-code': EXT_DISABLE_INDENTED_CODE,
|
||||
}
|
||||
|
||||
html_flag_map = {
|
||||
'skip-html': HTML_SKIP_HTML,
|
||||
'escape': HTML_ESCAPE,
|
||||
'hard-wrap': HTML_HARD_WRAP,
|
||||
'use-xhtml': HTML_USE_XHTML,
|
||||
}
|
||||
|
||||
|
||||
def args_to_int(mapping, argument):
|
||||
"""
|
||||
Convert list of strings to an int using a mapping.
|
||||
"""
|
||||
if isinstance(argument, int):
|
||||
if argument == 0:
|
||||
return 0
|
||||
deprecation('passing extensions and flags as constants is deprecated')
|
||||
return argument
|
||||
elif isinstance(argument, (tuple, list)):
|
||||
return reduce(op.or_, [mapping[n] for n in argument if n in mapping], 0)
|
||||
raise TypeError('argument must be a list of strings or an int')
|
||||
|
||||
|
||||
def deprecation(message):
|
||||
warnings.warn(message, DeprecationWarning, stacklevel=3)
|
||||
|
||||
|
||||
def to_string(buffer):
|
||||
if buffer == ffi.NULL or buffer.size == 0:
|
||||
return ''
|
||||
return ffi.string(buffer.data, buffer.size).decode('utf-8')
|
|
@ -1,14 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from chibitest import TestCase, ok
|
||||
from misaka import _args_to_int, extension_map, \
|
||||
from misaka import extension_map, \
|
||||
EXT_TABLES, EXT_FENCED_CODE, EXT_FOOTNOTES
|
||||
from misaka.utils import args_to_int
|
||||
|
||||
|
||||
class ArgsToIntTest(TestCase):
|
||||
def test_args(self):
|
||||
expected = EXT_TABLES | EXT_FENCED_CODE | EXT_FOOTNOTES
|
||||
result = _args_to_int(
|
||||
result = args_to_int(
|
||||
extension_map,
|
||||
('tables', 'fenced-code', 'footnotes'))
|
||||
|
||||
|
@ -16,6 +17,6 @@ class ArgsToIntTest(TestCase):
|
|||
|
||||
def test_int(self):
|
||||
expected = EXT_TABLES | EXT_FENCED_CODE | EXT_FOOTNOTES
|
||||
result = _args_to_int(extension_map, expected)
|
||||
result = args_to_int(extension_map, expected)
|
||||
|
||||
ok(result) == expected
|
||||
|
|
Loading…
Reference in New Issue