mirror of
https://github.com/flutter/packages.git
synced 2025-07-02 08:34:31 +08:00
Enforce flutter formatting (#349)
This commit is contained in:
@ -31,4 +31,5 @@ jobs:
|
||||
with:
|
||||
channel: ${{ matrix.flutter_version }}
|
||||
- run: flutter analyze
|
||||
- run: flutter format --dry-run --set-exit-if-changed .
|
||||
- run: flutter test
|
||||
|
@ -64,7 +64,8 @@ final MarkdownStyleSheet Function(BuildContext, MarkdownStyleSheetBaseTheme?)
|
||||
);
|
||||
};
|
||||
|
||||
Widget _handleDataSchemeUri(Uri uri, final double? width, final double? height) {
|
||||
Widget _handleDataSchemeUri(
|
||||
Uri uri, final double? width, final double? height) {
|
||||
final String mimeType = uri.data!.mimeType;
|
||||
if (mimeType.startsWith('image/')) {
|
||||
return Image.memory(
|
||||
|
@ -10,7 +10,25 @@ import '_functions_io.dart' if (dart.library.html) '_functions_web.dart';
|
||||
import 'style_sheet.dart';
|
||||
import 'widget.dart';
|
||||
|
||||
const List<String> _kBlockTags = const <String>['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'blockquote', 'pre', 'ol', 'ul', 'hr', 'table', 'thead', 'tbody', 'tr'];
|
||||
const List<String> _kBlockTags = const <String>[
|
||||
'p',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'li',
|
||||
'blockquote',
|
||||
'pre',
|
||||
'ol',
|
||||
'ul',
|
||||
'hr',
|
||||
'table',
|
||||
'thead',
|
||||
'tbody',
|
||||
'tr'
|
||||
];
|
||||
|
||||
const List<String> _kListTags = const <String>['ul', 'ol'];
|
||||
|
||||
@ -174,14 +192,16 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
_addAnonymousBlockIfNeeded();
|
||||
if (_isListTag(tag)) {
|
||||
_listIndents.add(tag);
|
||||
if (element.attributes["start"] != null) start = int.parse(element.attributes["start"]!) - 1;
|
||||
if (element.attributes["start"] != null)
|
||||
start = int.parse(element.attributes["start"]!) - 1;
|
||||
} else if (tag == 'blockquote') {
|
||||
_isInBlockquote = true;
|
||||
} else if (tag == 'table') {
|
||||
_tables.add(_TableElement());
|
||||
} else if (tag == 'tr') {
|
||||
final length = _tables.single.rows.length;
|
||||
BoxDecoration? decoration = styleSheet.tableCellsDecoration as BoxDecoration?;
|
||||
BoxDecoration? decoration =
|
||||
styleSheet.tableCellsDecoration as BoxDecoration?;
|
||||
if (length == 0 || length % 2 == 1) decoration = null;
|
||||
_tables.single.rows.add(TableRow(
|
||||
decoration: decoration,
|
||||
@ -211,7 +231,9 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
// The Markdown parser passes empty table data tags for blank
|
||||
// table cells. Insert a text node with an empty string in this
|
||||
// case for the table cell to get properly created.
|
||||
if (element.tag == 'td' && element.children != null && element.children!.isEmpty) {
|
||||
if (element.tag == 'td' &&
|
||||
element.children != null &&
|
||||
element.children!.isEmpty) {
|
||||
element.children!.add(md.Text(''));
|
||||
}
|
||||
|
||||
@ -226,7 +248,13 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
}
|
||||
|
||||
String? extractTextFromElement(element) {
|
||||
return element is md.Element && (element.children?.isNotEmpty ?? false) ? element.children!.map((e) => e is md.Text ? e.text : extractTextFromElement(e)).join("") : ((element.attributes?.isNotEmpty ?? false) ? element.attributes["alt"] : "");
|
||||
return element is md.Element && (element.children?.isNotEmpty ?? false)
|
||||
? element.children!
|
||||
.map((e) => e is md.Text ? e.text : extractTextFromElement(e))
|
||||
.join("")
|
||||
: ((element.attributes?.isNotEmpty ?? false)
|
||||
? element.attributes["alt"]
|
||||
: "");
|
||||
}
|
||||
|
||||
@override
|
||||
@ -262,7 +290,8 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
|
||||
Widget? child;
|
||||
if (_blocks.isNotEmpty && builders.containsKey(_blocks.last.tag)) {
|
||||
child = builders[_blocks.last.tag!]!.visitText(text, styleSheet.styles[_blocks.last.tag!]);
|
||||
child = builders[_blocks.last.tag!]!
|
||||
.visitText(text, styleSheet.styles[_blocks.last.tag!]);
|
||||
} else if (_blocks.last.tag == 'pre') {
|
||||
child = Scrollbar(
|
||||
child: SingleChildScrollView(
|
||||
@ -274,7 +303,9 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
} else {
|
||||
child = _buildRichText(
|
||||
TextSpan(
|
||||
style: _isInBlockquote ? styleSheet.blockquote!.merge(_inlines.last.style) : _inlines.last.style,
|
||||
style: _isInBlockquote
|
||||
? styleSheet.blockquote!.merge(_inlines.last.style)
|
||||
: _inlines.last.style,
|
||||
text: _isInBlockquote ? text.text : trimText(text.text),
|
||||
recognizer: _linkHandlers.isNotEmpty ? _linkHandlers.last : null,
|
||||
),
|
||||
@ -298,7 +329,9 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
|
||||
if (current.children.isNotEmpty) {
|
||||
child = Column(
|
||||
crossAxisAlignment: fitContent ? CrossAxisAlignment.start : CrossAxisAlignment.stretch,
|
||||
crossAxisAlignment: fitContent
|
||||
? CrossAxisAlignment.start
|
||||
: CrossAxisAlignment.stretch,
|
||||
children: current.children,
|
||||
);
|
||||
} else {
|
||||
@ -322,11 +355,19 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
bullet = _buildBullet(_listIndents.last);
|
||||
}
|
||||
child = Row(
|
||||
textBaseline: listItemCrossAxisAlignment == MarkdownListItemCrossAxisAlignment.start ? null : TextBaseline.alphabetic,
|
||||
crossAxisAlignment: listItemCrossAxisAlignment == MarkdownListItemCrossAxisAlignment.start ? CrossAxisAlignment.start : CrossAxisAlignment.baseline,
|
||||
textBaseline: listItemCrossAxisAlignment ==
|
||||
MarkdownListItemCrossAxisAlignment.start
|
||||
? null
|
||||
: TextBaseline.alphabetic,
|
||||
crossAxisAlignment: listItemCrossAxisAlignment ==
|
||||
MarkdownListItemCrossAxisAlignment.start
|
||||
? CrossAxisAlignment.start
|
||||
: CrossAxisAlignment.baseline,
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: styleSheet.listIndent! + styleSheet.listBulletPadding!.left + styleSheet.listBulletPadding!.right,
|
||||
width: styleSheet.listIndent! +
|
||||
styleSheet.listBulletPadding!.left +
|
||||
styleSheet.listBulletPadding!.right,
|
||||
child: bullet,
|
||||
),
|
||||
Expanded(child: child)
|
||||
@ -364,7 +405,8 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
final _InlineElement parent = _inlines.last;
|
||||
|
||||
if (builders.containsKey(tag)) {
|
||||
final Widget? child = builders[tag]!.visitElementAfter(element, styleSheet.styles[tag]);
|
||||
final Widget? child =
|
||||
builders[tag]!.visitElementAfter(element, styleSheet.styles[tag]);
|
||||
if (child != null) current.children[0] = child;
|
||||
} else if (tag == 'img') {
|
||||
// create an image widget for this image
|
||||
@ -436,7 +478,8 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
}
|
||||
|
||||
if (_linkHandlers.isNotEmpty) {
|
||||
TapGestureRecognizer recognizer = _linkHandlers.last as TapGestureRecognizer;
|
||||
TapGestureRecognizer recognizer =
|
||||
_linkHandlers.last as TapGestureRecognizer;
|
||||
return GestureDetector(child: child, onTap: recognizer.onTap);
|
||||
} else {
|
||||
return child;
|
||||
@ -464,7 +507,8 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
if (bulletBuilder != null) {
|
||||
return Padding(
|
||||
padding: styleSheet.listBulletPadding!,
|
||||
child: bulletBuilder!(index, isUnordered ? BulletStyle.unorderedList : BulletStyle.orderedList),
|
||||
child: bulletBuilder!(index,
|
||||
isUnordered ? BulletStyle.unorderedList : BulletStyle.orderedList),
|
||||
);
|
||||
}
|
||||
|
||||
@ -553,20 +597,28 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
) {
|
||||
List<Widget> mergedTexts = <Widget>[];
|
||||
for (Widget child in children) {
|
||||
if (mergedTexts.isNotEmpty && mergedTexts.last is RichText && child is RichText) {
|
||||
if (mergedTexts.isNotEmpty &&
|
||||
mergedTexts.last is RichText &&
|
||||
child is RichText) {
|
||||
RichText previous = mergedTexts.removeLast() as RichText;
|
||||
TextSpan previousTextSpan = previous.text as TextSpan;
|
||||
List<TextSpan> children = previousTextSpan.children != null ? List.from(previousTextSpan.children!) : [previousTextSpan];
|
||||
List<TextSpan> children = previousTextSpan.children != null
|
||||
? List.from(previousTextSpan.children!)
|
||||
: [previousTextSpan];
|
||||
children.add(child.text as TextSpan);
|
||||
TextSpan? mergedSpan = _mergeSimilarTextSpans(children);
|
||||
mergedTexts.add(_buildRichText(
|
||||
mergedSpan,
|
||||
textAlign: textAlign,
|
||||
));
|
||||
} else if (mergedTexts.isNotEmpty && mergedTexts.last is SelectableText && child is SelectableText) {
|
||||
} else if (mergedTexts.isNotEmpty &&
|
||||
mergedTexts.last is SelectableText &&
|
||||
child is SelectableText) {
|
||||
SelectableText previous = mergedTexts.removeLast() as SelectableText;
|
||||
TextSpan previousTextSpan = previous.textSpan!;
|
||||
List<TextSpan> children = previousTextSpan.children != null ? List.from(previousTextSpan.children!) : [previousTextSpan];
|
||||
List<TextSpan> children = previousTextSpan.children != null
|
||||
? List.from(previousTextSpan.children!)
|
||||
: [previousTextSpan];
|
||||
if (child.textSpan != null) {
|
||||
children.add(child.textSpan!);
|
||||
}
|
||||
@ -629,7 +681,10 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
|
||||
for (int index = 1; index < textSpans.length; index++) {
|
||||
TextSpan? nextChild = textSpans[index];
|
||||
if (nextChild is TextSpan && nextChild.recognizer == mergedSpans.last.recognizer && nextChild.semanticsLabel == mergedSpans.last.semanticsLabel && nextChild.style == mergedSpans.last.style) {
|
||||
if (nextChild is TextSpan &&
|
||||
nextChild.recognizer == mergedSpans.last.recognizer &&
|
||||
nextChild.semanticsLabel == mergedSpans.last.semanticsLabel &&
|
||||
nextChild.style == mergedSpans.last.style) {
|
||||
TextSpan previous = mergedSpans.removeLast();
|
||||
mergedSpans.add(TextSpan(
|
||||
text: previous.toPlainText() + nextChild.toPlainText(),
|
||||
@ -644,7 +699,9 @@ class MarkdownBuilder implements md.NodeVisitor {
|
||||
|
||||
// When the mergered spans compress into a single TextSpan return just that
|
||||
// TextSpan, otherwise bundle the set of TextSpans under a single parent.
|
||||
return mergedSpans.length == 1 ? mergedSpans.first : TextSpan(children: mergedSpans);
|
||||
return mergedSpans.length == 1
|
||||
? mergedSpans.first
|
||||
: TextSpan(children: mergedSpans);
|
||||
}
|
||||
|
||||
Widget _buildRichText(TextSpan? text, {TextAlign? textAlign}) {
|
||||
|
@ -74,7 +74,8 @@ abstract class MarkdownElementBuilder {
|
||||
/// to [preferredStyle].
|
||||
///
|
||||
/// If you needn't build a widget, return null.
|
||||
Widget? visitElementAfter(md.Element element, TextStyle? preferredStyle) => null;
|
||||
Widget? visitElementAfter(md.Element element, TextStyle? preferredStyle) =>
|
||||
null;
|
||||
}
|
||||
|
||||
/// Enum to specify which theme being used when creating [MarkdownStyleSheet]
|
||||
@ -151,7 +152,8 @@ abstract class MarkdownWidget extends StatefulWidget {
|
||||
this.bulletBuilder,
|
||||
this.builders = const {},
|
||||
this.fitContent = false,
|
||||
this.listItemCrossAxisAlignment = MarkdownListItemCrossAxisAlignment.baseline,
|
||||
this.listItemCrossAxisAlignment =
|
||||
MarkdownListItemCrossAxisAlignment.baseline,
|
||||
}) : super(key: key);
|
||||
|
||||
/// The Markdown to display.
|
||||
@ -238,7 +240,8 @@ abstract class MarkdownWidget extends StatefulWidget {
|
||||
_MarkdownWidgetState createState() => _MarkdownWidgetState();
|
||||
}
|
||||
|
||||
class _MarkdownWidgetState extends State<MarkdownWidget> implements MarkdownBuilderDelegate {
|
||||
class _MarkdownWidgetState extends State<MarkdownWidget>
|
||||
implements MarkdownBuilderDelegate {
|
||||
List<Widget>? _children;
|
||||
final List<GestureRecognizer> _recognizers = <GestureRecognizer>[];
|
||||
|
||||
@ -251,7 +254,8 @@ class _MarkdownWidgetState extends State<MarkdownWidget> implements MarkdownBuil
|
||||
@override
|
||||
void didUpdateWidget(MarkdownWidget oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.data != oldWidget.data || widget.styleSheet != oldWidget.styleSheet) {
|
||||
if (widget.data != oldWidget.data ||
|
||||
widget.styleSheet != oldWidget.styleSheet) {
|
||||
_parseMarkdown();
|
||||
}
|
||||
}
|
||||
@ -263,8 +267,10 @@ class _MarkdownWidgetState extends State<MarkdownWidget> implements MarkdownBuil
|
||||
}
|
||||
|
||||
void _parseMarkdown() {
|
||||
final MarkdownStyleSheet fallbackStyleSheet = kFallbackStyle(context, widget.styleSheetTheme);
|
||||
final MarkdownStyleSheet styleSheet = fallbackStyleSheet.merge(widget.styleSheet);
|
||||
final MarkdownStyleSheet fallbackStyleSheet =
|
||||
kFallbackStyle(context, widget.styleSheetTheme);
|
||||
final MarkdownStyleSheet styleSheet =
|
||||
fallbackStyleSheet.merge(widget.styleSheet);
|
||||
|
||||
_disposeRecognizers();
|
||||
|
||||
@ -300,7 +306,8 @@ class _MarkdownWidgetState extends State<MarkdownWidget> implements MarkdownBuil
|
||||
|
||||
void _disposeRecognizers() {
|
||||
if (_recognizers.isEmpty) return;
|
||||
final List<GestureRecognizer> localRecognizers = List<GestureRecognizer>.from(_recognizers);
|
||||
final List<GestureRecognizer> localRecognizers =
|
||||
List<GestureRecognizer>.from(_recognizers);
|
||||
_recognizers.clear();
|
||||
for (GestureRecognizer recognizer in localRecognizers) recognizer.dispose();
|
||||
}
|
||||
@ -358,7 +365,8 @@ class MarkdownBody extends MarkdownWidget {
|
||||
MarkdownCheckboxBuilder? checkboxBuilder,
|
||||
MarkdownBulletBuilder? bulletBuilder,
|
||||
Map<String, MarkdownElementBuilder> builders = const {},
|
||||
MarkdownListItemCrossAxisAlignment listItemCrossAxisAlignment = MarkdownListItemCrossAxisAlignment.baseline,
|
||||
MarkdownListItemCrossAxisAlignment listItemCrossAxisAlignment =
|
||||
MarkdownListItemCrossAxisAlignment.baseline,
|
||||
this.shrinkWrap = true,
|
||||
this.fitContent = true,
|
||||
}) : super(
|
||||
@ -392,7 +400,8 @@ class MarkdownBody extends MarkdownWidget {
|
||||
if (children!.length == 1) return children.single;
|
||||
return Column(
|
||||
mainAxisSize: shrinkWrap ? MainAxisSize.min : MainAxisSize.max,
|
||||
crossAxisAlignment: fitContent ? CrossAxisAlignment.start : CrossAxisAlignment.stretch,
|
||||
crossAxisAlignment:
|
||||
fitContent ? CrossAxisAlignment.start : CrossAxisAlignment.stretch,
|
||||
children: children,
|
||||
);
|
||||
}
|
||||
@ -426,7 +435,8 @@ class Markdown extends MarkdownWidget {
|
||||
MarkdownCheckboxBuilder? checkboxBuilder,
|
||||
MarkdownBulletBuilder? bulletBuilder,
|
||||
Map<String, MarkdownElementBuilder> builders = const {},
|
||||
MarkdownListItemCrossAxisAlignment listItemCrossAxisAlignment = MarkdownListItemCrossAxisAlignment.baseline,
|
||||
MarkdownListItemCrossAxisAlignment listItemCrossAxisAlignment =
|
||||
MarkdownListItemCrossAxisAlignment.baseline,
|
||||
this.padding = const EdgeInsets.all(16.0),
|
||||
this.controller,
|
||||
this.physics,
|
||||
|
@ -51,7 +51,8 @@ void defineTests() {
|
||||
);
|
||||
|
||||
final RichText textWidget = tester.widget(find.byType(RichText));
|
||||
final TextSpan span = (textWidget.text as TextSpan).children![1] as TextSpan;
|
||||
final TextSpan span =
|
||||
(textWidget.text as TextSpan).children![1] as TextSpan;
|
||||
|
||||
expect(span.children, null);
|
||||
expect(span.recognizer.runtimeType, equals(TapGestureRecognizer));
|
||||
|
@ -69,7 +69,18 @@ void defineTests() {
|
||||
);
|
||||
|
||||
final Iterable<Widget> widgets = tester.allWidgets;
|
||||
expectTextStrings(widgets, <String>['1.', 'Item 1', '2.', 'Item 2', '3.', 'Item 3', '10.', 'Item 10', '11.', 'Item 11']);
|
||||
expectTextStrings(widgets, <String>[
|
||||
'1.',
|
||||
'Item 1',
|
||||
'2.',
|
||||
'Item 2',
|
||||
'3.',
|
||||
'Item 3',
|
||||
'10.',
|
||||
'Item 10',
|
||||
'11.',
|
||||
'Item 11'
|
||||
]);
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -98,7 +109,8 @@ void defineTests() {
|
||||
|
||||
testWidgets('custom bullet builder', (WidgetTester tester) async {
|
||||
final String data = '* Item 1\n* Item 2\n1) Item 3\n2) Item 4';
|
||||
final MarkdownBulletBuilder builder = (int index, BulletStyle style) => Text('$index ${style == BulletStyle.orderedList ? 'ordered' : 'unordered'}');
|
||||
final MarkdownBulletBuilder builder = (int index, BulletStyle style) => Text(
|
||||
'$index ${style == BulletStyle.orderedList ? 'ordered' : 'unordered'}');
|
||||
|
||||
await tester.pumpWidget(
|
||||
boilerplate(
|
||||
@ -124,7 +136,8 @@ void defineTests() {
|
||||
'custom checkbox builder',
|
||||
(WidgetTester tester) async {
|
||||
const String data = '- [x] Item 1\n- [ ] Item 2';
|
||||
final MarkdownCheckboxBuilder builder = (bool checked) => Text('$checked');
|
||||
final MarkdownCheckboxBuilder builder =
|
||||
(bool checked) => Text('$checked');
|
||||
|
||||
await tester.pumpWidget(
|
||||
boilerplate(
|
||||
|
@ -60,7 +60,8 @@ void defineTests() {
|
||||
|
||||
// code
|
||||
expect(style.code!.color, cTheme.textTheme.textStyle.color);
|
||||
expect(style.code!.fontSize, cTheme.textTheme.textStyle.fontSize! * 0.85);
|
||||
expect(
|
||||
style.code!.fontSize, cTheme.textTheme.textStyle.fontSize! * 0.85);
|
||||
expect(style.code!.fontFamily, 'monospace');
|
||||
expect(
|
||||
style.code!.backgroundColor, CupertinoColors.systemGrey6.darkColor);
|
||||
@ -149,7 +150,8 @@ void defineTests() {
|
||||
|
||||
// code
|
||||
expect(style.code!.color, theme.textTheme.bodyText2!.color);
|
||||
expect(style.code!.fontSize, theme.textTheme.bodyText2!.fontSize! * 0.85);
|
||||
expect(
|
||||
style.code!.fontSize, theme.textTheme.bodyText2!.fontSize! * 0.85);
|
||||
expect(style.code!.fontFamily, 'monospace');
|
||||
expect(style.code!.backgroundColor, theme.cardColor);
|
||||
|
||||
|
@ -74,8 +74,8 @@ void defineTests() {
|
||||
);
|
||||
|
||||
final Iterable<Widget> widgets = tester.allWidgets;
|
||||
final RichText richText =
|
||||
widgets.lastWhere((Widget widget) => widget is RichText) as RichText;
|
||||
final RichText richText = widgets
|
||||
.lastWhere((Widget widget) => widget is RichText) as RichText;
|
||||
|
||||
expectTextStrings(widgets, <String>['Header', 'italic']);
|
||||
expect(richText.text.style!.fontStyle, FontStyle.italic);
|
||||
|
@ -74,7 +74,8 @@ void defineTests() {
|
||||
),
|
||||
);
|
||||
|
||||
final RichText text = tester.widgetList(find.byType(RichText)).single as RichText;
|
||||
final RichText text =
|
||||
tester.widgetList(find.byType(RichText)).single as RichText;
|
||||
expect(text.textAlign, TextAlign.justify);
|
||||
},
|
||||
);
|
||||
@ -103,8 +104,9 @@ void defineTests() {
|
||||
),
|
||||
);
|
||||
|
||||
final SelectableText text =
|
||||
tester.widgetList(find.byType(SelectableText)).single as SelectableText;
|
||||
final SelectableText text = tester
|
||||
.widgetList(find.byType(SelectableText))
|
||||
.single as SelectableText;
|
||||
expect(text.textAlign, TextAlign.justify);
|
||||
},
|
||||
);
|
||||
|
@ -88,8 +88,8 @@ void defineTests() {
|
||||
);
|
||||
|
||||
final Iterable<Widget> widgets = tester.allWidgets;
|
||||
final SizedBox widget =
|
||||
widgets.firstWhere((Widget widget) => widget is SizedBox) as SizedBox;
|
||||
final SizedBox widget = widgets
|
||||
.firstWhere((Widget widget) => widget is SizedBox) as SizedBox;
|
||||
expect(widget.runtimeType, SizedBox);
|
||||
},
|
||||
);
|
||||
|
Reference in New Issue
Block a user