Process Tables.
| 36 | |
| 37 | |
| 38 | class TableProcessor(BlockProcessor): |
| 39 | """ Process Tables. """ |
| 40 | |
| 41 | RE_CODE_PIPES = re.compile(r'(?:(\\\\)|(\\`+)|(`+)|(\\\|)|(\|))') |
| 42 | RE_END_BORDER = re.compile(r'(?<!\\)(?:\\\\)*\|$') |
| 43 | |
| 44 | def __init__(self, parser: blockparser.BlockParser, config: dict[str, Any]): |
| 45 | self.border: bool | int = False |
| 46 | self.separator: Sequence[str] = '' |
| 47 | self.config = config |
| 48 | |
| 49 | super().__init__(parser) |
| 50 | |
| 51 | def test(self, parent: etree.Element, block: str) -> bool: |
| 52 | """ |
| 53 | Ensure first two rows (column header and separator row) are valid table rows. |
| 54 | |
| 55 | Keep border check and separator row do avoid repeating the work. |
| 56 | """ |
| 57 | is_table = False |
| 58 | rows = [row.strip(' ') for row in block.split('\n')] |
| 59 | if len(rows) > 1: |
| 60 | header0 = rows[0] |
| 61 | self.border = PIPE_NONE |
| 62 | if header0.startswith('|'): |
| 63 | self.border |= PIPE_LEFT |
| 64 | if self.RE_END_BORDER.search(header0) is not None: |
| 65 | self.border |= PIPE_RIGHT |
| 66 | row = self._split_row(header0) |
| 67 | row0_len = len(row) |
| 68 | is_table = row0_len > 1 |
| 69 | |
| 70 | # Each row in a single column table needs at least one pipe. |
| 71 | if not is_table and row0_len == 1 and self.border: |
| 72 | for index in range(1, len(rows)): |
| 73 | is_table = rows[index].startswith('|') |
| 74 | if not is_table: |
| 75 | is_table = self.RE_END_BORDER.search(rows[index]) is not None |
| 76 | if not is_table: |
| 77 | break |
| 78 | |
| 79 | if is_table: |
| 80 | row = self._split_row(rows[1]) |
| 81 | is_table = (len(row) == row0_len) and set(''.join(row)) <= set('|:- ') |
| 82 | if is_table: |
| 83 | self.separator = row |
| 84 | |
| 85 | return is_table |
| 86 | |
| 87 | def run(self, parent: etree.Element, blocks: list[str]) -> None: |
| 88 | """ Parse a table block and build table. """ |
| 89 | block = blocks.pop(0).split('\n') |
| 90 | header = block[0].strip(' ') |
| 91 | rows = [] if len(block) < 3 else block[2:] |
| 92 | |
| 93 | # Get alignment of columns |
| 94 | align: list[str | None] = [] |
| 95 | for c in self.separator: |
no outgoing calls
no test coverage detected
searching dependent graphs…