diff --git a/tests/ui/test_ui_tools.py b/tests/ui/test_ui_tools.py
index 7d003b3d52f..ed09d525701 100644
--- a/tests/ui/test_ui_tools.py
+++ b/tests/ui/test_ui_tools.py
@@ -1332,7 +1332,17 @@ def test_private_message_to_self(self, mocker):
('
', ['[RULER NOT RENDERED]']),
('', ['[IMAGE NOT RENDERED]']),
('', ['[IMAGE NOT RENDERED]']),
- ('', ['[TABLE NOT RENDERED]']),
+ ('Firstname | Lastname |
'
+ 'John | Doe |
Mary | Moe'
+ ' |
', [
+ ('bold', '------------------------\n'),
+ ('bold', '| Firstname | Lastname |\n'),
+ ('bold', '------------------------\n'),
+ '| John | Doe |\n',
+ '------------------------\n',
+ '| Mary | Moe |\n',
+ '------------------------',
+ ]),
('some-math', ['some-math']),
('some-math', ['some-math']),
('', ['', ' * ', '', 'text']),
diff --git a/zulipterminal/helper.py b/zulipterminal/helper.py
index cf9093af4cd..5252bd55a9d 100644
--- a/zulipterminal/helper.py
+++ b/zulipterminal/helper.py
@@ -485,3 +485,43 @@ def notify(title: str, html_text: str) -> None:
if command:
res = subprocess.run(shlex.split(command), stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT)
+
+
+def render_table(element: Any) -> List[Union[str, Tuple[str, str]]]:
+ """
+ Renders table to be displayed in the MessageBox.
+ """
+ # Header.
+ headers = element.find('thead').findChild().find_all('th')
+ # Cells store data column-wise.
+ cells = [[] for _ in headers] # type: List[List[str]]
+ for index, header in enumerate(headers):
+ cells[index].append(' ' + header.text + ' ')
+
+ # Body.
+ rows = element.find('tbody').find_all('tr')
+ for row in rows:
+ for index, data in enumerate(row.find_all('td')):
+ cells[index].append(' ' + data.text + ' ')
+
+ # Rendering.
+ col_width = [len(max(column, key=lambda s: len(s))) for column in cells]
+ dashes = ('-' * (sum(col_width) + len(headers) + 1)) + '\n'
+ contents = [] # type: List[Union[str, Tuple[str, str]]]
+ contents.append(('bold', dashes))
+ rows_count = len(rows) + 1 # +1 to include header.
+ for index in range(rows_count):
+ row = '|' + '|'.join(col[index].ljust(col_width[col_index])
+ for col_index, col in enumerate(cells)) + '|\n'
+ if index == 0:
+ # Make the headers bold.
+ contents.append(('bold', row))
+ contents.append(('bold', dashes))
+ else:
+ contents.append(row)
+ if index == rows_count - 1:
+ # Remove '\n' for the last row.
+ contents.append(dashes[:-1])
+ else:
+ contents.append(dashes)
+ return contents
diff --git a/zulipterminal/ui_tools/boxes.py b/zulipterminal/ui_tools/boxes.py
index 6c3b317e273..4a88876d63d 100644
--- a/zulipterminal/ui_tools/boxes.py
+++ b/zulipterminal/ui_tools/boxes.py
@@ -13,7 +13,7 @@
from zulipterminal.config.keys import is_command_key, keys_for_command
from zulipterminal.helper import (
- Message, match_groups, match_stream, match_user,
+ Message, match_groups, match_stream, match_user, render_table,
)
from zulipterminal.urwid_types import urwid_Size
@@ -386,7 +386,6 @@ def soup2markup(self, soup: Any) -> List[Any]:
'br': '', # No indicator of absence
'hr': 'RULER',
'img': 'IMAGE',
- 'table': 'TABLE'
}
unrendered_div_classes = { # In pairs of 'div_class': 'text'
# TODO: Support embedded content & twitter preview?
@@ -482,6 +481,8 @@ def soup2markup(self, soup: Any) -> List[Any]:
# TODO: Support nested lists
markup.append(' * ')
markup.extend(self.soup2markup(element))
+ elif element.name == 'table':
+ markup.extend(render_table(element))
else:
markup.extend(self.soup2markup(element))
return markup