saminsohag

baseline for bloc type component is fixed

1 ## 1.0.16 1 ## 1.0.16
2 2
3 * `IndentMd` and `BlockQuote` fixed. 3 * `IndentMd` and `BlockQuote` fixed.
  4 +* Baseline of bloc type component is fixed.
4 5
5 ## 1.0.15 6 ## 1.0.15
6 7
  1 +description: This file stores settings for Dart & Flutter DevTools.
  2 +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
  3 +extensions:
  1 +description: This file stores settings for Dart & Flutter DevTools.
  2 +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
  3 +extensions:
@@ -76,57 +76,216 @@ class _MyHomePageState extends State<MyHomePage> { @@ -76,57 +76,216 @@ class _MyHomePageState extends State<MyHomePage> {
76 TextDirection _direction = TextDirection.ltr; 76 TextDirection _direction = TextDirection.ltr;
77 final TextEditingController _controller = TextEditingController( 77 final TextEditingController _controller = TextEditingController(
78 text: r''' 78 text: r'''
79 -## ChatGPT Response 79 +```markdown
  80 +# Complex Markdown Document for Testing
  81 +
  82 +This document is designed to **challenge** your `gpt_markdown` package by incorporating a wide variety of Markdown components including headers, lists, tables, code blocks, blockquotes, footnotes, and LaTeX math expressions.
  83 +
  84 +---
  85 +
  86 +## Table of Contents
  87 +1. [Headers and Emphasis](#headers-and-emphasis)
  88 +2. [Lists](#lists)
  89 +3. [Code Blocks and Inline Code](#code-blocks-and-inline-code)
  90 +4. [Tables](#tables)
  91 +5. [Blockquotes and Nested Elements](#blockquotes-and-nested-elements)
  92 +6. [Mathematical Expressions](#mathematical-expressions)
  93 +7. [Links and Images](#links-and-images)
  94 +8. [Footnotes](#footnotes)
  95 +9. [Horizontal Rules and Miscellaneous](#horizontal-rules-and-miscellaneous)
  96 +
  97 +---
  98 +
  99 +## Headers and Emphasis
  100 +
  101 +### Header Levels
  102 +Markdown supports multiple header levels:
  103 +- `# Header 1`
  104 +- `## Header 2`
  105 +- `### Header 3`
  106 +- `#### Header 4`
  107 +- `##### Header 5`
  108 +- `###### Header 6`
  109 +
  110 +### Emphasis Examples
  111 +- *Italicized text* using single asterisks or underscores.
  112 +- **Bold text** using double asterisks or underscores.
  113 +- ***Bold and italic*** by combining them.
  114 +- ~~Strikethrough~~ text using two tildes.
  115 +
  116 +---
  117 +
  118 +## Lists
  119 +
  120 +### Unordered List
  121 +- Item 1
  122 + - Nested Item 1.1
  123 + - Nested Item 1.2
  124 + - Deeply Nested Item 1.2.1
  125 +- Item 2
  126 + - [ ] Task not completed
  127 + - [x] Task completed
  128 +
  129 +### Ordered List
  130 +1. First item
  131 +2. Second item with nested list:
  132 + 1. Subitem 2.1
  133 + 2. Subitem 2.2
  134 +3. Third item
  135 +
  136 +### Mixed List Example
  137 +- **Fruits**
  138 + 1. Apple
  139 + 2. Banana
  140 + 3. Cherry
  141 +- **Vegetables**
  142 + - Carrot
  143 + - Lettuce
  144 + - Spinach
  145 +
  146 +---
  147 +
  148 +## Code Blocks and Inline Code
  149 +
  150 +### Inline Code
  151 +Here is an example of inline code: `print("Hello, world!")`.
  152 +
  153 +### Fenced Code Block (Python)
  154 +```python
  155 +def greet(name):
  156 + """
  157 + Greets a person with the provided name.
  158 + """
  159 + print(f"Hello, {name}!")
  160 +
  161 +greet("Alice")
  162 +```
80 163
81 -Welcome to ChatGPT! Below is an example of a response with Markdown and LaTeX code: 164 +### Fenced Code Block (JavaScript)
  165 +```javascript
  166 +function greet(name) {
  167 + console.log(`Hello, ${name}!`);
  168 +}
  169 +greet("Bob");
  170 +```
82 171
83 -### Markdown Example 172 +---
84 173
  174 +## Tables
85 175
86 -```  
87 -class MarkdownHelper { 176 +Here is a table demonstrating various elements:
88 177
  178 +| Syntax | Description | Example |
  179 +| ----------- | ---------------------------------------- | --------------------------------- |
  180 +| Header | Title | **Bold Header** |
  181 +| Paragraph | Text with *italic* and **bold** elements | This is a sample paragraph. |
  182 +| Inline Code | `code snippet` | `let x = 10;` |
89 183
90 - Map<String, Widget> getTitleWidget(m.Node node) => title.getTitleWidget(node); 184 +Additional table with alignment:
91 185
92 - Widget getPWidget(m.Element node) => p.getPWidget(node); 186 +| Left Align | Center Align | Right Align |
  187 +| :--------- |:------------:| ----------:|
  188 +| Row 1 | Row 1 | Row 1 |
  189 +| Row 2 | Row 2 | Row 2 |
93 190
94 - Widget getPreWidget(m.Node node) => pre.getPreWidget(node);  
95 -  
96 -}  
97 -``` 191 +---
98 192
  193 +## Blockquotes and Nested Elements
99 194
100 -You can use Markdown to format text easily. Here are some examples: 195 +> **Blockquote Header**
  196 +>
  197 +> This is a blockquote. You can include **bold** and *italic* text, as well as `inline code` within blockquotes.
  198 +>
  199 +> > ### Nested Blockquote
  200 +> > - Nested list item 1
  201 +> > - Nested list item 2
  202 +> > 1. Numbered subitem 1
  203 +> > 2. Numbered subitem 2
  204 +> >
  205 +> > ```python
  206 +> > # Code snippet inside nested blockquote
  207 +> > for i in range(3):
  208 +> > print(i)
  209 +> > ```
  210 +>
  211 +> Back to the outer blockquote.
101 212
102 -- `Highlighted Text`: `This text is highlighted`  
103 -- **Bold Text**: **This text is bold**  
104 -- *Italic Text*: *This text is italicized*  
105 -- [Link](https://www.example.com): [This is a link](https://www.example.com)  
106 -- Lists:  
107 - 1. Item 1  
108 - 2. Item 2  
109 - 3. Item 3 213 +---
110 214
111 -### LaTeX Example 215 +## Mathematical Expressions
112 216
113 -You can also use LaTeX for mathematical expressions. Here's an example: 217 +### Inline Math
  218 +You can write inline math using the `\( ... \)` syntax. For example, the quadratic formula is given by:
  219 +\( x = \frac{-b \pm \sqrt{b^2-4ac}}{2a} \).
114 220
115 -- **Equation**: \( f(x) = x^2 + 2x + 1 \)  
116 -- **Integral**: \( \int_{0}^{1} x^2 \, dx \)  
117 -- **Matrix**: 221 +### Display Math
  222 +Display math can be rendered using the `\[ ... \]` syntax. For example, consider the integral:
  223 +\[
  224 +\int_{-\infty}^{\infty} e^{-x^2} \, dx = \sqrt{\pi}
  225 +\]
118 226
  227 +More complex display equations:
119 \[ 228 \[
120 -\begin{bmatrix}  
121 -1 & 2 & 3 \\  
122 -4 & 5 & 6 \\  
123 -7 & 8 & 9  
124 -\end{bmatrix} 229 +E = mc^2 \quad \text{and} \quad F = ma
125 \] 230 \]
126 231
127 -### Conclusion 232 +---
  233 +
  234 +## Links and Images
  235 +
  236 +### Links
  237 +Here are examples of links:
  238 +- [OpenAI](https://www.openai.com)
  239 +- [GitHub](https://github.com)
  240 +
  241 +### Images
  242 +Inline images can be embedded as follows:
  243 +![Alt Text for Image](https://via.placeholder.com/150 "Image Title")
  244 +
  245 +Images can also be referenced with links:
  246 +[![Linked Image](https://via.placeholder.com/100 "Thumbnail")](https://via.placeholder.com/500 "Full Image")
128 247
129 -Markdown and LaTeX can be powerful tools for formatting text and mathematical expressions in your Flutter app. If you have any questions or need further assistance, feel free to ask! 248 +---
  249 +
  250 +## Footnotes
  251 +
  252 +Here is a statement with a footnote.[^1] Another reference can be added here.[^long]
  253 +
  254 +[^1]: This is a simple footnote.
  255 +[^long]: This footnote contains a longer explanation to showcase how multiple lines can be formatted in a footnote. It supports Markdown formatting such as **bold** and *italic* text.
  256 +
  257 +---
  258 +
  259 +## Horizontal Rules and Miscellaneous
  260 +
  261 +Horizontal rules can be used to separate sections:
  262 +
  263 +---
  264 +
  265 +### Task List Example
  266 +- [x] Write complex Markdown document
  267 +- [x] Include LaTeX math expressions
  268 +- [ ] Add more Markdown components if needed
  269 +
  270 +### Nested Quotes with Code and Math
  271 +> **Example of Nested Components**
  272 +>
  273 +> - Inline code: `sum = a + b`
  274 +> - Math expression: \( \sum_{i=1}^n i = \frac{n(n+1)}{2} \)
  275 +> - More text with **bold** formatting.
  276 +>
  277 +> ```javascript
  278 +> // JavaScript code example inside a nested blockquote
  279 +> const sum = (n) => (n * (n + 1)) / 2;
  280 +> console.log(sum(10));
  281 +> ```
  282 +
  283 +---
  284 +
  285 +## Conclusion
  286 +
  287 +This document was created to test the robustness of Markdown parsers and to ensure that all components, including advanced LaTeX expressions and nested structures, are rendered correctly. Enjoy testing and feel free to extend it further!
  288 +```
130 ''', 289 ''',
131 ); 290 );
132 File? file; 291 File? file;
@@ -95,15 +95,15 @@ class GptMarkdown extends StatelessWidget { @@ -95,15 +95,15 @@ class GptMarkdown extends StatelessWidget {
95 final UnOrderedListBuilder? unOrderedListBuilder; 95 final UnOrderedListBuilder? unOrderedListBuilder;
96 96
97 /// A method to remove extra lines inside block LaTeX. 97 /// A method to remove extra lines inside block LaTeX.
98 - String _removeExtraLinesInsideBlockLatex(String text) {  
99 - return text.replaceAllMapped(  
100 - RegExp(r"\\\[(.*?)\\\]", multiLine: true, dotAll: true),  
101 - (match) {  
102 - String content = match[0] ?? "";  
103 - return content.replaceAllMapped(RegExp(r"\n[\n\ ]+"), (match) => "\n");  
104 - },  
105 - );  
106 - } 98 + // String _removeExtraLinesInsideBlockLatex(String text) {
  99 + // return text.replaceAllMapped(
  100 + // RegExp(r"\\\[(.*?)\\\]", multiLine: true, dotAll: true),
  101 + // (match) {
  102 + // String content = match[0] ?? "";
  103 + // return content.replaceAllMapped(RegExp(r"\n[\n\ ]+"), (match) => "\n");
  104 + // },
  105 + // );
  106 + // }
107 107
108 @override 108 @override
109 Widget build(BuildContext context) { 109 Widget build(BuildContext context) {
@@ -124,7 +124,7 @@ class GptMarkdown extends StatelessWidget { @@ -124,7 +124,7 @@ class GptMarkdown extends StatelessWidget {
124 }, 124 },
125 ); 125 );
126 } 126 }
127 - tex = _removeExtraLinesInsideBlockLatex(tex); 127 + // tex = _removeExtraLinesInsideBlockLatex(tex);
128 return ClipRRect( 128 return ClipRRect(
129 child: MdWidget( 129 child: MdWidget(
130 tex, 130 tex,
@@ -2,7 +2,7 @@ part of 'gpt_markdown.dart'; @@ -2,7 +2,7 @@ part of 'gpt_markdown.dart';
2 2
3 /// Markdown components 3 /// Markdown components
4 abstract class MarkdownComponent { 4 abstract class MarkdownComponent {
5 - static final List<MarkdownComponent> components = [ 5 + static List<MarkdownComponent> get components => [
6 CodeBlockMd(), 6 CodeBlockMd(),
7 NewLines(), 7 NewLines(),
8 BlockQuote(), 8 BlockQuote(),
@@ -25,7 +25,7 @@ abstract class MarkdownComponent { @@ -25,7 +25,7 @@ abstract class MarkdownComponent {
25 IndentMd(), 25 IndentMd(),
26 ]; 26 ];
27 27
28 - static final List<MarkdownComponent> inlineComponents = [ 28 + static List<MarkdownComponent> get inlineComponents => [
29 ImageMd(), 29 ImageMd(),
30 ATagMd(), 30 ATagMd(),
31 TableMd(), 31 TableMd(),
@@ -68,29 +68,7 @@ abstract class MarkdownComponent { @@ -68,29 +68,7 @@ abstract class MarkdownComponent {
68 dotAll: each.exp.isDotAll, 68 dotAll: each.exp.isDotAll,
69 ); 69 );
70 if (exp.hasMatch(element)) { 70 if (exp.hasMatch(element)) {
71 - if (each.inline) {  
72 - spans.add(each.span(context, element, config));  
73 - } else {  
74 - spans.addAll([  
75 - TextSpan(  
76 - text: "\n ",  
77 - style: TextStyle(  
78 - fontSize: 0,  
79 - height: 0,  
80 - color: config.style?.color,  
81 - ),  
82 - ),  
83 - each.span(context, element, config),  
84 - TextSpan(  
85 - text: "\n ",  
86 - style: TextStyle(  
87 - fontSize: 0,  
88 - height: 0,  
89 - color: config.style?.color,  
90 - ),  
91 - ),  
92 - ]);  
93 - } 71 + spans.add(each.span(context, element, config));
94 return ""; 72 return "";
95 } 73 }
96 } 74 }
@@ -156,7 +134,12 @@ abstract class BlockMd extends MarkdownComponent { @@ -156,7 +134,12 @@ abstract class BlockMd extends MarkdownComponent {
156 child: child, 134 child: child,
157 ); 135 );
158 } 136 }
159 - return WidgetSpan(child: child, alignment: PlaceholderAlignment.middle); 137 + child = Row(children: [Expanded(child: child)]);
  138 + return WidgetSpan(
  139 + child: child,
  140 + alignment: PlaceholderAlignment.baseline,
  141 + baseline: TextBaseline.alphabetic,
  142 + );
160 } 143 }
161 144
162 Widget build( 145 Widget build(
@@ -293,7 +276,7 @@ class HrLine extends BlockMd { @@ -293,7 +276,7 @@ class HrLine extends BlockMd {
293 /// Checkbox component 276 /// Checkbox component
294 class CheckBoxMd extends BlockMd { 277 class CheckBoxMd extends BlockMd {
295 @override 278 @override
296 - String get expString => (r"\[(\x?)\]\ (\S[^\n]*?)$"); 279 + String get expString => (r"\[((?:\x|\ ))\]\ (\S[^\n]*?)$");
297 get onLinkTab => null; 280 get onLinkTab => null;
298 281
299 @override 282 @override
@@ -314,7 +297,7 @@ class CheckBoxMd extends BlockMd { @@ -314,7 +297,7 @@ class CheckBoxMd extends BlockMd {
314 /// Radio Button component 297 /// Radio Button component
315 class RadioButtonMd extends BlockMd { 298 class RadioButtonMd extends BlockMd {
316 @override 299 @override
317 - String get expString => (r"\((\x?)\)\ (\S[^\n]*)$"); 300 + String get expString => (r"\(((?:\x|\ ))\)\ (\S[^\n]*)$");
318 get onLinkTab => null; 301 get onLinkTab => null;
319 302
320 @override 303 @override
@@ -390,7 +373,7 @@ class UnOrderedList extends BlockMd { @@ -390,7 +373,7 @@ class UnOrderedList extends BlockMd {
390 ) { 373 ) {
391 var match = this.exp.firstMatch(text); 374 var match = this.exp.firstMatch(text);
392 375
393 - var child = MdWidget("${match?[1]?.trim()}", false, config: config); 376 + var child = MdWidget("${match?[1]?.trim()}", true, config: config);
394 377
395 return config.unOrderedListBuilder?.call( 378 return config.unOrderedListBuilder?.call(
396 context, 379 context,
@@ -428,7 +411,7 @@ class OrderedList extends BlockMd { @@ -428,7 +411,7 @@ class OrderedList extends BlockMd {
428 411
429 var no = "${match?[1]}"; 412 var no = "${match?[1]}";
430 413
431 - var child = MdWidget("${match?[2]?.trim()}", false, config: config); 414 + var child = MdWidget("${match?[2]?.trim()}", true, config: config);
432 return config.orderedListBuilder?.call( 415 return config.orderedListBuilder?.call(
433 context, 416 context,
434 no, 417 no,
@@ -582,7 +565,8 @@ class ItalicMd extends InlineMd { @@ -582,7 +565,8 @@ class ItalicMd extends InlineMd {
582 565
583 class LatexMathMultiLine extends BlockMd { 566 class LatexMathMultiLine extends BlockMd {
584 @override 567 @override
585 - String get expString => (r"\\\[(((?!\n\n).)*?)\\\]|(\\begin.*?\\end{.*?})"); 568 + String get expString => (r"\ *\\\[((?:.)*?)\\\]|(\ *\\begin.*?\\end{.*?})");
  569 + // (r"\ *\\\[((?:(?!\n\n\n).)*?)\\\]|(\\begin.*?\\end{.*?})");
586 @override 570 @override
587 RegExp get exp => RegExp(expString, dotAll: true, multiLine: true); 571 RegExp get exp => RegExp(expString, dotAll: true, multiLine: true);
588 572
@@ -593,7 +577,7 @@ class LatexMathMultiLine extends BlockMd { @@ -593,7 +577,7 @@ class LatexMathMultiLine extends BlockMd {
593 final GptMarkdownConfig config, 577 final GptMarkdownConfig config,
594 ) { 578 ) {
595 var p0 = exp.firstMatch(text.trim()); 579 var p0 = exp.firstMatch(text.trim());
596 - String mathText = p0?[1] ?? p0?[2] ?? ""; 580 + String mathText = p0?[1] ?? p0?[2] ?? '';
597 var workaround = config.latexWorkaround ?? (String tex) => tex; 581 var workaround = config.latexWorkaround ?? (String tex) => tex;
598 582
599 var builder = 583 var builder =
@@ -20,24 +20,21 @@ class MdWidget extends StatelessWidget { @@ -20,24 +20,21 @@ class MdWidget extends StatelessWidget {
20 20
21 @override 21 @override
22 Widget build(BuildContext context) { 22 Widget build(BuildContext context) {
23 - List<InlineSpan> list = [];  
24 - list.addAll(  
25 - MarkdownComponent.generate(  
26 - context,  
27 - exp,  
28 - // .replaceAllMapped(  
29 - // RegExp(  
30 - // r"\\\[(.*?)\\\]|(\\begin.*?\\end{.*?})",  
31 - // multiLine: true,  
32 - // dotAll: true,  
33 - // ), (match) {  
34 - // //  
35 - // String body = (match[1] ?? match[2])?.replaceAll("\n", " ") ?? "";  
36 - // return "\\[$body\\]";  
37 - // }),  
38 - config,  
39 - includeGlobalComponents,  
40 - ), 23 + List<InlineSpan> list = MarkdownComponent.generate(
  24 + context,
  25 + exp,
  26 + // .replaceAllMapped(
  27 + // RegExp(
  28 + // r"\\\[(.*?)\\\]|(\\begin.*?\\end{.*?})",
  29 + // multiLine: true,
  30 + // dotAll: true,
  31 + // ), (match) {
  32 + // //
  33 + // String body = (match[1] ?? match[2])?.replaceAll("\n", " ") ?? "";
  34 + // return "\\[$body\\]";
  35 + // }),
  36 + config,
  37 + includeGlobalComponents,
41 ); 38 );
42 return config.getRich( 39 return config.getRich(
43 TextSpan(children: list, style: config.style?.copyWith()), 40 TextSpan(children: list, style: config.style?.copyWith()),