Improve handling of tables

This commit is contained in:
RunasSudo 2019-09-11 11:10:43 +10:00
parent dbc94bc119
commit 8f1b233dbe
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
3 changed files with 76 additions and 29 deletions

View File

@ -148,9 +148,7 @@ class LaTeXRenderer(mistletoe.latex_renderer.LaTeXRenderer):
align = ['X' for col in token.column_align] align = ['X' for col in token.column_align]
if hasattr(token, 'header'): if hasattr(token, 'header'):
for i, col in enumerate(token.header.children): for i, col in enumerate(token.header.children):
if '[' in col.children[0].content.split(' ')[0]: align[i] += '[{}]'.format(col.weight)
param = col.children[0].content[col.children[0].content.index('['):col.children[0].content.index(']')+1]
align[i] += param
result = [ result = [
format('{\\footnotesize\\begin{longtabu} to \\dimexpr\\columnwidth-<lmarg>\\relax [r] {'), format('{\\footnotesize\\begin{longtabu} to \\dimexpr\\columnwidth-<lmarg>\\relax [r] {'),
@ -170,24 +168,22 @@ class LaTeXRenderer(mistletoe.latex_renderer.LaTeXRenderer):
return ''.join(result) return ''.join(result)
def render_table_header(self, token): def render_table_header(self, token):
cells1 = ['{\\bfseries Column ' + self.render_inner(child).split(' ')[0].split('[')[0] + '}' for child in token.children] cells1 = ['{\\bfseries Column ' + child.label + '}' for child in token.children]
cells2 = ['{\\bfseries ' + ' '.join(self.render_inner(child).split(' ')[1:]) + '}' for child in token.children] cells2 = ['{\\bfseries ' + self.render_inner(child) + '}' for child in token.children]
return ' & '.join(cells1) + ' \\\\\\midrule\n' + ' & '.join(cells2) + ' \\\\' return ' & '.join(cells1) + ' \\\\\\midrule\n' + ' & '.join(cells2) + ' \\\\'
def render_table_row(self, token): def render_table_row(self, token):
cells = [self.render_table_cell(child, colnum) for colnum, child in enumerate(token.children)] cells = [self.render_table_cell(child) for child in token.children]
return ' & '.join(cells) + ' \\\\' return ' & '.join(cells) + ' \\\\'
def render_table_cell(self, token, colnum): def render_table_cell(self, token):
inner = self.render_inner(token) if token.colnum == 0 and token.label:
if colnum == 0:
return format(r'\makebox[2.2em][l]{<rownum>.}<content>', return format(r'\makebox[2.2em][l]{<rownum>.}<content>',
rownum=inner.split(' ')[0], rownum=token.label,
content=' '.join(inner.split(' ')[1:]) content=self.render_inner(token)
) )
else: else:
return inner return self.render_inner(token)
def render_document(self, token): def render_document(self, token):
template = r''' template = r'''

View File

@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
from itertools import zip_longest
import re import re
import mistletoe import mistletoe
@ -155,3 +156,60 @@ mistletoe.block_token.add_token(Definition)
def convert_leading_tabs(string): def convert_leading_tabs(string):
return string return string
mistletoe.block_token.Quote.convert_leading_tabs = convert_leading_tabs mistletoe.block_token.Quote.convert_leading_tabs = convert_leading_tabs
class Table(mistletoe.block_token.BlockToken):
def __init__(self, lines):
if '---' in lines[1]:
self.column_align = [mistletoe.block_token.Table.parse_align(column)
for column in mistletoe.block_token.Table.split_delimiter(lines[1])]
self.header = TableRow(lines[0], 0, self.column_align)
self.children = [TableRow(line, rownum + 1, self.column_align) for rownum, line in enumerate(lines[2:])]
else:
self.column_align = [None]
self.children = [TableRow(line, rownum) for rownum, line in enumerate(lines)]
@staticmethod
def start(line):
return '|' in line
@staticmethod
def read(lines):
lines.anchor()
line_buffer = [next(lines)]
while lines.peek() is not None and '|' in lines.peek():
line_buffer.append(next(lines))
if len(line_buffer) < 2 or '---' not in line_buffer[1]:
lines.reset()
return None
return line_buffer
class TableRow(mistletoe.block_token.BlockToken):
def __init__(self, line, rownum, row_align=None):
self.rownum = rownum
self.row_align = row_align or [None]
cells = filter(None, line.strip().split('|'))
self.children = [TableCell(x[0].strip() if x[0] else '', self, colnum, x[1])
for colnum, x in enumerate(zip_longest(cells, self.row_align))]
self.label = self.children[0].label
class TableCell(mistletoe.block_token.BlockToken):
pattern1 = re.compile(r'\s*([0-9A-Za-z]+\s+)?(\[[0-9]+\])?(.*)')
def __init__(self, inner, row, colnum, align=None):
self.row = row
self.colnum = colnum
self.align = align
if self.colnum == 0 or self.row.rownum == 0:
label, weight, content = self.pattern1.match(inner).group(1, 2, 3)
self.label = label.strip() if label else None
self.weight = int(weight[1:-1]) if weight else 1
self.children = mistletoe.span_token.tokenize_inner(content)
else:
self.label = None
self.weight = None
self.children = mistletoe.span_token.tokenize_inner(inner)
mistletoe.block_token.remove_token(mistletoe.block_token.Table)
mistletoe.block_token.add_token(Table)

View File

@ -155,13 +155,8 @@ class RTFRenderer(mistletoe.base_renderer.BaseRenderer):
result = [format(r'{\sa0\trowd\trgaph120\trleft<lmarg>')] result = [format(r'{\sa0\trowd\trgaph120\trleft<lmarg>')]
# Get column weights # Get column weights
weights = []
if hasattr(token, 'header'): if hasattr(token, 'header'):
for col in token.header.children: weights = [col.weight for col in token.header.children]
if '[' in col.children[0].content.split(' ')[0]:
weights.append(int(col.children[0].content[col.children[0].content.index('[')+1:col.children[0].content.index(']')]))
else:
weights.append(1)
else: else:
weights = [1 for col in token.column_align] weights = [1 for col in token.column_align]
@ -184,24 +179,22 @@ class RTFRenderer(mistletoe.base_renderer.BaseRenderer):
return ''.join(result) return ''.join(result)
def render_table_header(self, token): def render_table_header(self, token):
cells1 = ['{\\b Column ' + self.render_inner(child).split(' ')[0].split('[')[0] + '\\intbl\\cell}' for child in token.children] cells1 = ['{\\b Column ' + child.label + '\\intbl\\cell}' for child in token.children]
cells2 = ['{\\b ' + ' '.join(self.render_inner(child).split(' ')[1:]) + '\\intbl\\cell}' for child in token.children] cells2 = ['{\\b ' + self.render_inner(child) + '\\intbl\\cell}' for child in token.children]
return ''.join(cells1) + '\\row' + ''.join(cells2) + '\\row ' return ''.join(cells1) + '\\row' + ''.join(cells2) + '\\row '
def render_table_row(self, token): def render_table_row(self, token):
return ''.join([self.render_table_cell(cell, i) for i, cell in enumerate(token.children)]) + '\\row ' return ''.join([self.render_table_cell(cell) for cell in token.children]) + '\\row '
def render_table_cell(self, token, colnum): def render_table_cell(self, token):
inner = self.render_inner(token) if token.colnum == 0 and token.label:
if colnum == 0:
return format(r'{<rownum>. <content>\intbl\cell}', return format(r'{<rownum>. <content>\intbl\cell}',
rownum=inner.split(' ')[0], rownum=token.label,
content=' '.join(inner.split(' ')[1:]) content=self.render_inner(token)
) )
else: else:
return format(r'{<content>\intbl\cell}', return format(r'{<content>\intbl\cell}',
content=inner content=self.render_inner(token)
) )
def render_thematic_break(self, token): def render_thematic_break(self, token):