processStrList method

List<String> processStrList(
  1. List<EasyRichTextPattern> patternList,
  2. String temText
)

Implementation

List<String> processStrList(
    List<EasyRichTextPattern> patternList, String temText) {
  List<String> strList = [];
  List<List<int>> positions = [];

  patternList.asMap().forEach((index, pattern) {
    String thisRegExPattern;
    String targetString = pattern.targetString;
    String stringBeforeTarget = pattern.stringBeforeTarget;
    String stringAfterTarget = pattern.stringAfterTarget;

    bool matchLeftWordBoundary = pattern.matchLeftWordBoundary;
    bool matchRightWordBoundary = pattern.matchRightWordBoundary;
    bool matchWordBoundaries = pattern.matchWordBoundaries;
    //if hasSpecialCharacters then unicode is
    bool unicode = !pattern.hasSpecialCharacters;

    String wordBoundaryStringBeforeTarget1 = "\\b";
    String wordBoundaryStringBeforeTarget2 = "\\s";
    String wordBoundaryStringAfterTarget1 = "\\s";
    String wordBoundaryStringAfterTarget2 = "\\b";

    String leftBoundary = "(?<!\\w)";
    String rightBoundary = "(?!\\w)";

    ///if any of matchWordBoundaries or matchLeftWordBoundary is false
    ///set leftBoundary = ""
    if (!matchWordBoundaries || !matchLeftWordBoundary) {
      leftBoundary = "";
      wordBoundaryStringBeforeTarget1 = "";
      wordBoundaryStringAfterTarget1 = "";
    }

    if (!matchWordBoundaries || !matchRightWordBoundary) {
      rightBoundary = "";
      wordBoundaryStringBeforeTarget2 = "";
      wordBoundaryStringAfterTarget2 = "";
    }

    bool isHan = RegExp(r"[\u4e00-\u9fa5]+",
            caseSensitive: caseSensitive, unicode: unicode)
        .hasMatch(targetString);

    bool isArabic = RegExp(r"[\u0621-\u064A]+",
            caseSensitive: caseSensitive, unicode: unicode)
        .hasMatch(targetString);

    /// if target string is Han or Arabic character
    /// set matchWordBoundaries = false
    /// set wordBoundaryStringBeforeTarget = ""
    if (isHan || isArabic) {
      matchWordBoundaries = false;
      leftBoundary = "";
      rightBoundary = "";
      wordBoundaryStringBeforeTarget1 = "";
      wordBoundaryStringBeforeTarget2 = "";
      wordBoundaryStringAfterTarget1 = "";
      wordBoundaryStringAfterTarget2 = "";
    }

    String stringBeforeTargetRegex = "";
    if (stringBeforeTarget != "") {
      stringBeforeTargetRegex =
          "(?<=$wordBoundaryStringBeforeTarget1$stringBeforeTarget$wordBoundaryStringBeforeTarget2)";
    }
    String stringAfterTargetRegex = "";
    if (stringAfterTarget != "") {
      stringAfterTargetRegex =
          "(?=$wordBoundaryStringAfterTarget1$stringAfterTarget$wordBoundaryStringAfterTarget2)";
    }

    //modify targetString by matchWordBoundaries and wordBoundaryStringBeforeTarget settings
    thisRegExPattern =
        '($stringBeforeTargetRegex$leftBoundary$targetString$rightBoundary$stringAfterTargetRegex)';
    RegExp exp = new RegExp(thisRegExPattern,
        caseSensitive: caseSensitive, unicode: unicode);
    var allMatches = exp.allMatches(temText);
    // print(thisRegExPattern);

    //check matchOption ['all','first','last', 0, 1, 2, 3, 10]

    int matchesLength = allMatches.length;
    List<int> matchIndexList = [];
    var matchOption = pattern.matchOption;
    if (matchOption is String) {
      switch (matchOption) {
        case 'all':
          matchIndexList = new List<int>.generate(matchesLength, (i) => i);
          break;
        case 'first':
          matchIndexList = [0];
          break;
        case 'last':
          matchIndexList = [matchesLength - 1];
          break;
        default:
          matchIndexList = new List<int>.generate(matchesLength, (i) => i);
      }
    } else if (matchOption is List<dynamic>) {
      matchOption.forEach(
        (option) {
          switch (option) {
            case 'all':
              matchIndexList =
                  new List<int>.generate(matchesLength, (i) => i);
              break;
            case 'first':
              matchIndexList.add(0);
              break;
            case 'last':
              matchIndexList.add(matchesLength - 1);
              break;
            default:
              if (option is int) matchIndexList.add(option);
          }
        },
      );
    }

    ///eg. positions = [[7,11],[26,30],]
    allMatches.toList().asMap().forEach((index, match) {
      if (matchIndexList.indexOf(index) > -1) {
        positions.add([match.start, match.end]);
      }
    });
  });
  //in some cases the sorted result is still disordered;need re-sort the 1d list;
  positions.sort((a, b) => a[0].compareTo(b[0]));

  //remove invalid positions
  List<List<int>> postionsToRemove = [];
  for (var i = 1; i < positions.length; i++) {
    if (positions[i][0] < positions[i - 1][1]) {
      postionsToRemove.add(positions[i]);
    }
  }
  postionsToRemove.forEach((position) {
    positions.remove(position);
  });

  //convert positions to 1d list
  List<int> splitPositions = [0];
  positions.forEach((position) {
    splitPositions.add(position[0]);
    splitPositions.add(position[1]);
  });
  splitPositions.add(temText.length);
  splitPositions.sort();

  splitPositions.asMap().forEach((index, splitPosition) {
    if (index != 0) {
      strList
          .add(temText.substring(splitPositions[index - 1], splitPosition));
    }
  });
  return strList;
}