diff --git a/frontend/src/test/utils/citationParser.test.ts b/frontend/src/test/utils/citationParser.test.ts index 50d5cd7..16d6a6f 100644 --- a/frontend/src/test/utils/citationParser.test.ts +++ b/frontend/src/test/utils/citationParser.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest' -import { processCitations } from '../../utils/citationParser' +import { processCitations, bulletizeMarkdown } from '../../utils/citationParser' import type { SourceMetadata } from '../../types' const mockSources: SourceMetadata[] = [ @@ -145,3 +145,40 @@ describe('processCitations', () => { expect(result).toContain('/pdf-viewer') }) }) + +describe('bulletizeMarkdown', () => { + it('converts paragraphs to bullet points', () => { + const input = 'First paragraph.\n\nSecond paragraph.\n\nThird paragraph.' + const result = bulletizeMarkdown(input) + expect(result).toBe('- First paragraph.\n- Second paragraph.\n- Third paragraph.') + }) + + it('preserves content that already has bullet points', () => { + const input = '- Already a bullet\n- Second bullet' + const result = bulletizeMarkdown(input) + expect(result).toBe(input) + }) + + it('preserves numbered lists', () => { + const input = '1. First item\n2. Second item' + const result = bulletizeMarkdown(input) + expect(result).toBe(input) + }) + + it('handles single line', () => { + const input = 'Just one line.' + const result = bulletizeMarkdown(input) + expect(result).toBe('- Just one line.') + }) + + it('handles text with inline newlines (soft wrap)', () => { + const input = 'Line one\nstill same paragraph.' + const result = bulletizeMarkdown(input) + expect(result).toBe('- Line one still same paragraph.') + }) + + it('returns empty string for empty input', () => { + expect(bulletizeMarkdown('')).toBe('') + expect(bulletizeMarkdown(' \n ')).toBe('') + }) +}) diff --git a/frontend/src/utils/citationParser.ts b/frontend/src/utils/citationParser.ts index 084af38..efb1980 100644 --- a/frontend/src/utils/citationParser.ts +++ b/frontend/src/utils/citationParser.ts @@ -1,6 +1,19 @@ import type { SourceMetadata, SubQuestionSources } from '../types' import { getPdfViewerUrl } from '../lib/api' +export function bulletizeMarkdown(text: string): string { + if (!text.trim()) return '' + + const lines = text.split('\n') + const hasBullets = lines.some( + (line) => /^(\s*[-*+]|\s*\d+[.)]\s)/.test(line.trimStart()) + ) + if (hasBullets) return text + + const paragraphs = text.split(/\n{2,}/).filter((p) => p.trim()) + return paragraphs.map((p) => `- ${p.replace(/\n/g, ' ').trim()}`).join('\n') +} + const SUPPORTED_EXTENSIONS = /\.(pdf|docx|txt)$/i function stripExtension(filename: string): string {