From afe1cd0918e182b8107ffa81b9f9d6cdec4615ae Mon Sep 17 00:00:00 2001
From: Clawd <ai@clawd.bot>
Date: Sat, 28 Feb 2026 13:45:59 -0800
Subject: Add markdown table rendering support

- Add renderTable() function to parse markdown tables
- Process tables before other markdown transformations
- Handle header row, separator row, and body rows
- Add table CSS styling (borders, alternating row colors, padding)
---
 renderer/src/components/DocumentPane.tsx | 67 +++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

(limited to 'renderer/src/components/DocumentPane.tsx')

diff --git a/renderer/src/components/DocumentPane.tsx b/renderer/src/components/DocumentPane.tsx
index a22ecad..c2e1b2c 100644
--- a/renderer/src/components/DocumentPane.tsx
+++ b/renderer/src/components/DocumentPane.tsx
@@ -9,9 +9,72 @@ interface DocumentPaneProps {
   showOnboarding?: boolean;
 }
 
+function renderTable(tableLines: string[]): string {
+  if (tableLines.length < 2) return tableLines.join("\n");
+  
+  const parseRow = (line: string): string[] => {
+    return line
+      .split("|")
+      .slice(1, -1) // Remove empty first/last from |col|col|
+      .map((cell) => cell.trim());
+  };
+
+  const headerCells = parseRow(tableLines[0]);
+  // Skip separator row (index 1)
+  const bodyRows = tableLines.slice(2);
+
+  let html = '<table><thead><tr>';
+  headerCells.forEach((cell) => {
+    html += `<th>${cell}</th>`;
+  });
+  html += '</tr></thead><tbody>';
+  
+  bodyRows.forEach((row) => {
+    if (row.trim()) {
+      html += '<tr>';
+      parseRow(row).forEach((cell) => {
+        html += `<td>${cell}</td>`;
+      });
+      html += '</tr>';
+    }
+  });
+  
+  html += '</tbody></table>';
+  return html;
+}
+
 function renderMarkdown(md: string): string {
+  // First, handle tables (before other transformations)
+  const lines = md.split("\n");
+  const processedLines: string[] = [];
+  let tableBuffer: string[] = [];
+  let inTable = false;
+
+  for (const line of lines) {
+    const isTableLine = /^\|.*\|$/.test(line.trim());
+    
+    if (isTableLine) {
+      inTable = true;
+      tableBuffer.push(line);
+    } else {
+      if (inTable && tableBuffer.length > 0) {
+        processedLines.push(renderTable(tableBuffer));
+        tableBuffer = [];
+        inTable = false;
+      }
+      processedLines.push(line);
+    }
+  }
+  
+  // Handle table at end of content
+  if (tableBuffer.length > 0) {
+    processedLines.push(renderTable(tableBuffer));
+  }
+
+  let result = processedLines.join("\n");
+
   return (
-    md
+    result
       // Headers
       .replace(/^### (.*$)/gm, "<h3>$1</h3>")
       .replace(/^## (.*$)/gm, "<h2>$1</h2>")
@@ -43,6 +106,8 @@ function renderMarkdown(md: string): string {
       .replace(/(<\/pre>)<\/p>/g, "$1")
       .replace(/<p>(<li)/g, "$1")
       .replace(/(<\/li>)<\/p>/g, "$1")
+      .replace(/<p>(<table>)/g, "$1")
+      .replace(/(<\/table>)<\/p>/g, "$1")
   );
 }
 
-- 
cgit v1.2.3

