Skip to content

Commit af8ff20

Browse files
Kurogoma4DTecHaxter
authored andcommitted
[flutter_markdown] Ensure customize nested bullet list style. (flutter#6384)
See flutter/flutter#145670 .
1 parent bad79d1 commit af8ff20

File tree

7 files changed

+186
-6
lines changed

7 files changed

+186
-6
lines changed

packages/flutter_markdown/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.7.0
2+
3+
* **BREAKING CHANGES**:
4+
* Replaces parameters at `bulletBuilder` with `MarkdownBulletParameters`.
5+
* Introduces a new parameter `nestLevel` that exposes the bullet item's nesting level.
6+
17
## 0.6.23
28

39
* Gracefully handle image dimension parsing failures.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// TODO(goderbauer): Restructure the examples to avoid this ignore, https://github.com/flutter/flutter/issues/110208.
6+
// ignore_for_file: avoid_implementing_value_types
7+
8+
import 'package:flutter/material.dart';
9+
import 'package:flutter_markdown/flutter_markdown.dart';
10+
import '../shared/markdown_demo_widget.dart';
11+
12+
// ignore_for_file: public_member_api_docs
13+
14+
const String _markdownData = '''
15+
# Custom Ordered List Demo
16+
17+
## Unordered List
18+
19+
- first
20+
- second
21+
- first
22+
- first
23+
- second
24+
- first
25+
- second
26+
27+
## Ordered List
28+
29+
1. first
30+
2. second
31+
1. first
32+
1. first
33+
2. second
34+
1. first
35+
1. second
36+
''';
37+
38+
const String _notes = '''
39+
# Custom Bullet List Demo
40+
---
41+
42+
## Overview
43+
44+
This is the custom bullet list demo. This demo shows how to customize the bullet list style.
45+
This demo example is being preserved for reference purposes.
46+
''';
47+
48+
class CustomBulletListDemo extends StatelessWidget
49+
implements MarkdownDemoWidget {
50+
const CustomBulletListDemo({super.key});
51+
52+
static const String _title = 'Custom Bullet List Demo';
53+
54+
@override
55+
String get title => CustomBulletListDemo._title;
56+
57+
@override
58+
String get description => 'Shows how to customize the bullet list style.';
59+
60+
@override
61+
Future<String> get data => Future<String>.value(_markdownData);
62+
63+
@override
64+
Future<String> get notes => Future<String>.value(_notes);
65+
66+
@override
67+
Widget build(BuildContext context) {
68+
return Scaffold(
69+
body: SafeArea(
70+
child: Markdown(
71+
data: _markdownData,
72+
bulletBuilder: (MarkdownBulletParameters parameters) => FittedBox(
73+
fit: BoxFit.scaleDown,
74+
child: switch (parameters.style) {
75+
BulletStyle.unorderedList => const Text('・'),
76+
BulletStyle.orderedList =>
77+
Text('${parameters.nestLevel}-${parameters.index + 1}.'),
78+
},
79+
),
80+
),
81+
),
82+
);
83+
}
84+
}

packages/flutter_markdown/example/lib/screens/home_screen.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:flutter/material.dart';
66
import '../demos/basic_markdown_demo.dart';
77
import '../demos/centered_header_demo.dart';
8+
import '../demos/custom_bullet_list_demo.dart';
89
import '../demos/extended_emoji_demo.dart';
910
import '../demos/markdown_body_shrink_wrap_demo.dart';
1011
import '../demos/minimal_markdown_demo.dart';
@@ -30,6 +31,7 @@ class HomeScreen extends StatelessWidget {
3031
OriginalMarkdownDemo(),
3132
const CenteredHeaderDemo(),
3233
const MarkdownBodyShrinkWrapDemo(),
34+
const CustomBulletListDemo(),
3335
];
3436

3537
@override

packages/flutter_markdown/lib/src/builder.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,15 @@ class MarkdownBuilder implements md.NodeVisitor {
611611
if (bulletBuilder != null) {
612612
return Padding(
613613
padding: styleSheet.listBulletPadding!,
614-
child: bulletBuilder!(index,
615-
isUnordered ? BulletStyle.unorderedList : BulletStyle.orderedList),
614+
child: bulletBuilder!(
615+
MarkdownBulletParameters(
616+
index: index,
617+
style: isUnordered
618+
? BulletStyle.unorderedList
619+
: BulletStyle.orderedList,
620+
nestLevel: _listIndents.length - 1,
621+
),
622+
),
616623
);
617624
}
618625

packages/flutter_markdown/lib/src/widget.dart

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,30 @@ typedef MarkdownCheckboxBuilder = Widget Function(bool value);
4646
/// Signature for custom bullet widget.
4747
///
4848
/// Used by [MarkdownWidget.bulletBuilder]
49-
typedef MarkdownBulletBuilder = Widget Function(int index, BulletStyle style);
49+
typedef MarkdownBulletBuilder = Widget Function(
50+
MarkdownBulletParameters parameters,
51+
);
52+
53+
/// An parameters of [MarkdownBulletBuilder].
54+
///
55+
/// Used by [MarkdownWidget.bulletBuilder]
56+
class MarkdownBulletParameters {
57+
/// Creates a new instance of [MarkdownBulletParameters].
58+
const MarkdownBulletParameters({
59+
required this.index,
60+
required this.style,
61+
required this.nestLevel,
62+
});
63+
64+
/// The index of the bullet on that nesting level.
65+
final int index;
66+
67+
/// The style of the bullet.
68+
final BulletStyle style;
69+
70+
/// The nest level of the bullet.
71+
final int nestLevel;
72+
}
5073

5174
/// Enumeration sent to the user when calling [MarkdownBulletBuilder]
5275
///

packages/flutter_markdown/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
44
formatted with simple Markdown tags.
55
repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
66
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
7-
version: 0.6.23
7+
version: 0.7.0
88

99
environment:
1010
sdk: ^3.3.0

packages/flutter_markdown/test/list_test.dart

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,35 @@ void defineTests() {
9494
]);
9595
},
9696
);
97+
98+
testWidgets('custom bullet builder', (WidgetTester tester) async {
99+
const String data =
100+
'* Item 1\n * Item 2\n * Item 3\n * Item 4\n* Item 5';
101+
Widget builder(MarkdownBulletParameters parameters) => Text(
102+
'${parameters.index} ${parameters.style == BulletStyle.orderedList ? 'ordered' : 'unordered'} ${parameters.nestLevel}',
103+
);
104+
105+
await tester.pumpWidget(
106+
boilerplate(
107+
Markdown(data: data, bulletBuilder: builder),
108+
),
109+
);
110+
111+
final Iterable<Widget> widgets = tester.allWidgets;
112+
113+
expectTextStrings(widgets, <String>[
114+
'0 unordered 0',
115+
'Item 1',
116+
'0 unordered 1',
117+
'Item 2',
118+
'0 unordered 2',
119+
'Item 3',
120+
'1 unordered 1',
121+
'Item 4',
122+
'1 unordered 0',
123+
'Item 5',
124+
]);
125+
});
97126
});
98127

99128
group('Ordered List', () {
@@ -135,6 +164,35 @@ void defineTests() {
135164
final Iterable<Widget> widgets = tester.allWidgets;
136165
expectTextStrings(widgets, <String>['1.', 'one', 'two']);
137166
});
167+
168+
testWidgets('custom bullet builder', (WidgetTester tester) async {
169+
const String data =
170+
'1. Item 1\n 1. Item 2\n 1. Item 3\n 1. Item 4\n1. Item 5';
171+
Widget builder(MarkdownBulletParameters parameters) => Text(
172+
'${parameters.index} ${parameters.style == BulletStyle.orderedList ? 'ordered' : 'unordered'} ${parameters.nestLevel}',
173+
);
174+
175+
await tester.pumpWidget(
176+
boilerplate(
177+
Markdown(data: data, bulletBuilder: builder),
178+
),
179+
);
180+
181+
final Iterable<Widget> widgets = tester.allWidgets;
182+
183+
expectTextStrings(widgets, <String>[
184+
'0 ordered 0',
185+
'Item 1',
186+
'0 ordered 1',
187+
'Item 2',
188+
'0 ordered 2',
189+
'Item 3',
190+
'1 ordered 1',
191+
'Item 4',
192+
'1 ordered 0',
193+
'Item 5',
194+
]);
195+
});
138196
});
139197

140198
group('Task List', () {
@@ -161,8 +219,8 @@ void defineTests() {
161219

162220
testWidgets('custom bullet builder', (WidgetTester tester) async {
163221
const String data = '* Item 1\n* Item 2\n1) Item 3\n2) Item 4';
164-
Widget builder(int index, BulletStyle style) => Text(
165-
'$index ${style == BulletStyle.orderedList ? 'ordered' : 'unordered'}');
222+
Widget builder(MarkdownBulletParameters parameters) => Text(
223+
'${parameters.index} ${parameters.style == BulletStyle.orderedList ? 'ordered' : 'unordered'}');
166224

167225
await tester.pumpWidget(
168226
boilerplate(

0 commit comments

Comments
 (0)