+
diff --git a/src/components/MarkdownMessage.tsx b/src/components/MarkdownMessage.tsx
index deb1fc5..9a4b5f6 100644
--- a/src/components/MarkdownMessage.tsx
+++ b/src/components/MarkdownMessage.tsx
@@ -20,6 +20,25 @@ const applyInlineMarkdown = (value: string) => {
return text;
};
+const splitTableRow = (line: string) => {
+ const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
+ return trimmed.split("|").map(cell => applyInlineMarkdown(cell.trim()));
+};
+
+const isTableSeparator = (line: string) => {
+ const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
+ if (!trimmed) return false;
+
+ return trimmed
+ .split("|")
+ .every(cell => /^:?-{3,}:?$/.test(cell.trim()));
+};
+
+const isTableRow = (line: string) => {
+ const trimmed = line.trim();
+ return trimmed.includes("|") && splitTableRow(trimmed).length > 1;
+};
+
const renderMarkdown = (markdown: string) => {
const lines = markdown.replace(/\r\n/g, "\n").split("\n");
const html: string[] = [];
@@ -46,6 +65,36 @@ const renderMarkdown = (markdown: string) => {
continue;
}
+ const headingMatch = trimmed.match(/^(#{1,6})\s+(.+)$/);
+ if (headingMatch) {
+ const level = headingMatch[1].length;
+ const text = applyInlineMarkdown(headingMatch[2].trim());
+ html.push(`
${text}`);
+ i += 1;
+ continue;
+ }
+
+ if (
+ i + 1 < lines.length &&
+ isTableRow(lines[i]) &&
+ isTableSeparator(lines[i + 1])
+ ) {
+ const headerCells = splitTableRow(lines[i]);
+ const bodyRows: string[] = [];
+ i += 2;
+
+ while (i < lines.length && lines[i].trim() && isTableRow(lines[i])) {
+ const cells = splitTableRow(lines[i]).map(cell => `
${cell} | `);
+ bodyRows.push(`
${cells.join("")}
`);
+ i += 1;
+ }
+
+ html.push(
+ `
${headerCells.map(cell => `| ${cell} | `).join("")}
${bodyRows.length > 0 ? `${bodyRows.join("")}` : ""}
`
+ );
+ continue;
+ }
+
if (/^[-*]\s+/.test(trimmed)) {
const items: string[] = [];
while (i < lines.length && /^[-*]\s+/.test(lines[i].trim())) {
@@ -97,12 +146,17 @@ export const MarkdownMessage: Component<{