From 6521739947b30a3d0de950c4186310703998e2fd Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Mon, 26 Oct 2026 11:22:07 +0700 Subject: [PATCH] fix(markdown): preserve inline code formatting and heading sizes (#7889) Scale inline code with the enclosing block using theme tokens, and preserve its size and font through bold and links. Use contextual package patches so clean installs reproduce the verified native source. --- .../e2e/mobile/markdown-formatting/README.md | 25 + .../e2e/mobile/markdown-formatting/native.tsx | 52 ++ packages/app/package.json | 2 +- .../src/components/markdown/renderer.test.ts | 15 + .../app/src/components/markdown/styles.ts | 2 +- ...own+1.2.0-nightly-20261014-766fc0e67.patch | 508 ++++++++++++++++-- 6 files changed, 557 insertions(+), 47 deletions(-) create mode 100644 packages/app/e2e/mobile/markdown-formatting/README.md create mode 100644 packages/app/e2e/mobile/markdown-formatting/native.tsx diff --git a/packages/app/e2e/mobile/markdown-formatting/README.md b/packages/app/e2e/mobile/markdown-formatting/README.md new file mode 100644 index 0000000000..c2ab0ddc65 --- /dev/null +++ b/packages/app/e2e/mobile/markdown-formatting/README.md @@ -0,0 +1,25 @@ +# Inline code formatting + +This fixture renders the production `MarkdownRenderer` with plain, bold, italic, +combined emphasis, strikethrough and linked code, plus bold code in headings, +lists and quotes. Toggle regular/compact text. Inline code uses the theme’s +code-to-body size ratio at every heading level; fenced code keeps the code-size +token. Bold and links preserve the resulting size. Check the glyphs, not the background height: native backgrounds use +line metrics. + +Use a development client rebuilt from this checkout. Follow the temporary entry +point and Metro workflow in [status-ring](../status-ring/README.md), importing +`MarkdownFormattingRegression` from `./e2e/mobile/markdown-formatting/native`. +Open the same Metro URL in a browser to compare web. Restore `index.ts` afterward. + +The package patch contains `InlineCodeFormattingTest`, which exercises actual +Android spans in Robolectric native graphics mode, covering draw and measurement, +span order, code inside paragraph/heading sizes, bold/italic composition, and +links preserving code and emphasized prose fonts. +It runs in the existing `test:android` CI job. To run only this regression locally, +from `packages/app/android` after Expo prebuild: + +```sh +./gradlew :react-native-enriched-markdown:testDebugUnitTest \ + --tests '*InlineCodeFormattingTest' --no-daemon --max-workers=2 +``` diff --git a/packages/app/e2e/mobile/markdown-formatting/native.tsx b/packages/app/e2e/mobile/markdown-formatting/native.tsx new file mode 100644 index 0000000000..d5d9a64aa0 --- /dev/null +++ b/packages/app/e2e/mobile/markdown-formatting/native.tsx @@ -0,0 +1,52 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { useCallback, useState } from "react"; +import { Button, ScrollView, Text } from "react-native"; +import { StyleSheet } from "react-native-unistyles"; +import { GestureHandlerRootView } from "react-native-gesture-handler"; +import { MarkdownRenderer } from "@/components/markdown/renderer"; + +const styles = StyleSheet.create((theme) => ({ + root: { flex: 1 }, + scroll: { backgroundColor: theme.colors.surface0 }, + content: { padding: 32, paddingTop: 60 }, + title: { color: theme.colors.foreground }, +})); + +const queryClient = new QueryClient(); + +const source = [ + "Plain: `MMMMiiii`", + "Bold: **`MMMMiiii`**", + "Italic: *`MMMMiiii`*", + "Both: ***`MMMMiiii`***", + "Strike: ~~`MMMMiiii`~~", + "Link: [`MMMMiiii`](https://example.com)", + "# Heading **`MMMMiiii`**", + "## Heading *`MMMMiiii`*", + "### Heading [`MMMMiiii`](https://example.com)", + "#### Heading ~~`MMMMiiii`~~", + "##### Heading ***`MMMMiiii`***", + "###### Heading `MMMMiiii`", + "- List **`MMMMiiii`**", + "> Quote **`MMMMiiii`**", + "Normal **bold** and *italic* prose.", +].join("\n\n"); + +export default function MarkdownFormattingRegression() { + const [compact, setCompact] = useState(false); + const toggleCompact = useCallback(() => setCompact((value) => !value), []); + return ( + + + + Inline code formatting regression +