Skip to content

Commit bb9145e

Browse files
committed
WIP: New CSSBoxWidget bugfixes
1 parent edc5df2 commit bb9145e

10 files changed

+288
-578
lines changed

lib/custom_render.dart

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import 'dart:convert';
66
import 'package:flutter/gestures.dart';
77
import 'package:flutter/material.dart';
88
import 'package:flutter_html/flutter_html.dart';
9+
import 'package:flutter_html/src/css_box_widget.dart';
10+
import 'package:flutter_html/src/html_elements.dart';
911
import 'package:flutter_html/src/utils.dart';
1012

1113
typedef CustomRenderMatcher = bool Function(RenderContext context);
@@ -15,7 +17,8 @@ CustomRenderMatcher tagMatcher(String tag) => (context) {
1517
};
1618

1719
CustomRenderMatcher blockElementMatcher() => (context) {
18-
return context.tree.style.display == Display.BLOCK &&
20+
return (context.tree.style.display == Display.BLOCK ||
21+
context.tree.style.display == Display.INLINE_BLOCK) &&
1922
(context.tree.children.isNotEmpty ||
2023
context.tree.element?.localName == "hr");
2124
};
@@ -108,7 +111,7 @@ class SelectableCustomRender extends CustomRender {
108111
}) : super.inlineSpan(inlineSpan: null);
109112
}
110113

111-
CustomRender blockElementRender({Style? style, List<InlineSpan>? children, required Size containingBlockSize}) =>
114+
CustomRender blockElementRender({Style? style, List<InlineSpan>? children}) =>
112115
CustomRender.inlineSpan(inlineSpan: (context, buildChildren) {
113116
if (context.parser.selectable) {
114117
return TextSpan(
@@ -127,36 +130,36 @@ CustomRender blockElementRender({Style? style, List<InlineSpan>? children, requi
127130
);
128131
}
129132
return WidgetSpan(
130-
child: ContainerSpan(
131-
key: context.key,
132-
renderContext: context,
133-
style: style ?? context.tree.style,
134-
shrinkWrap: context.parser.shrinkWrap,
135-
containingBlockSize: containingBlockSize,
136-
children: children ??
137-
context.tree.children
138-
.expandIndexed((i, childTree) => [
139-
context.parser.parseTree(context, childTree),
140-
if (i != context.tree.children.length - 1 &&
141-
childTree.style.display == Display.BLOCK &&
142-
childTree.element?.localName != "html" &&
143-
childTree.element?.localName != "body")
144-
TextSpan(text: "\n"),
145-
])
146-
.toList(),
147-
));
133+
alignment: PlaceholderAlignment.baseline,
134+
baseline: TextBaseline.alphabetic,
135+
child: CSSBoxWidget.withInlineSpanChildren(
136+
key: context.key,
137+
style: style ?? context.tree.style,
138+
shrinkWrap: context.parser.shrinkWrap,
139+
childIsReplaced: REPLACED_EXTERNAL_ELEMENTS.contains(context.tree.name),
140+
children: children ??
141+
context.tree.children
142+
.expandIndexed((i, childTree) => [
143+
context.parser.parseTree(context, childTree),
144+
//TODO can this newline be added in a different step?
145+
if (i != context.tree.children.length - 1 &&
146+
childTree.style.display == Display.BLOCK &&
147+
childTree.element?.localName != "html" &&
148+
childTree.element?.localName != "body")
149+
TextSpan(text: "\n"),
150+
]).toList(),
151+
),
152+
);
148153
});
149154

150155
CustomRender listElementRender(
151-
{Style? style, Widget? child, List<InlineSpan>? children, required Size containingBlockSize}) =>
156+
{Style? style, Widget? child, List<InlineSpan>? children}) =>
152157
CustomRender.inlineSpan(
153158
inlineSpan: (context, buildChildren) => WidgetSpan(
154-
child: ContainerSpan(
159+
child: CSSBoxWidget(
155160
key: context.key,
156-
renderContext: context,
157161
style: style ?? context.tree.style,
158162
shrinkWrap: context.parser.shrinkWrap,
159-
containingBlockSize: containingBlockSize,
160163
child: Row(
161164
crossAxisAlignment: CrossAxisAlignment.start,
162165
mainAxisSize: MainAxisSize.min,
@@ -203,9 +206,8 @@ CustomRender listElementRender(
203206
? 10.0
204207
: 0.0)
205208
: EdgeInsets.zero,
206-
child: StyledText(
207-
textSpan: TextSpan(
208-
children: _getListElementChildren(
209+
child: CSSBoxWidget.withInlineSpanChildren(
210+
children: _getListElementChildren(
209211
style?.listStylePosition ??
210212
context.tree.style.listStylePosition,
211213
buildChildren)
@@ -225,16 +227,15 @@ CustomRender listElementRender(
225227
height: 0, width: 0))
226228
]
227229
: []),
228-
style: style?.generateTextStyle() ??
229-
context.style.generateTextStyle(),
230-
),
231230
style: style ?? context.style,
232-
renderContext: context,
233-
)))
231+
),
232+
),
233+
),
234234
],
235235
),
236236
),
237-
));
237+
),
238+
);
238239

239240
CustomRender replacedElementRender(
240241
{PlaceholderAlignment? alignment,
@@ -475,14 +476,9 @@ CustomRender verticalAlignRender(
475476
key: context.key,
476477
offset: Offset(
477478
0, verticalOffset ?? _getVerticalOffset(context.tree)),
478-
child: StyledText(
479-
textSpan: TextSpan(
480-
style: style?.generateTextStyle() ??
481-
context.style.generateTextStyle(),
482-
children: children ?? buildChildren.call(),
483-
),
479+
child: CSSBoxWidget.withInlineSpanChildren(
480+
children: children ?? buildChildren.call(),
484481
style: context.style,
485-
renderContext: context,
486482
),
487483
),
488484
));
@@ -505,10 +501,10 @@ CustomRender fallbackRender({Style? style, List<InlineSpan>? children}) =>
505501
.toList(),
506502
));
507503

508-
Map<CustomRenderMatcher, CustomRender> generateDefaultRenders(Size containingBlockSize) {
504+
Map<CustomRenderMatcher, CustomRender> generateDefaultRenders() {
509505
return {
510-
blockElementMatcher(): blockElementRender(containingBlockSize: containingBlockSize),
511-
listElementMatcher(): listElementRender(containingBlockSize: containingBlockSize),
506+
blockElementMatcher(): blockElementRender(),
507+
listElementMatcher(): listElementRender(),
512508
textContentElementMatcher(): textContentElementRender(),
513509
dataUriMatcher(): base64ImageRender(),
514510
assetUriMatcher(): assetImageRender(),

lib/flutter_html.dart

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -177,29 +177,21 @@ class _HtmlState extends State<Html> {
177177

178178
@override
179179
Widget build(BuildContext context) {
180-
return Container(
181-
width: widget.shrinkWrap ? null : MediaQuery.of(context).size.width,
182-
child: LayoutBuilder(
183-
builder: (context, constraints) {
184-
return HtmlParser(
185-
key: widget._anchorKey,
186-
htmlData: documentElement,
187-
onLinkTap: widget.onLinkTap,
188-
onAnchorTap: widget.onAnchorTap,
189-
onImageTap: widget.onImageTap,
190-
onCssParseError: widget.onCssParseError,
191-
onImageError: widget.onImageError,
192-
shrinkWrap: widget.shrinkWrap,
193-
selectable: false,
194-
style: widget.style,
195-
customRenders: {}
196-
..addAll(widget.customRenders)
197-
..addAll(generateDefaultRenders(MediaQuery.of(context).size)),
198-
tagsList: widget.tagsList.isEmpty ? Html.tags : widget.tagsList,
199-
constraints: constraints,
200-
);
201-
}
202-
),
180+
return HtmlParser(
181+
key: widget._anchorKey,
182+
htmlData: documentElement,
183+
onLinkTap: widget.onLinkTap,
184+
onAnchorTap: widget.onAnchorTap,
185+
onImageTap: widget.onImageTap,
186+
onCssParseError: widget.onCssParseError,
187+
onImageError: widget.onImageError,
188+
shrinkWrap: widget.shrinkWrap,
189+
selectable: false,
190+
style: widget.style,
191+
customRenders: {}
192+
..addAll(widget.customRenders)
193+
..addAll(generateDefaultRenders()),
194+
tagsList: widget.tagsList.isEmpty ? Html.tags : widget.tagsList,
203195
);
204196
}
205197
}
@@ -311,7 +303,9 @@ class SelectableHtml extends StatefulWidget {
311303
final OnCssParseError? onCssParseError;
312304

313305
/// A parameter that should be set when the HTML widget is expected to be
314-
/// flexible
306+
/// have a flexible width, that doesn't always fill its maximum width
307+
/// constraints. For example, auto horizontal margins are ignored, and
308+
/// block-level elements only take up the width they need.
315309
final bool shrinkWrap;
316310

317311
/// A list of HTML tags that are the only tags that are rendered. By default, this list is empty and all supported HTML tags are rendered.
@@ -352,29 +346,23 @@ class _SelectableHtmlState extends State<SelectableHtml> {
352346
Widget build(BuildContext context) {
353347
return Container(
354348
width: widget.shrinkWrap ? null : MediaQuery.of(context).size.width,
355-
child: LayoutBuilder(
356-
builder: (context, constraints) {
357-
return HtmlParser(
358-
key: widget._anchorKey,
359-
htmlData: documentElement,
360-
onLinkTap: widget.onLinkTap,
361-
onAnchorTap: widget.onAnchorTap,
362-
onImageTap: null,
363-
onCssParseError: widget.onCssParseError,
364-
onImageError: null,
365-
shrinkWrap: widget.shrinkWrap,
366-
selectable: true,
367-
style: widget.style,
368-
customRenders: {}
369-
..addAll(widget.customRenders)
370-
..addAll(generateDefaultRenders(MediaQuery.of(context).size)),
371-
tagsList:
372-
widget.tagsList.isEmpty ? SelectableHtml.tags : widget.tagsList,
373-
selectionControls: widget.selectionControls,
374-
scrollPhysics: widget.scrollPhysics,
375-
constraints: constraints,
376-
);
377-
}
349+
child: HtmlParser(
350+
key: widget._anchorKey,
351+
htmlData: documentElement,
352+
onLinkTap: widget.onLinkTap,
353+
onAnchorTap: widget.onAnchorTap,
354+
onImageTap: null,
355+
onCssParseError: widget.onCssParseError,
356+
onImageError: null,
357+
shrinkWrap: widget.shrinkWrap,
358+
selectable: true,
359+
style: widget.style,
360+
customRenders: {}
361+
..addAll(widget.customRenders)
362+
..addAll(generateDefaultRenders()),
363+
tagsList: widget.tagsList.isEmpty ? SelectableHtml.tags : widget.tagsList,
364+
selectionControls: widget.selectionControls,
365+
scrollPhysics: widget.scrollPhysics,
378366
),
379367
);
380368
}

0 commit comments

Comments
 (0)