From 870892fdcfede51d979ee8c214f4784e5a4a21a9 Mon Sep 17 00:00:00 2001 From: iamstanlee Date: Thu, 3 Jun 2021 13:52:28 -0700 Subject: [PATCH] migrate pkg to null safety --- lib/src/linkify.dart | 41 +++++++++++++++++++++++++++++++ lib/src/utils/regex.dart | 7 ++++++ lib/src/utils/utils.dart | 1 + pubspec.yaml | 4 +-- test/linkify_text_test.dart | 4 +-- test/regex_test.dart | 49 +++++++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 test/regex_test.dart diff --git a/lib/src/linkify.dart b/lib/src/linkify.dart index 1eae82a..54912c2 100644 --- a/lib/src/linkify.dart +++ b/lib/src/linkify.dart @@ -1,3 +1,44 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; + enum LinkOptions { url, email, hashTag } +TextSpan formatText( + {required String text, TextStyle? textStyle, TextStyle? linkStyle}) { + RegExp re = RegExp( + r"(((ht|f)tp(s?)://)|www.)[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*/?([a-zA-Z0-9\-.\?,'/\\\+&%\$#_=]*)?"); + // return the full text if there's no match + if (!re.hasMatch(text)) { + return TextSpan(text: text, style: textStyle); + } + + List texts = text.split(re); + List spans = []; + List links = re.allMatches(text).toList(); + + for (String text in texts) { + spans.add(TextSpan(text: text, style: textStyle)); + if (links.length > 0) { + RegExpMatch match = links.removeAt(0); + String link = match.input.substring(match.start, match.end); + + // add the link + spans.add( + TextSpan( + text: link, + style: linkStyle, + recognizer: TapGestureRecognizer() + ..onTap = () { + String l = link.startsWith('www') ? 'http://$link' : link; + if (l.endsWith('.') || l.endsWith(',') || l.endsWith(';')) { + l = l.substring(0, l.length - 1); + } + }, + ), + ); + } + } + + return TextSpan(children: spans); +} diff --git a/lib/src/utils/regex.dart b/lib/src/utils/regex.dart index e69de29..17abebc 100644 --- a/lib/src/utils/regex.dart +++ b/lib/src/utils/regex.dart @@ -0,0 +1,7 @@ +RegExp urlRegex = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+'); + +RegExp hashtagRegex = + RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+'); + +RegExp emailRegex = RegExp( + r"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$"); diff --git a/lib/src/utils/utils.dart b/lib/src/utils/utils.dart index e69de29..145ff75 100644 --- a/lib/src/utils/utils.dart +++ b/lib/src/utils/utils.dart @@ -0,0 +1 @@ + nullify(dynamic value) {} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index e25b607..6826152 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ author: homepage: environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' flutter: ">=1.17.0" dependencies: @@ -15,7 +15,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - test: + test: ^1.16.5 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/linkify_text_test.dart b/test/linkify_text_test.dart index 0da434d..ee9468a 100644 --- a/test/linkify_text_test.dart +++ b/test/linkify_text_test.dart @@ -1,5 +1,3 @@ import 'package:flutter_test/flutter_test.dart'; -void main() { - test('adds one to input values', () {}); -} +void main() {} diff --git a/test/regex_test.dart b/test/regex_test.dart new file mode 100644 index 0000000..64edf39 --- /dev/null +++ b/test/regex_test.dart @@ -0,0 +1,49 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:linkify_text/src/utils/regex.dart'; + +// final text = +// "My website url: https://blasanka.github.io/Google search using: www.google.com, social media is facebook.com, http://example.com/method?param=flutterstackoverflow.com is my greatest website. DartPad share: https://github.com/dart-lang/dart-pad/wiki/Sharing-Guide, see this example and edit it here"; + +void main() { + group('Regular Expression', () { + test("Should match all emails", () { + List _emails = ["hello@world.com", "foo.bar@js.com"]; + _emails.forEach((e) { + bool hasMatch = emailRegex.hasMatch(e); + expect(hasMatch, true); + }); + }); + test("Should match all urls", () { + List _urls = [ + "http://domain.com", + "http://domain.com/", + "https://domain.com", + "https://domain.com/", + "https://www.domain.com", + "www.domain.com", + "https://domain.com/Google?", + "https://domain.com/Google/search", + "https://domain.com/Google?param=", + "https://domain.com/Google?param=helloworld", + "https://sub.domain.com/Google?param=helloworld#hash", + ]; + _urls.forEach((u) { + bool hasMatch = emailRegex.hasMatch(u); + expect(hasMatch, true); + }); + }); + test("Should match all hashtags", () { + List _hashtags = [ + "#1", + "#trending", + "#_trending", + "#TRENDING", + "#trending_topic", + ]; + _hashtags.forEach((h) { + bool hasMatch = emailRegex.hasMatch(h); + expect(hasMatch, true); + }); + }); + }); +}