@@ -16,6 +16,7 @@ import 'package:flutter_html/src/utils.dart';
16
16
import 'package:flutter_html/style.dart' ;
17
17
import 'package:html/dom.dart' as dom;
18
18
import 'package:html/parser.dart' as htmlparser;
19
+ import 'package:numerus/numerus.dart' ;
19
20
import 'package:webview_flutter/webview_flutter.dart' ;
20
21
21
22
typedef OnTap = void Function (
@@ -591,29 +592,107 @@ class HtmlParser extends StatelessWidget {
591
592
///
592
593
/// The function uses the [_processListCharactersRecursive] function to do most of its work.
593
594
static StyledElement _processListCharacters (StyledElement tree) {
594
- final olStack = ListQueue <Context < int > >();
595
+ final olStack = ListQueue <Context >();
595
596
tree = _processListCharactersRecursive (tree, olStack);
596
597
return tree;
597
598
}
598
599
599
600
/// [_processListCharactersRecursive] uses a Stack of integers to properly number and
600
601
/// bullet all list items according to the [ListStyleType] they have been given.
601
602
static StyledElement _processListCharactersRecursive (
602
- StyledElement tree, ListQueue <Context <int >> olStack) {
603
- if (tree.name == 'ol' ) {
604
- olStack.add (Context ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
603
+ StyledElement tree, ListQueue <Context > olStack) {
604
+ if (tree.name == 'ol' && tree.style.listStyleType != null ) {
605
+ switch (tree.style.listStyleType! ) {
606
+ case ListStyleType .LOWER_LATIN :
607
+ case ListStyleType .LOWER_ALPHA :
608
+ case ListStyleType .UPPER_LATIN :
609
+ case ListStyleType .UPPER_ALPHA :
610
+ olStack.add (Context <String >('a' ));
611
+ if ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ]! ) : null ) != null ) {
612
+ var start = int .tryParse (tree.attributes['start' ]! ) ?? 1 ;
613
+ var x = 1 ;
614
+ while (x < start) {
615
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
616
+ x++ ;
617
+ }
618
+ }
619
+ break ;
620
+ default :
621
+ olStack.add (Context <int >((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
622
+ break ;
623
+ }
605
624
} else if (tree.style.display == Display .LIST_ITEM && tree.style.listStyleType != null ) {
606
625
switch (tree.style.listStyleType! ) {
626
+ case ListStyleType .CIRCLE :
627
+ tree.style.markerContent = '○' ;
628
+ break ;
629
+ case ListStyleType .SQUARE :
630
+ tree.style.markerContent = '■' ;
631
+ break ;
607
632
case ListStyleType .DISC :
608
633
tree.style.markerContent = '•' ;
609
634
break ;
610
635
case ListStyleType .DECIMAL :
611
636
if (olStack.isEmpty) {
612
- olStack.add (Context ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
637
+ olStack.add (Context < int > ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
613
638
}
614
639
olStack.last.data += 1 ;
615
640
tree.style.markerContent = '${olStack .last .data }.' ;
616
641
break ;
642
+ case ListStyleType .LOWER_LATIN :
643
+ case ListStyleType .LOWER_ALPHA :
644
+ if (olStack.isEmpty) {
645
+ olStack.add (Context <String >('a' ));
646
+ if ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ]! ) : null ) != null ) {
647
+ var start = int .tryParse (tree.attributes['start' ]! ) ?? 1 ;
648
+ var x = 1 ;
649
+ while (x < start) {
650
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
651
+ x++ ;
652
+ }
653
+ }
654
+ }
655
+ tree.style.markerContent = olStack.last.data.toString () + "." ;
656
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
657
+ break ;
658
+ case ListStyleType .UPPER_LATIN :
659
+ case ListStyleType .UPPER_ALPHA :
660
+ if (olStack.isEmpty) {
661
+ olStack.add (Context <String >('a' ));
662
+ if ((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ]! ) : null ) != null ) {
663
+ var start = int .tryParse (tree.attributes['start' ]! ) ?? 1 ;
664
+ var x = 1 ;
665
+ while (x < start) {
666
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
667
+ x++ ;
668
+ }
669
+ }
670
+ }
671
+ tree.style.markerContent = olStack.last.data.toString ().toUpperCase () + "." ;
672
+ olStack.last.data = olStack.last.data.toString ().nextLetter ();
673
+ break ;
674
+ case ListStyleType .LOWER_ROMAN :
675
+ if (olStack.isEmpty) {
676
+ olStack.add (Context <int >((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
677
+ }
678
+ olStack.last.data += 1 ;
679
+ if (olStack.last.data <= 0 ) {
680
+ tree.style.markerContent = '${olStack .last .data }.' ;
681
+ } else {
682
+ tree.style.markerContent = (olStack.last.data as int ).toRomanNumeralString ()! .toLowerCase () + "." ;
683
+ }
684
+ break ;
685
+ case ListStyleType .UPPER_ROMAN :
686
+ if (olStack.isEmpty) {
687
+ olStack.add (Context <int >((tree.attributes['start' ] != null ? int .tryParse (tree.attributes['start' ] ?? "" ) ?? 1 : 1 ) - 1 ));
688
+ }
689
+ olStack.last.data += 1 ;
690
+ if (olStack.last.data <= 0 ) {
691
+ tree.style.markerContent = '${olStack .last .data }.' ;
692
+ } else {
693
+ tree.style.markerContent = (olStack.last.data as int ).toRomanNumeralString ()! + "." ;
694
+ }
695
+ break ;
617
696
}
618
697
}
619
698
@@ -902,3 +981,24 @@ class StyledText extends StatelessWidget {
902
981
return null ;
903
982
}
904
983
}
984
+
985
+ extension IterateLetters on String {
986
+ String nextLetter () {
987
+ String s = this .toLowerCase ();
988
+ if (s == "z" ) {
989
+ return String .fromCharCode (s.codeUnitAt (0 ) - 25 ) + String .fromCharCode (s.codeUnitAt (0 ) - 25 ); // AA or aa
990
+ } else {
991
+ var lastChar = s.substring (s.length - 1 );
992
+ var sub = s.substring (0 , s.length - 1 );
993
+ if (lastChar == "z" ) {
994
+ // If a string of length > 1 ends in Z/z,
995
+ // increment the string (excluding the last Z/z) recursively,
996
+ // and append A/a (depending on casing) to it
997
+ return sub.nextLetter () + 'a' ;
998
+ } else {
999
+ // (take till last char) append with (increment last char)
1000
+ return sub + String .fromCharCode (lastChar.codeUnitAt (0 ) + 1 );
1001
+ }
1002
+ }
1003
+ }
1004
+ }
0 commit comments