@@ -15,6 +15,7 @@ import 'package:flutter_html/src/utils.dart';
15
15
import 'package:flutter_html/style.dart' ;
16
16
import 'package:html/dom.dart' as dom;
17
17
import 'package:html/parser.dart' as htmlparser;
18
+ import 'package:numerus/numerus.dart' ;
18
19
import 'package:webview_flutter/webview_flutter.dart' ;
19
20
20
21
typedef OnTap = void Function (
@@ -536,29 +537,107 @@ class HtmlParser extends StatelessWidget {
536
537
///
537
538
/// The function uses the [_processListCharactersRecursive] function to do most of its work.
538
539
static StyledElement _processListCharacters (StyledElement tree) {
539
- final olStack = ListQueue <Context < int > >();
540
+ final olStack = ListQueue <Context >();
540
541
tree = _processListCharactersRecursive (tree, olStack);
541
542
return tree;
542
543
}
543
544
544
545
/// [_processListCharactersRecursive] uses a Stack of integers to properly number and
545
546
/// bullet all list items according to the [ListStyleType] they have been given.
546
547
static StyledElement _processListCharactersRecursive (
547
- StyledElement tree, ListQueue <Context <int >> olStack) {
548
- if (tree.name == 'ol' ) {
549
- olStack.add (Context ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
548
+ StyledElement tree, ListQueue <Context > olStack) {
549
+ if (tree.name == 'ol' && tree.style.listStyleType != null ) {
550
+ switch (tree.style.listStyleType! ) {
551
+ case ListStyleType .LOWER_LATIN :
552
+ case ListStyleType .LOWER_ALPHA :
553
+ case ListStyleType .UPPER_LATIN :
554
+ case ListStyleType .UPPER_ALPHA :
555
+ olStack.add (Context <String >('a' ));
556
+ if ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ]! ) : null ) != null ) {
557
+ var start = int .tryParse (tree.attributes['start' ]! ) ?? 1 ;
558
+ var x = 1 ;
559
+ while (x < start) {
560
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
561
+ x++ ;
562
+ }
563
+ }
564
+ break ;
565
+ default :
566
+ olStack.add (Context <int >((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
567
+ break ;
568
+ }
550
569
} else if (tree.style.display == Display .LIST_ITEM && tree.style.listStyleType != null ) {
551
570
switch (tree.style.listStyleType! ) {
571
+ case ListStyleType .CIRCLE :
572
+ tree.style.markerContent = '○' ;
573
+ break ;
574
+ case ListStyleType .SQUARE :
575
+ tree.style.markerContent = '■' ;
576
+ break ;
552
577
case ListStyleType .DISC :
553
578
tree.style.markerContent = '•' ;
554
579
break ;
555
580
case ListStyleType .DECIMAL :
556
581
if (olStack.isEmpty) {
557
- olStack.add (Context ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
582
+ olStack.add (Context < int > ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
558
583
}
559
584
olStack.last.data += 1 ;
560
585
tree.style.markerContent = '${olStack .last .data }.' ;
561
586
break ;
587
+ case ListStyleType .LOWER_LATIN :
588
+ case ListStyleType .LOWER_ALPHA :
589
+ if (olStack.isEmpty) {
590
+ olStack.add (Context <String >('a' ));
591
+ if ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ]! ) : null ) != null ) {
592
+ var start = int .tryParse (tree.attributes['start' ]! ) ?? 1 ;
593
+ var x = 1 ;
594
+ while (x < start) {
595
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
596
+ x++ ;
597
+ }
598
+ }
599
+ }
600
+ tree.style.markerContent = olStack.last.data.toString () + "." ;
601
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
602
+ break ;
603
+ case ListStyleType .UPPER_LATIN :
604
+ case ListStyleType .UPPER_ALPHA :
605
+ if (olStack.isEmpty) {
606
+ olStack.add (Context <String >('a' ));
607
+ if ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ]! ) : null ) != null ) {
608
+ var start = int .tryParse (tree.attributes['start' ]! ) ?? 1 ;
609
+ var x = 1 ;
610
+ while (x < start) {
611
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
612
+ x++ ;
613
+ }
614
+ }
615
+ }
616
+ tree.style.markerContent = olStack.last.data.toString ().toUpperCase () + "." ;
617
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
618
+ break ;
619
+ case ListStyleType .LOWER_ROMAN :
620
+ if (olStack.isEmpty) {
621
+ olStack.add (Context <int >((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
622
+ }
623
+ olStack.last.data += 1 ;
624
+ if (olStack.last.data <= 0 ) {
625
+ tree.style.markerContent = '${olStack .last .data }.' ;
626
+ } else {
627
+ tree.style.markerContent = (olStack.last.data as int ).toRomanNumeralString ()! .toLowerCase () + "." ;
628
+ }
629
+ break ;
630
+ case ListStyleType .UPPER_ROMAN :
631
+ if (olStack.isEmpty) {
632
+ olStack.add (Context <int >((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
633
+ }
634
+ olStack.last.data += 1 ;
635
+ if (olStack.last.data <= 0 ) {
636
+ tree.style.markerContent = '${olStack .last .data }.' ;
637
+ } else {
638
+ tree.style.markerContent = (olStack.last.data as int ).toRomanNumeralString ()! + "." ;
639
+ }
640
+ break ;
562
641
}
563
642
}
564
643
@@ -847,3 +926,24 @@ class StyledText extends StatelessWidget {
847
926
return null ;
848
927
}
849
928
}
929
+
930
+ extension IterateLetters on String {
931
+ String nextLetter () {
932
+ String s = this .toLowerCase ();
933
+ if (s == "z" ) {
934
+ return String .fromCharCode (s.codeUnitAt (0 ) - 25 ) + String .fromCharCode (s.codeUnitAt (0 ) - 25 ); // AA or aa
935
+ } else {
936
+ var lastChar = s.substring (s.length - 1 );
937
+ var sub = s.substring (0 , s.length - 1 );
938
+ if (lastChar == "z" ) {
939
+ // If a string of length > 1 ends in Z/z,
940
+ // increment the string (excluding the last Z/z) recursively,
941
+ // and append A/a (depending on casing) to it
942
+ return sub.nextLetter () + 'a' ;
943
+ } else {
944
+ // (take till last char) append with (increment last char)
945
+ return sub + String .fromCharCode (lastChar.codeUnitAt (0 ) + 1 );
946
+ }
947
+ }
948
+ }
949
+ }
0 commit comments