File size: 3,459 Bytes
d1ceb73 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
import re
from ..util import strip_end
__all__ = ['def_list']
# https://michelf.ca/projects/php-markdown/extra/#def-list
DEF_PATTERN = (
r'^(?P<def_list_head>(?:[^\n]+\n)+?)'
r'\n?(?:'
r'\:[ \t]+.*\n'
r'(?:[^\n]+\n)*' # lazy continue line
r'(?:(?:[ \t]*\n)*[ \t]+[^\n]+\n)*'
r'(?:[ \t]*\n)*'
r')+'
)
DEF_RE = re.compile(DEF_PATTERN, re.M)
DD_START_RE = re.compile(r'^:[ \t]+', re.M)
TRIM_RE = re.compile(r'^ {0,4}', re.M)
HAS_BLANK_LINE_RE = re.compile(r'\n[ \t]*\n$')
def parse_def_list(block, m, state):
pos = m.end()
children = list(_parse_def_item(block, m))
m = DEF_RE.match(state.src, pos)
while m:
children.extend(list(_parse_def_item(block, m)))
pos = m.end()
m = DEF_RE.match(state.src, pos)
state.append_token({
'type': 'def_list',
'children': children,
})
return pos
def _parse_def_item(block, m):
head = m.group('def_list_head')
for line in head.splitlines():
yield {
'type': 'def_list_head',
'text': line,
}
src = m.group(0)
end = len(head)
m = DD_START_RE.search(src, end)
start = m.start()
prev_blank_line = src[end:start] == '\n'
while m:
m = DD_START_RE.search(src, start + 1)
if not m:
break
end = m.start()
text = src[start:end].replace(':', ' ', 1)
children = _process_text(block, text, prev_blank_line)
prev_blank_line = bool(HAS_BLANK_LINE_RE.search(text))
yield {
'type': 'def_list_item',
'children': children,
}
start = end
text = src[start:].replace(':', ' ', 1)
children = _process_text(block, text, prev_blank_line)
yield {
'type': 'def_list_item',
'children': children,
}
def _process_text(block, text, loose):
text = TRIM_RE.sub('', text)
state = block.state_cls()
state.process(strip_end(text))
# use default list rules
block.parse(state, block.list_rules)
tokens = state.tokens
if not loose and len(tokens) == 1 and tokens[0]['type'] == 'paragraph':
tokens[0]['type'] = 'block_text'
return tokens
def render_def_list(renderer, text):
return '<dl>\n' + text + '</dl>\n'
def render_def_list_head(renderer, text):
return '<dt>' + text + '</dt>\n'
def render_def_list_item(renderer, text):
return '<dd>' + text + '</dd>\n'
def def_list(md):
"""A mistune plugin to support def list, spec defined at
https://michelf.ca/projects/php-markdown/extra/#def-list
Here is an example:
.. code-block:: text
Apple
: Pomaceous fruit of plants of the genus Malus in
the family Rosaceae.
Orange
: The fruit of an evergreen tree of the genus Citrus.
It will be converted into HTML:
.. code-block:: html
<dl>
<dt>Apple</dt>
<dd>Pomaceous fruit of plants of the genus Malus in
the family Rosaceae.</dd>
<dt>Orange</dt>
<dd>The fruit of an evergreen tree of the genus Citrus.</dd>
</dl>
:param md: Markdown instance
"""
md.block.register('def_list', DEF_PATTERN, parse_def_list, before='paragraph')
if md.renderer and md.renderer.NAME == 'html':
md.renderer.register('def_list', render_def_list)
md.renderer.register('def_list_head', render_def_list_head)
md.renderer.register('def_list_item', render_def_list_item)
|