mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
Add remark_breaks to handle newlines (#183)
This commit is contained in:
parent
34cfd156d1
commit
2d8211aea7
4 changed files with 136 additions and 0 deletions
|
|
@ -63,6 +63,7 @@
|
|||
"react-markdown": "^10.1.0",
|
||||
"react-use": "^17.6.0",
|
||||
"recharts": "^2.15.3",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"require-in-the-middle": "^7.5.2",
|
||||
"shiki": "^3.7.0",
|
||||
"sonner": "^2.0.3",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useMemo, useEffect, useState } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkBreaks from 'remark-breaks';
|
||||
import { Link2 } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
|
|
@ -312,6 +313,7 @@ export const Messages = ({
|
|||
) : (
|
||||
<div className="text-sm leading-relaxed markdown-prose">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkBreaks]}
|
||||
components={{
|
||||
a: PlainTextLink,
|
||||
code: CodeBlock,
|
||||
|
|
|
|||
97
apps/web/src/components/ui/__tests__/Messages.test.tsx
Normal file
97
apps/web/src/components/ui/__tests__/Messages.test.tsx
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import { render, screen } from '@testing-library/react';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
import { Messages } from '@/app/(authenticated)/usage/Messages';
|
||||
import type { Message } from '@/actions/analytics/messages';
|
||||
|
||||
// Mock the hooks and dependencies
|
||||
vi.mock('@/hooks/useAutoScroll', () => ({
|
||||
useAutoScroll: () => ({
|
||||
containerRef: { current: null },
|
||||
scrollToBottom: vi.fn(),
|
||||
autoScrollToBottom: vi.fn(),
|
||||
userHasScrolled: false,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/formatters', () => ({
|
||||
formatTimestamp: (timestamp: number) => new Date(timestamp).toLocaleString(),
|
||||
}));
|
||||
|
||||
describe('Messages Component - Newline Handling', () => {
|
||||
const createMockMessage = (text: string, id = '1'): Message => ({
|
||||
id,
|
||||
orgId: null,
|
||||
userId: 'test-user',
|
||||
taskId: 'test-task',
|
||||
text,
|
||||
timestamp: Date.now(),
|
||||
ts: Date.now(),
|
||||
type: 'say',
|
||||
say: 'text',
|
||||
ask: null,
|
||||
mode: 'code',
|
||||
reasoning: null,
|
||||
partial: null,
|
||||
});
|
||||
|
||||
it('should render messages with newlines properly', () => {
|
||||
const messageWithNewlines = createMockMessage('Line 1\nLine 2\nLine 3');
|
||||
|
||||
render(<Messages messages={[messageWithNewlines]} />);
|
||||
|
||||
// The text should be present in the document
|
||||
expect(screen.getByText(/Line 1/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Line 2/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Line 3/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle multiple consecutive newlines', () => {
|
||||
const messageWithMultipleNewlines = createMockMessage(
|
||||
'Paragraph 1\n\nParagraph 2\n\n\nParagraph 3',
|
||||
);
|
||||
|
||||
render(<Messages messages={[messageWithMultipleNewlines]} />);
|
||||
|
||||
expect(screen.getByText(/Paragraph 1/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Paragraph 2/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Paragraph 3/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle mixed content with newlines', () => {
|
||||
const mixedContent = createMockMessage(
|
||||
'Regular text\n**Bold text**\n`code snippet`\nMore text',
|
||||
);
|
||||
|
||||
render(<Messages messages={[mixedContent]} />);
|
||||
|
||||
expect(screen.getByText(/Regular text/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Bold text/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/code snippet/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/More text/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle command messages without markdown processing', () => {
|
||||
const commandMessage: Message = {
|
||||
id: '1',
|
||||
orgId: null,
|
||||
userId: 'test-user',
|
||||
taskId: 'test-task',
|
||||
text: 'npm install\ncd project\nls -la',
|
||||
timestamp: Date.now(),
|
||||
ts: Date.now(),
|
||||
type: 'ask',
|
||||
say: null,
|
||||
ask: 'command',
|
||||
mode: 'code',
|
||||
reasoning: null,
|
||||
partial: null,
|
||||
};
|
||||
|
||||
render(<Messages messages={[commandMessage]} />);
|
||||
|
||||
// Command messages should preserve newlines in the monospace container
|
||||
const commandContainer = screen.getByText(/npm install/);
|
||||
expect(commandContainer).toBeInTheDocument();
|
||||
expect(commandContainer.closest('.font-mono')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
36
pnpm-lock.yaml
generated
36
pnpm-lock.yaml
generated
|
|
@ -299,6 +299,9 @@ importers:
|
|||
recharts:
|
||||
specifier: ^2.15.3
|
||||
version: 2.15.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
remark-breaks:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
require-in-the-middle:
|
||||
specifier: ^7.5.2
|
||||
version: 7.5.2
|
||||
|
|
@ -3979,6 +3982,10 @@ packages:
|
|||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
escape-string-regexp@5.0.0:
|
||||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
eslint-config-prettier@10.1.5:
|
||||
resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==}
|
||||
hasBin: true
|
||||
|
|
@ -5006,6 +5013,9 @@ packages:
|
|||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
|
||||
|
||||
mdast-util-from-markdown@2.0.2:
|
||||
resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
|
||||
|
||||
|
|
@ -5018,6 +5028,9 @@ packages:
|
|||
mdast-util-mdxjs-esm@2.0.1:
|
||||
resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
|
||||
|
||||
mdast-util-newline-to-break@2.0.0:
|
||||
resolution: {integrity: sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==}
|
||||
|
||||
mdast-util-phrasing@4.1.0:
|
||||
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
|
||||
|
||||
|
|
@ -5893,6 +5906,9 @@ packages:
|
|||
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
remark-breaks@4.0.0:
|
||||
resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==}
|
||||
|
||||
remark-parse@11.0.0:
|
||||
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
||||
|
||||
|
|
@ -10593,6 +10609,8 @@ snapshots:
|
|||
|
||||
escape-string-regexp@4.0.0: {}
|
||||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
eslint-config-prettier@10.1.5(eslint@9.29.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
eslint: 9.29.0(jiti@2.4.2)
|
||||
|
|
@ -11697,6 +11715,13 @@ snapshots:
|
|||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
escape-string-regexp: 5.0.0
|
||||
unist-util-is: 6.0.0
|
||||
unist-util-visit-parents: 6.0.1
|
||||
|
||||
mdast-util-from-markdown@2.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
|
@ -11753,6 +11778,11 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
mdast-util-newline-to-break@2.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-find-and-replace: 3.0.2
|
||||
|
||||
mdast-util-phrasing@4.1.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
|
@ -12800,6 +12830,12 @@ snapshots:
|
|||
gopd: 1.2.0
|
||||
set-function-name: 2.0.2
|
||||
|
||||
remark-breaks@4.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-newline-to-break: 2.0.0
|
||||
unified: 11.0.5
|
||||
|
||||
remark-parse@11.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue