Update version to 1.0.14 and add list rendering customization. Introduced `order…
…edListBuilder` and `unOrderedListBuilder` parameters for enhanced list rendering in GptMarkdown.
Showing
5 changed files
with
123 additions
and
94 deletions
| 1 | +## 1.0.14 | ||
| 2 | + | ||
| 3 | +* Added `orderedListBuilder` and `unOrderedListBuilder` parameters to customize list rendering. | ||
| 4 | + | ||
| 1 | ## 1.0.13 | 5 | ## 1.0.13 |
| 2 | 6 | ||
| 3 | * Fixed issue [#49](https://github.com/Infinitix-LLC/gpt_markdown/issues/49). | 7 | * Fixed issue [#49](https://github.com/Infinitix-LLC/gpt_markdown/issues/49). |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | 2 | ||
| 3 | +/// A builder function for the ordered list. | ||
| 4 | +typedef OrderedListBuilder = | ||
| 5 | + Widget Function( | ||
| 6 | + BuildContext context, | ||
| 7 | + String no, | ||
| 8 | + Widget child, | ||
| 9 | + GptMarkdownConfig config, | ||
| 10 | + ); | ||
| 11 | + | ||
| 12 | +/// A builder function for the unordered list. | ||
| 13 | +typedef UnOrderedListBuilder = | ||
| 14 | + Widget Function( | ||
| 15 | + BuildContext context, | ||
| 16 | + Widget child, | ||
| 17 | + GptMarkdownConfig config, | ||
| 18 | + ); | ||
| 19 | + | ||
| 20 | +/// A builder function for the source tag. | ||
| 21 | +typedef SourceTagBuilder = | ||
| 22 | + Widget Function(BuildContext context, String content, TextStyle textStyle); | ||
| 23 | + | ||
| 24 | +/// A builder function for the code block. | ||
| 25 | +typedef CodeBlockBuilder = | ||
| 26 | + Widget Function( | ||
| 27 | + BuildContext context, | ||
| 28 | + String name, | ||
| 29 | + String code, | ||
| 30 | + bool closed, | ||
| 31 | + ); | ||
| 32 | + | ||
| 33 | +/// A builder function for the LaTeX. | ||
| 34 | +typedef LatexBuilder = | ||
| 35 | + Widget Function( | ||
| 36 | + BuildContext context, | ||
| 37 | + String tex, | ||
| 38 | + TextStyle textStyle, | ||
| 39 | + bool inline, | ||
| 40 | + ); | ||
| 41 | + | ||
| 42 | +/// A builder function for the link. | ||
| 43 | +typedef LinkBuilder = | ||
| 44 | + Widget Function( | ||
| 45 | + BuildContext context, | ||
| 46 | + String text, | ||
| 47 | + String url, | ||
| 48 | + TextStyle style, | ||
| 49 | + ); | ||
| 50 | + | ||
| 51 | +/// A builder function for the highlight. | ||
| 52 | +typedef HighlightBuilder = | ||
| 53 | + Widget Function(BuildContext context, String text, TextStyle style); | ||
| 54 | + | ||
| 55 | +/// A builder function for the image. | ||
| 56 | +typedef ImageBuilder = Widget Function(BuildContext context, String imageUrl); | ||
| 57 | + | ||
| 3 | /// A configuration class for the GPT Markdown component. | 58 | /// A configuration class for the GPT Markdown component. |
| 4 | /// | 59 | /// |
| 5 | /// The [GptMarkdownConfig] class is used to configure the GPT Markdown component. | 60 | /// The [GptMarkdownConfig] class is used to configure the GPT Markdown component. |
| @@ -19,6 +74,8 @@ class GptMarkdownConfig { | @@ -19,6 +74,8 @@ class GptMarkdownConfig { | ||
| 19 | this.codeBuilder, | 74 | this.codeBuilder, |
| 20 | this.sourceTagBuilder, | 75 | this.sourceTagBuilder, |
| 21 | this.highlightBuilder, | 76 | this.highlightBuilder, |
| 77 | + this.orderedListBuilder, | ||
| 78 | + this.unOrderedListBuilder, | ||
| 22 | this.linkBuilder, | 79 | this.linkBuilder, |
| 23 | this.imageBuilder, | 80 | this.imageBuilder, |
| 24 | this.maxLines, | 81 | this.maxLines, |
| @@ -44,33 +101,22 @@ class GptMarkdownConfig { | @@ -44,33 +101,22 @@ class GptMarkdownConfig { | ||
| 44 | final String Function(String tex)? latexWorkaround; | 101 | final String Function(String tex)? latexWorkaround; |
| 45 | 102 | ||
| 46 | /// The LaTeX builder. | 103 | /// The LaTeX builder. |
| 47 | - final Widget Function( | ||
| 48 | - BuildContext context, | ||
| 49 | - String tex, | ||
| 50 | - TextStyle textStyle, | ||
| 51 | - bool inline, | ||
| 52 | - )? | ||
| 53 | - latexBuilder; | 104 | + final LatexBuilder? latexBuilder; |
| 54 | 105 | ||
| 55 | /// The source tag builder. | 106 | /// The source tag builder. |
| 56 | - final Widget Function( | ||
| 57 | - BuildContext context, | ||
| 58 | - String content, | ||
| 59 | - TextStyle textStyle, | ||
| 60 | - )? | ||
| 61 | - sourceTagBuilder; | 107 | + final SourceTagBuilder? sourceTagBuilder; |
| 62 | 108 | ||
| 63 | /// Whether to follow the link color. | 109 | /// Whether to follow the link color. |
| 64 | final bool followLinkColor; | 110 | final bool followLinkColor; |
| 65 | 111 | ||
| 66 | /// The code builder. | 112 | /// The code builder. |
| 67 | - final Widget Function( | ||
| 68 | - BuildContext context, | ||
| 69 | - String name, | ||
| 70 | - String code, | ||
| 71 | - bool closed, | ||
| 72 | - )? | ||
| 73 | - codeBuilder; | 113 | + final CodeBlockBuilder? codeBuilder; |
| 114 | + | ||
| 115 | + /// The Ordered List builder. | ||
| 116 | + final OrderedListBuilder? orderedListBuilder; | ||
| 117 | + | ||
| 118 | + /// The Unordered List builder. | ||
| 119 | + final UnOrderedListBuilder? unOrderedListBuilder; | ||
| 74 | 120 | ||
| 75 | /// The maximum number of lines. | 121 | /// The maximum number of lines. |
| 76 | final int? maxLines; | 122 | final int? maxLines; |
| @@ -79,18 +125,13 @@ class GptMarkdownConfig { | @@ -79,18 +125,13 @@ class GptMarkdownConfig { | ||
| 79 | final TextOverflow? overflow; | 125 | final TextOverflow? overflow; |
| 80 | 126 | ||
| 81 | /// The highlight builder. | 127 | /// The highlight builder. |
| 82 | - final Widget Function(BuildContext context, String text, TextStyle style)? | ||
| 83 | - highlightBuilder; | ||
| 84 | - final Widget Function( | ||
| 85 | - BuildContext context, | ||
| 86 | - String text, | ||
| 87 | - String url, | ||
| 88 | - TextStyle style, | ||
| 89 | - )? | ||
| 90 | - linkBuilder; | 128 | + final HighlightBuilder? highlightBuilder; |
| 129 | + | ||
| 130 | + /// The link builder. | ||
| 131 | + final LinkBuilder? linkBuilder; | ||
| 91 | 132 | ||
| 92 | /// The image builder. | 133 | /// The image builder. |
| 93 | - final Widget Function(BuildContext, String imageUrl)? imageBuilder; | 134 | + final ImageBuilder? imageBuilder; |
| 94 | 135 | ||
| 95 | /// A copy of the configuration with the specified parameters. | 136 | /// A copy of the configuration with the specified parameters. |
| 96 | GptMarkdownConfig copyWith({ | 137 | GptMarkdownConfig copyWith({ |
| @@ -100,39 +141,17 @@ class GptMarkdownConfig { | @@ -100,39 +141,17 @@ class GptMarkdownConfig { | ||
| 100 | final TextAlign? textAlign, | 141 | final TextAlign? textAlign, |
| 101 | final TextScaler? textScaler, | 142 | final TextScaler? textScaler, |
| 102 | final String Function(String tex)? latexWorkaround, | 143 | final String Function(String tex)? latexWorkaround, |
| 103 | - final Widget Function( | ||
| 104 | - BuildContext context, | ||
| 105 | - String tex, | ||
| 106 | - TextStyle textStyle, | ||
| 107 | - bool inline, | ||
| 108 | - )? | ||
| 109 | - latexBuilder, | ||
| 110 | - final Widget Function( | ||
| 111 | - BuildContext context, | ||
| 112 | - String content, | ||
| 113 | - TextStyle textStyle, | ||
| 114 | - )? | ||
| 115 | - sourceTagBuilder, | ||
| 116 | - bool? followLinkColor, | ||
| 117 | - final Widget Function( | ||
| 118 | - BuildContext context, | ||
| 119 | - String name, | ||
| 120 | - String code, | ||
| 121 | - bool closed, | ||
| 122 | - )? | ||
| 123 | - codeBuilder, | 144 | + final LatexBuilder? latexBuilder, |
| 145 | + final SourceTagBuilder? sourceTagBuilder, | ||
| 146 | + final bool? followLinkColor, | ||
| 147 | + final CodeBlockBuilder? codeBuilder, | ||
| 124 | final int? maxLines, | 148 | final int? maxLines, |
| 125 | final TextOverflow? overflow, | 149 | final TextOverflow? overflow, |
| 126 | - final Widget Function(BuildContext context, String text, TextStyle style)? | ||
| 127 | - highlightBuilder, | ||
| 128 | - final Widget Function( | ||
| 129 | - BuildContext context, | ||
| 130 | - String text, | ||
| 131 | - String url, | ||
| 132 | - TextStyle style, | ||
| 133 | - )? | ||
| 134 | - linkBuilder, | ||
| 135 | - final Widget Function(BuildContext, String imageUrl)? imageBuilder, | 150 | + final HighlightBuilder? highlightBuilder, |
| 151 | + final LinkBuilder? linkBuilder, | ||
| 152 | + final ImageBuilder? imageBuilder, | ||
| 153 | + final OrderedListBuilder? orderedListBuilder, | ||
| 154 | + final UnOrderedListBuilder? unOrderedListBuilder, | ||
| 136 | }) { | 155 | }) { |
| 137 | return GptMarkdownConfig( | 156 | return GptMarkdownConfig( |
| 138 | style: style ?? this.style, | 157 | style: style ?? this.style, |
| @@ -150,6 +169,8 @@ class GptMarkdownConfig { | @@ -150,6 +169,8 @@ class GptMarkdownConfig { | ||
| 150 | highlightBuilder: highlightBuilder ?? this.highlightBuilder, | 169 | highlightBuilder: highlightBuilder ?? this.highlightBuilder, |
| 151 | linkBuilder: linkBuilder ?? this.linkBuilder, | 170 | linkBuilder: linkBuilder ?? this.linkBuilder, |
| 152 | imageBuilder: imageBuilder ?? this.imageBuilder, | 171 | imageBuilder: imageBuilder ?? this.imageBuilder, |
| 172 | + orderedListBuilder: orderedListBuilder ?? this.orderedListBuilder, | ||
| 173 | + unOrderedListBuilder: unOrderedListBuilder ?? this.unOrderedListBuilder, | ||
| 153 | ); | 174 | ); |
| 154 | } | 175 | } |
| 155 | 176 |
| @@ -38,6 +38,8 @@ class GptMarkdown extends StatelessWidget { | @@ -38,6 +38,8 @@ class GptMarkdown extends StatelessWidget { | ||
| 38 | this.linkBuilder, | 38 | this.linkBuilder, |
| 39 | this.maxLines, | 39 | this.maxLines, |
| 40 | this.overflow, | 40 | this.overflow, |
| 41 | + this.orderedListBuilder, | ||
| 42 | + this.unOrderedListBuilder, | ||
| 41 | }); | 43 | }); |
| 42 | 44 | ||
| 43 | /// The direction of the text. | 45 | /// The direction of the text. |
| @@ -66,44 +68,31 @@ class GptMarkdown extends StatelessWidget { | @@ -66,44 +68,31 @@ class GptMarkdown extends StatelessWidget { | ||
| 66 | final TextOverflow? overflow; | 68 | final TextOverflow? overflow; |
| 67 | 69 | ||
| 68 | /// The LaTeX builder. | 70 | /// The LaTeX builder. |
| 69 | - final Widget Function( | ||
| 70 | - BuildContext context, | ||
| 71 | - String tex, | ||
| 72 | - TextStyle style, | ||
| 73 | - bool inline, | ||
| 74 | - )? | ||
| 75 | - latexBuilder; | 71 | + final LatexBuilder? latexBuilder; |
| 76 | 72 | ||
| 77 | /// Whether to follow the link color. | 73 | /// Whether to follow the link color. |
| 78 | final bool followLinkColor; | 74 | final bool followLinkColor; |
| 79 | 75 | ||
| 80 | /// The code builder. | 76 | /// The code builder. |
| 81 | - final Widget Function( | ||
| 82 | - BuildContext context, | ||
| 83 | - String name, | ||
| 84 | - String code, | ||
| 85 | - bool closed, | ||
| 86 | - )? | ||
| 87 | - codeBuilder; | 77 | + final CodeBlockBuilder? codeBuilder; |
| 88 | 78 | ||
| 89 | /// The source tag builder. | 79 | /// The source tag builder. |
| 90 | - final Widget Function(BuildContext, String, TextStyle)? sourceTagBuilder; | 80 | + final SourceTagBuilder? sourceTagBuilder; |
| 91 | 81 | ||
| 92 | /// The highlight builder. | 82 | /// The highlight builder. |
| 93 | - final Widget Function(BuildContext context, String text, TextStyle style)? | ||
| 94 | - highlightBuilder; | 83 | + final HighlightBuilder? highlightBuilder; |
| 95 | 84 | ||
| 96 | /// The link builder. | 85 | /// The link builder. |
| 97 | - final Widget Function( | ||
| 98 | - BuildContext context, | ||
| 99 | - String text, | ||
| 100 | - String url, | ||
| 101 | - TextStyle style, | ||
| 102 | - )? | ||
| 103 | - linkBuilder; | 86 | + final LinkBuilder? linkBuilder; |
| 104 | 87 | ||
| 105 | /// The image builder. | 88 | /// The image builder. |
| 106 | - final Widget Function(BuildContext, String imageUrl)? imageBuilder; | 89 | + final ImageBuilder? imageBuilder; |
| 90 | + | ||
| 91 | + /// The ordered list builder. | ||
| 92 | + final OrderedListBuilder? orderedListBuilder; | ||
| 93 | + | ||
| 94 | + /// The unordered list builder. | ||
| 95 | + final UnOrderedListBuilder? unOrderedListBuilder; | ||
| 107 | 96 | ||
| 108 | /// A method to remove extra lines inside block LaTeX. | 97 | /// A method to remove extra lines inside block LaTeX. |
| 109 | String _removeExtraLinesInsideBlockLatex(String text) { | 98 | String _removeExtraLinesInsideBlockLatex(String text) { |
| @@ -155,6 +144,8 @@ class GptMarkdown extends StatelessWidget { | @@ -155,6 +144,8 @@ class GptMarkdown extends StatelessWidget { | ||
| 155 | highlightBuilder: highlightBuilder, | 144 | highlightBuilder: highlightBuilder, |
| 156 | linkBuilder: linkBuilder, | 145 | linkBuilder: linkBuilder, |
| 157 | imageBuilder: imageBuilder, | 146 | imageBuilder: imageBuilder, |
| 147 | + orderedListBuilder: orderedListBuilder, | ||
| 148 | + unOrderedListBuilder: unOrderedListBuilder, | ||
| 158 | ), | 149 | ), |
| 159 | ), | 150 | ), |
| 160 | ); | 151 | ); |
| @@ -329,7 +329,11 @@ class UnOrderedList extends BlockMd { | @@ -329,7 +329,11 @@ class UnOrderedList extends BlockMd { | ||
| 329 | final GptMarkdownConfig config, | 329 | final GptMarkdownConfig config, |
| 330 | ) { | 330 | ) { |
| 331 | var match = this.exp.firstMatch(text); | 331 | var match = this.exp.firstMatch(text); |
| 332 | - return UnorderedListView( | 332 | + |
| 333 | + var child = MdWidget("${match?[1]?.trim()}", config: config); | ||
| 334 | + | ||
| 335 | + return config.unOrderedListBuilder?.call(context, child, config) ?? | ||
| 336 | + UnorderedListView( | ||
| 333 | bulletColor: | 337 | bulletColor: |
| 334 | (config.style?.color ?? DefaultTextStyle.of(context).style.color), | 338 | (config.style?.color ?? DefaultTextStyle.of(context).style.color), |
| 335 | padding: 7, | 339 | padding: 7, |
| @@ -340,7 +344,7 @@ class UnOrderedList extends BlockMd { | @@ -340,7 +344,7 @@ class UnOrderedList extends BlockMd { | ||
| 340 | DefaultTextStyle.of(context).style.fontSize ?? | 344 | DefaultTextStyle.of(context).style.fontSize ?? |
| 341 | kDefaultFontSize), | 345 | kDefaultFontSize), |
| 342 | textDirection: config.textDirection, | 346 | textDirection: config.textDirection, |
| 343 | - child: MdWidget("${match?[1]?.trim()}", config: config), | 347 | + child: child, |
| 344 | ); | 348 | ); |
| 345 | } | 349 | } |
| 346 | } | 350 | } |
| @@ -348,7 +352,7 @@ class UnOrderedList extends BlockMd { | @@ -348,7 +352,7 @@ class UnOrderedList extends BlockMd { | ||
| 348 | /// Ordered list component | 352 | /// Ordered list component |
| 349 | class OrderedList extends BlockMd { | 353 | class OrderedList extends BlockMd { |
| 350 | @override | 354 | @override |
| 351 | - String get expString => (r"([0-9]+\.)\ ([^\n]+)$"); | 355 | + String get expString => (r"([0-9]+)\.\ ([^\n]+)$"); |
| 352 | 356 | ||
| 353 | @override | 357 | @override |
| 354 | Widget build( | 358 | Widget build( |
| @@ -357,13 +361,23 @@ class OrderedList extends BlockMd { | @@ -357,13 +361,23 @@ class OrderedList extends BlockMd { | ||
| 357 | final GptMarkdownConfig config, | 361 | final GptMarkdownConfig config, |
| 358 | ) { | 362 | ) { |
| 359 | var match = this.exp.firstMatch(text.trim()); | 363 | var match = this.exp.firstMatch(text.trim()); |
| 360 | - return OrderedListView( | ||
| 361 | - no: "${match?[1]}", | 364 | + |
| 365 | + var no = "${match?[1]}"; | ||
| 366 | + | ||
| 367 | + var child = MdWidget("${match?[2]?.trim()}", config: config); | ||
| 368 | + return config.orderedListBuilder?.call( | ||
| 369 | + context, | ||
| 370 | + no, | ||
| 371 | + child, | ||
| 372 | + config.copyWith(), | ||
| 373 | + ) ?? | ||
| 374 | + OrderedListView( | ||
| 375 | + no: "$no.", | ||
| 362 | textDirection: config.textDirection, | 376 | textDirection: config.textDirection, |
| 363 | style: (config.style ?? const TextStyle()).copyWith( | 377 | style: (config.style ?? const TextStyle()).copyWith( |
| 364 | fontWeight: FontWeight.w100, | 378 | fontWeight: FontWeight.w100, |
| 365 | ), | 379 | ), |
| 366 | - child: MdWidget("${match?[2]?.trim()}", config: config), | 380 | + child: child, |
| 367 | ); | 381 | ); |
| 368 | } | 382 | } |
| 369 | } | 383 | } |
| @@ -426,7 +440,6 @@ class BoldMd extends InlineMd { | @@ -426,7 +440,6 @@ class BoldMd extends InlineMd { | ||
| 426 | final GptMarkdownConfig config, | 440 | final GptMarkdownConfig config, |
| 427 | ) { | 441 | ) { |
| 428 | var match = exp.firstMatch(text.trim()); | 442 | var match = exp.firstMatch(text.trim()); |
| 429 | - print(match); | ||
| 430 | var conf = config.copyWith( | 443 | var conf = config.copyWith( |
| 431 | style: | 444 | style: |
| 432 | config.style?.copyWith(fontWeight: FontWeight.bold) ?? | 445 | config.style?.copyWith(fontWeight: FontWeight.bold) ?? |
| 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.13 | 3 | +version: 1.0.14 |
| 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