Let the markdown renderer draw tables, and stop headings shouting
Two things a reply could not render, both from the same cause: the renderer was pinned nineteen releases back. Tables arrived in the library at 0.30.0. On 0.26.0 a GFM table was not a table at all -- the rows fell through as text and ran together, pipes and all. They now draw as a table, and scroll sideways when they are wider than the phone rather than losing the last column. Headings took the renderer's defaults, which are the Material *display* styles: `#` came out at 57sp and `##` at 45sp, both larger than this app's own screen titles, so any reply with a heading in it read as shouting. They now descend from headlineSmall to labelSmall -- six steps, every one a different size, so two levels of nesting never draw the same. The pin was not carelessness, which is the part worth recording: the version comment says Maven Central was checked on 2026-08-29 and 0.26.0 was the newest stable. It still answers that, because `search.maven.org/solrsearch` is stale for this artifact -- it knows nothing past 0.27.0-rc02. `maven-metadata.xml` in the repository itself lists up to 0.45.0, updated 2026-08-28. The comment now says to read the metadata rather than the search API, since the same check will otherwise be made the same way next time. The colour mapping moved with the API: `markdownColor` no longer carries `codeText`, `inlineCodeText` or `linkText`, which now ride on the typography as the style's own colour and a `TextLinkStyles`. Same Catppuccin values as before. `tableBackground` is set to the tint code blocks use rather than the library's 2%-alpha default, which on this surface was invisible. Checked on the emulator against a reply carrying all six heading levels, inline code, a link, and a three-column table -- including scrolling the table to confirm the clipped last column is reachable rather than lost.
This commit is contained in:
1 parent
6b4911c67b
commit
2bf90daada
2 files changed
+65
-11
No files matched your search
@@ -3,7 +3,10 @@ package com.example.aiapp
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextLinkStyles
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import com.mikepenz.markdown.m3.Markdown
|
||||
import com.mikepenz.markdown.m3.markdownColor
|
||||
import com.mikepenz.markdown.m3.markdownTypography
|
||||
@@ -13,31 +16,75 @@ import com.mikepenz.markdown.m3.markdownTypography
|
||||
*
|
||||
* The parsing is the library's. Markdown is somebody else's specification, and a hand-written
|
||||
* subset of one disagrees with it at the edges -- which is where the bug reports come from, one
|
||||
* case at a time. This file's whole job is the mapping onto the app's palette.
|
||||
* case at a time. This file's whole job is the mapping onto the app's palette and type scale.
|
||||
*
|
||||
* Colours come from the theme rather than from the renderer's defaults, so code, links and rules
|
||||
* are the same Catppuccin values the rest of the app uses. Nothing here picks a colour of its own.
|
||||
*/
|
||||
@Composable
|
||||
fun MarkdownText(text: String, modifier: Modifier = Modifier) {
|
||||
val body = MaterialTheme.typography.bodyLarge
|
||||
Markdown(
|
||||
content = text,
|
||||
colors =
|
||||
markdownColor(
|
||||
text = MaterialTheme.colorScheme.onSurface,
|
||||
codeText = codeColor,
|
||||
inlineCodeText = codeColor,
|
||||
linkText = linkColor,
|
||||
dividerColor = MaterialTheme.colorScheme.outlineVariant,
|
||||
codeBackground = MaterialTheme.colorScheme.surfaceVariant,
|
||||
inlineCodeBackground = MaterialTheme.colorScheme.surfaceVariant,
|
||||
// The same tint a code block gets, rather than the renderer's 2%-alpha default:
|
||||
// two adjacent tints that differ by a fiftieth read as one flat block on a phone,
|
||||
// so the table would have had a border-less grid and nothing saying where it began.
|
||||
tableBackground = MaterialTheme.colorScheme.surfaceVariant,
|
||||
),
|
||||
// Body text at the size everything else in the transcript uses, and code in a monospace
|
||||
// face: a code block set in the body font stops looking like code at all.
|
||||
typography =
|
||||
markdownTypography(
|
||||
text = MaterialTheme.typography.bodyLarge,
|
||||
code = MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
||||
// A ladder that starts near the body text and descends, because these are headings
|
||||
// inside a chat message rather than the top of a document. The renderer's defaults
|
||||
// are the Material *display* styles -- `#` came out at 57sp and `##` at 45sp, which
|
||||
// is bigger than this app's own screen titles and reads as the reply shouting.
|
||||
//
|
||||
// Every step is a different size, so two levels of nesting never draw the same:
|
||||
// one clear step per level is the whole job of a heading.
|
||||
h1 = MaterialTheme.typography.headlineSmall,
|
||||
h2 = MaterialTheme.typography.titleLarge,
|
||||
h3 = MaterialTheme.typography.titleMedium,
|
||||
h4 = MaterialTheme.typography.titleSmall,
|
||||
h5 = MaterialTheme.typography.labelMedium,
|
||||
h6 = MaterialTheme.typography.labelSmall,
|
||||
// Body text at the size everything else in the transcript uses.
|
||||
text = body,
|
||||
paragraph = body,
|
||||
ordered = body,
|
||||
bullet = body,
|
||||
list = body,
|
||||
table = body,
|
||||
// Code in a monospace face: a code block set in the body font stops looking like
|
||||
// code at all. The colour rides on the style here rather than in `markdownColor`,
|
||||
// which stopped carrying `codeText`/`inlineCodeText`/`linkText` when the renderer
|
||||
// moved them onto the typography.
|
||||
code =
|
||||
MaterialTheme.typography.bodyMedium.copy(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
color = codeColor,
|
||||
),
|
||||
inlineCode =
|
||||
body.copy(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
// Unspecified so an inline span keeps the size of the line it sits in.
|
||||
fontSize = TextUnit.Unspecified,
|
||||
color = codeColor,
|
||||
),
|
||||
textLink =
|
||||
TextLinkStyles(
|
||||
style =
|
||||
body
|
||||
.copy(
|
||||
color = linkColor,
|
||||
textDecoration = TextDecoration.Underline,
|
||||
)
|
||||
.toSpanStyle()
|
||||
),
|
||||
),
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user