From 4ae58b0554c3770e5642371ab8bc81bbe7d7ed89 Mon Sep 17 00:00:00 2001 From: Chaehyun Lee Date: Fri, 20 Mar 2026 23:16:56 +0900 Subject: [PATCH 1/2] Fix markdown table parsing and selection on web - Preserve empty interior cells when parsing tables (fixes column misalignment when first header cell is empty) - Add selectable prop to table text elements (enables text selection and copy on web, matching other markdown blocks) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- .../components/markdown/MarkdownView.tsx | 9 +++++---- .../components/markdown/parseMarkdownBlock.ts | 17 ++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/happy-app/sources/components/markdown/MarkdownView.tsx b/packages/happy-app/sources/components/markdown/MarkdownView.tsx index 0cb1d54cb7..1eb5e4681d 100644 --- a/packages/happy-app/sources/components/markdown/MarkdownView.tsx +++ b/packages/happy-app/sources/components/markdown/MarkdownView.tsx @@ -65,7 +65,7 @@ export const MarkdownView = React.memo((props: { } else if (block.type === 'options') { return ; } else if (block.type === 'table') { - return ; + return ; } else { return null; } @@ -235,7 +235,8 @@ function RenderTableBlock(props: { headers: string[], rows: string[][], first: boolean, - last: boolean + last: boolean, + selectable: boolean }) { const columnCount = props.headers.length; const rowCount = props.rows.length; @@ -261,7 +262,7 @@ function RenderTableBlock(props: { > {/* Header cell for this column */} - {header} + {header} {/* Data cells for this column */} {props.rows.map((row, rowIndex) => ( @@ -272,7 +273,7 @@ function RenderTableBlock(props: { isLastRow(rowIndex) && style.tableCellLast ]} > - {row[colIndex] ?? ''} + {row[colIndex] ?? ''} ))} diff --git a/packages/happy-app/sources/components/markdown/parseMarkdownBlock.ts b/packages/happy-app/sources/components/markdown/parseMarkdownBlock.ts index 03d76563b8..fe122d47ef 100644 --- a/packages/happy-app/sources/components/markdown/parseMarkdownBlock.ts +++ b/packages/happy-app/sources/components/markdown/parseMarkdownBlock.ts @@ -23,12 +23,11 @@ function parseTable(lines: string[], startIndex: number): { table: MarkdownBlock return { table: null, nextIndex: startIndex }; } - // Extract header cells from the first line, filtering out empty cells that may result from leading/trailing pipes - const headerLine = tableLines[0].trim(); + // Extract header cells from the first line, stripping leading/trailing pipes but preserving empty interior cells + const headerLine = tableLines[0].trim().replace(/^\||\|$/g, ''); const headers = headerLine .split('|') - .map(cell => cell.trim()) - .filter(cell => cell.length > 0); + .map(cell => cell.trim()); if (headers.length === 0) { return { table: null, nextIndex: startIndex }; @@ -39,15 +38,11 @@ function parseTable(lines: string[], startIndex: number): { table: MarkdownBlock for (let i = 2; i < tableLines.length; i++) { const rowLine = tableLines[i].trim(); if (rowLine.startsWith('|')) { - const rowCells = rowLine + const rowCells = rowLine.replace(/^\||\|$/g, '') .split('|') - .map(cell => cell.trim()) - .filter(cell => cell.length > 0); + .map(cell => cell.trim()); - // Include rows that contain actual content, filtering out empty rows - if (rowCells.length > 0) { - rows.push(rowCells); - } + rows.push(rowCells); } } From e34e764b9cce019ba4f8e499116744dc441ecdad Mon Sep 17 00:00:00 2001 From: Chaehyun Lee Date: Fri, 20 Mar 2026 23:31:37 +0900 Subject: [PATCH 2/2] Fix empty table cell height collapse Empty cells had no text content causing lineHeight to not apply, resulting in cells ~1/3 the height of populated cells. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- packages/happy-app/sources/components/markdown/MarkdownView.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/happy-app/sources/components/markdown/MarkdownView.tsx b/packages/happy-app/sources/components/markdown/MarkdownView.tsx index 1eb5e4681d..e596d945a1 100644 --- a/packages/happy-app/sources/components/markdown/MarkdownView.tsx +++ b/packages/happy-app/sources/components/markdown/MarkdownView.tsx @@ -527,6 +527,7 @@ const style = StyleSheet.create((theme) => ({ borderBottomWidth: 1, borderBottomColor: theme.colors.divider, alignItems: 'flex-start', + minHeight: 40, // padding (8+8) + lineHeight (24) to prevent empty cell collapse }, tableCellFirst: { borderTopWidth: 0,