[flutter_markdown] Fix shrinkWrap not taken into account with single child (#2195)

diff --git a/packages/flutter_markdown/CHANGELOG.md b/packages/flutter_markdown/CHANGELOG.md
index 1b31a06..091ab1e 100644
--- a/packages/flutter_markdown/CHANGELOG.md
+++ b/packages/flutter_markdown/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.10+3
+
+* Fixes shrinkWrap not taken into account with single child ([flutter/flutter#105299](https://github.com/flutter/flutter/issues/105299)).
+
 ## 0.6.10+2
 
 * Migrates from `ui.hash*` to `Object.hash*`.
diff --git a/packages/flutter_markdown/example/lib/demos/markdown_body_shrink_wrap_demo.dart b/packages/flutter_markdown/example/lib/demos/markdown_body_shrink_wrap_demo.dart
new file mode 100644
index 0000000..97c3daa
--- /dev/null
+++ b/packages/flutter_markdown/example/lib/demos/markdown_body_shrink_wrap_demo.dart
@@ -0,0 +1,104 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_markdown/flutter_markdown.dart';
+import '../shared/dropdown_menu.dart';
+import '../shared/markdown_demo_widget.dart';
+
+// ignore_for_file: public_member_api_docs
+
+const String _data = '''
+**MarkdownBody**
+''';
+
+const String _notes = '''
+# Shrink wrap demo 
+---
+
+## Overview
+
+This example demonstrates how `MarkdownBody`'s `shrinkWrap` property works.
+
+- If `shrinkWrap` is `true`, `MarkdownBody` will take the minimum height that 
+  wraps its content.
+- If `shrinkWrap` is `false`, `MarkdownBody` will expand to the maximum allowed 
+  height.
+''';
+
+class MarkdownBodyShrinkWrapDemo extends StatefulWidget
+    implements MarkdownDemoWidget {
+  const MarkdownBodyShrinkWrapDemo({Key? key}) : super(key: key);
+
+  static const String _title = 'Shrink wrap demo';
+
+  @override
+  String get title => MarkdownBodyShrinkWrapDemo._title;
+
+  @override
+  String get description => "This example demonstrates how MarkdownBody's "
+      'shrinkWrap property works.';
+
+  @override
+  Future<String> get data => Future<String>.value(_data);
+
+  @override
+  Future<String> get notes => Future<String>.value(_notes);
+
+  @override
+  State<MarkdownBodyShrinkWrapDemo> createState() =>
+      _MarkdownBodyShrinkWrapDemoState();
+}
+
+class _MarkdownBodyShrinkWrapDemoState
+    extends State<MarkdownBodyShrinkWrapDemo> {
+  bool _shrinkWrap = true;
+
+  final Map<String, bool> _shrinkWrapMenuItems = <String, bool>{
+    'true': true,
+    'false': false,
+  };
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: <Widget>[
+        DropdownMenu<bool>(
+          items: _shrinkWrapMenuItems,
+          label: 'Shrink wrap:',
+          initialValue: _shrinkWrap,
+          onChanged: (bool? value) {
+            if (value != _shrinkWrap) {
+              setState(() {
+                _shrinkWrap = value!;
+              });
+            }
+          },
+        ),
+        Expanded(
+          child: Stack(
+            children: <Widget>[
+              Align(
+                alignment: Alignment.bottomCenter,
+                child: Container(
+                  decoration: BoxDecoration(
+                    color: Colors.grey.withOpacity(0.5),
+                    border: Border.all(
+                      color: Colors.red,
+                      width: 2,
+                    ),
+                  ),
+                  child: MarkdownBody(
+                    data: _data,
+                    shrinkWrap: _shrinkWrap,
+                  ),
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/packages/flutter_markdown/example/lib/screens/home_screen.dart b/packages/flutter_markdown/example/lib/screens/home_screen.dart
index 5d32544..df17ab0 100644
--- a/packages/flutter_markdown/example/lib/screens/home_screen.dart
+++ b/packages/flutter_markdown/example/lib/screens/home_screen.dart
@@ -6,6 +6,7 @@
 import '../demos/basic_markdown_demo.dart';
 import '../demos/centered_header_demo.dart';
 import '../demos/extended_emoji_demo.dart';
+import '../demos/markdown_body_shrink_wrap_demo.dart';
 import '../demos/minimal_markdown_demo.dart';
 import '../demos/original_demo.dart';
 import '../demos/subscript_syntax_demo.dart';
@@ -28,6 +29,7 @@
     const ExtendedEmojiDemo(),
     OriginalMarkdownDemo(),
     const CenteredHeaderDemo(),
+    const MarkdownBodyShrinkWrapDemo(),
   ];
 
   @override
diff --git a/packages/flutter_markdown/lib/src/builder.dart b/packages/flutter_markdown/lib/src/builder.dart
index 0f6b20e..fe7ab32 100644
--- a/packages/flutter_markdown/lib/src/builder.dart
+++ b/packages/flutter_markdown/lib/src/builder.dart
@@ -364,6 +364,7 @@
 
       if (current.children.isNotEmpty) {
         child = Column(
+          mainAxisSize: MainAxisSize.min,
           crossAxisAlignment: fitContent
               ? CrossAxisAlignment.start
               : CrossAxisAlignment.stretch,
diff --git a/packages/flutter_markdown/lib/src/widget.dart b/packages/flutter_markdown/lib/src/widget.dart
index 0e4ca00..6a0c28a 100644
--- a/packages/flutter_markdown/lib/src/widget.dart
+++ b/packages/flutter_markdown/lib/src/widget.dart
@@ -436,12 +436,14 @@
           softLineBreak: softLineBreak,
         );
 
-  /// See [ScrollView.shrinkWrap]
+  /// If [shrinkWrap] is `true`, [MarkdownBody] will take the minimum height
+  /// that wraps its content. Otherwise, [MarkdownBody] will expand to the
+  /// maximum allowed height.
   final bool shrinkWrap;
 
   @override
   Widget build(BuildContext context, List<Widget>? children) {
-    if (children!.length == 1) {
+    if (children!.length == 1 && shrinkWrap) {
       return children.single;
     }
     return Column(
diff --git a/packages/flutter_markdown/pubspec.yaml b/packages/flutter_markdown/pubspec.yaml
index 1e8634c..716fca4 100644
--- a/packages/flutter_markdown/pubspec.yaml
+++ b/packages/flutter_markdown/pubspec.yaml
@@ -4,7 +4,7 @@
   formatted with simple Markdown tags.
 repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
-version: 0.6.10+2
+version: 0.6.10+3
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/flutter_markdown/test/markdown_body_shrink_wrap_test.dart b/packages/flutter_markdown/test/markdown_body_shrink_wrap_test.dart
new file mode 100644
index 0000000..4cf2afc
--- /dev/null
+++ b/packages/flutter_markdown/test/markdown_body_shrink_wrap_test.dart
@@ -0,0 +1,73 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/widgets.dart';
+import 'package:flutter_markdown/flutter_markdown.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'utils.dart';
+
+void main() => defineTests();
+
+void defineTests() {
+  group('MarkdownBody shrinkWrap test', () {
+    testWidgets(
+      'Given a MarkdownBody with shrinkWrap=true '
+      'Then it wraps its content',
+      (WidgetTester tester) async {
+        await tester.pumpWidget(boilerplate(Stack(
+          children: const <Widget>[
+            Text('shrinkWrap=true'),
+            Align(
+              alignment: Alignment.bottomCenter,
+              child: MarkdownBody(
+                data: 'This is a [link](https://flutter.dev/)',
+                shrinkWrap: true,
+              ),
+            ),
+          ],
+        )));
+
+        final Rect stackRect = tester.getRect(find.byType(Stack));
+        final Rect textRect = tester.getRect(find.byType(Text));
+        final Rect markdownBodyRect = tester.getRect(find.byType(MarkdownBody));
+
+        // The Text should be on the top of the Stack
+        expect(textRect.top, equals(stackRect.top));
+        expect(textRect.bottom, lessThan(stackRect.bottom));
+        // The MarkdownBody should be on the bottom of the Stack
+        expect(markdownBodyRect.top, greaterThan(stackRect.top));
+        expect(markdownBodyRect.bottom, equals(stackRect.bottom));
+      },
+    );
+    testWidgets(
+      'Given a MarkdownBody with shrinkWrap=false '
+      'Then it expands to the maximum allowed height',
+      (WidgetTester tester) async {
+        await tester.pumpWidget(boilerplate(Stack(
+          children: const <Widget>[
+            Text('shrinkWrap=false test'),
+            Align(
+              alignment: Alignment.bottomCenter,
+              child: MarkdownBody(
+                data: 'This is a [link](https://flutter.dev/)',
+                shrinkWrap: false,
+              ),
+            ),
+          ],
+        )));
+
+        final Rect stackRect = tester.getRect(find.byType(Stack));
+        final Rect textRect = tester.getRect(find.byType(Text));
+        final Rect markdownBodyRect = tester.getRect(find.byType(MarkdownBody));
+
+        // The Text should be on the top of the Stack
+        expect(textRect.top, equals(stackRect.top));
+        expect(textRect.bottom, lessThan(stackRect.bottom));
+        // The MarkdownBody should take all Stack's height
+        expect(markdownBodyRect.top, equals(stackRect.top));
+        expect(markdownBodyRect.bottom, equals(stackRect.bottom));
+      },
+    );
+  });
+}