feat: add GitHub alert banner component#603
Open
mikepenz wants to merge 2 commits into
Open
Conversation
- org.jetbrains:markdown 0.7.5 -> 0.7.6
Render GFM alerts (`> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!WARNING]`, `> [!CAUTION]`) as an accent bar with a tinted icon and title, followed by the alert's block content. The parser has emitted `GFMElementTypes.ALERT` nodes since markdown 0.7.5, but they fell through to the `else` branch of `MarkdownElementInternal`, so the title was swallowed and the body rendered as bare children. - `MarkdownAlertType` resolves the marker from the `ALERT_TITLE` token, case-insensitively - `MarkdownAlert` mirrors `MarkdownBlockQuote`'s bar drawing and child dispatch - `MarkdownComponents.alert` + `ALERT ->` dispatch, overridable like every other element - `MarkdownAlertColors`, `MarkdownAlertDimens` and `MarkdownAlertPadding` group the alert configuration, reached via `markdownColor(alert = ...)`, `markdownDimens(alert = ...)` and `markdownPadding(alert = ...)` - `MarkdownTypography.alertTitle` styles the title; `MarkdownA11yLabels.alert` labels the container - Icons ship as `ImageVector`s built with `addPathNodes`, keeping the core module free of a material dependency, and are swappable through `LocalMarkdownAlertIcons` Material's color schemes carry no slot with the semantics alerts rely on (a green "tip", an amber "warning"), so `MarkdownAlertColorDefaults` ships GitHub's light and dark palettes. m2 selects between them via `MaterialTheme.colors.isLight`, m3 derives it from `colorScheme.background.luminance()`. Note the `> ` marker is a `MarkdownTokenTypes.BLOCK_QUOTE` while a nested quote inside an alert is a `MarkdownElementTypes.BLOCK_QUOTE`; only the former is skipped, so nested quotes still render. BREAKING CHANGE: `MarkdownColors`, `MarkdownDimens`, `MarkdownPadding`, `MarkdownTypography` and `MarkdownComponents` each gained a member. Direct implementers of these interfaces must add the new override; consumers of `markdownColor()`, `markdownDimens()`, `markdownPadding()`, `markdownTypography()` and `markdownComponents()` are unaffected. Adds `AlertAstShapeTest` pinning the AST shape the component depends on, and 44 Paparazzi snapshots across m2/m3 in light and dark.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds first-class rendering for GitHub-flavoured “alerts” (> [!NOTE], > [!WARNING], etc.) by introducing a dedicated MarkdownAlert element, theming/config models (colors/dimens/padding/typography), and component dispatch so alerts are overridable like other markdown elements. This closes the gap where GFMElementTypes.ALERT nodes were previously falling through and losing the alert title.
Changes:
- Introduces alert domain + rendering:
MarkdownAlertType,MarkdownAlert, alert icons/colors/dimens/padding, andLocalMarkdownAlertIcons. - Wires alert dispatch through
MarkdownComponents.alertandMarkdownElementInternal(ALERT -> ...), plus a helper to resolve the alert type from the AST. - Adds comprehensive tests/snapshots + documentation updates, and bumps the
org.jetbrains:markdownversion to0.7.6with regenerated API dumps.
Reviewed changes
Copilot reviewed 31 out of 75 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| sample/shared/src/commonMain/composeResources/files/sample.md | Adds alert examples to the sample markdown content. |
| sample/android/src/main/kotlin/com/mikepenz/markdown/ui/m3/AlertsTests.kt | Adds m3 Paparazzi preview coverage for alert variants and edge cases. |
| sample/android/src/main/kotlin/com/mikepenz/markdown/ui/m2/AlertsTests.kt | Adds m2 Paparazzi preview coverage for alert variants and edge cases. |
| README.md | Documents alert support, theming knobs, and icon overriding. |
| multiplatform-markdown-renderer/src/commonTest/kotlin/com/mikepenz/markdown/parser/AlertAstShapeTest.kt | Pins the AST shape emitted for alerts, including nested blockquote handling. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/utils/Extensions.kt | Adds ASTNode.findAlertType(...) helper to resolve an alert type from ALERT_TITLE. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownTypography.kt | Extends typography with alertTitle styling. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownPadding.kt | Extends padding model with alert: MarkdownAlertPadding. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownDimens.kt | Extends dimens model with alert: MarkdownAlertDimens. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownColors.kt | Extends colors model with alert: MarkdownAlertColors. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownAlertType.kt | Adds enum for the 5 GitHub alert markers with parsing helper. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownAlertPadding.kt | Adds alert padding model + factory. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownAlertIcons.kt | Adds alert icon model, defaults, and icon factories (no material-icons dependency). |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownAlertDimens.kt | Adds alert dimens model + factory. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownAlertColors.kt | Adds alert color model + GitHub light/dark defaults + factory. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownA11yLabels.kt | Adds a11y label generator for alert containers. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/MarkdownExtension.kt | Adds ALERT -> components.alert(...) dispatch. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/elements/MarkdownAlert.kt | Implements the new alert rendering element (bar + icon/title + block content). |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/ComposeLocal.kt | Adds LocalMarkdownAlertIcons composition local. |
| multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/components/MarkdownComponents.kt | Adds alert component slot + default implementation using MarkdownAlert. |
| multiplatform-markdown-renderer/api/multiplatform-markdown-renderer.klib.api | Updates public API dump for new models/functions and signature changes. |
| multiplatform-markdown-renderer/api/jvm/multiplatform-markdown-renderer.api | Updates JVM API dump for new alert APIs and signature changes. |
| multiplatform-markdown-renderer-m3/src/commonMain/kotlin/com/mikepenz/markdown/m3/MarkdownTypography.kt | Adds alertTitle default styling for m3. |
| multiplatform-markdown-renderer-m3/src/commonMain/kotlin/com/mikepenz/markdown/m3/MarkdownColors.kt | Adds alert colors to m3, deriving dark/light from background luminance. |
| multiplatform-markdown-renderer-m3/api/multiplatform-markdown-renderer-m3.klib.api | Updates m3 klib API dump for function signature changes. |
| multiplatform-markdown-renderer-m3/api/jvm/multiplatform-markdown-renderer-m3.api | Updates m3 JVM API dump for function signature changes. |
| multiplatform-markdown-renderer-m2/src/commonMain/kotlin/com/mikepenz/markdown/m2/MarkdownTypography.kt | Adds alertTitle default styling for m2. |
| multiplatform-markdown-renderer-m2/src/commonMain/kotlin/com/mikepenz/markdown/m2/MarkdownColors.kt | Adds alert colors to m2, selecting default palette via MaterialTheme.colors.isLight. |
| multiplatform-markdown-renderer-m2/api/multiplatform-markdown-renderer-m2.klib.api | Updates m2 klib API dump for function signature changes. |
| multiplatform-markdown-renderer-m2/api/jvm/multiplatform-markdown-renderer-m2.api | Updates m2 JVM API dump for function signature changes. |
| gradle/libs.versions.toml | Bumps org.jetbrains:markdown to 0.7.6. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| !pastTitle -> if (child.type == GFMTokenTypes.ALERT_TITLE) pastTitle = true | ||
| child.type == EOL || child.type == WHITE_SPACE || child.type == BLOCK_QUOTE -> Unit | ||
| else -> { | ||
| if (seenContent) Spacer(Modifier.height(padding.titleSpacing)) |
| modifier = Modifier | ||
| .semantics { contentDescription = a11yLabels.alert(title) } | ||
| .drawBehind { | ||
| val x = bar.calculateStartPadding(LayoutDirection.Ltr).toPx() |
Comment on lines
+16
to
+17
| /** Padding above and below the alert's block content */ | ||
| val content: PaddingValues |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Renders GitHub alerts —
NOTE,TIP,IMPORTANT,WARNING,CAUTION— as an accent bar with a tinted icon and title, followed by the alert's block content.The GFM parser has emitted
GFMElementTypes.ALERTnodes since markdown0.7.5, but they fell through to theelsebranch ofMarkdownElementInternal, so the[!NOTE]title was swallowed and the body rendered as bare children.Changes
Follows the existing component architecture:
MarkdownAlertType— the five markers, resolved case-insensitively from theALERT_TITLEtoken.MarkdownAlert— mirrorsMarkdownBlockQuote's bar drawing and child dispatch.MarkdownComponents.alert+ALERT ->dispatch, so it is overridable like every other element.MarkdownAlertColors/MarkdownAlertDimens/MarkdownAlertPadding— grouped configuration models, each with the usualinterface+ privateDefault*+ factory shape.MarkdownTypography.alertTitlestyles the title,MarkdownA11yLabels.alertlabels the container.ImageVectors built viaaddPathNodes, so the core module keeps itscompileOnlyruntime/ui/foundation dependency set, and are swappable throughLocalMarkdownAlertIcons.Theming
Material's color schemes carry no slot with the semantics these alerts rely on — a green "tip", an amber "warning" — so
MarkdownAlertColorDefaultsships GitHub's light and dark palettes rather than deriving them from the theme. m2 selects between them viaMaterialTheme.colors.isLight; m3 has no such flag, so it derives darkness fromcolorScheme.background.luminance(). Every color stays overridable.One subtlety worth reviewing
The
>marker the parser leaves in the tree is aMarkdownTokenTypes.BLOCK_QUOTE, while a nested blockquote inside an alert is aMarkdownElementTypes.BLOCK_QUOTE. Same name, different type. My first pass skipped the element type, which silently dropped nested quotes.MarkdownAlertnow skips only the marker token, andAlertAstShapeTest.nestedBlockQuoteIsAnElementNotAMarkerTokenpins the distinction.Breaking change
MarkdownColors,MarkdownDimens,MarkdownPadding,MarkdownTypographyandMarkdownComponentseach gained one member. Direct implementers of these interfaces must add the new override. Consumers of themarkdownColor()/markdownDimens()/markdownPadding()/markdownTypography()/markdownComponents()factories are unaffected — the new parameters are defaulted..apifiles regenerated viaapiDump; the diff is signature-arity changes only, no member removals.Testing
AlertAstShapeTest(7 tests) pins the AST shape the component depends on../gradlew apiCheck :multiplatform-markdown-renderer:jvmTest :sample:android:verifyPaparazziDebugpasses.sample.md, so all sample apps exercise them.Not included
CHANGELOG.mdis a one-line pointer to the GitHub releases page and has been untouched since the initial commit, so I left it alone — these notes are meant for the release entry instead.