feat(markdown-renderer): complete unfinished code blocks during streaming#1814
feat(markdown-renderer): complete unfinished code blocks during streaming#1814Killusions wants to merge 3 commits intomainfrom
Conversation
Add max-inline-size constraint to message bubble and wrapper to prevent overflow. Fix attachment preview backdrop click behavior. Use index-based tracking for message list and add scroll-to-bottom on message send. Update example action labels for clarity.
…line and caching Rewrite the markdown renderer to use a recursive processing pipeline with placeholder-based architecture. Add SSR support via optional doc/isBrowser parameters. Introduce LRU caching for code blocks and tables. Improve table rendering with proper thead/th support. Add code-wrapper structure with language labels. Update SCSS for new structural layout including code-wrapper, table-wrapper, and table-scroll-container.
…ming Add temporary closing marker logic that automatically completes unfinished code blocks during streaming (to make it more smooth)
There was a problem hiding this comment.
Code Review
This pull request refactors the markdown renderer for SSR support, implements LRU caching for code blocks and tables, and updates component styles and UX labels. It also adds automatic scrolling to the chat container. Feedback includes a suggestion to import ChangeDetectionStrategy for OnPush compliance and a recommendation to optimize table row filtering for better performance and SSR compatibility.
| */ | ||
| import { Component, effect, inject, input, ElementRef } from '@angular/core'; | ||
| import { DOCUMENT, isPlatformBrowser } from '@angular/common'; | ||
| import { Component, effect, inject, input, ElementRef, PLATFORM_ID } from '@angular/core'; |
There was a problem hiding this comment.
The ChangeDetectionStrategy enum should be imported from @angular/core to support the use of OnPush change detection in the component.
| import { Component, effect, inject, input, ElementRef, PLATFORM_ID } from '@angular/core'; | |
| import { ChangeDetectionStrategy, Component, effect, inject, input, ElementRef, PLATFORM_ID } from '@angular/core'; |
| const filteredRows = rows.filter(row => { | ||
| const tempTable = docRef.createElement('table'); | ||
| tempTable.innerHTML = `<tbody>${row}</tbody>`; | ||
| const tableCells = tempTable.querySelectorAll('td, th'); | ||
| return Array.from(tableCells).some(cell => { | ||
| const hasText = !!cell.textContent?.trim(); | ||
| const hasHtml = !!cell.innerHTML?.trim(); | ||
| return hasText || hasHtml; | ||
| }); | ||
| }); |
There was a problem hiding this comment.
The current approach of filtering empty rows by creating a temporary DOM element and parsing HTML for every row is computationally expensive and breaks Server-Side Rendering (SSR) compatibility, as browser-specific DOM APIs are not available on the server. A more efficient approach would be to check for content during the row generation phase in the forEach loop above (around line 359) and only add the row to the rows array if it contains non-empty cells or is a header row.
References
- Avoid using browser-specific DOM APIs in code that needs to support Server-Side Rendering (SSR), as they are not available on the server.
Merge after #1810 and #1811
Add temporary closing marker logic that automatically completes unfinished code blocks during streaming (to make it more smooth)
Documentation.
Examples.
Dashboards Demo.
Playwright report.
Coverage Reports: