AgentDock
AgentDock copied to clipboard
Refactor Markdown Rendering & Syntax Highlighting
Problem Description
The current system for rendering Markdown and highlighting code blocks, primarily within src/components/chat/chat-markdown.tsx and src/components/ui/markdown-renderer.tsx (specifically the HighlightedPre component), relies heavily on client-side processing using the shiki library within a useEffect hook.
This approach leads to several issues:
-
Flash of Unstyled Code (FOUC): Users briefly see un-highlighted code blocks before
shikiloads and processes the code on the client-side, especially noticeable on initial load or slower connections. -
Performance Impact:
-
Bundle Size:
shiki, especially with multiple languages/themes, can significantly increase the client-side JavaScript bundle size. - Client Load: The user's browser must perform the computationally intensive task of tokenizing and highlighting code, impacting rendering performance, especially on lower-end devices or with large code blocks.
-
Bundle Size:
- Layout Shifts: Minor layout shifts can occur when the code block is re-rendered with highlighting applied.
-
Inefficiency: We have libraries like
rehype-pretty-code,unified,remark-parse, andremark-rehypeinstalled (package.json), which are designed for server-side Markdown processing and syntax highlighting, but they are not being leveraged effectively for this purpose in the current rendering flow.
Proposed Solution
Refactor the Markdown rendering and syntax highlighting process to prioritize server-side rendering where possible and optimize the client-side handling for streaming content.
-
Implement Server-Side Highlighting (SSR/SSG):
- For any Markdown rendered statically or outside the live chat stream (e.g., potential uses of
MarkdownRendererin documentation, static pages, etc.), implement server-side syntax highlighting. - Utilize the existing
unifiedecosystem (remark-parse->remark-rehype->rehype-pretty-code->rehype-stringify) to process Markdown into pre-highlighted HTML on the server before sending it to the client. - This would likely involve creating a dedicated server utility function or leveraging Next.js data fetching methods / Server Components.
- The client-side
HighlightedPrecomponent should be bypassed for this server-rendered content.
- For any Markdown rendered statically or outside the live chat stream (e.g., potential uses of
-
Optimize Client-Side Highlighting (Streaming Chat -
ChatMarkdown):- Since live streaming necessitates some client-side processing, review and optimize the current implementation in
ChatMarkdownandHighlightedPre. -
Ensure Single Execution: Verify that the highlighting logic runs only once per message after the stream has fully completed (the current use of
finalContentstate inChatMarkdownshould help achieve this). -
Improve Loading State: Replace the brief display of unstyled code with a more explicit loading indicator or skeleton (like
MermaidSkeletonused for diagrams) whileshikiis processing asynchronously. -
(Optional) Bundle Size Reduction: Investigate strategies to minimize the bundle size impact of
shiki(e.g., asynchronously loadingshikiitself, loading only necessary languages/themes).
- Since live streaming necessitates some client-side processing, review and optimize the current implementation in
Acceptance Criteria
- Markdown rendered outside of live chat streams (if any) uses server-side highlighting, eliminating FOUC.
- Reduced client-side JavaScript bundle size attributable to syntax highlighting libraries.
- Improved perceived rendering performance for pages with code blocks.
- Code blocks within streaming
ChatMarkdowndisplay a clear loading state instead of raw code while highlighting is processed. - Highlighting within
ChatMarkdownis applied reliably once the stream finishes. - Minimal layout shifts during rendering and highlighting.
References
-
rehype-pretty-codedocumentation. -
unified,remark,rehypeecosystem documentation.