buildTextSpan method

  1. @override
TextSpan buildTextSpan({
  1. required BuildContext context,
  2. TextStyle? style,
  3. required bool withComposing,
})
override

Builds TextSpan from current editing value.

By default makes text in composing range appear as underlined. Descendants can override this method to customize appearance of text.

Implementation

@override
TextSpan buildTextSpan({
  required BuildContext context,
  TextStyle? style,
  required bool withComposing,
}) {
  final List<TextSpan> textSpanChildren = <TextSpan>[];
  int position = 0;

  for (final match in _getTagMatches(text)) {
    final textBeforeTag = text.substring(position, match.start);
    textSpanChildren.add(TextSpan(text: textBeforeTag));

    position = match.end;

    final tag = _parseTagString(match.group(0)!);
    if (tag == null) {
      textSpanChildren.add(TextSpan(text: match.group(0)));
      continue;
    }
    final tagText = tag.toModifiedString(
      toFrontendConverter,
      toBackendConverter,
      isFrontend: true,
    );

    final textStyle =
        textStyleBuilder?.call(context, tag.style.prefix, tag.taggable) ??
            style;
    // The Flutter engine does not render zero-width spaces with actual zero
    // width, so we need to split the tag into two parts: the leading space
    // markers and the actual tag text, while applying a zero letter spacing
    // to the former. This issue is tracked on the Flutter GitHub repository:
    // https://github.com/flutter/flutter/issues/160251
    final lastSpaceMarker = tagText.lastIndexOf(spaceMarker);
    if (lastSpaceMarker != -1) {
      textSpanChildren.add(TextSpan(
        text: tagText.substring(0, lastSpaceMarker + 1),
        style: const TextStyle(letterSpacing: 0),
      ));
      textSpanChildren.add(TextSpan(
        text: tagText.substring(lastSpaceMarker + 1),
        style: textStyle,
      ));
      continue;
    }

    textSpanChildren.add(TextSpan(text: tagText, style: textStyle));
  }

  final textAfterAllTags = text.substring(position, text.length);
  textSpanChildren.add(TextSpan(text: textAfterAllTags));
  return TextSpan(style: style, children: textSpanChildren);
}