Custom Components
Register your own Flutter widgets as Markdown elements. Block components replace whole lines; inline components can appear inside a sentence alongside text. Both use regular expressions to match custom syntax in the Markdown string.
components
Block-level
Match multi-line patterns, replace with any widget
inlineComponents
Inline
Match within a line, rendered alongside text
sourceTagBuilder
Citations
Render AI citation/source references
Block component
A block component that turns <callout type="warning">...</callout> into a styled callout box — useful when your AI model is prompted to output structured annotations.
1import 'package:flutter/material.dart';
2import 'package:gpt_markdown/gpt_markdown.dart';
3
4// A custom block component that renders a styled callout box.
5// Triggered when the AI outputs: <callout type="warning">text</callout>
6
7final calloutComponent = MarkdownComponent(
8 exp: RegExp(r'<callout type="(\w+)">(.*?)</callout>', dotAll: true),
9 builder: (context, match, style) {
10 final type = match.group(1) ?? 'info';
11 final text = match.group(2) ?? '';
12 final colors = {
13 'warning': (Colors.orange.shade50, Colors.orange.shade400),
14 'error': (Colors.red.shade50, Colors.red.shade400),
15 'info': (Colors.blue.shade50, Colors.blue.shade400),
16 };
17 final (bg, border) = colors[type] ?? colors['info']!;
18 return Container(
19 margin: const EdgeInsets.symmetric(vertical: 8),
20 padding: const EdgeInsets.all(12),
21 decoration: BoxDecoration(
22 color: bg,
23 border: Border(left: BorderSide(color: border, width: 4)),
24 borderRadius: BorderRadius.circular(4),
25 ),
26 child: Text(text, style: style),
27 );
28 },
29);
30
31// Register it:
32GptMarkdown(
33 content,
34 components: [calloutComponent],
35)Inline component
An inline component that renders <badge color="green">NEW</badge> as a colored pill badge, rendered within a sentence.
1import 'package:flutter/material.dart';
2import 'package:gpt_markdown/gpt_markdown.dart';
3
4// A custom inline component that renders colored badges.
5// Triggered by: <badge color="green">NEW</badge>
6
7final badgeComponent = InlineMarkdownComponent(
8 exp: RegExp(r'<badge color="(\w+)">(.*?)</badge>'),
9 builder: (context, match, style) {
10 final color = match.group(1) ?? 'blue';
11 final label = match.group(2) ?? '';
12 final colorMap = {
13 'green': Colors.green,
14 'blue': Colors.blue,
15 'red': Colors.red,
16 'orange': Colors.orange,
17 };
18 final c = colorMap[color] ?? Colors.blue;
19 return Container(
20 padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
21 decoration: BoxDecoration(
22 color: c.withOpacity(0.15),
23 borderRadius: BorderRadius.circular(4),
24 border: Border.all(color: c.withOpacity(0.4)),
25 ),
26 child: Text(
27 label,
28 style: style?.copyWith(
29 color: c.shade700,
30 fontSize: 11,
31 fontWeight: FontWeight.w600,
32 letterSpacing: 0.3,
33 ),
34 ),
35 );
36 },
37);
38
39// Register it:
40GptMarkdown(
41 content,
42 inlineComponents: [badgeComponent],
43)Registering multiple
Pass any number of components in the list — they are tested in order.
1GptMarkdown(
2 content,
3 components: [
4 calloutComponent,
5 sectionDividerComponent,
6 codePlaygroundComponent,
7 ],
8 inlineComponents: [
9 badgeComponent,
10 tooltipComponent,
11 ],
12)Citation / source tags
The package has first-class support for AI citation tags via sourceTagBuilder.
1// The package has built-in support for AI citation tags like:
2// <source>1</source> or [1] style references.
3// Use sourceTagBuilder to render them your way:
4
5GptMarkdown(
6 content,
7 sourceTagBuilder: (context, sources) {
8 return Row(
9 mainAxisSize: MainAxisSize.min,
10 children: sources.map((src) => GestureDetector(
11 onTap: () => openSource(src),
12 child: Container(
13 margin: const EdgeInsets.only(left: 2),
14 padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
15 decoration: BoxDecoration(
16 color: Colors.blue.shade50,
17 borderRadius: BorderRadius.circular(4),
18 ),
19 child: Text(
20 src,
21 style: const TextStyle(fontSize: 10, color: Colors.blue),
22 ),
23 ),
24 )).toList(),
25 );
26 },
27)Tip — prompt your AI to use custom tags
Custom components work best when you include tag instructions in your system prompt. For example: "When highlighting a warning, wrap it in <callout type="warning">...</callout>."