Skip to content

Add Markdown View (read-only) with CommonMark/GFM rendering, links, code syntax highlighting, and follow-up API/sizing fixes#4955

Merged
tig merged 75 commits intodevelopfrom
copilot/add-markdown-renderer
Apr 17, 2026
Merged

Add Markdown View (read-only) with CommonMark/GFM rendering, links, code syntax highlighting, and follow-up API/sizing fixes#4955
tig merged 75 commits intodevelopfrom
copilot/add-markdown-renderer

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 13, 2026

Proposed Changes/Todos

  • Add Markdown : View, IDesignable as a read-only CommonMark/GFM renderer with scrolling, links, tables, lists/tasks, block quotes, thematic breaks, and optional sixel image fallback behavior.
  • Add TextMate-based syntax highlighting support (TextMateSyntaxHighlighter) and related styling support.
  • Add Examples/mdv standalone Markdown viewer and UICatalog Markdown scenarios.
  • Add comprehensive markdown-focused tests under Tests/UnitTestsParallelizable/Views/Markdown/.
  • Address PR feedback by correcting Markdown.DefaultMarkdownSample API doc links to real public types:
    • Markdown
    • MarkdownTable
    • MarkdownCodeBlock
  • Address PR feedback by renaming MarkdownTable.Data to MarkdownTable.TableData to avoid hiding View.Data, and update affected call sites/tests.
  • Add a regression test for MarkdownCodeBlock content-size updates across repeated CodeLines changes, then fix autosizing so content-managed dimensions keep updating unless explicitly user-set.

Pull Request checklist:

  • I've named my PR in the form of "Fixes #issue. Terse description."
  • My code follows the style guidelines of Terminal.Gui - if you use Visual Studio, hit CTRL-K-D to automatically reformat your files before committing.
  • My code follows the Terminal.Gui library design guidelines
  • I ran dotnet test before commit
  • I have made corresponding changes to the API documentation (using /// style comments)
  • My changes generate no new warnings
  • I have checked my code and corrected any poor grammar or misspellings
  • I conducted basic QA to assure all features are working

Copilot AI and others added 2 commits April 13, 2026 09:25
tig and others added 25 commits April 14, 2026 13:36
Refactored MarkdownView parsing logic to use early returns and explicit types, improving readability and aligning with code style guidelines. Enhanced code block fence detection, added XML doc comments, and made minor formatting adjustments for consistency. Simplified constructors and improved window creation in the Markdown scenario.
- ListView on left shows all .md files from docfx/docs/ (fetched from GitHub API)
- MarkdownView on right renders the selected document
- Async HTTP loading for both file list and doc content
- SpinnerView in status bar during loading operations
- Error handling shows errors in MarkdownView instead of crashing
- Link clicks displayed in status bar
- Plans doc with all review issues found in PR #4955

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Changed scenario metadata to "Deepdives" with updated description.
- Renamed docs API URL constant for naming consistency.
- SpinnerView: AutoSpin now set via Initialized event, not by default.
- MarkdownView: Attribute selection no longer depends on focus.
- Enabled vertical scrollbar in MarkdownView by default.
- Added null check to App.Invoke in SpinnerView to prevent exceptions.
Added a parameterized test to MarkdownViewTests that verifies stray or unclosed special characters in markdown input do not cause infinite loops. The test covers various edge cases and asserts that rendering always produces at least one line.
Refactored MarkdownView to use StyledSegment for style selection, enabling context-aware rendering for links, code, and list markers. Improved word wrapping to prefer word boundaries, with hard breaks as fallback. Updated code style for project conventions and set default SchemeName. Added comprehensive Copilot-generated unit tests covering word wrap, style rendering, and link handling. Performed minor cleanups and variable renaming for clarity.
Refactored IntermediateBlock and RenderedLine to use primary constructors and added IsCodeBlock property. Updated MarkdownView to render code block lines with a full-width dimmed background. Propagated IsCodeBlock through layout and parsing logic. Improved test style and added a test to verify code block background rendering. Applied code style fixes for consistency.
Code blocks in MarkdownView now display a "⧉" copy button, allowing users to copy code block contents with a mouse click. Introduced CodeBlockRegion and CopyButtonHitTarget types to track code block regions and clickable areas. Refactored layout, draw, and mouse event handling to support this feature. Updated ChatView and SingleTurnView to use MarkdownView for markdown rendering and code block copy support. Moved MarkdownStyleRole to its own file and added unit tests for code block copy functionality.
Copy buttons for code blocks are now actual Button SubViews, styled to match code block backgrounds and positioned at the end of each code block's first visible line. The old manual hit-testing and drawing logic was removed. The copy glyph is now provided by Glyphs.Copy. Thematic breaks are rendered using LineCanvas. Parsing and layout were updated to track and handle thematic breaks correctly.
Introduces MarkdownTable and TableData for parsing and rendering GitHub-style Markdown tables as SubViews with box-drawing borders, column alignment, and proper cell content. Updates MarkdownView parsing and layout to detect tables, manage SubViews, and skip table lines in main drawing. Adds cleanup logic for table SubViews and comprehensive unit tests for parsing, rendering, and edge cases. Refactors related test code for consistency.
Refactored MarkdownView and MarkdownTable to use a new stateless MarkdownInlineParser for all inline Markdown formatting (bold, italic, code, links, images). Introduced MarkdownAttributeHelper to ensure consistent mapping of MarkdownStyleRole to Attribute across views. MarkdownTable now supports inline formatting in cells. Removed redundant parsing and attribute logic from MarkdownView. Added comprehensive unit tests for MarkdownInlineParser and MarkdownTable inline rendering. Updated documentation to reflect the new architecture.
Implements word-wrapping for MarkdownTable cell content, expanding row heights as needed. Borders now use screen coordinates and are merged by the parent MarkdownView. Cell drawing is refactored to handle wrapped lines with correct alignment and padding. Column width calculation now strips markdown formatting for accurate sizing. Table height logic is updated to reflect wrapped rows. Adds unit tests for wrapping, border rendering, markdown stripping, and height calculation.
Clarified and enforced a strict early return/guard clause rule in all major documentation and validation guides. Added `.claude/rules/early-return.md` with detailed guidance and examples. Updated code in `Markdown.cs` and `MarkdownTable.cs` to follow this pattern. Added comprehensive tests for the new table column width algorithm in `MarkdownTableTests.cs`, all using early returns as prescribed.
Improves word-wrapping to avoid breaking inside unclosed parentheses, fixing awkward line breaks in Markdown links with parentheses. Sets default content width to 80, enables horizontal scroll bar, and updates content width only on viewport size changes. Adds tests for correct parsing and rendering of such links.
SetContentSize now always uses Viewport.Width for content width instead of the maximum of _maxLineWidth and Viewport.Width. This change prevents the content width from exceeding the viewport, which may affect horizontal scrolling and layout.
- Added LineAttribute to Line for custom rendering attributes
- Refactored Line.Style setter for early return
- Thematic breaks in MarkdownView now use Line subviews
- Removed direct canvas rendering for thematic breaks
- Managed lifecycle of thematic break views in MarkdownView
- Reset MarkdownView viewport on new content load
- Added and updated unit tests for new behaviors
- Updated spinner style and AutoSpin handling in Markdown scenario
- Set StatusBar AlignmentModes to IgnoreFirstOrLast
- Refactored Line to use auto-properties for Style and LineAttribute
- Thematic breaks in MarkdownView now inset (X=1, Width=Dim.Fill(1))
- Improved anchor link handling in MarkdownView mouse logic
- Adjusted MarkdownViewTests for new thematic break rendering
SyncCopyButtons now uses Pos.AnchorEnd() for button X position, simplifying layout logic. GenerateAnchorSlug now replaces each space with a hyphen, matching GitHub's behavior. Added a test for anchor slug generation with special characters.
Refactored link handling to use MarkdownLinkRegion, enabling keyboard and mouse navigation with active link highlighting. Added command bindings for link navigation and activation. MarkdownTable now recalculates layout on resize. Improved copy button focus behavior and cleaned up legacy code.
MarkdownView now prioritizes externally set content width for layout, enabling accurate text wrapping and table sizing when resized. Introduced _externalContentWidth and _inLayout to manage layout state and prevent recursion. Updated OnContentSizeChanged to handle width changes correctly. Enhanced tests to verify line count and anchor movement when content width changes. Minor scenario and comment clarifications included.
Replaced inline code block drawing with a new internal MarkdownCodeBlock SubView that handles its own background, content, and copy button. Removed CodeBlockRegion and related logic. Updated layout and cleanup for SubView management. Added a test to verify code block width matches content size.
- MarkdownCodeBlock and MarkdownTable are now public and implement IDesignable for standalone and design-time use.
- Added parameterless constructors and public properties (CodeLines, Data) for direct content assignment.
- Implemented EnableForDesign to provide sample content and auto-sizing in design tools.
- MarkdownView exposes DefaultMarkdownSample for consistent sample content.
- Added unit tests for new constructors, properties, and designable support.
- Introduced MarkdownTester scenario in UICatalog for live Markdown editing and preview.
- Updated doc comments and code style for consistency with project conventions.
- Fix WrapSegments infinite loop when grapheme wider than column width
- Move MarkdownTable layout from draw to OnSubViewLayout
- Set ContentSize after BuildRenderedLines for proper scrolling
- Add HasFocus check for active-link highlight (prevents color reversal without focus)
- Emit OSC8 hyperlinks in active-link drawing branch
- Reset active link index on focus loss via OnHasFocusChanged
- Remove diagnostic Logging.Trace calls and cleanup tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI changed the title Add Markdown View (read-only) with CommonMark/GFM rendering, links, and code syntax highlighting Add Markdown View (read-only) with CommonMark/GFM rendering, links, code syntax highlighting, and follow-up API/sizing fixes Apr 16, 2026
Copilot finished work on behalf of tig April 16, 2026 20:11
tig and others added 5 commits April 17, 2026 08:12
- Refactored UI layout to use explicit Thickness constructors in ThemeViewer and Themes scenarios.
- Changed ThemeViewer scheme ordering: built-in schemes first, then custom schemes alphabetically.
- Added AttributeViewer to Themes scenario for displaying attribute details.
- Enhanced default Markdown sample with more features and clarity.
- Introduced AttributeViewer class with nullable reference types enabled.
- Added ast-based-lowering.md: plan for AST-based Markdown lowering.
- Added scheme-naming-review.md: review and proposal for scheme naming and new Accent scheme.
…e-refactor

Co-authored-by: tig <585482+tig@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@YourRobotOverlord YourRobotOverlord left a comment

Choose a reason for hiding this comment

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

This is wonderful! The only thing I could find was the scheme not switching fully after switching more than once.

Image

Copilot AI and others added 14 commits April 16, 2026 21:45
Added new Markdown table examples with centered columns and emojis. Updated MarkdownTable sample to include an "Owner" column and more data. Commented out fixed Width in MarkdownTable. Introduced two regression tests to ensure wide glyphs do not cause column misalignment, and added a helper for buffer validation.
Refactor codebase for modern C# style: use inline initializers, collection expressions, and improved pattern matching. Apply Allman braces and spacing conventions. Fix scroll-to-top logic, enhance code block rendering, and adjust copy button placement. Update README for usage and themes. Minor test, grammar, and cleanup improvements.
Introduce ShowCopyButtons to control copy button visibility in Markdown and MarkdownCodeBlock. Suppress copy buttons in print mode. Update RenderMarkdown to accept terminal size and improve help/error output handling.
Improve MarkdownCodeBlock copy glyph hit-testing by expanding its clickable area. Add tests to verify copy-to-clipboard behavior and ensure ShowCopyButton/ShowCopyButtons disables both glyph and copy action. Refactor test code for style consistency and update test utilities. No changes to Markdown rendering logic.
Tests now use FakeClipboard for isolation and reliability. Clipboard state is recorded before and after simulated copy actions to ensure no unintended changes occur. Assertions verify that code block text is not copied when copy buttons are disabled. Minor code cleanups were also applied.
Ensures clipboard operations are isolated in tests by assigning a FakeClipboard to the driver. Simplifies clipboard assertions since null is no longer possible.
@tig tig merged commit c6d67e3 into develop Apr 17, 2026
11 checks passed
@tig tig deleted the copilot/add-markdown-renderer branch April 17, 2026 00:47
tig added a commit that referenced this pull request Apr 22, 2026
* Initial plan

* Remove mdv example from repo and add to showcase

Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/95b13b12-e204-4484-8d7b-ede8494e283d

Co-authored-by: tig <585482+tig@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants