diff --git a/CHANGELOG.md b/CHANGELOG.md index 86357d4..9ff8d25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ -## 7.0.0+1 -- readme + +## 7.0.1 + +- Fix issue where international phone numbers would be transformed as if those were local ones. ## 7.0.0 This major introduces a more accurate parsing logic taking into account caller and destination country. diff --git a/README.md b/README.md index b2e640e..c3f0a09 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ Dart library for parsing phone numbers. Inspired by Google's libphonenumber and The advantage of this lib instead of libphonenumber is that it instantly supports all platforms (no need for channeling). +## Breaking Changes starting from version 7.0.0 +- Removed most factory methods on PhoneNumber in favor of `parse()` method, e.g. removed `fromRaw()` and substituted it with `parse()`, check the READ.ME +- Renamed validate and validateWithLength to isValid and isValidateLength ## Features @@ -20,11 +23,6 @@ The advantage of this lib instead of libphonenumber is that it instantly support Use the class `PhoneNumber` as a starting point - -```dart -// raw parsing -PhoneNumber.fromRaw('655 5705 76', ) - ```dart import 'package:phone_numbers_parser/phone_numbers_parser.dart'; @@ -56,18 +54,18 @@ void main(List arguments) { 'hey my phone number is: +33 939 876 218, but you can call me on +33 939 876 999 too'; final found = PhoneNumber.findPotentialPhoneNumbers(text); print('found: $found'); - +} ``` # validation ```dart - final valid = frPhone1.validate(); - final validMobile = frPhone1.validate(type: PhoneNumberType.mobile); - final validFixed = frPhone1.validate(type: PhoneNumberType.fixedLine); - print('valid: $valid'); // true - print('valid mobile: $validMobile'); // true - print('valid fixed line: $validFixed'); // false +final valid = frPhone1.validate(); +final validMobile = frPhone1.validate(type: PhoneNumberType.mobile); +final validFixed = frPhone1.validate(type: PhoneNumberType.fixedLine); +print('valid: $valid'); // true +print('valid mobile: $validMobile'); // true +print('valid fixed line: $validFixed'); // false ``` ### Formatting @@ -76,44 +74,41 @@ Formatting is region specific, so the formats will vary by iso code to accommoda for local formats. ```dart - final phoneNumber = - PhoneNumber.parse('2025550119', destinationCountry: IsoCode.US); - final formattedNsn = phoneNumber.getFormattedNsn(); - print('formatted: $formattedNsn'); // 202-555-0119/ 202-555-0119 +final phoneNumber = + PhoneNumber.parse('2025550119', destinationCountry: IsoCode.US); +final formattedNsn = phoneNumber.getFormattedNsn(); +print('formatted: $formattedNsn'); // 202-555-0119/ 202-555-0119 ``` ### Range ```dart - print('Ranges:'); - final first = PhoneNumber.parse('+33 655 5705 00'); - final last = PhoneNumber.parse('+33 655 5705 03'); - final range = PhoneNumber.getRange(first, last); - - print('Count: ${range.count}'); - print('Expand: ${range.expandRange().join(',')}'); - - if (first > last) { - print("this shouldn't be."); - } - - final one = PhoneNumber.parse('+33 655 5705 01'); - final two = PhoneNumber.parse('+33 655 5705 02'); - - if (one.isAdjacentTo(two)) { - print('We are together'); - } - if (one.isSequentialTo(two)) { - print('$two comes after $one'); - } - - /// treat the phone no. like an int - final three = two + 1; - print('Its still a phone No. $three'); - two - 1 == one; - final another = one + 2; - print('$another == $three'); - +print('Ranges:'); +final first = PhoneNumber.parse('+33 655 5705 00'); +final last = PhoneNumber.parse('+33 655 5705 03'); +final range = PhoneNumber.getRange(first, last); + +print('Count: ${range.count}'); +print('Expand: ${range.expandRange().join(',')}'); + +if (first > last) { + print("this shouldn't be."); +} + +final one = PhoneNumber.parse('+33 655 5705 01'); +final two = PhoneNumber.parse('+33 655 5705 02'); + +if (one.isAdjacentTo(two)) { + print('We are together'); +} +if (one.isSequentialTo(two)) { + print('$two comes after $one'); +} + +/// treat the phone no. like an int +final three = two + 1; +print('Its still a phone No. $three'); +two - 1 == one; +final another = one + 2; +print('$another == $three'); ``` - - diff --git a/lib/src/parsers/_international_prefix_parser.dart b/lib/src/parsers/_international_prefix_parser.dart index 40bf71f..954398c 100644 --- a/lib/src/parsers/_international_prefix_parser.dart +++ b/lib/src/parsers/_international_prefix_parser.dart @@ -1,9 +1,9 @@ import 'package:phone_number_metadata/phone_number_metadata.dart'; abstract class InternationalPrefixParser { - /// remove the international prefix of a phone number if present. + /// Removes the exit code from a phone number if present. /// - /// It expects a normalized [phoneNumber] without the country calling code. + /// It expects a normalized [phoneNumber]. /// if phone starts with + it is removed /// if starts with 00 or 011 /// we consider those as internationalPrefix as diff --git a/lib/src/parsers/phone_parser.dart b/lib/src/parsers/phone_parser.dart index aa7aad3..fa4fc98 100644 --- a/lib/src/parsers/phone_parser.dart +++ b/lib/src/parsers/phone_parser.dart @@ -1,12 +1,13 @@ import 'package:meta/meta.dart'; import 'package:phone_number_metadata/phone_number_metadata.dart'; -import 'package:phone_numbers_parser/phone_numbers_parser.dart'; -import 'package:phone_numbers_parser/src/parsers/_country_code_parser.dart'; -import 'package:phone_numbers_parser/src/parsers/_international_prefix_parser.dart'; -import 'package:phone_numbers_parser/src/parsers/_national_number_parser.dart'; -import 'package:phone_numbers_parser/src/parsers/_text_parser.dart'; -import 'package:phone_numbers_parser/src/utils/_metadata_finder.dart'; -import 'package:phone_numbers_parser/src/utils/_metadata_matcher.dart'; + +import '../../phone_numbers_parser.dart'; +import '../utils/_metadata_finder.dart'; +import '../utils/_metadata_matcher.dart'; +import '_country_code_parser.dart'; +import '_international_prefix_parser.dart'; +import '_national_number_parser.dart'; +import '_text_parser.dart'; /// {@template phoneNumber} /// Parses a phone number given caller or destination information. @@ -57,17 +58,22 @@ abstract class PhoneParser { withoutExitCode, destinationMetadata.countryCode, ); - var nsn = NationalNumberParser.removeNationalPrefix( - national, - destinationMetadata, - ); - nsn = NationalNumberParser.transformLocalNsnToInternationalUsingPatterns( - nsn, - destinationMetadata, - ); + final containsCountryCode = national.length != withoutExitCode.length; + var nsn = national; + if (!containsCountryCode) { + nsn = NationalNumberParser.removeNationalPrefix( + national, + destinationMetadata, + ); + nsn = NationalNumberParser.transformLocalNsnToInternationalUsingPatterns( + nsn, + destinationMetadata, + ); + } + // at this point we have the phone number that has been processed, but // if it is invalid, we remove the processing of the nsn part - // this allows for a better behavior in some input usages where the + // this allows for a better behavior in some widget input usages where the // text is changed on validity. final parsed = PhoneNumber(isoCode: destinationMetadata.isoCode, nsn: nsn); if (parsed.isValid()) return parsed; diff --git a/pubspec.lock b/pubspec.lock index 1b825e5..6e6205b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,337 +5,385 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "569ddca58d535e601dd1584afa117710abc999d036c0cd2c51777fb257df78e8" + url: "https://pub.dev" source: hosted - version: "45.0.0" + version: "53.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "10927c4b7c7c88b1adbca278c3d5531db92e2f4b4abf04e2919a800af965f3f5" + url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "5.5.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.1" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.6.3" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" dart_countries: dependency: "direct main" description: name: dart_countries - url: "https://pub.dartlang.org" + sha256: c42fc90c38d57c857960b793c45d9cf2ba227f5eeb43c69d25d9ea47a9d44553 + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.4" frontend_server_client: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.7" lints: dependency: "direct dev" description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: c94db23593b89766cda57aab9ac311e3616cf87c6fa4e9749df032f66f30dcb8 + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.14" meta: dependency: "direct main" description: name: meta - url: "https://pub.dartlang.org" + sha256: "12307e7f0605ce3da64cf0db90e5fcab0869f3ca03f76be6bb2991ce0a55e82b" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.4" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + url: "https://pub.dev" source: hosted version: "2.0.1" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" phone_number_metadata: dependency: "direct main" description: name: phone_number_metadata - url: "https://pub.dartlang.org" + sha256: "5788320b6bc58d85b1151e6406f52caa9c7f879064ed11bd4f945d3ca5c88fda" + url: "https://pub.dev" source: hosted version: "5.0.4" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.3" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306 + url: "https://pub.dev" source: hosted version: "3.0.1" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c + url: "https://pub.dev" source: hosted version: "1.1.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.3" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" source: hosted - version: "0.10.10" + version: "0.10.12" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test: dependency: "direct dev" description: name: test - url: "https://pub.dartlang.org" + sha256: "5301f54eb6fe945daa99bc8df6ece3f88b5ceaa6f996f250efdaaf63e22886be" + url: "https://pub.dev" source: hosted - version: "1.21.4" + version: "1.23.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "6182294da5abf431177fccc1ee02401f6df30f766bc6130a0852c6b6d7ee6b2d" + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.18" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: d2e9240594b409565524802b84b7b39341da36dd6fd8e1660b53ad928ec3e9af + url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.4.24" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: a4040e9852e56bf8a3c5a2e08a56f6facd76e75500cf2a922ce5d52394c4998a + url: "https://pub.dev" source: hosted - version: "9.3.0" + version: "11.0.1" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.17.0 <3.0.0" + dart: ">=2.19.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 26ede31..988ce30 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: phone_numbers_parser description: Dart library for parsing phone numbers. Inspired by Google's libphonenumber and PhoneNumberKit for ios. -version: 7.0.0+1 +version: 7.0.1 homepage: https://github.com/cedvdb/phone_number_parser environment: diff --git a/test/phone_number_test.dart b/test/phone_number_test.dart index d8798d2..82658fa 100644 --- a/test/phone_number_test.dart +++ b/test/phone_number_test.dart @@ -25,10 +25,6 @@ void main() { PhoneNumber.parse('33 6 86 57 90 14').international, equals(international), ); - expect( - PhoneNumber.parse('33 06 86 57 90 14').international, - equals(international), - ); }); test('should parse for caller', () { @@ -102,7 +98,17 @@ void main() { PhoneNumber.parse('0499 99 99 99', destinationCountry: IsoCode.BE) .nsn, equals('499999999')); - // expect() + }); + + test( + 'should not transform international phone numbers from local to international', + () { + final fullBermudaNumber = PhoneNumber.parse('+14412957070'); + final incompleteBermudaNumber = PhoneNumber.parse('+14412957'); + expect(fullBermudaNumber.nsn, equals('4412957070')); // OK + + expect(incompleteBermudaNumber.nsn, + equals('4412957')); // 4414412957 WRONG ( expected) }); test('should parse incomplete raw phone numbers', () {