Skip to content

Commit dc92077

Browse files
committed
plain text nodes inside blockquote, ol, and ul, are now properly indented
1 parent 7136a59 commit dc92077

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

lib/html_parser.dart

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class ParseContext {
102102
String blockType; // blockType can be 'p', 'div', 'ul', 'ol', 'blockquote'
103103
bool condenseWhitespace = true;
104104
bool spansOnly = false;
105+
bool inBlock = false;
105106
TextStyle childStyle;
106107

107108
ParseContext(
@@ -113,6 +114,7 @@ class ParseContext {
113114
this.blockType,
114115
this.condenseWhitespace = true,
115116
this.spansOnly = false,
117+
this.inBlock = false,
116118
this.childStyle}) {
117119
childStyle = childStyle ?? TextStyle();
118120
}
@@ -126,6 +128,7 @@ class ParseContext {
126128
blockType = parseContext.blockType;
127129
condenseWhitespace = parseContext.condenseWhitespace;
128130
spansOnly = parseContext.spansOnly;
131+
inBlock = parseContext.inBlock;
129132
childStyle = parseContext.childStyle ?? TextStyle();
130133
}
131134
}
@@ -298,14 +301,14 @@ class HtmlRichTextParser extends StatelessWidget {
298301
return;
299302
}
300303

301-
// empty strings of whitespace might be significant or not, condense it by default
302-
if (node.text.trim() == "" &&
303-
node.text.indexOf(" ") != -1 &&
304-
parseContext.condenseWhitespace) {
305-
node.text = " ";
306-
}
304+
// if (node.text.trim() == "" &&
305+
// node.text.indexOf(" ") != -1 &&
306+
// parseContext.condenseWhitespace) {
307+
// node.text = " ";
308+
// }
307309

308310
// we might want to preserve internal whitespace
311+
// empty strings of whitespace might be significant or not, condense it by default
309312
String finalText = parseContext.condenseWhitespace
310313
? condenseHtmlWhitespace(node.text)
311314
: node.text;
@@ -315,6 +318,9 @@ class HtmlRichTextParser extends StatelessWidget {
315318
parseContext.parentElement is LinkTextSpan))
316319
finalText = finalText.trim();
317320

321+
// if the finalText is actually empty, just return
322+
if (finalText.isEmpty) return;
323+
318324
// NOW WE HAVE OUR TRULY FINAL TEXT
319325
// debugPrint("Plain Text Node: '$finalText'");
320326

@@ -326,10 +332,48 @@ class HtmlRichTextParser extends StatelessWidget {
326332

327333
// in this class, a ParentElement must be a BlockText, LinkTextSpan, Row, Column, TextSpan
328334

335+
// the parseContext might actually be a block level style element, so we
336+
// need to honor the indent and styling specified by that block style.
337+
// e.g. ol, ul, blockquote
338+
bool treatLikeBlock =
339+
['blockquote', 'ul', 'ol'].indexOf(parseContext.blockType) != -1;
340+
329341
// if there is no parentElement, contain the span in a BlockText
330342
if (parseContext.parentElement == null) {
343+
// if this is inside a context that should be treated like a block
344+
// but the context is not actually a block, create a block
345+
// and append it to the root widget tree
346+
if (treatLikeBlock) {
347+
Decoration decoration;
348+
if (parseContext.blockType == 'blockquote') {
349+
decoration = BoxDecoration(
350+
border:
351+
Border(left: BorderSide(color: Colors.black38, width: 2.0)),
352+
);
353+
parseContext.childStyle = parseContext.childStyle.merge(TextStyle(
354+
fontStyle: FontStyle.italic,
355+
));
356+
}
357+
BlockText blockText = BlockText(
358+
margin: EdgeInsets.only(
359+
top: 8.0,
360+
bottom: 8.0,
361+
left: parseContext.indentLevel * indentSize),
362+
padding: EdgeInsets.all(2.0),
363+
decoration: decoration,
364+
child: RichText(
365+
textAlign: TextAlign.left,
366+
text: span,
367+
),
368+
);
369+
parseContext.rootWidgetList.add(blockText);
370+
} else {
371+
parseContext.rootWidgetList
372+
.add(BlockText(child: RichText(text: span)));
373+
}
374+
375+
// this allows future items to be added as children
331376
parseContext.parentElement = span;
332-
parseContext.rootWidgetList.add(BlockText(child: RichText(text: span)));
333377

334378
// if the parent is a LinkTextSpan, keep the main attributes of that span going.
335379
} else if (parseContext.parentElement is LinkTextSpan) {
@@ -348,6 +392,7 @@ class HtmlRichTextParser extends StatelessWidget {
348392
}
349393
return;
350394
}
395+
351396
// OTHER ELEMENT NODES
352397
else if (node is dom.Element) {
353398
assert(() {
@@ -460,6 +505,7 @@ class HtmlRichTextParser extends StatelessWidget {
460505
child: RichText(text: span),
461506
);
462507
parseContext.rootWidgetList.add(blockElement);
508+
nextContext.inBlock = true;
463509
}
464510
nextContext.childStyle = linkStyle;
465511
nextContext.parentElement = span;
@@ -559,6 +605,7 @@ class HtmlRichTextParser extends StatelessWidget {
559605
parseContext.rootWidgetList.add(blockText);
560606
nextContext.parentElement = blockText.child.text;
561607
nextContext.spansOnly = true;
608+
nextContext.inBlock = true;
562609
break;
563610

564611
case "h1":
@@ -614,10 +661,11 @@ class HtmlRichTextParser extends StatelessWidget {
614661
));
615662
}
616663
BlockText blockText = BlockText(
617-
margin: EdgeInsets.symmetric(vertical: 8.0),
618-
padding: EdgeInsets.only(
619-
left: parseContext.indentLevel * indentSize,
620-
),
664+
margin: EdgeInsets.only(
665+
top: 8.0,
666+
bottom: 8.0,
667+
left: parseContext.indentLevel * indentSize),
668+
padding: EdgeInsets.all(2.0),
621669
decoration: decoration,
622670
child: RichText(
623671
textAlign: textAlign,
@@ -631,6 +679,7 @@ class HtmlRichTextParser extends StatelessWidget {
631679
parseContext.rootWidgetList.add(blockText);
632680
nextContext.parentElement = blockText.child.text;
633681
nextContext.spansOnly = true;
682+
nextContext.inBlock = true;
634683
}
635684
}
636685

0 commit comments

Comments
 (0)