mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 10:12:44 +00:00
fix(markdown): linked inline code keeps inline code size
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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 };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -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 = <a {...anchorProps}>{children}</a>;
|
||||
const anchorStyle = useMemo(
|
||||
() => ({ ...anchorProps.style, overflowWrap: "anywhere" as const }),
|
||||
[anchorProps.style],
|
||||
);
|
||||
const anchor = (
|
||||
<a {...anchorProps} style={anchorStyle}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
return (
|
||||
<Tooltip delayDuration={400}>
|
||||
<TooltipTrigger asChild onHoverIn={onHoverIn}>
|
||||
|
||||
@@ -60,7 +60,6 @@ export function createMarkdownStyles(
|
||||
linkVariants: {
|
||||
"^(?!https?://).+": {
|
||||
color: theme.colors.accentBright,
|
||||
pill: { borderRadius: 4, paddingHorizontal: 3 },
|
||||
},
|
||||
},
|
||||
code: {
|
||||
|
||||
@@ -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 <mark style={styles.highlight}>{renderChildren(node)}</mark>;
|
||||
}
|
||||
|
||||
-function CodeRenderer({ node, styles, renderChildren }: RendererProps) {
|
||||
+function CodeRenderer({ node, styles, parentType, renderChildren }: RendererProps) {
|
||||
return (
|
||||
- <code style={styles.code}>{node.content ?? renderChildren(node)}</code>
|
||||
+ <code style={parentType === 'Link' ? { ...styles.code, color: 'inherit' } : styles.code}>{node.content ?? renderChildren(node)}</code>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user