Showing
7 changed files
with
109 additions
and
24 deletions
| @@ -126,7 +126,7 @@ packages: | @@ -126,7 +126,7 @@ packages: | ||
| 126 | path: ".." | 126 | path: ".." |
| 127 | relative: true | 127 | relative: true |
| 128 | source: path | 128 | source: path |
| 129 | - version: "1.0.9" | 129 | + version: "1.0.15" |
| 130 | http: | 130 | http: |
| 131 | dependency: transitive | 131 | dependency: transitive |
| 132 | description: | 132 | description: |
| @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; | @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; | ||
| 2 | 2 | ||
| 3 | /// A custom widget that adds an indent to the left or right of its child. | 3 | /// A custom widget that adds an indent to the left or right of its child. |
| 4 | /// | 4 | /// |
| 5 | -/// The [IndentWidget] widget is used to create a visual indent in the UI. | 5 | +/// The [BlockQuoteWidget] widget is used to create a visual indent in the UI. |
| 6 | /// It takes a [child] parameter which is the content of the widget, | 6 | /// It takes a [child] parameter which is the content of the widget, |
| 7 | /// a [direction] parameter which specifies the direction of the indent, | 7 | /// a [direction] parameter which specifies the direction of the indent, |
| 8 | /// and a [color] parameter to set the color of the indent. | 8 | /// and a [color] parameter to set the color of the indent. |
| 9 | -class IndentWidget extends StatelessWidget { | ||
| 10 | - const IndentWidget({ | 9 | +class BlockQuoteWidget extends StatelessWidget { |
| 10 | + const BlockQuoteWidget({ | ||
| 11 | super.key, | 11 | super.key, |
| 12 | required this.child, | 12 | required this.child, |
| 13 | required this.direction, | 13 | required this.direction, |
| @@ -128,6 +128,7 @@ class GptMarkdown extends StatelessWidget { | @@ -128,6 +128,7 @@ class GptMarkdown extends StatelessWidget { | ||
| 128 | return ClipRRect( | 128 | return ClipRRect( |
| 129 | child: MdWidget( | 129 | child: MdWidget( |
| 130 | tex, | 130 | tex, |
| 131 | + true, | ||
| 131 | config: GptMarkdownConfig( | 132 | config: GptMarkdownConfig( |
| 132 | textDirection: textDirection, | 133 | textDirection: textDirection, |
| 133 | style: style, | 134 | style: style, |
| @@ -5,7 +5,7 @@ abstract class MarkdownComponent { | @@ -5,7 +5,7 @@ abstract class MarkdownComponent { | ||
| 5 | static final List<MarkdownComponent> components = [ | 5 | static final List<MarkdownComponent> components = [ |
| 6 | CodeBlockMd(), | 6 | CodeBlockMd(), |
| 7 | NewLines(), | 7 | NewLines(), |
| 8 | - IndentMd(), | 8 | + BlockQuote(), |
| 9 | ImageMd(), | 9 | ImageMd(), |
| 10 | ATagMd(), | 10 | ATagMd(), |
| 11 | TableMd(), | 11 | TableMd(), |
| @@ -20,7 +20,20 @@ abstract class MarkdownComponent { | @@ -20,7 +20,20 @@ abstract class MarkdownComponent { | ||
| 20 | ItalicMd(), | 20 | ItalicMd(), |
| 21 | LatexMath(), | 21 | LatexMath(), |
| 22 | LatexMathMultiLine(), | 22 | LatexMathMultiLine(), |
| 23 | + HighlightedText(), | ||
| 24 | + SourceTag(), | ||
| 25 | + IndentMd(), | ||
| 26 | + ]; | ||
| 27 | + | ||
| 28 | + static final List<MarkdownComponent> inlineComponents = [ | ||
| 23 | ImageMd(), | 29 | ImageMd(), |
| 30 | + ATagMd(), | ||
| 31 | + TableMd(), | ||
| 32 | + StrikeMd(), | ||
| 33 | + BoldMd(), | ||
| 34 | + ItalicMd(), | ||
| 35 | + LatexMath(), | ||
| 36 | + LatexMathMultiLine(), | ||
| 24 | HighlightedText(), | 37 | HighlightedText(), |
| 25 | SourceTag(), | 38 | SourceTag(), |
| 26 | ]; | 39 | ]; |
| @@ -30,10 +43,14 @@ abstract class MarkdownComponent { | @@ -30,10 +43,14 @@ abstract class MarkdownComponent { | ||
| 30 | BuildContext context, | 43 | BuildContext context, |
| 31 | String text, | 44 | String text, |
| 32 | final GptMarkdownConfig config, | 45 | final GptMarkdownConfig config, |
| 46 | + bool includeGlobalComponents, | ||
| 33 | ) { | 47 | ) { |
| 48 | + var components = | ||
| 49 | + includeGlobalComponents | ||
| 50 | + ? MarkdownComponent.components | ||
| 51 | + : MarkdownComponent.inlineComponents; | ||
| 34 | List<InlineSpan> spans = []; | 52 | List<InlineSpan> spans = []; |
| 35 | - List<String> regexes = | ||
| 36 | - components.map<String>((e) => e.exp.pattern).toList(); | 53 | + Iterable<String> regexes = components.map<String>((e) => e.exp.pattern); |
| 37 | final combinedRegex = RegExp( | 54 | final combinedRegex = RegExp( |
| 38 | regexes.join("|"), | 55 | regexes.join("|"), |
| 39 | multiLine: true, | 56 | multiLine: true, |
| @@ -46,7 +63,7 @@ abstract class MarkdownComponent { | @@ -46,7 +63,7 @@ abstract class MarkdownComponent { | ||
| 46 | for (var each in components) { | 63 | for (var each in components) { |
| 47 | var p = each.exp.pattern; | 64 | var p = each.exp.pattern; |
| 48 | var exp = RegExp( | 65 | var exp = RegExp( |
| 49 | - '^$p', | 66 | + '^$p\$', |
| 50 | multiLine: each.exp.isMultiLine, | 67 | multiLine: each.exp.isMultiLine, |
| 51 | dotAll: each.exp.isDotAll, | 68 | dotAll: each.exp.isDotAll, |
| 52 | ); | 69 | ); |
| @@ -133,7 +150,11 @@ abstract class BlockMd extends MarkdownComponent { | @@ -133,7 +150,11 @@ abstract class BlockMd extends MarkdownComponent { | ||
| 133 | var child = build(context, text, config); | 150 | var child = build(context, text, config); |
| 134 | length = min(length, 4); | 151 | length = min(length, 4); |
| 135 | if (length > 0) { | 152 | if (length > 0) { |
| 136 | - child = UnorderedListView(spacing: length * 1.0, child: child); | 153 | + child = UnorderedListView( |
| 154 | + spacing: length * 1.0, | ||
| 155 | + textDirection: config.textDirection, | ||
| 156 | + child: child, | ||
| 157 | + ); | ||
| 137 | } | 158 | } |
| 138 | return WidgetSpan(child: child, alignment: PlaceholderAlignment.middle); | 159 | return WidgetSpan(child: child, alignment: PlaceholderAlignment.middle); |
| 139 | } | 160 | } |
| @@ -145,6 +166,40 @@ abstract class BlockMd extends MarkdownComponent { | @@ -145,6 +166,40 @@ abstract class BlockMd extends MarkdownComponent { | ||
| 145 | ); | 166 | ); |
| 146 | } | 167 | } |
| 147 | 168 | ||
| 169 | +/// Indent component | ||
| 170 | +class IndentMd extends BlockMd { | ||
| 171 | + @override | ||
| 172 | + String get expString => (r"^(\ \ +)([^\n]+)$"); | ||
| 173 | + @override | ||
| 174 | + Widget build( | ||
| 175 | + BuildContext context, | ||
| 176 | + String text, | ||
| 177 | + final GptMarkdownConfig config, | ||
| 178 | + ) { | ||
| 179 | + var match = this.exp.firstMatch(text); | ||
| 180 | + var conf = config.copyWith(); | ||
| 181 | + return Directionality( | ||
| 182 | + textDirection: config.textDirection, | ||
| 183 | + child: Row( | ||
| 184 | + children: [ | ||
| 185 | + Expanded( | ||
| 186 | + child: config.getRich( | ||
| 187 | + TextSpan( | ||
| 188 | + children: MarkdownComponent.generate( | ||
| 189 | + context, | ||
| 190 | + match?[2]?.trim() ?? "", | ||
| 191 | + conf, | ||
| 192 | + false, | ||
| 193 | + ), | ||
| 194 | + ), | ||
| 195 | + ), | ||
| 196 | + ), | ||
| 197 | + ], | ||
| 198 | + ), | ||
| 199 | + ); | ||
| 200 | + } | ||
| 201 | +} | ||
| 202 | + | ||
| 148 | /// Heading component | 203 | /// Heading component |
| 149 | class HTag extends BlockMd { | 204 | class HTag extends BlockMd { |
| 150 | @override | 205 | @override |
| @@ -174,6 +229,7 @@ class HTag extends BlockMd { | @@ -174,6 +229,7 @@ class HTag extends BlockMd { | ||
| 174 | context, | 229 | context, |
| 175 | "${match.namedGroup('data')}", | 230 | "${match.namedGroup('data')}", |
| 176 | conf, | 231 | conf, |
| 232 | + false, | ||
| 177 | )), | 233 | )), |
| 178 | if (match.namedGroup('hash')!.length == 1) ...[ | 234 | if (match.namedGroup('hash')!.length == 1) ...[ |
| 179 | const TextSpan( | 235 | const TextSpan( |
| @@ -205,8 +261,12 @@ class NewLines extends InlineMd { | @@ -205,8 +261,12 @@ class NewLines extends InlineMd { | ||
| 205 | final GptMarkdownConfig config, | 261 | final GptMarkdownConfig config, |
| 206 | ) { | 262 | ) { |
| 207 | return TextSpan( | 263 | return TextSpan( |
| 208 | - text: "\n\n\n\n", | ||
| 209 | - style: TextStyle(fontSize: 6, color: config.style?.color), | 264 | + text: "\n\n", |
| 265 | + style: TextStyle( | ||
| 266 | + fontSize: config.style?.fontSize ?? 14, | ||
| 267 | + height: 1.15, | ||
| 268 | + color: config.style?.color, | ||
| 269 | + ), | ||
| 210 | ); | 270 | ); |
| 211 | } | 271 | } |
| 212 | } | 272 | } |
| @@ -246,7 +306,7 @@ class CheckBoxMd extends BlockMd { | @@ -246,7 +306,7 @@ class CheckBoxMd extends BlockMd { | ||
| 246 | return CustomCb( | 306 | return CustomCb( |
| 247 | value: ("${match?[1]}" == "x"), | 307 | value: ("${match?[1]}" == "x"), |
| 248 | textDirection: config.textDirection, | 308 | textDirection: config.textDirection, |
| 249 | - child: MdWidget("${match?[2]}", config: config), | 309 | + child: MdWidget("${match?[2]}", false, config: config), |
| 250 | ); | 310 | ); |
| 251 | } | 311 | } |
| 252 | } | 312 | } |
| @@ -267,13 +327,13 @@ class RadioButtonMd extends BlockMd { | @@ -267,13 +327,13 @@ class RadioButtonMd extends BlockMd { | ||
| 267 | return CustomRb( | 327 | return CustomRb( |
| 268 | value: ("${match?[1]}" == "x"), | 328 | value: ("${match?[1]}" == "x"), |
| 269 | textDirection: config.textDirection, | 329 | textDirection: config.textDirection, |
| 270 | - child: MdWidget("${match?[2]}", config: config), | 330 | + child: MdWidget("${match?[2]}", false, config: config), |
| 271 | ); | 331 | ); |
| 272 | } | 332 | } |
| 273 | } | 333 | } |
| 274 | 334 | ||
| 275 | -/// Indent | ||
| 276 | -class IndentMd extends InlineMd { | 335 | +/// Block quote component |
| 336 | +class BlockQuote extends InlineMd { | ||
| 277 | @override | 337 | @override |
| 278 | bool get inline => false; | 338 | bool get inline => false; |
| 279 | @override | 339 | @override |
| @@ -292,7 +352,7 @@ class IndentMd extends InlineMd { | @@ -292,7 +352,7 @@ class IndentMd extends InlineMd { | ||
| 292 | // data = data.replaceAll(RegExp(r'\n\ {' '$spaces' '}'), '\n').trim(); | 352 | // data = data.replaceAll(RegExp(r'\n\ {' '$spaces' '}'), '\n').trim(); |
| 293 | data = data.trim(); | 353 | data = data.trim(); |
| 294 | var child = TextSpan( | 354 | var child = TextSpan( |
| 295 | - children: MarkdownComponent.generate(context, data, config), | 355 | + children: MarkdownComponent.generate(context, data, config, true), |
| 296 | ); | 356 | ); |
| 297 | return TextSpan( | 357 | return TextSpan( |
| 298 | children: [ | 358 | children: [ |
| @@ -301,7 +361,7 @@ class IndentMd extends InlineMd { | @@ -301,7 +361,7 @@ class IndentMd extends InlineMd { | ||
| 301 | textDirection: config.textDirection, | 361 | textDirection: config.textDirection, |
| 302 | child: Padding( | 362 | child: Padding( |
| 303 | padding: const EdgeInsets.symmetric(vertical: 2), | 363 | padding: const EdgeInsets.symmetric(vertical: 2), |
| 304 | - child: IndentWidget( | 364 | + child: BlockQuoteWidget( |
| 305 | color: Theme.of(context).colorScheme.onSurfaceVariant, | 365 | color: Theme.of(context).colorScheme.onSurfaceVariant, |
| 306 | direction: config.textDirection, | 366 | direction: config.textDirection, |
| 307 | child: Padding( | 367 | child: Padding( |
| @@ -330,7 +390,7 @@ class UnOrderedList extends BlockMd { | @@ -330,7 +390,7 @@ class UnOrderedList extends BlockMd { | ||
| 330 | ) { | 390 | ) { |
| 331 | var match = this.exp.firstMatch(text); | 391 | var match = this.exp.firstMatch(text); |
| 332 | 392 | ||
| 333 | - var child = MdWidget("${match?[1]?.trim()}", config: config); | 393 | + var child = MdWidget("${match?[1]?.trim()}", false, config: config); |
| 334 | 394 | ||
| 335 | return config.unOrderedListBuilder?.call( | 395 | return config.unOrderedListBuilder?.call( |
| 336 | context, | 396 | context, |
| @@ -368,7 +428,7 @@ class OrderedList extends BlockMd { | @@ -368,7 +428,7 @@ class OrderedList extends BlockMd { | ||
| 368 | 428 | ||
| 369 | var no = "${match?[1]}"; | 429 | var no = "${match?[1]}"; |
| 370 | 430 | ||
| 371 | - var child = MdWidget("${match?[2]?.trim()}", config: config); | 431 | + var child = MdWidget("${match?[2]?.trim()}", false, config: config); |
| 372 | return config.orderedListBuilder?.call( | 432 | return config.orderedListBuilder?.call( |
| 373 | context, | 433 | context, |
| 374 | no, | 434 | no, |
| @@ -450,7 +510,12 @@ class BoldMd extends InlineMd { | @@ -450,7 +510,12 @@ class BoldMd extends InlineMd { | ||
| 450 | const TextStyle(fontWeight: FontWeight.bold), | 510 | const TextStyle(fontWeight: FontWeight.bold), |
| 451 | ); | 511 | ); |
| 452 | return TextSpan( | 512 | return TextSpan( |
| 453 | - children: MarkdownComponent.generate(context, "${match?[1]}", conf), | 513 | + children: MarkdownComponent.generate( |
| 514 | + context, | ||
| 515 | + "${match?[1]}", | ||
| 516 | + conf, | ||
| 517 | + false, | ||
| 518 | + ), | ||
| 454 | style: conf.style, | 519 | style: conf.style, |
| 455 | ); | 520 | ); |
| 456 | } | 521 | } |
| @@ -476,7 +541,12 @@ class StrikeMd extends InlineMd { | @@ -476,7 +541,12 @@ class StrikeMd extends InlineMd { | ||
| 476 | const TextStyle(decoration: TextDecoration.lineThrough), | 541 | const TextStyle(decoration: TextDecoration.lineThrough), |
| 477 | ); | 542 | ); |
| 478 | return TextSpan( | 543 | return TextSpan( |
| 479 | - children: MarkdownComponent.generate(context, "${match?[1]}", conf), | 544 | + children: MarkdownComponent.generate( |
| 545 | + context, | ||
| 546 | + "${match?[1]}", | ||
| 547 | + conf, | ||
| 548 | + false, | ||
| 549 | + ), | ||
| 480 | style: conf.style, | 550 | style: conf.style, |
| 481 | ); | 551 | ); |
| 482 | } | 552 | } |
| @@ -504,7 +574,7 @@ class ItalicMd extends InlineMd { | @@ -504,7 +574,7 @@ class ItalicMd extends InlineMd { | ||
| 504 | ), | 574 | ), |
| 505 | ); | 575 | ); |
| 506 | return TextSpan( | 576 | return TextSpan( |
| 507 | - children: MarkdownComponent.generate(context, "$data", conf), | 577 | + children: MarkdownComponent.generate(context, "$data", conf, false), |
| 508 | style: conf.style, | 578 | style: conf.style, |
| 509 | ); | 579 | ); |
| 510 | } | 580 | } |
| @@ -898,6 +968,7 @@ class TableMd extends BlockMd { | @@ -898,6 +968,7 @@ class TableMd extends BlockMd { | ||
| 898 | ), | 968 | ), |
| 899 | child: MdWidget( | 969 | child: MdWidget( |
| 900 | (e[index] ?? "").trim(), | 970 | (e[index] ?? "").trim(), |
| 971 | + false, | ||
| 901 | config: config, | 972 | config: config, |
| 902 | ), | 973 | ), |
| 903 | ), | 974 | ), |
| @@ -2,11 +2,19 @@ part of 'gpt_markdown.dart'; | @@ -2,11 +2,19 @@ part of 'gpt_markdown.dart'; | ||
| 2 | 2 | ||
| 3 | /// It creates a markdown widget closed to each other. | 3 | /// It creates a markdown widget closed to each other. |
| 4 | class MdWidget extends StatelessWidget { | 4 | class MdWidget extends StatelessWidget { |
| 5 | - const MdWidget(this.exp, {super.key, required this.config}); | 5 | + const MdWidget( |
| 6 | + this.exp, | ||
| 7 | + this.includeGlobalComponents, { | ||
| 8 | + super.key, | ||
| 9 | + required this.config, | ||
| 10 | + }); | ||
| 6 | 11 | ||
| 7 | /// The expression to be displayed. | 12 | /// The expression to be displayed. |
| 8 | final String exp; | 13 | final String exp; |
| 9 | 14 | ||
| 15 | + /// Whether to include global components. | ||
| 16 | + final bool includeGlobalComponents; | ||
| 17 | + | ||
| 10 | /// The configuration of the markdown widget. | 18 | /// The configuration of the markdown widget. |
| 11 | final GptMarkdownConfig config; | 19 | final GptMarkdownConfig config; |
| 12 | 20 | ||
| @@ -28,6 +36,7 @@ class MdWidget extends StatelessWidget { | @@ -28,6 +36,7 @@ class MdWidget extends StatelessWidget { | ||
| 28 | // return "\\[$body\\]"; | 36 | // return "\\[$body\\]"; |
| 29 | // }), | 37 | // }), |
| 30 | config, | 38 | config, |
| 39 | + includeGlobalComponents, | ||
| 31 | ), | 40 | ), |
| 32 | ); | 41 | ); |
| 33 | return config.getRich( | 42 | return config.getRich( |
| 1 | name: gpt_markdown | 1 | name: gpt_markdown |
| 2 | description: "Powerful Markdown & LaTeX Renderer for Flutter: Rich Text, Math, Tables, Links, and Text Selection. Ideal for ChatGPT, Gemini, and more." | 2 | description: "Powerful Markdown & LaTeX Renderer for Flutter: Rich Text, Math, Tables, Links, and Text Selection. Ideal for ChatGPT, Gemini, and more." |
| 3 | -version: 1.0.15 | 3 | +version: 1.0.16 |
| 4 | homepage: https://github.com/Infinitix-LLC/gpt_markdown | 4 | homepage: https://github.com/Infinitix-LLC/gpt_markdown |
| 5 | 5 | ||
| 6 | environment: | 6 | environment: |
-
Please register or login to post a comment