diff --git a/docs/markdown-renderer.md b/docs/markdown-renderer.md
index c1d62fa817..219bec14b5 100644
--- a/docs/markdown-renderer.md
+++ b/docs/markdown-renderer.md
@@ -18,7 +18,7 @@ Math and video are disabled. Task lists and admonitions are enabled; task checkb
Mermaid fences use the existing isolated diagram runtime and fullscreen viewer. Web dispatches them through the library’s code-block override. Native has no block-renderer hook, so the renderer extracts only Mermaid fences and places the existing WebView host between library-rendered segments. This is the only block exception; see [native selection limitations](native-text-selection.md) for diagram grouping and leading inline images. Streaming keeps the last valid diagram visible while the next revision renders.
-Native code blocks use the library's copy control and compiled grammars. Web code blocks use `HighlightedCodeBlock` through the library's `renderers.codeBlock` override. The patch also preserves web list numbering and link titles, marks pending parses with `aria-busy` so Find waits for rendered text, and carries link syntax through native and web tap events. The package patch is tracked by [upstream PR #997](https://github.com/software-mansion/enriched-markdown/pull/997); remove the patch when the pinned release includes it.
+Native code blocks use the library's copy control and compiled grammars. Web code blocks use `HighlightedCodeBlock` through the library's `renderers.codeBlock` override. The patch also preserves web list numbering and link titles, marks pending parses with `aria-busy` so Find waits for rendered text, and carries link syntax through native and web tap events. Web inline code inside a link inherits only the link colour; its code font, size and background stay intact. Keep link variants colour-only: native pills replace text runs and prevent paths from wrapping; Android pills also use the surrounding block’s font size. The package patch is tracked by [upstream PR #997](https://github.com/software-mansion/enriched-markdown/pull/997); remove the patch when the pinned release includes it.
The library determines how incomplete Markdown appears during streaming. Completed text uses the same component and engine as history. Find and scroll-to-message address source message ids; selection-copy understands semantic HTML and the web code component's copy metadata.
diff --git a/packages/app/e2e/browser/plan-card-markdown.spec.ts b/packages/app/e2e/browser/plan-card-markdown.spec.ts
index a5d5cd204a..5dcf2a2cec 100644
--- a/packages/app/e2e/browser/plan-card-markdown.spec.ts
+++ b/packages/app/e2e/browser/plan-card-markdown.spec.ts
@@ -118,3 +118,73 @@ async function openSharedMarkdownFile(page: Page, name: string) {
await returnToSharedMarkdownChat(page);
await page.getByTestId("assistant-message").getByRole("link", { name, exact: true }).click();
}
+
+test("linked inline code keeps code typography and wraps long paths", async ({
+ page,
+}, testInfo) => {
+ const longPath =
+ "packages/app/src/components/markdown/renderer/very-long-directory-name/another-long-directory-name/file.ts:12";
+ const session = await seedMockAgentWorkspace({
+ repoPrefix: "inline-code-style-",
+ title: "Inline code style",
+ featureValues: {
+ mockAssistantResponse:
+ "Compare `ordinary_token`, `file.ts:12`, `https://example.com`. At the end of this line open `" +
+ longPath +
+ "`.",
+ },
+ initialPrompt: "Show inline code",
+ });
+ try {
+ await session.client.waitForFinish(session.agentId, 30_000);
+ await openAgentRoute(page, session);
+ const message = page.getByTestId("assistant-message");
+ await expect(message.getByRole("link", { name: longPath, exact: true })).toBeVisible();
+ const measurements = await measureInlineCode(message);
+ await testInfo.attach("inline-code-measurements", {
+ body: JSON.stringify(measurements, null, 2),
+ contentType: "application/json",
+ });
+ expect(measurements.codes).toHaveLength(4);
+ const [plain, file, url, long] = measurements.codes;
+ for (const linked of [file, url, long]) {
+ expect(linked.fontSize).toBe(plain.fontSize);
+ expect(linked.fontFamily).toBe(plain.fontFamily);
+ expect(linked.backgroundColor).toBe(plain.backgroundColor);
+ expect(linked.color).toBe(linked.anchorColor);
+ expect(linked.color).not.toBe(plain.color);
+ }
+ expect(long.lines).toBeGreaterThan(1);
+ expect(long.right).toBeLessThanOrEqual(measurements.right + 1);
+ } finally {
+ await session.cleanup();
+ }
+});
+
+async function measureInlineCode(message: Locator) {
+ return message.evaluate((element) => {
+ // Constrain the paragraph to exercise an inline path at a line boundary.
+ const paragraph = element.querySelector("p")!;
+ paragraph.style.width = "300px";
+ const codes = Array.from(paragraph.querySelectorAll("code"), (code) => {
+ const style = getComputedStyle(code);
+ const range = document.createRange();
+ range.selectNodeContents(code);
+ const rects = Array.from(range.getClientRects());
+ return {
+ text: code.textContent,
+ fontSize: style.fontSize,
+ fontFamily: style.fontFamily,
+ backgroundColor: style.backgroundColor,
+ color: style.color,
+ anchorColor: code.closest("a") ? getComputedStyle(code.closest("a")!).color : null,
+ whiteSpace: style.whiteSpace,
+ overflowWrap: style.overflowWrap,
+ rects: rects.map((rect) => ({ left: rect.left, right: rect.right, top: rect.top })),
+ lines: new Set(rects.map((rect) => rect.top)).size,
+ right: Math.max(...rects.map((rect) => rect.right)),
+ };
+ });
+ return { codes, right: paragraph.getBoundingClientRect().right };
+ });
+}
diff --git a/packages/app/src/components/markdown/renderer.test.ts b/packages/app/src/components/markdown/renderer.test.ts
index 5a0b972c3c..1703a4c5fc 100644
--- a/packages/app/src/components/markdown/renderer.test.ts
+++ b/packages/app/src/components/markdown/renderer.test.ts
@@ -200,7 +200,9 @@ it.each([
borderColor: "transparent",
});
expect(style.link?.color).toBe(theme.colors.accentBright);
- expect(style.linkVariants?.["^(?!https?://).+"]?.color).toBe(theme.colors.accentBright);
+ expect(style.linkVariants?.["^(?!https?://).+"]).toEqual({
+ color: theme.colors.accentBright,
+ });
expect(style.thematicBreak?.color).toBe(theme.colors.border);
},
);
diff --git a/packages/app/src/components/markdown/renderers.web.tsx b/packages/app/src/components/markdown/renderers.web.tsx
index abf341d051..6f0afc666b 100644
--- a/packages/app/src/components/markdown/renderers.web.tsx
+++ b/packages/app/src/components/markdown/renderers.web.tsx
@@ -1,5 +1,5 @@
import { Text } from "react-native";
-import { forwardRef, type ComponentProps } from "react";
+import { forwardRef, useMemo, type ComponentProps } from "react";
import type {
CodeBlockRendererProps,
LinkRendererProps,
@@ -29,7 +29,15 @@ function WebCodeBlock({ code, language }: CodeBlockRendererProps) {
function WebLink({ link, anchorProps, children }: LinkRendererProps) {
const { tooltipPath, onHoverIn } = useFileLink(markdownLinkSource(link.url, link.sourceType));
- const anchor = {children};
+ const anchorStyle = useMemo(
+ () => ({ ...anchorProps.style, overflowWrap: "anywhere" as const }),
+ [anchorProps.style],
+ );
+ const anchor = (
+
+ {children}
+
+ );
return (
diff --git a/packages/app/src/components/markdown/styles.ts b/packages/app/src/components/markdown/styles.ts
index da3175d7a2..03d6c69b23 100644
--- a/packages/app/src/components/markdown/styles.ts
+++ b/packages/app/src/components/markdown/styles.ts
@@ -60,7 +60,6 @@ export function createMarkdownStyles(
linkVariants: {
"^(?!https?://).+": {
color: theme.colors.accentBright,
- pill: { borderRadius: 4, paddingHorizontal: 3 },
},
},
code: {
diff --git a/patches/react-native-enriched-markdown+1.2.0-nightly-20261014-766fc0e67.patch b/patches/react-native-enriched-markdown+1.2.0-nightly-20261014-766fc0e67.patch
index cf0c983066..7c1d282c7b 100644
--- a/patches/react-native-enriched-markdown+1.2.0-nightly-20261014-766fc0e67.patch
+++ b/patches/react-native-enriched-markdown+1.2.0-nightly-20261014-766fc0e67.patch
@@ -2283,9 +2283,22 @@ diff --git a/node_modules/react-native-enriched-markdown/lib/typescript/src/inde
export type { EnrichedMarkdownTextProps } from './types/MarkdownTextProps.web';
export type { MarkdownStyle, Md4cFlags } from './types/MarkdownStyle';
diff --git a/node_modules/react-native-enriched-markdown/src/web/renderers/InlineRenderers.tsx b/node_modules/react-native-enriched-markdown/src/web/renderers/InlineRenderers.tsx
+index 091eb19..bbee3ce 100644
--- a/node_modules/react-native-enriched-markdown/src/web/renderers/InlineRenderers.tsx
+++ b/node_modules/react-native-enriched-markdown/src/web/renderers/InlineRenderers.tsx
-@@ -58,16 +58,25 @@
+@@ -48,9 +48,9 @@ function HighlightRenderer({ node, styles, renderChildren }: RendererProps) {
+ return {renderChildren(node)};
+ }
+
+-function CodeRenderer({ node, styles, renderChildren }: RendererProps) {
++function CodeRenderer({ node, styles, parentType, renderChildren }: RendererProps) {
+ return (
+- {node.content ?? renderChildren(node)}
++ {node.content ?? renderChildren(node)}
+ );
+ }
+
+@@ -58,16 +58,25 @@ function LinkRenderer({
node,
style,
callbacks,
@@ -2312,7 +2325,7 @@ diff --git a/node_modules/react-native-enriched-markdown/src/web/renderers/Inlin
}
};
-@@ -78,18 +87,27 @@
+@@ -78,18 +87,27 @@ function LinkRenderer({
}
};
@@ -2353,9 +2366,23 @@ diff --git a/node_modules/react-native-enriched-markdown/src/web/renderers/Inlin
function LatexMathInlineRenderer({
diff --git a/node_modules/react-native-enriched-markdown/lib/module/web/renderers/InlineRenderers.js b/node_modules/react-native-enriched-markdown/lib/module/web/renderers/InlineRenderers.js
+index c8311d4..d1e698c 100644
--- a/node_modules/react-native-enriched-markdown/lib/module/web/renderers/InlineRenderers.js
+++ b/node_modules/react-native-enriched-markdown/lib/module/web/renderers/InlineRenderers.js
-@@ -103,18 +103,24 @@
+@@ -92,10 +92,11 @@ function HighlightRenderer({
+ function CodeRenderer({
+ node,
+ styles,
++ parentType,
+ renderChildren
+ }) {
+ return /*#__PURE__*/_jsx("code", {
+- style: styles.code,
++ style: parentType === 'Link' ? { ...styles.code, color: 'inherit' } : styles.code,
+ children: node.content ?? renderChildren(node)
+ });
+ }
+@@ -103,18 +104,24 @@ function LinkRenderer({
node,
style,
callbacks,
@@ -2383,7 +2410,7 @@ diff --git a/node_modules/react-native-enriched-markdown/lib/module/web/renderer
}
};
const handleContextMenu = event => {
-@@ -125,15 +131,24 @@
+@@ -125,15 +132,24 @@ function LinkRenderer({
});
}
};