Skip to content

Conversation

@JorkeyLiu
Copy link

@JorkeyLiu JorkeyLiu commented Apr 15, 2025

Context

The Markdown rendering previously used for chat messages (primarily via ChatRow.tsx) was incomplete and failed to render several standard Markdown elements correctly. Notably, list markers (both unordered bullets and ordered numbers) were not displayed, and GFM elements like tables appeared as unformatted plain text.

After switching to a more standard-compliant Markdown renderer (@/components/ui/markdown/Markdown.tsx) to address these fundamental rendering issues, further visual inconsistencies were observed compared to the previous implementation. These included differences in list indentation depth, bold text weight, and the styling (background, font, padding, border, alignment) of inline code blocks.

The primary root cause was the use of an incomplete and non-standard Markdown renderer (MarkdownBlock.tsx) in the main chat message rendering path. Secondary styling issues arose from the inherent visual differences between the old styled-components -based styling and the new Tailwind CSS-based styling after switching to the standard renderer.

Implementation

  • Identified two distinct Markdown rendering implementations:
    • @/components/common/MarkdownBlock.tsx: Used react-remark and styled-components. This implementation lacked complete CommonMark support (missing list markers) and GFM support (no tables). It had custom styling, auto-URL linking, and Mermaid support.
    • @/components/ui/markdown/Markdown.tsx: Uses react-markdown with remark-gfm and Tailwind CSS. Provides more robust and standard-compliant Markdown rendering, including GFM features.
  • Determined that ChatRow.tsx, responsible for rendering many chat messages, was incorrectly relying on the limited MarkdownBlock.tsx implementation.
  • Solution Part 1 (Core Fix): Refactored ChatRow.tsx to consistently use the shared, standard-compliant @/components/ui/markdown/Markdown.tsx component. This resolved the fundamental rendering issues for lists, tables, and other standard elements.
  • Solution Part 2 (Styling Adjustments): Fine-tuned the Tailwind CSS classes within the shared @/components/ui/markdown/Markdown.tsx component to address visual discrepancies introduced by the renderer switch. Adjustments included list indentation (pl-[2.5em]), bold weight (font-semibold), inline code styling (background, color, padding, border, font, alignment), and ensuring the base font size uses var(--vscode-font-size).
  • Solution Part 3 (UI Feature Restoration): Re-implemented the hover-to-copy functionality and specific negative vertical margins (originally present in ChatRow.tsx 's local wrapper) by creating a new wrapper component (MarkdownWithCopy) within ChatRow.tsx around the shared <Markdown /> component. This restored specific UI interactions and layout nuances desired for chat messages.

The solution involved replacing the deficient renderer with a standard-compliant one (react-markdown + remark-gfm), unifying the Markdown implementation used by ChatRow.tsx. Subsequently, styles were adjusted in the shared component, and specific UI features/layout wrappers were reintroduced in the calling component (ChatRow.tsx) to achieve functional and visual consistency with the intended design.

Screenshots

image
image
image

How to Test

To Reproduce
Steps to reproduce the behavior:

  1. Ask Roo Code assistant for generating some Markdown contents for rendering test.
  2. Observe the message rendered in the chat view (likely via ChatRow.tsx).
  3. Notice the table is not formatted and code block is not highlighted.
  4. (After initial fix attempts) Observe other Markdown elements like lists, bold text, and inline code blocks and compare their styling to previous versions or other parts of the UI.

Expected behavior

  • Markdown tables should render as structured tables with appropriate borders and padding.
  • List indentation should be consistent and sufficiently deep for readability.
  • Bold text should have a standard, readable weight (e.g., font-semibold).
  • Inline code blocks should have a distinct background color (matching --vscode-textCodeBlock-background), appropriate padding, border, font, and alignment consistent with the surrounding text.

Get in Touch

[email protected]


Important

Refactored chat message rendering to use a standard-compliant Markdown renderer, fixed styling issues, and restored hover-to-copy functionality.

  • Behavior:
    • Refactored ChatRow.tsx to use Markdown.tsx for standard-compliant Markdown rendering, fixing issues with lists, tables, and other elements.
    • Restored hover-to-copy functionality in ChatRow.tsx using a new MarkdownWithCopy wrapper.
  • Styling:
    • Adjusted Tailwind CSS classes in Markdown.tsx for list indentation, bold text weight, and inline code styling.
    • Updated CodeBlock.tsx to handle code highlighting based on completion status and theme.
  • Testing:
    • Added module name mappings for react-markdown, remark-gfm, and shiki in jest.config.cjs for testing purposes.
  • Misc:
    • Updated package.json to include shiki as a dependency.

This description was created by Ellipsis for 356831df0f38639fda4c1d0aa09121e6ad5e8771. It will automatically update as commits are pushed.

JorkeyLiu and others added 6 commits April 13, 2025 13:27
…y or another symbolic link (RooCodeInc#2513)

* read symbolic linked dir and files recursively

* add symlinked dir and nested symlink test case for custom-instructions

* enhance comments

* add changeset
* changeset version bump

* Updating CHANGELOG.md format

* Update CHANGELOG.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: R00-B0T <[email protected]>
Co-authored-by: Matt Rubens <[email protected]>
@JorkeyLiu JorkeyLiu requested review from cte and mrubens as code owners April 15, 2025 07:03
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Apr 15, 2025
@changeset-bot
Copy link

changeset-bot bot commented Apr 15, 2025

⚠️ No Changeset found

Latest commit: 799cf15

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ellipsis-dev
Copy link
Contributor

ellipsis-dev bot commented Apr 15, 2025

Hello @JorkeyLiu,

Thank you for your contribution! Upon reviewing the pull request, it seems that the changes are primarily focused on improving markdown rendering and styling in chat messages, which is a cohesive set of changes. However, there are also updates to the content security policy and jest configuration, which might be unrelated to the markdown improvements.

Could you please consider splitting the pull request into two separate ones if these changes are not interdependent? For example:

  1. Markdown Rendering and Styling Improvements: This would include changes related to the MarkdownWithCopy component, CodeBlock updates, and any styling adjustments.
  2. Configuration and Security Updates: This would cover changes to the content security policy and jest configuration.

This separation could help in reviewing and testing the changes more effectively. Let me know if you have any questions or if there's anything else I can assist with.

Thank you!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new MarkdownWithCopy component’s copy button currently appears only on hover. Consider adding keyboard accessibility (e.g. via tabindex and onFocus events) to ensure users on touch devices or keyboard-only users can also trigger the copy action.

@adamhill
Copy link
Contributor

adamhill commented Apr 15, 2025

Any chance we can add the a11y suggestion from ellipsis-bot for keyboard accessibility?

Thanks

@hannesrudolph hannesrudolph moved this from New to Issue [In Progress] in Roo Code Roadmap Apr 15, 2025
@hannesrudolph hannesrudolph moved this from Issue [In Progress] to PR [Pre Approval Review] in Roo Code Roadmap Apr 15, 2025
@JorkeyLiu
Copy link
Author

Hello @JorkeyLiu,

Thank you for your contribution! Upon reviewing the pull request, it seems that the changes are primarily focused on improving markdown rendering and styling in chat messages, which is a cohesive set of changes. However, there are also updates to the content security policy and jest configuration, which might be unrelated to the markdown improvements.

Could you please consider splitting the pull request into two separate ones if these changes are not interdependent? For example:

  1. Markdown Rendering and Styling Improvements: This would include changes related to the MarkdownWithCopy component, CodeBlock updates, and any styling adjustments.
  2. Configuration and Security Updates: This would cover changes to the content security policy and jest configuration.

This separation could help in reviewing and testing the changes more effectively. Let me know if you have any questions or if there's anything else I can assist with.

Thank you!

  1. CSP Dependency (Code Block Functionality):

    • Our updated CodeBlock component utilizes the shiki library for syntax highlighting, which relies on WebAssembly (WASM) to run its grammar engine.
    • In the production build environment, the default webview CSP blocked the loading and instantiation of this WASM module because the 'wasm-unsafe-eval' directive was missing from script-src. This caused the CodeBlock component to fail in the installed extension.
    • Adding 'wasm-unsafe-eval' to the CSP script-src directive is a direct prerequisite for the CodeBlock component to work as intended in the actual installed plugin.
  2. Jest Configuration Dependency (Code Block & Markdown Testing):

    • The Jest test environment (JSDOM) cannot fully support all features of shiki (WASM dependency), react-markdown
    • Therefore, I added configuration to jest.config.cjs under moduleNameMapper to mock these three libraries using identity-obj-proxy.
    • This change is required to ensure that unit tests involving components that use these libraries (like Markdown.tsx, CodeBlock.tsx, etc.) can run successfully and pass.

If we were to split the CSP and Jest changes into a separate PR, the Markdown improvements in this PR would effectively be broken upon merging, and the related unit tests would fail, until the other changes were also merged.

@JorkeyLiu JorkeyLiu force-pushed the improvement/table-css branch from b5072c0 to d1d9c84 Compare April 16, 2025 08:36
@JorkeyLiu
Copy link
Author

This commit will also fix chat view flickering issue (BTW)

@samhvw8
Copy link
Contributor

samhvw8 commented Apr 25, 2025

@JorkeyLiu Do you have discord account ?

@KJ7LNW
Copy link
Contributor

KJ7LNW commented May 1, 2025

Thank you for standardizing the markdown display!

FYI: CodeBlock was just merged with Shiki rendering to handle all multi-line syntax-highlighting, and it is used consistently in many places throughout the code base. Feel free to style Shiki consistently since it was merged as a stable feature in 3.15. Shiki supports many existing themes, currently only github-{dark,light} are supported based on detecting vscode's light or dark theme selection. There is definitely room for improvement for either customizing our own Roo Shiki theme, or by providing a global configuration to select the theme that the user prefers to use (if not the github default style).

I see that you have a copy button on your codeblock sample above, so in the interest of avoiding duplicate work it would be great to continue using the existing CodeBlock Shiki implementation; <CodeBlock> has the following features:

  • line-wrap/unwrap toggle
  • expandable/collapsable to 500px
  • copy button
  • language selection pull-down
  • automatic theme selection based on light and dark
  • inner/outer scroll box handling so that the outer container scrolls when the inner container hits its limit
  • scroll-pass-through when the inner container does not scroll

@hannesrudolph hannesrudolph moved this from PR [Pre Approval Review] to PR [Greenlit] in Roo Code Roadmap May 5, 2025
@village-way
Copy link
Contributor

hope this pr to be merged, to solve the markdown 'unorder list' and 'order list' render problem

@mrubens
Copy link
Collaborator

mrubens commented May 13, 2025

Thank you for the PR. I’ll review closely today.

@mrubens
Copy link
Collaborator

mrubens commented May 13, 2025

I attempted to merge main into this branch - happy to push if it's not stepping on toes.

The table and ordered/unordered list rendering is a great improvement!

I did notice some issues though:

  • The code blocks don't seem to have syntax highlighting
  • The copy buttons show up all the time, not just on hover, and take on the color of the surrounding text
  • There's a duplicative copy button that shows up on hover
  • In general we should find a way to align on which code block to use

Screenshot 2025-05-13 at 11 18 26 AM

Is there a way for us to port the tables and lists to the markdown component that we're currently using while we try to align on the path forward, or will that be a lot of wasted work?

@KJ7LNW
Copy link
Contributor

KJ7LNW commented May 13, 2025

happy to push if it's not stepping on toes.

I am not a fan of the <CodeBlock> replacement; merging this would PR introduce several regressions for <CodeBlock> rendering (listed above).

However:

I really like that the author is standardizing markdown CSS, fixing bullets, headings, enumerations, etc. If we can keep the new markdown CSS for everything else, and have still render multi-line code blocks using the existing <CodeBlock> w/ Shiki highlight that @cte and I worked on, which literally everything else uses, and then I would be glad to see this merged.

Proposed solution:

  1. Modify this PR to remove ui/markdown/CodeBlock.tsx so ui/markdown/Markdown.tsx directly uses the existing common/CodeBlock.tsx component
  2. Merge only markdown CSS changes UI (ie, not CodeBlock)
  3. Create a new PR for any code block changes that the author would like to propose --- and then we need to test it well to make sure that no regressions are introduced.

Additionally,

The following needs to be tested in this Markdown rework before merging:

  1. clickable file links from feat: clickable code references in model responses navigate to source lines #3087
  2. mermaid
  3. boomerang <new_task> output shown in the UI ChatView before clicking "accept new task"
  4. verify that CodeBlock is unchanged (ie, ai: "show me a sample of 5 programming languages, some longer than others and one that is very long")
  5. other UI considerations?

@samhvw8 can you think of anything else that would need to be tested in markdown user interface if the markdown rendering engine changes?

@JorkeyLiu
Copy link
Author

Thanks for your reviewing.

The code blocks don't seem to have syntax highlighting

The code blocks should be rendered after streaming output, but there may have some timing issues sometimes, I'll make time to look into it.

The copy buttons show up all the time, not just on hover, and take on the color of the surrounding text

Currently yes

There's a duplicative copy button that shows up on hover

The bottom button is for copying the whole markdown content, it does the same as always.

Is there a way for us to port the tables and lists to the markdown component that we're currently using while we try to align on the path forward, or will that be a lot of wasted work?

It cannot be simply ported or migrated to MarkdownBlock.tsx in which you need to elaborately code the whole CSS to make it work, while if we use Markdown.tsx, it can be achieved simply like this.

table({ children }) {
	return <table className="w-full my-2 border-collapse border border-border">{children}</table>
},

That's why I post this pr, it seems a mistake to use MarkdownBlock.tsx instead of Markdown.tsx.

happy to push if it's not stepping on toes.

I appreciate @KJ7LNW 's work very much. I almost migrated the navigation feature to Markdown.tsx as soon as I saw it for my personal use. It works perfectly, and it's almost compatible with this pr already, just need to add the handleLinkClick helper function in Markdown.tsx to make it work, which takes about 30 lines. I could also update this pr with the navigation feature migration if it's necessary.

@KJ7LNW
Copy link
Contributor

KJ7LNW commented May 14, 2025

The code blocks should be rendered after streaming output, but there may have some timing issues sometimes, I'll make time to look into it.

Please retain the current real-time stream-rendering, as it does now, because it is quite useful for review of very long commands (eg, git commit -m "long multi-line message") and long code samples as it comes to the user.

Really everything needs to support real-time stream-rendering.

There's a duplicative copy button that shows up on hover

The bottom button is for copying the whole markdown content, it does the same as always.

There is a copy-as-markdown feature presently, so definitely keep that; I use it all the time and others may too.

I could also update this pr with the navigation feature migration if it's necessary

Please do, lets avoid any regressions.

@KJ7LNW KJ7LNW self-requested a review May 16, 2025 03:01
@KJ7LNW
Copy link
Contributor

KJ7LNW commented May 16, 2025

Please convert this PR to a draft so it does not get merged before we are done with review.

@JorkeyLiu JorkeyLiu force-pushed the improvement/table-css branch from 122b9fe to 799cf15 Compare May 16, 2025 03:24
@JorkeyLiu
Copy link
Author

Fixed code blocks rendering issue, now it will be rendered 100% after streaming output.
Added a helper function to make link navigation work.

@KJ7LNW
Copy link
Contributor

KJ7LNW commented May 16, 2025

I see that you imported Shiki, but this is what we need to do for this first pull request:

  1. Modify this PR to remove ui/markdown/CodeBlock.tsx so ui/markdown/Markdown.tsx directly uses the existing common/CodeBlock.tsx component
  2. Merge only markdown CSS changes UI (ie, not CodeBlock)
  3. Create a new PR for any code block changes that the author would like to propose --- and then we need to test it well to make sure that no regressions are introduced.

@hannesrudolph
Copy link
Collaborator

I see that you imported Shiki, but this is what we need to do for this first pull request:

  1. Modify this PR to remove ui/markdown/CodeBlock.tsx so ui/markdown/Markdown.tsx directly uses the existing common/CodeBlock.tsx component

  2. Merge only markdown CSS changes UI (ie, not CodeBlock)

  3. Create a new PR for any code block changes that the author would like to propose --- and then we need to test it well to make sure that no regressions are introduced.

@mrubens I think this makes sense.

@hannesrudolph hannesrudolph moved this from New to PR [Greenlit] in Roo Code Roadmap May 20, 2025
@hannesrudolph hannesrudolph moved this from TEMP to Needs Preliminary Review in Roo Code Roadmap May 27, 2025
@daniel-lxs daniel-lxs moved this from PR [Needs Preliminary Review] to PR [Draft / In Progress] in Roo Code Roadmap May 28, 2025
@daniel-lxs daniel-lxs marked this pull request as draft June 3, 2025 23:36
@hannesrudolph
Copy link
Collaborator

stale

@github-project-automation github-project-automation bot moved this from PR [Greenlit] to Done in Roo Code Roadmap Jul 7, 2025
@github-project-automation github-project-automation bot moved this from PR [Draft / In Progress] to Done in Roo Code Roadmap Jul 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR - Draft / In Progress size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.