feat: add notes preview helper with tests
Made-with: Cursor
This commit is contained in:
26
backend/utils/notes-preview.js
Normal file
26
backend/utils/notes-preview.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
function computeNotesPreview(notes) {
|
||||||
|
if (!notes || notes.trim() === '') {
|
||||||
|
return { has_notes: false, notes_preview: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstParagraph = notes.split(/\n\n/)[0];
|
||||||
|
|
||||||
|
const stripped = firstParagraph
|
||||||
|
.replace(/^#{1,6}\s+/gm, '') // headers
|
||||||
|
.replace(/\*\*(.+?)\*\*/g, '$1') // bold
|
||||||
|
.replace(/\*(.+?)\*/g, '$1') // italic with *
|
||||||
|
.replace(/_(.+?)_/g, '$1') // italic with _
|
||||||
|
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // links
|
||||||
|
.replace(/^[-*+]\s+/gm, '') // list markers
|
||||||
|
.replace(/\n/g, ' ') // collapse remaining newlines
|
||||||
|
.replace(/\s+/g, ' ') // collapse whitespace
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
const truncated = stripped.length > 150
|
||||||
|
? stripped.slice(0, 150) + '...'
|
||||||
|
: stripped;
|
||||||
|
|
||||||
|
return { has_notes: true, notes_preview: truncated };
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { computeNotesPreview };
|
||||||
64
tests/api/session-notes.test.js
Normal file
64
tests/api/session-notes.test.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
const { computeNotesPreview } = require('../../backend/utils/notes-preview');
|
||||||
|
|
||||||
|
describe('computeNotesPreview', () => {
|
||||||
|
test('returns has_notes false and null preview for null input', () => {
|
||||||
|
const result = computeNotesPreview(null);
|
||||||
|
expect(result).toEqual({ has_notes: false, notes_preview: null });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns has_notes false and null preview for empty string', () => {
|
||||||
|
const result = computeNotesPreview('');
|
||||||
|
expect(result).toEqual({ has_notes: false, notes_preview: null });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns first paragraph as preview', () => {
|
||||||
|
const notes = 'First paragraph here.\n\nSecond paragraph here.';
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.has_notes).toBe(true);
|
||||||
|
expect(result.notes_preview).toBe('First paragraph here.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strips markdown bold formatting', () => {
|
||||||
|
const notes = '**Bold text** and more';
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toBe('Bold text and more');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strips markdown italic formatting', () => {
|
||||||
|
const notes = '*Italic text* and _also italic_';
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toBe('Italic text and also italic');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strips markdown links', () => {
|
||||||
|
const notes = 'Check [this link](http://example.com) out';
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toBe('Check this link out');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strips markdown headers', () => {
|
||||||
|
const notes = '## Header text';
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toBe('Header text');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strips markdown list markers', () => {
|
||||||
|
const notes = '- Item one\n- Item two';
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toBe('Item one Item two');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('truncates to 150 characters with ellipsis', () => {
|
||||||
|
const notes = 'A'.repeat(200);
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toHaveLength(153); // 150 + '...'
|
||||||
|
expect(result.notes_preview.endsWith('...')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('does not truncate text at or under 150 characters', () => {
|
||||||
|
const notes = 'A'.repeat(150);
|
||||||
|
const result = computeNotesPreview(notes);
|
||||||
|
expect(result.notes_preview).toHaveLength(150);
|
||||||
|
expect(result.notes_preview).not.toContain('...');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user