Skip to content

Instantly share code, notes, and snippets.

@LordOlumide
Created March 18, 2025 20:11
Show Gist options
  • Select an option

  • Save LordOlumide/2d5dd37ef8eea89c4e53f1c5a6755cb5 to your computer and use it in GitHub Desktop.

Select an option

Save LordOlumide/2d5dd37ef8eea89c4e53f1c5a6755cb5 to your computer and use it in GitHub Desktop.
abstract class RichLogic {
static String removeAllSpecialFormatting(String text) => text
.replaceAll('*', '')
.replaceAll('#', '')
.replaceAll('[', '')
.replaceAll(']', '')
.replaceAll('{', '')
.replaceAll('}', '');
static Future<SelectableText> formatTextToRichLinkable({
required BuildContext context,
required String input,
required TextStyle normalStyle,
required Color linkColor,
}) async {
List<TextSpan> spans = [];
String remaining = input;
while (remaining.isNotEmpty) {
if (remaining.startsWith('***')) {
final endIndex = remaining.indexOf('***', 3);
if (endIndex == -1) {
spans.add(TextSpan(text: remaining));
break;
} else {
String boldItalicText = remaining.substring(3, endIndex);
spans.add(
TextSpan(
text: boldItalicText,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
),
),
);
remaining = remaining.substring(endIndex + 3);
}
} else if (remaining.startsWith('**')) {
final endIndex = remaining.indexOf('**', 2);
if (endIndex == -1) {
spans.add(TextSpan(text: remaining));
break;
} else {
String boldText = remaining.substring(2, endIndex);
spans.add(
TextSpan(
text: boldText,
style: const TextStyle(fontWeight: FontWeight.bold),
),
);
remaining = remaining.substring(endIndex + 2);
}
} else if (remaining.startsWith('*')) {
final endIndex = remaining.indexOf('*', 1);
if (endIndex == -1) {
spans.add(TextSpan(text: remaining));
break;
} else {
String italicText = remaining.substring(1, endIndex);
spans.add(
TextSpan(
text: italicText,
style: const TextStyle(fontStyle: FontStyle.italic),
),
);
remaining = remaining.substring(endIndex + 1);
}
} else if (remaining.startsWith('#')) {
final endIndex = remaining.indexOf('#', 1);
if (endIndex == -1) {
spans.add(TextSpan(text: remaining));
break;
} else {
String headingText = remaining.substring(1, endIndex);
spans.add(
TextSpan(
text: headingText.toUpperCase(),
style: TextStyle(
fontSize: (normalStyle.fontSize ?? 16) + 1,
fontWeight: FontWeight.bold,
),
),
);
remaining = remaining.substring(endIndex + 1);
}
} else if (remaining.startsWith('[')) {
final endIndex = remaining.indexOf(']', 1);
if (endIndex == -1) {
spans.add(TextSpan(text: remaining));
break;
} else {
String linkText = remaining.substring(1, endIndex);
spans.add(_formatToExternalLink(context, linkText));
remaining = remaining.substring(endIndex + 1);
}
} else {
final nextSpecialIndex =
remaining.indexOf(RegExp(r'\*\*\*|\*\{|\*|\{|\[|#'));
if (nextSpecialIndex == -1) {
spans.add(TextSpan(text: remaining));
break;
} else {
spans.add(TextSpan(text: remaining.substring(0, nextSpecialIndex)));
remaining = remaining.substring(nextSpecialIndex);
}
}
}
return SelectableText.rich(
TextSpan(
children: spans,
style: normalStyle,
),
);
}
static TextSpan _formatToExternalLink(BuildContext context, String linkText) {
return TextSpan(
text: linkText,
style: const TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () => UrlOpener.openUrl(context, linkText),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment