Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/mistune/plugins/table.py: 96%
97 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1import re
2from ..helpers import PREVENT_BACKSLASH
4# https://michelf.ca/projects/php-markdown/extra/#table
6__all__ = ['table', 'table_in_quote', 'table_in_list']
9TABLE_PATTERN = (
10 r'^ {0,3}\|(?P<table_head>.+)\|[ \t]*\n'
11 r' {0,3}\|(?P<table_align> *[-:]+[-| :]*)\|[ \t]*\n'
12 r'(?P<table_body>(?: {0,3}\|.*\|[ \t]*(?:\n|$))*)\n*'
13)
14NP_TABLE_PATTERN = (
15 r'^ {0,3}(?P<nptable_head>\S.*\|.*)\n'
16 r' {0,3}(?P<nptable_align>[-:]+ *\|[-| :]*)\n'
17 r'(?P<nptable_body>(?:.*\|.*(?:\n|$))*)\n*'
18)
20TABLE_CELL = re.compile(r'^ {0,3}\|(.+)\|[ \t]*$')
21CELL_SPLIT = re.compile(r' *' + PREVENT_BACKSLASH + r'\| *')
22ALIGN_CENTER = re.compile(r'^ *:-+: *$')
23ALIGN_LEFT = re.compile(r'^ *:-+ *$')
24ALIGN_RIGHT = re.compile(r'^ *-+: *$')
27def parse_table(block, m, state):
28 pos = m.end()
29 header = m.group('table_head')
30 align = m.group('table_align')
31 thead, aligns = _process_thead(header, align)
32 if not thead:
33 return
35 rows = []
36 body = m.group('table_body')
37 for text in body.splitlines():
38 m = TABLE_CELL.match(text)
39 if not m: # pragma: no cover
40 return
41 row = _process_row(m.group(1), aligns)
42 if not row:
43 return
44 rows.append(row)
46 children = [thead, {'type': 'table_body', 'children': rows}]
47 state.append_token({'type': 'table', 'children': children})
48 return pos
51def parse_nptable(block, m, state):
52 header = m.group('nptable_head')
53 align = m.group('nptable_align')
54 thead, aligns = _process_thead(header, align)
55 if not thead:
56 return
58 rows = []
59 body = m.group('nptable_body')
60 for text in body.splitlines():
61 row = _process_row(text, aligns)
62 if not row:
63 return
64 rows.append(row)
66 children = [thead, {'type': 'table_body', 'children': rows}]
67 state.append_token({'type': 'table', 'children': children})
68 return m.end()
71def _process_thead(header, align):
72 headers = CELL_SPLIT.split(header)
73 aligns = CELL_SPLIT.split(align)
74 if len(headers) != len(aligns):
75 return None, None
77 for i, v in enumerate(aligns):
78 if ALIGN_CENTER.match(v):
79 aligns[i] = 'center'
80 elif ALIGN_LEFT.match(v):
81 aligns[i] = 'left'
82 elif ALIGN_RIGHT.match(v):
83 aligns[i] = 'right'
84 else:
85 aligns[i] = None
87 children = [
88 {
89 'type': 'table_cell',
90 'text': text.strip(),
91 'attrs': {'align': aligns[i], 'head': True}
92 }
93 for i, text in enumerate(headers)
94 ]
95 thead = {'type': 'table_head', 'children': children}
96 return thead, aligns
99def _process_row(text, aligns):
100 cells = CELL_SPLIT.split(text)
101 if len(cells) != len(aligns):
102 return None
104 children = [
105 {
106 'type': 'table_cell',
107 'text': text.strip(),
108 'attrs': {'align': aligns[i], 'head': False}
109 }
110 for i, text in enumerate(cells)
111 ]
112 return {'type': 'table_row', 'children': children}
115def render_table(renderer, text):
116 return '<table>\n' + text + '</table>\n'
119def render_table_head(renderer, text):
120 return '<thead>\n<tr>\n' + text + '</tr>\n</thead>\n'
123def render_table_body(renderer, text):
124 return '<tbody>\n' + text + '</tbody>\n'
127def render_table_row(renderer, text):
128 return '<tr>\n' + text + '</tr>\n'
131def render_table_cell(renderer, text, align=None, head=False):
132 if head:
133 tag = 'th'
134 else:
135 tag = 'td'
137 html = ' <' + tag
138 if align:
139 html += ' style="text-align:' + align + '"'
141 return html + '>' + text + '</' + tag + '>\n'
144def table(md):
145 """A mistune plugin to support table, spec defined at
146 https://michelf.ca/projects/php-markdown/extra/#table
148 Here is an example:
150 .. code-block:: text
152 First Header | Second Header
153 ------------- | -------------
154 Content Cell | Content Cell
155 Content Cell | Content Cell
157 :param md: Markdown instance
158 """
159 md.block.register('table', TABLE_PATTERN, parse_table, before='paragraph')
160 md.block.register('nptable', NP_TABLE_PATTERN, parse_nptable, before='paragraph')
162 if md.renderer and md.renderer.NAME == 'html':
163 md.renderer.register('table', render_table)
164 md.renderer.register('table_head', render_table_head)
165 md.renderer.register('table_body', render_table_body)
166 md.renderer.register('table_row', render_table_row)
167 md.renderer.register('table_cell', render_table_cell)
170def table_in_quote(md):
171 """Enable table plugin in block quotes."""
172 md.block.insert_rule(md.block.block_quote_rules, 'table', before='paragraph')
173 md.block.insert_rule(md.block.block_quote_rules, 'nptable', before='paragraph')
176def table_in_list(md):
177 """Enable table plugin in list."""
178 md.block.insert_rule(md.block.list_rules, 'table', before='paragraph')
179 md.block.insert_rule(md.block.list_rules, 'nptable', before='paragraph')