Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 30 additions & 0 deletions ui/desktop/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ui/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"react-select": "^5.10.2",
"react-syntax-highlighter": "^15.6.1",
"react-toastify": "^11.0.5",
"remark-breaks": "^4.0.0",
"remark-gfm": "^4.0.1",
"split-type": "^0.3.4",
"swr": "^2.3.6",
Expand Down
62 changes: 62 additions & 0 deletions ui/desktop/src/components/MarkdownContent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,66 @@ Unclosed code block`;
});
});
});

describe('Line Break Functionality', () => {
it('preserves single line breaks with remark-breaks plugin', async () => {
const content = `First line
Second line
Third line`;

const { container } = render(<MarkdownContent content={content} />);

await waitFor(() => {
// Check that all text content is present (text may be split by <br> tags)
expect(container).toHaveTextContent('First line');
expect(container).toHaveTextContent('Second line');
expect(container).toHaveTextContent('Third line');
});

// Check that line breaks are preserved (rendered as <br> tags)
const brElements = container.querySelectorAll('br');
expect(brElements.length).toBeGreaterThan(0);
});

it('handles mixed content with line breaks', async () => {
const content = `# Header
Paragraph with
line breaks.

- List item 1
- List item 2`;

const { container } = render(<MarkdownContent content={content} />);

await waitFor(() => {
expect(screen.getByRole('heading', { level: 1, name: 'Header' })).toBeInTheDocument();

// Check that text content is present (text may be split by <br> tags)
expect(container).toHaveTextContent('Paragraph with');
expect(container).toHaveTextContent('line breaks.');
expect(screen.getByText('List item 1')).toBeInTheDocument();
expect(screen.getByText('List item 2')).toBeInTheDocument();
});
});

it('maintains existing markdown features with line breaks', async () => {
const content = `**Bold text**
with line break

\`code\` and
more text`;

const { container } = render(<MarkdownContent content={content} />);

await waitFor(() => {
// Bold text should still work
const boldElement = container.querySelector('strong');
expect(boldElement).toBeInTheDocument();
expect(boldElement).toHaveTextContent('Bold text');

// Code should still work
expect(screen.getByText('code')).toBeInTheDocument();
});
});
});
});
3 changes: 2 additions & 1 deletion ui/desktop/src/components/MarkdownContent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import remarkBreaks from 'remark-breaks';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { Check, Copy } from './icons';
Expand Down Expand Up @@ -126,7 +127,7 @@ export default function MarkdownContent({ content, className = '' }: MarkdownCon
prose-li:m-0prose-li:font-sans ${className}`}
>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
remarkPlugins={[remarkGfm, remarkBreaks]}
components={{
a: ({ ...props }) => <a {...props} target="_blank" rel="noopener noreferrer" />,
code: MarkdownCode,
Expand Down
Loading