Material3MarkdownRenderer

The Markdown renderer that draws the blocks the default cannot: lists, block quotes, tables, and code, in Material 3.

Installed through LocalA2uiMarkdownRenderer, the seam Text already reads, and nothing else changes:

CompositionLocalProvider(LocalA2uiMarkdownRenderer provides Material3MarkdownRenderer) {
A2uiSurface(/* ... */)
}

Its own module, because it brings a parser (org.jetbrains:markdown) and a2ui-material3 declines to put one on every consumer's class path. A host that wants the default's subset keeps it by not depending on this.

What it keeps of A2uiMarkdownRenderer's contract. The style and color Text resolved for the variant are applied to every block, so a caption's list is bodySmall and dimmed like the caption's prose, and headings are sized in em relative to that style rather than in the theme's headline sizes -- the same ratios the default draws, so switching renderers changes what a list looks like and not what a heading does. The bar beside a quote, the tint behind code and the rules of a table are drawn in the text colour that resolves -- color, else the style's, else LocalContentColor -- so inside a filled Button they are the label's colour and not a surface colour on the primary. The modifier goes on the outermost thing drawn, which is the column of blocks.

The specification's exclusions are kept here. Links reduce to their label and no LinkAnnotation is ever attached, for the reason the seam gives: a link that opened would hand the agent a way past openUrl. Images are their alt text. Raw HTML, inline or block, is not drawn.

Its bound is the default's: above MAX_MARKDOWN_INPUT characters the source is handed to A2uiMarkdownRenderer.Inline, which at that length draws it verbatim, so the point at which an agent's text stops being parsed is the same whichever renderer is installed. Within the bound the parser's cost is the parser's -- a pathological sixteen thousand characters of [ takes it under two seconds on a laptop JVM -- and nesting is bounded separately by MAX_BLOCK_DEPTH, since the parser accepts a depth the stack on wasmJs would not.

Not a Checkbox for a GFM task item, not a clickable anything, and not the theme's headline styles: each would be a decision about the agent's text that the agent did not make.

Functions

Link copied to clipboard
open override fun Markdown(source: String, style: TextStyle, color: Color, modifier: Modifier)