Skip to content

Feat/gignit markdown renderer#273

Open
ariane-emory wants to merge 4 commits intodevfrom
feat/gignit--markdown-renderer
Open

Feat/gignit markdown renderer#273
ariane-emory wants to merge 4 commits intodevfrom
feat/gignit--markdown-renderer

Conversation

@ariane-emory
Copy link
Copy Markdown
Owner

Summary

Updated version of Gignit's Markdown renderer.

Custom markdown renderer that works alongside upstream's experimental markdown flag. When OPENCODE_EXPERIMENTAL_MARKDOWN is set, upstream's <markdown> element is used unchanged. When unset (default), a hybrid renderer provides enhanced markdown formatting with proper table rendering, tree-sitter syntax highlighting, and theme support.

Single commit, additive only - no upstream code removed or modified beyond minimal integration points.

Features

  • Box-drawing table rendering with cell word wrap and unicode-aware widths
  • Tree-sitter syntax highlighting for code blocks via native <code> element
  • Task list checkbox rendering (- [x] / - [ ])
  • Strikethrough support (~~text~~)
  • Header background panels for h1/h2
  • Diff code block coloring (+/- lines)
  • CLI markdown rendering via UI.markdown() with theme support
  • Theme loader supporting all 33 upstream themes

Files Changed

File Change Description
cli/markdown-renderer.ts New (1310 lines) Core rendering engine
cli/theme-loader.ts New (127 lines) Loads all 33 upstream themes, converts to renderer format
cli/cmd/tui/routes/session/index.tsx +113 lines TUI integration: TextPart, Prose, CodeBlock, MarkdownDiff components
cli/cmd/run.ts +12 lines CLI theme loading for non-interactive mode
cli/ui.ts +5 lines UI.markdown() now calls custom renderer with theme support

Total: 5 files, 1552 additions, 15 deletions

Architecture

The renderer integrates with upstream's existing OPENCODE_EXPERIMENTAL_MARKDOWN flag:

TextPart component
  |
  +-- OPENCODE_EXPERIMENTAL_MARKDOWN=1
  |     -> upstream's <markdown> element (untouched)
  |
  +-- OPENCODE_EXPERIMENTAL_MARKDOWN unset (default)
        -> parseMarkdownSegments() splits markdown into text + code segments
             |
             +-- Text segments -> renderMarkdownThemedStyled() -> StyledText -> <text>
             +-- Code segments -> tree-sitter via <code filetype={lang}> (native OpenTUI)

CLI mode (opencode run):

User config -> loadTheme() -> MarkdownTheme
Markdown -> renderMarkdownThemedStyled() -> TextChunks -> ANSI -> stdout

Table Rendering

Before (plain text):          After (box-drawing):
| Header | Value |            +---------+-------+
| A      | B     |            | Header  | Value |
                              +---------+-------+
                              | A       | B     |
                              +---------+-------+
image

Related Issues

…x highlighting, and all-messages toggle

- New markdown-renderer.ts with full markdown parsing (headings, bold, italic, code, tables, lists, blockquotes)
- New theme-loader.ts for syntax highlighting themes
- Toggle markdown rendering on all assistant messages via command palette (System category)
- Fix nested inline markdown inside bold/italic in tables
- markdownAll signal anchored after animationsEnabled to avoid stack conflicts
theme was moved from Config (opencode.json) to TuiConfig (tui.json) upstream.
Since run.ts executes in-process, call TuiConfig.get() directly instead of
sdk.config.get() which no longer has a theme field in the v2 Config type.
When a treesitter grammar produces zero highlights (e.g. bash/shell),
CodeRenderable falls back to textBuffer.setText() which renders with the
native default foreground color (white), ignoring the syntaxStyle entirely.

Two fixes applied in CodeBlock:
- Set fg={theme.markdownCodeBlock} on the <code> element so the native
  TextBufferRenderable default foreground uses the theme color instead of
  white, covering the zero-highlights setText() path.
- Build a derived SyntaxStyle that overrides the 'default' scope with
  markdownCodeBlock, so tokens that fall through treesitter without a
  matching scope rule also use the theme color rather than theme.text.

This means users can control codeblock text color independently from
general UI text color via the markdownCodeBlock theme key.
@ariane-emory ariane-emory deleted the feat/gignit--markdown-renderer branch May 5, 2026 14:32
@ariane-emory ariane-emory restored the feat/gignit--markdown-renderer branch May 5, 2026 14:33
@ariane-emory ariane-emory reopened this May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants