@@ -16,6 +16,7 @@ import 'package:flutter_html/src/utils.dart';
1616import 'package:flutter_html/style.dart' ;
1717import 'package:html/dom.dart' as dom;
1818import 'package:html/parser.dart' as htmlparser;
19+ import 'package:numerus/numerus.dart' ;
1920import 'package:webview_flutter/webview_flutter.dart' ;
2021
2122typedef OnTap = void Function (
@@ -591,29 +592,107 @@ class HtmlParser extends StatelessWidget {
591592 ///
592593 /// The function uses the [_processListCharactersRecursive] function to do most of its work.
593594 static StyledElement _processListCharacters (StyledElement tree) {
594- final olStack = ListQueue <Context < int > >();
595+ final olStack = ListQueue <Context >();
595596 tree = _processListCharactersRecursive (tree, olStack);
596597 return tree;
597598 }
598599
599600 /// [_processListCharactersRecursive] uses a Stack of integers to properly number and
600601 /// bullet all list items according to the [ListStyleType] they have been given.
601602 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+ }
605624 } else if (tree.style.display == Display .LIST_ITEM && tree.style.listStyleType != null ) {
606625 switch (tree.style.listStyleType! ) {
626+ case ListStyleType .CIRCLE :
627+ tree.style.markerContent = '○' ;
628+ break ;
629+ case ListStyleType .SQUARE :
630+ tree.style.markerContent = '■' ;
631+ break ;
607632 case ListStyleType .DISC :
608633 tree.style.markerContent = '•' ;
609634 break ;
610635 case ListStyleType .DECIMAL :
611636 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 ));
613638 }
614639 olStack.last.data += 1 ;
615640 tree.style.markerContent = '${olStack .last .data }.' ;
616641 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 ;
617696 }
618697 }
619698
@@ -902,3 +981,24 @@ class StyledText extends StatelessWidget {
902981 return null ;
903982 }
904983}
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