Skip to content

Commit 520ff3c

Browse files
committed
fix: Fix various issues with list rendering
1 parent deb726a commit 520ff3c

File tree

6 files changed

+202
-196
lines changed

6 files changed

+202
-196
lines changed

lib/custom_render.dart

Lines changed: 41 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -155,112 +155,49 @@ CustomRender blockElementRender({Style? style, List<InlineSpan>? children}) =>
155155
});
156156

157157
CustomRender listElementRender(
158-
{Style? style, Widget? child, List<InlineSpan>? children}) =>
159-
CustomRender.inlineSpan(
160-
inlineSpan: (context, buildChildren) {
161-
final listStyleType = style?.listStyleType ??
162-
context.style.listStyleType ??
163-
ListStyleType.decimal;
164-
final counterStyle =
165-
CounterStyleRegistry.lookup(listStyleType.counterStyle);
166-
String counterContent;
167-
if (style?.marker?.content.isNormal ??
168-
context.style.marker?.content.isNormal ??
169-
true) {
170-
counterContent = counterStyle.generateMarkerContent(
171-
context.tree.counters.lastOrNull?.value ?? 0);
172-
} else if (!(style?.marker?.content.display ??
173-
context.style.marker?.content.display ??
174-
true)) {
175-
counterContent = '';
176-
} else {
177-
counterContent = style?.marker?.content.replacementContent ??
178-
context.style.marker?.content.replacementContent ??
179-
counterStyle.generateMarkerContent(
180-
context.tree.counters.lastOrNull?.value ?? 0);
181-
}
182-
final markerWidget = counterContent.isNotEmpty
183-
? Text.rich(TextSpan(
158+
{Style? style, Widget? child, List<InlineSpan>? children}) {
159+
return CustomRender.inlineSpan(
160+
inlineSpan: (context, buildChildren) {
161+
final usedStyle = style ?? context.style;
162+
final listStyleType = usedStyle.listStyleType ?? ListStyleType.decimal;
163+
final counterStyle =
164+
CounterStyleRegistry.lookup(listStyleType.counterStyle);
165+
String counterContent;
166+
if (usedStyle.marker?.content.isNormal ?? true) {
167+
counterContent = counterStyle.generateMarkerContent(
168+
context.tree.counters.lastOrNull?.value ?? 0,
169+
);
170+
} else if (!(usedStyle.marker?.content.display ?? true)) {
171+
counterContent = '';
172+
} else {
173+
counterContent = usedStyle.marker?.content.replacementContent ??
174+
counterStyle.generateMarkerContent(
175+
context.tree.counters.lastOrNull?.value ?? 0,
176+
);
177+
}
178+
final listChildren = buildChildren()
179+
..insertAll(
180+
0,
181+
[
182+
if (usedStyle.listStylePosition == ListStylePosition.inside)
183+
TextSpan(
184184
text: counterContent,
185-
style: context.tree.style.marker?.style?.generateTextStyle(),
186-
))
187-
: const SizedBox(width: 0, height: 0); //TODO this is hardcoded
188-
189-
return WidgetSpan(
190-
child: CssBoxWidget(
191-
key: context.key,
192-
style: style ?? context.tree.style,
193-
shrinkWrap: context.parser.shrinkWrap,
194-
child: Row(
195-
crossAxisAlignment: CrossAxisAlignment.start,
196-
mainAxisSize: MainAxisSize.min,
197-
textDirection: style?.direction ?? context.tree.style.direction,
198-
children: [
199-
(style?.listStylePosition ??
200-
context.tree.style.listStylePosition) ==
201-
ListStylePosition.outside
202-
? Padding(
203-
padding: style?.padding?.nonNegative ??
204-
context.tree.style.padding?.nonNegative ??
205-
EdgeInsets.only(
206-
left: (style?.direction ??
207-
context.tree.style.direction) !=
208-
TextDirection.rtl
209-
? 10.0
210-
: 0.0,
211-
right: (style?.direction ??
212-
context.tree.style.direction) ==
213-
TextDirection.rtl
214-
? 10.0
215-
: 0.0),
216-
child: markerWidget,
217-
)
218-
: const SizedBox(height: 0, width: 0),
219-
const Text("\u0020",
220-
textAlign: TextAlign.right,
221-
style: TextStyle(fontWeight: FontWeight.w400)),
222-
Expanded(
223-
child: Padding(
224-
padding: (style?.listStylePosition ??
225-
context.tree.style.listStylePosition) ==
226-
ListStylePosition.inside
227-
? EdgeInsets.only(
228-
left: (style?.direction ??
229-
context.tree.style.direction) !=
230-
TextDirection.rtl
231-
? 10.0
232-
: 0.0,
233-
right: (style?.direction ??
234-
context.tree.style.direction) ==
235-
TextDirection.rtl
236-
? 10.0
237-
: 0.0)
238-
: EdgeInsets.zero,
239-
child: CssBoxWidget.withInlineSpanChildren(
240-
children: _getListElementChildren(
241-
style?.listStylePosition ??
242-
context.tree.style.listStylePosition,
243-
buildChildren)
244-
..insertAll(
245-
0,
246-
context.tree.style.listStylePosition ==
247-
ListStylePosition.inside
248-
? [
249-
WidgetSpan(
250-
alignment: PlaceholderAlignment.middle,
251-
child: markerWidget)
252-
]
253-
: []),
254-
style: style ?? context.style,
255-
),
256-
),
257-
),
258-
],
259-
),
260-
),
185+
style: usedStyle.marker?.style?.generateTextStyle(),
186+
),
187+
],
261188
);
262-
},
263-
);
189+
190+
return WidgetSpan(
191+
child: CssBoxWidget.withInlineSpanChildren(
192+
key: context.key,
193+
style: usedStyle,
194+
shrinkWrap: context.parser.shrinkWrap,
195+
children: listChildren,
196+
),
197+
);
198+
},
199+
);
200+
}
264201

265202
CustomRender replacedElementRender(
266203
{PlaceholderAlignment? alignment,
@@ -546,20 +483,6 @@ Map<CustomRenderMatcher, CustomRender> generateDefaultRenders() {
546483
};
547484
}
548485

549-
List<InlineSpan> _getListElementChildren(
550-
ListStylePosition? position, Function() buildChildren) {
551-
List<InlineSpan> children = buildChildren.call();
552-
if (position == ListStylePosition.inside) {
553-
const tabSpan = WidgetSpan(
554-
child: Text("\t",
555-
textAlign: TextAlign.right,
556-
style: TextStyle(fontWeight: FontWeight.w400)),
557-
);
558-
children.insert(0, tabSpan);
559-
}
560-
return children;
561-
}
562-
563486
InlineSpan _getInteractableChildren(RenderContext context,
564487
InteractableElement tree, InlineSpan childSpan, TextStyle childStyle) {
565488
if (childSpan is TextSpan) {

lib/html_parser.dart

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,9 @@ class HtmlParser extends StatelessWidget {
322322
tree = _removeEmptyElements(tree);
323323

324324
tree = _calculateRelativeValues(tree, devicePixelRatio);
325-
tree = _processListMarkers(tree);
325+
tree = _preprocessListMarkers(tree);
326326
tree = _processCounters(tree);
327+
tree = _processListMarkers(tree);
327328
tree = _processBeforesAndAfters(tree);
328329
tree = _collapseMargins(tree);
329330
return tree;
@@ -532,9 +533,9 @@ class HtmlParser extends StatelessWidget {
532533
.replaceAll(RegExp(" {2,}"), " ");
533534
}
534535

535-
/// [processListMarkers] adds marker pseudo elements to the front of all list
536+
/// [preprocessListMarkers] adds marker pseudo elements to the front of all list
536537
/// items.
537-
static StyledElement _processListMarkers(StyledElement tree) {
538+
static StyledElement _preprocessListMarkers(StyledElement tree) {
538539
tree.style.listStylePosition ??= ListStylePosition.outside;
539540

540541
if (tree.style.display == Display.listItem) {
@@ -544,6 +545,10 @@ class HtmlParser extends StatelessWidget {
544545
style: tree.style,
545546
);
546547

548+
// Inherit styles from originating widget
549+
tree.style.marker!.style =
550+
tree.style.copyOnlyInherited(tree.style.marker!.style ?? Style());
551+
547552
// Add the implicit counter-increment on `list-item` if it isn't set
548553
// explicitly already
549554
tree.style.counterIncrement ??= {};
@@ -561,7 +566,7 @@ class HtmlParser extends StatelessWidget {
561566
}
562567

563568
for (var child in tree.children) {
564-
_processListMarkers(child);
569+
_preprocessListMarkers(child);
565570
}
566571

567572
return tree;
@@ -584,15 +589,20 @@ class HtmlParser extends StatelessWidget {
584589
// Increment any counters that are to be incremented
585590
if (tree.style.counterIncrement != null) {
586591
tree.style.counterIncrement!.forEach((counterName, increment) {
587-
tree.counters.lastWhereOrNull(
588-
(counter) => counter.name == counterName,
589-
)?.increment(increment ?? 1);
592+
tree.counters
593+
.lastWhereOrNull(
594+
(counter) => counter.name == counterName,
595+
)
596+
?.increment(increment ?? 1);
590597

591598
// If we didn't newly create the counter, increment the counter in the old copy as well.
592-
if(tree.style.counterReset == null || !tree.style.counterReset!.containsKey(counterName)) {
593-
counters?.lastWhereOrNull(
599+
if (tree.style.counterReset == null ||
600+
!tree.style.counterReset!.containsKey(counterName)) {
601+
counters
602+
?.lastWhereOrNull(
594603
(counter) => counter.name == counterName,
595-
)?.increment(increment ?? 1);
604+
)
605+
?.increment(increment ?? 1);
596606
}
597607
});
598608
}
@@ -604,6 +614,36 @@ class HtmlParser extends StatelessWidget {
604614
return tree;
605615
}
606616

617+
static StyledElement _processListMarkers(StyledElement tree) {
618+
if (tree.style.display == Display.listItem) {
619+
final listStyleType = tree.style.listStyleType ?? ListStyleType.decimal;
620+
final counterStyle = CounterStyleRegistry.lookup(
621+
listStyleType.counterStyle,
622+
);
623+
String counterContent;
624+
if (tree.style.marker?.content.isNormal ?? true) {
625+
counterContent = counterStyle.generateMarkerContent(
626+
tree.counters.lastOrNull?.value ?? 0,
627+
);
628+
} else if (!(tree.style.marker?.content.display ?? true)) {
629+
counterContent = '';
630+
} else {
631+
counterContent = tree.style.marker?.content.replacementContent ??
632+
counterStyle.generateMarkerContent(
633+
tree.counters.lastOrNull?.value ?? 0,
634+
);
635+
}
636+
tree.style.marker = Marker(
637+
content: Content(counterContent), style: tree.style.marker?.style);
638+
}
639+
640+
for (var child in tree.children) {
641+
_processListMarkers(child);
642+
}
643+
644+
return tree;
645+
}
646+
607647
/// [_processBeforesAndAfters] adds text content to the beginning and end of
608648
/// the list of the trees children according to the `before` and `after` Style
609649
/// properties.

0 commit comments

Comments
 (0)