Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/mobile/src/lib/wideMarkdownBlocks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ describe("hasWideMarkdownBlock", () => {
expect(hasWideMarkdownBlock(" ```\ncode\n```")).toBe(true);
});

it("detects ordered-list markers with a simple heuristic", () => {
expect(hasWideMarkdownBlock("1. One\n2. Two\n3. Three\n4. Four\n5. Five")).toBe(true);
expect(hasWideMarkdownBlock("before\n3) Three")).toBe(true);
expect(hasWideMarkdownBlock(" 1. indented code")).toBe(false);
});

it("detects GFM tables", () => {
expect(hasWideMarkdownBlock("| a | b |\n| --- | --- |\n| 1 | 2 |")).toBe(true);
expect(hasWideMarkdownBlock("a | b\n:-- | --:\n1 | 2")).toBe(true);
Expand Down
17 changes: 12 additions & 5 deletions apps/mobile/src/lib/wideMarkdownBlocks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/**
* Detects markdown that the JS renderer draws as a standalone block View
* wrapping a horizontal ScrollView — fenced code blocks and GFM tables.
* Detects markdown that the JS renderer draws as a block requiring a definite
* user-bubble width — fenced code blocks, GFM tables, and ordered lists.
*
* Those blocks report an intrinsic width equal to their widest line, which is
* effectively unbounded. A user bubble sizes itself from its content
* Fenced code blocks and tables report an intrinsic width equal to their
* widest line, which is effectively unbounded. A user bubble sizes itself
* from its content
* (`maxWidth` with no `width`), so Android lays the bubble's children out
* during the unclamped intrinsic pass — where the surrounding paragraphs
* collapse to a single line — and never repositions them once the width is
Expand All @@ -12,12 +13,18 @@
* intrinsic pass entirely, which is the same reason review-comment bubbles
* already carry an explicit width.
*
* Ordered lists hit the same Android layout bug because each item contains a
* flexing content column inside a shrink-to-fit row.
*
* Indented (four-space) code blocks are deliberately not detected: they are
* vanishingly rare in chat input and the check would fire on ordinary nested
* list continuations.
*/

const FENCED_CODE_BLOCK = /^ {0,3}(?:```|~~~)/m;
// Trades some precision for a simple check, favoring false positives over false
// negatives: list-shaped paragraph may get a wider bubble
const ORDERED_LIST_ITEM = /^ {0,3}\d{1,9}[.)](?:[ \t]+|$)/m;

function isTableDelimiterRow(line: string): boolean {
const trimmed = line.trim();
Expand All @@ -28,7 +35,7 @@ function isTableDelimiterRow(line: string): boolean {
}

export function hasWideMarkdownBlock(text: string): boolean {
if (FENCED_CODE_BLOCK.test(text)) {
if (FENCED_CODE_BLOCK.test(text) || ORDERED_LIST_ITEM.test(text)) {
return true;
}
if (!text.includes("|")) {
Expand Down
Loading