Files
50ohm/renderer/table.py
T
2025-05-14 23:24:33 +02:00

79 lines
2.2 KiB
Python

import re
from mistletoe import span_token
from mistletoe.block_token import BlockToken
class Table(BlockToken):
@staticmethod
def start(line):
return "|" in line
@classmethod
def parse_header(cls, line):
# Parse header, extract alignment and make an ordinary row out of it
line = line.strip().strip("|") # Remove leading/trailing whitespace and pipes
columns = [col.strip() for col in line.split("|")] # Split by pipe |
alignment = []
header = "| "
for column in columns:
attr, val = re.match(r"^ ?(?:([lcrX]):)?(.*)", column).group(1, 2)
alignment.append(attr)
header += val + " | "
return header, alignment
@classmethod
def read(cls, lines):
header = next(lines)
header, alignment = cls.parse_header(header)
name = ""
caption = ""
rows = [TableRow(header)]
# Read table until the end: No more column definitions, caption, or empty line.
line_buffer = []
next_line = lines.peek()
while next_line is not None and next_line.strip() != "":
maybe_caption = re.match(r"\[table:([^:\]]+):([^:\]]+)\]", next_line)
if maybe_caption is not None:
name, caption = maybe_caption.group(1, 2)
next(lines)
break
elif "|" not in next_line:
break
else:
line_buffer.append(next(lines))
next_line = lines.peek()
rows.extend([TableRow(line) for line in line_buffer])
return alignment, rows, name, caption
def __init__(self, match):
self.alignment, self.children, self.name, self.caption = match
class TableRow(BlockToken):
@classmethod
def parse_row(cls, line):
line = line.strip().strip("|")
columns = [col.strip() for col in line.split("|")]
data = []
for column in columns:
data.append(TableCell(column))
return data
def __init__(self, match):
self.children = self.parse_row(match)
class TableCell(BlockToken):
def __init__(self, match):
super().__init__(match, span_token.tokenize_inner)