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
28 changes: 28 additions & 0 deletions libs/chat/src/lib/streaming/streaming-markdown.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,32 @@ describe('ChatStreamingMdComponent', () => {
expect(fixture.nativeElement.querySelector('p')).toBeNull();
expect(fixture.nativeElement.querySelector('h1')).toBeNull();
});

it('renders a paragraph for plain text WITHOUT a trailing newline (LLM-response shape)', () => {
// Regression: @cacheplane/partial-markdown@0.3 does not flush trailing
// text on finish() unless the buffer ends with '\n'. LLM responses
// typically omit the trailing newline. The component must push a
// sentinel newline before finish() so the message renders.
const fixture = TestBed.createComponent(HostComponent);
fixture.componentInstance.content.set('Hello — nice to meet you!');
fixture.componentInstance.streaming.set(false);
fixture.detectChanges();
const p = fixture.nativeElement.querySelector('p');
expect(p).toBeTruthy();
expect(p.textContent?.trim()).toBe('Hello — nice to meet you!');
});

it('renders plain text when streaming flips to false (mirrored else-branch)', () => {
// The else-if branch (no content change, streaming flipped to false)
// must also push a sentinel newline before finish().
const fixture = TestBed.createComponent(HostComponent);
fixture.componentInstance.content.set('Plain answer.');
fixture.componentInstance.streaming.set(true);
fixture.detectChanges();
fixture.componentInstance.streaming.set(false);
fixture.detectChanges();
const p = fixture.nativeElement.querySelector('p');
expect(p).toBeTruthy();
expect(p.textContent?.trim()).toBe('Plain answer.');
});
});
8 changes: 8 additions & 0 deletions libs/chat/src/lib/streaming/streaming-markdown.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,20 @@ export class ChatStreamingMdComponent {
if (c.length > 0) this.parser.push(c);
}
if (!isStreaming && !this.finished) {
// @cacheplane/partial-markdown@0.3 does not flush trailing text on
// finish() unless the buffer ends with a newline. Plain LLM
// responses often omit the trailing newline, which causes the
// parser to emit a document with zero children — i.e. the message
// renders empty. Push a sentinel newline first to force the open
// paragraph closed before we finalize.
if (!c.endsWith('\n')) this.parser.push('\n');
this.parser.finish();
this.finished = true;
}
this.prior = c;
} else if (!isStreaming && !this.finished) {
// Streaming flipped to false without new content; ensure parser is finalized.
if (!this.prior.endsWith('\n')) this.parser.push('\n');
this.parser.finish();
this.finished = true;
}
Expand Down
Loading