diff --git a/.github/workflows/dart.yaml b/.github/workflows/dart.yaml new file mode 100644 index 0000000..aad0c53 --- /dev/null +++ b/.github/workflows/dart.yaml @@ -0,0 +1,69 @@ +name: Dart CI + +on: + push: + branches: + - master + - develop + - release-* + pull_request: + branches: + - master + - develop + - release-* + +jobs: + test: + name: Unit tests + runs-on: ubuntu-latest + strategy: + matrix: + dart_sdk: [ 2.12.0, stable ] + + steps: + - name: Install Dart + uses: dart-lang/setup-dart@v1 + with: + sdk: ${{ matrix.dart_sdk }} + - name: Checkout + uses: actions/checkout@v2 + - name: Install dependencies + run: pub get + - name: Run tests + run: xvfb-run -a pub run test -p vm,chrome --coverage .coverage + - name: Format test coverage as LCOV + run: pub run coverage:format_coverage --lcov --packages=.packages --report-on lib --in .coverage/ --out .coverage/lcov.info + - name: Upload to CodeCov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./.coverage/lcov.info + + + analyse: + name: Code analysis + runs-on: ubuntu-latest + + container: + image: google/dart:latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install dependencies + run: pub get + - name: Run analyser + run: dartanalyzer lib test example + + format: + name: Code format + runs-on: ubuntu-latest + + container: + image: google/dart:latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Check code format + run: dartfmt -n --set-exit-if-changed . \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 39507c6..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: dart -branches: - only: - - master - - /^(?i:release)-.+$/ -dart: - - stable - - "2.2.0" -dart_task: - - test: --platform vm - - test: --platform chrome - - dartanalyzer: example lib test - - dartfmt: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 4967328..c15c84e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 3.0.0 +### API changes +- Minimum Dart SDK requirement changed to 2.12.0. +- All components have been updated for the new [null-safety](https://dart.dev/null-safety/understanding-null-safety) system (courtesy of [bsutton](https://github.com/bsutton)). + +### Fixes +- Fix a couple of broken references in the API documentation. + ## 2.0.1 ### Additions - Add [example/example.md](example/example.md) to make the new examples show up on pub.dev. diff --git a/README.md b/README.md index 926d028..5eb9c89 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # public_suffix [![pub package](https://img.shields.io/pub/v/public_suffix.svg)](https://pub.dev/packages/public_suffix) -[![Build Status](https://travis-ci.com/Komposten/public_suffix.svg?branch=master)](https://travis-ci.com/Komposten/public_suffix) +[![Dart CI](https://github.com/Komposten/public_suffix/actions/workflows/dart.yaml/badge.svg)](https://github.com/Komposten/public_suffix/actions/workflows/dart.yaml) +[![codecov](https://codecov.io/gh/Komposten/public_suffix/branch/master/graph/badge.svg)](https://codecov.io/gh/Komposten/public_suffix) **A domain parser based on the [Public Suffix List](https://publicsuffix.org/)** @@ -10,7 +11,7 @@ public_suffix is a dart library for identifying the public suffixes (or TLDs), r - Identify suffix, root domain, registrable domain (root + suffix) and subdomain from URLs. - Provide your own list of suffix rules to keep up to date with the rules you need. - Get results from matching with only ICANN/IANA rules or also include private ones. - - For example, a private rule can see the full `github.io` as suffix while ICANN only recognises the `io` part. + - For example, a private rule can see the full `github.io` as suffix while ICANN only recognises the `io` part. - Parse punycode encoded URLs and get both encoded and decoded results. - Check if URLs are subdomains, have valid domain parts, or end with known suffixes. @@ -32,14 +33,13 @@ public_suffix is a dart library for identifying the public suffixes (or TLDs), r import 'package:public_suffix/public_suffix.dart'; main() { - // Load a list of suffix rules from publicsuffix.org. + // Load a list of suffix rules. var suffixListString = 'load the list into this string'; DefaultSuffixRules.initFromString(suffixListString); - + // Parse a URL. - var parsedUrl = - PublicSuffix.fromString('https://www.komposten.github.io'); - + var parsedUrl = PublicSuffix(urlString: 'https://www.komposten.github.io'); + // Obtain information using the many getters, for example: print(parsedUrl.suffix); // github.io print(parsedUrl.root); // komposten @@ -47,7 +47,7 @@ main() { print(parsedUrl.icannDomain); // github.io // public_suffix also supports punycoded URLs: - parsedUrl = PublicSuffix.fromString('https://www.xn--6qq79v.cn'); + parsedUrl = PublicSuffix(urlString: 'https://www.xn--6qq79v.cn'); print(parsedUrl.domain); // xn--6qq79v.cn print(parsedUrl.punyDecoded.domain); // 你好.cn } @@ -112,7 +112,7 @@ Just like before, there are two ways of doing this: } ``` -**Note:** Don't overload publicsuffix.org's servers by repeatedly retrieving the suffix list from them. Cache a copy somewhere instead, and update that copy only when the master copy is updated. +**Note:** Don't overload publicsuffix.org's servers by repeatedly retrieving the suffix list from them. Cache a copy somewhere instead, and update that copy when the master copy is updated. ## Utility functions Several utility functions can be found in the `DomainUtils` class (imported from `public_suffix.dart`). These currently include: diff --git a/example/instance_list.dart b/example/instance_list.dart index 0d765fc..04fd9f5 100644 --- a/example/instance_list.dart +++ b/example/instance_list.dart @@ -11,8 +11,8 @@ Future main() async { // Parse a URL. // Specify a rule list to use that instead of DefaultSuffixRules. - var parsedUrl = PublicSuffix.fromString('https://www.komposten.github.io', - suffixRules: suffixRules); + var parsedUrl = PublicSuffix( + urlString: 'https://www.komposten.github.io', suffixRules: suffixRules); // Results when matching against both ICANN/IANA and private suffixes. print(parsedUrl.suffix); // github.io @@ -25,7 +25,8 @@ Future main() async { print(parsedUrl.icannDomain); // github.io // Punycode decoded results. - parsedUrl = PublicSuffix.fromString('https://www.xn--6qq79v.cn'); + parsedUrl = PublicSuffix( + urlString: 'https://www.xn--6qq79v.cn', suffixRules: suffixRules); print(parsedUrl.domain); // xn--6qq79v.cn print(parsedUrl.punyDecoded.domain); // 你好.cn } diff --git a/example/static_list.dart b/example/static_list.dart index 401fcd1..7b473c9 100644 --- a/example/static_list.dart +++ b/example/static_list.dart @@ -11,7 +11,7 @@ Future main() async { // Parse a URL. // If we don't specify a rule list, PublicSuffix uses DefaultSuffixRules. - var parsedUrl = PublicSuffix.fromString('https://www.komposten.github.io'); + var parsedUrl = PublicSuffix(urlString: 'https://www.komposten.github.io'); // Results when matching against both ICANN/IANA and private suffixes. print(parsedUrl.suffix); // github.io @@ -24,7 +24,7 @@ Future main() async { print(parsedUrl.icannDomain); // github.io // Punycode decoded results. - parsedUrl = PublicSuffix.fromString('https://www.xn--6qq79v.cn'); + parsedUrl = PublicSuffix(urlString: 'https://www.xn--6qq79v.cn'); print(parsedUrl.domain); // xn--6qq79v.cn print(parsedUrl.punyDecoded.domain); // 你好.cn diff --git a/lib/src/browser/suffix_rules_helper.dart b/lib/src/browser/suffix_rules_helper.dart index 497cbe1..644ff7b 100644 --- a/lib/src/browser/suffix_rules_helper.dart +++ b/lib/src/browser/suffix_rules_helper.dart @@ -29,10 +29,10 @@ class SuffixRulesHelper { /// /// An [Exception] is thrown if the request fails. static Future initDefaultListFromUri(Uri uri, - {bool withCredentials, - Map requestHeaders, + {bool? withCredentials, + Map? requestHeaders, dynamic sendData, - void Function(ProgressEvent) onProgress}) async { + void Function(ProgressEvent)? onProgress}) async { DefaultSuffixRules.initFromString(await _getUri(uri, withCredentials: withCredentials, requestHeaders: requestHeaders, @@ -51,10 +51,10 @@ class SuffixRulesHelper { /// /// An [Exception] is thrown if the request fails. static Future createListFromUri(Uri uri, - {bool withCredentials, - Map requestHeaders, + {bool? withCredentials, + Map? requestHeaders, dynamic sendData, - void Function(ProgressEvent) onProgress}) async { + void Function(ProgressEvent)? onProgress}) async { return SuffixRules.fromString(await _getUri(uri, withCredentials: withCredentials, requestHeaders: requestHeaders, @@ -62,11 +62,11 @@ class SuffixRulesHelper { onProgress: onProgress)); } - static Future _getUri(Uri uri, - {bool withCredentials, - Map requestHeaders, + static Future _getUri(Uri uri, + {bool? withCredentials, + Map? requestHeaders, dynamic sendData, - void Function(ProgressEvent) onProgress}) async { + void Function(ProgressEvent)? onProgress}) async { try { var request = await HttpRequest.request(uri.toString(), withCredentials: withCredentials, @@ -77,7 +77,6 @@ class SuffixRulesHelper { switch (request.status) { case 200: return request.responseText; - break; default: throw request; } @@ -85,7 +84,7 @@ class SuffixRulesHelper { var object = e; if (e is ProgressEvent) { - object = e.target; + throw Exception('Request for public suffix list failed: ${e.target}'); } if (object is HttpRequest) { diff --git a/lib/src/default_suffix_rules.dart b/lib/src/default_suffix_rules.dart index 8352b3d..e5f80b6 100644 --- a/lib/src/default_suffix_rules.dart +++ b/lib/src/default_suffix_rules.dart @@ -15,20 +15,20 @@ import 'package:public_suffix/public_suffix.dart'; /// /// After initialisation the rules can be accessed using [rules]. class DefaultSuffixRules { - static SuffixRules _rules; + static SuffixRules? _rules; /// Returns the default suffix rules. /// - /// [null] is returned if the list has not been initialised. - static SuffixRules get rules => _rules; + /// `null` is returned if the list has not been initialised. + static SuffixRules? get rules => _rules; /// Returns the default suffix rules or throws if they haven't /// been initialised. static SuffixRules rulesOrThrow() { if (hasInitialised()) { - return rules; + return rules!; } else { - throw StateError('PublicSuffixList has not been initialised!'); + throw StateError('DefaultSuffixRules has not been initialised!'); } } @@ -40,7 +40,7 @@ class DefaultSuffixRules { /// Initialises the default rule list from a multi-rule string. /// /// See [SuffixRules.fromString] for details. - static void initFromString(String rules) { + static void initFromString(String? rules) { _rules = SuffixRules.fromString(rules); } @@ -60,7 +60,7 @@ class DefaultSuffixRules { /// Disposes of the default rule list. /// - /// [hasInitialised] will return [false] after this has been called. + /// [hasInitialised] will return `false` after this has been called. static void dispose() { _rules = null; } diff --git a/lib/src/io/suffix_rules_helper.dart b/lib/src/io/suffix_rules_helper.dart index 8d84057..774b1da 100644 --- a/lib/src/io/suffix_rules_helper.dart +++ b/lib/src/io/suffix_rules_helper.dart @@ -69,7 +69,6 @@ class SuffixRulesHelper { switch (response.statusCode) { case 200: return await response.transform(Utf8Decoder()).join(); - break; default: throw Exception( 'Request for public suffix list failed: [${response.statusCode}]'); diff --git a/lib/src/public_suffix_base.dart b/lib/src/public_suffix_base.dart index 05d35e8..d313d39 100644 --- a/lib/src/public_suffix_base.dart +++ b/lib/src/public_suffix_base.dart @@ -15,20 +15,21 @@ import 'suffix_rules.dart'; /// A description of the public suffix, root domain and registrable domain for a URL. class PublicSuffix { - Uri _sourceUrl; + late final Uri _sourceUrl; bool _sourcePunycoded = false; - bool _hasKnownSuffix; - String _root; - String _suffix; - String _domain; - String _subdomain; - String _icannRoot; - String _icannSuffix; - String _icannDomain; - String _icannSubdomain; - - PublicSuffix _punyDecoded; + late final bool _hasKnownSuffix; + late final String _root; + late final String _suffix; + String? _domain; + String? _subdomain; + + late final String _icannRoot; + late final String _icannSuffix; + String? _icannDomain; + String? _icannSubdomain; + + late final PublicSuffix _punyDecoded; Uri get sourceUrl => _sourceUrl; @@ -36,14 +37,14 @@ class PublicSuffix { /// /// The registrable domain is the public suffix and one preceding label. /// For example, `images.google.co.uk` has the registrable domain `google.co.uk`. - String get domain => _domain; + String? get domain => _domain; /// Returns the subdomain part of the URL, based on both ICANN/IANA and private rules. /// /// The subdomain is the part of the host that precedes the registrable domain /// (see [domain]). /// For example, `images.google.co.uk` has the subdomain `images`. - String get subdomain => _subdomain; + String? get subdomain => _subdomain; /// Returns the root domain part of the URL, based on both ICANN/IANA and private rules. /// @@ -62,14 +63,14 @@ class PublicSuffix { /// /// The registrable domain is the public suffix and one preceding label. /// For example, `images.google.co.uk` has the registrable domain `google.co.uk`. - String get icannDomain => _icannDomain; + String? get icannDomain => _icannDomain; /// Returns the subdomain part of the URL, based on ICANN/IANA rules. /// /// The subdomain is the part of the host that precedes the registrable domain /// (see [domain]). /// For example, `images.google.co.uk` has the subdomain `images`. - String get icannSubdomain => _icannSubdomain; + String? get icannSubdomain => _icannSubdomain; /// Returns the root domain part of the URL, based on ICANN/IANA rules. /// @@ -89,7 +90,7 @@ class PublicSuffix { /// Checks if the URL was matched with a private rule rather than an ICANN/IANA rule. /// - /// If [true], then [root], [suffix] and [domain] will be different from the + /// If `true`, then [root], [suffix] and [domain] will be different from the /// `icann`-prefixed getters. bool isPrivateSuffix() => icannSuffix != _suffix; @@ -100,9 +101,9 @@ class PublicSuffix { /// Checks if the registrable domain is valid. /// - /// If [icann] is [true] the check will be based on [icannDomain], otherwise + /// If [icann] is `true` the check will be based on [icannDomain], otherwise /// [domain] is used. - /// If [acceptDefaultRule] is [false] URLs with suffixes only matching the + /// If [acceptDefaultRule] is `false` URLs with suffixes only matching the /// default rule (`*`) will be seen as invalid. bool hasValidDomain({bool icann = false, bool acceptDefaultRule = true}) { var _domain = (icann ? icannDomain : domain); @@ -117,23 +118,23 @@ class PublicSuffix { /// Checks if this object represents a subdomain of another. /// /// The domain and subdomain properties are compared to determine if - /// this object represents a subdomain of [other]. If [icann] is [true], + /// this object represents a subdomain of [other]. If [icann] is `true`, /// comparison will be based on only the ICANN/IANA rules. /// /// For example, `http://images.google.co.uk` is a subdomain of `http://google.co.uk`. /// /// If [other] has a subdomain and this object represents a subdomain of that, - /// [true] is still returned. + /// `true` is still returned. bool isSubdomainOf(PublicSuffix other, {bool icann = false}) { if (icann) { return icannDomain == other.icannDomain && icannSubdomain != null && (other.icannSubdomain == null || - icannSubdomain.endsWith(other.icannSubdomain)); + icannSubdomain!.endsWith(other.icannSubdomain!)); } else { return domain == other.domain && subdomain != null && - (other.subdomain == null || subdomain.endsWith(other.subdomain)); + (other.subdomain == null || subdomain!.endsWith(other.subdomain!)); } } @@ -158,8 +159,8 @@ class PublicSuffix { /// [suffixRules] can be used to specify the rules to be used when /// parsing the URL. If not specified, [DefaultSuffixRules.rules] will /// be used. - factory PublicSuffix.fromString(String url, - {SuffixRules suffixRules, Leniency leniency = Leniency.allowEmptyUrl}) { + static PublicSuffix? fromString(String? url, + {SuffixRules? suffixRules, Leniency leniency = Leniency.allowEmptyUrl}) { try { return PublicSuffix(urlString: url, suffixRules: suffixRules); } catch (e) { @@ -193,8 +194,8 @@ class PublicSuffix { /// [suffixRules] can be used to specify the rules to be used when /// parsing the URL. If not specified, [DefaultSuffixRules.rules] will /// be used. - factory PublicSuffix.fromUrl(Uri url, - {SuffixRules suffixRules, Leniency leniency = Leniency.allowEmptyUrl}) { + static PublicSuffix? fromUrl(Uri? url, + {SuffixRules? suffixRules, Leniency leniency = Leniency.allowEmptyUrl}) { try { return PublicSuffix(url: url, suffixRules: suffixRules); } catch (e) { @@ -209,11 +210,15 @@ class PublicSuffix { } PublicSuffix._(this._sourceUrl, String host, this._root, this._suffix, - this._icannRoot, this._icannSuffix) { + this._icannRoot, this._icannSuffix, + {required bool hasKnownSuffix}) + : _hasKnownSuffix = hasKnownSuffix { _domain = _buildRegistrableDomain(_root, _suffix); _icannDomain = _buildRegistrableDomain(_icannRoot, _icannSuffix); _subdomain = _getSubdomain(host, _domain); _icannSubdomain = _getSubdomain(host, _icannDomain); + + _punyDecoded = this; } /// Creates a new instance from a URL. @@ -229,12 +234,12 @@ class PublicSuffix { /// /// Throws an [ArgumentError] if [sourceUrl] is missing the authority component /// (e.g. if no protocol is specified). - PublicSuffix({Uri url, String urlString, SuffixRules suffixRules}) { + PublicSuffix({Uri? url, String? urlString, SuffixRules? suffixRules}) { if (url == null && urlString == null) { throw ArgumentError('Either url or urlString must be specified!'); } - _sourceUrl = url ?? Uri.parse(urlString); + _sourceUrl = url ?? Uri.parse(urlString!); if (!sourceUrl.hasAuthority) { throw ArgumentError( 'The URL is missing the authority component: $sourceUrl'); @@ -247,8 +252,8 @@ class PublicSuffix { void _parseUrl(Uri url, Map> suffixMap) { var host = _decodeHost(url); var matchingRules = _findMatchingRules(host, suffixMap); - var prevailingIcannRule = _getPrevailingRule(matchingRules['icann']); - var prevailingAllRule = _getPrevailingRule(matchingRules['all']); + var prevailingIcannRule = _getPrevailingRule(matchingRules['icann']!); + var prevailingAllRule = _getPrevailingRule(matchingRules['all']!); if (prevailingIcannRule.isException) { prevailingIcannRule = _trimExceptionRule(prevailingIcannRule); @@ -275,7 +280,8 @@ class PublicSuffix { var icannPuny = icannData['puny']; _punyDecoded = PublicSuffix._(sourceUrl, host, puny['root'], puny['suffix'], - icannPuny['root'], icannPuny['suffix']); + icannPuny['root'], icannPuny['suffix'], + hasKnownSuffix: _hasKnownSuffix); } String _decodeHost(Uri url) { @@ -288,7 +294,7 @@ class PublicSuffix { _sourcePunycoded = true; var offset = 0; punycodes.forEach((match) { - var decoded = punycodeDecode(match.group(0).substring(4)); + var decoded = punycodeDecode(match.group(0)!.substring(4)); host = host.replaceRange( match.start - offset, match.end - offset, decoded); offset += (match.end - match.start) - decoded.length; @@ -322,7 +328,7 @@ class PublicSuffix { } Rule _getPrevailingRule(List matchingRules) { - Rule prevailing; + Rule? prevailing; var longestLength = 0; for (var rule in matchingRules) { @@ -412,11 +418,11 @@ class PublicSuffix { }).join('.'); } - String _buildRegistrableDomain(String root, String suffix) { + String? _buildRegistrableDomain(String root, String? suffix) { return (root.isNotEmpty ? '$root.$suffix' : null); } - String _getSubdomain(String host, String registrableDomain) { + String? _getSubdomain(String host, String? registrableDomain) { var sub; if (registrableDomain != null) { diff --git a/lib/src/suffix_rules.dart b/lib/src/suffix_rules.dart index 5971b14..6d72697 100644 --- a/lib/src/suffix_rules.dart +++ b/lib/src/suffix_rules.dart @@ -15,8 +15,8 @@ import 'package:public_suffix/src/suffix_rules_parser.dart'; /// Rules are parsed from either a string or a list and can /// then be accessed using [rules] or [ruleMap]. class SuffixRules { - List _rules; - Map> _ruleMap; + late List _rules; + late Map> _ruleMap; /// Returns an unmodifiable list containing the current rules in the original order. List get rules => List.unmodifiable(_rules); @@ -36,19 +36,19 @@ class SuffixRules { /// The list is expected to follow the same format as the list at /// [publicsuffix.org](https://publicsuffix.org/list/public_suffix_list.dat). /// This includes the `BEGIN PRIVATE` and `END PRIVATE` tags/comments, - /// which are used by [process] to separate ICANN/IANA rules from private rules. - SuffixRules.fromString(String rules) + /// which are used by [SuffixRulesParser.process] to separate ICANN/IANA rules from private rules. + SuffixRules.fromString(String? rules) : this.fromList(rules?.split(RegExp(r'[\r\n]+'))); /// Creates a new rule list from a list of rule strings. /// /// [rules] is expected to contain the contents of a suffix list with one rule /// or comment per element. This includes the `BEGIN PRIVATE` and `END PRIVATE` - /// tags/comments, which are used by [process] to separate ICANN/IANA rules + /// tags/comments, which are used by [SuffixRulesParser.process] to separate ICANN/IANA rules /// from private rules. /// See [publicsuffix.org](https://publicsuffix.org/list/public_suffix_list.dat) /// for the rule format. - SuffixRules.fromList(List rules) { + SuffixRules.fromList(List? rules) { rules ??= []; var parser = SuffixRulesParser(); var processed = parser.process(rules); @@ -61,7 +61,7 @@ class SuffixRules { /// [rules] will be validated using a [SuffixRulesParser] /// and a [FormatException] will be thrown if one or more /// rules are invalid. - SuffixRules.fromRules(List rules) { + SuffixRules.fromRules(List? rules) { rules ??= []; var parser = SuffixRulesParser(); parser.validate(rules); @@ -78,7 +78,7 @@ class SuffixRules { for (var rule in rules) { var lastLabel = rule.labels.substring(rule.labels.lastIndexOf('.') + 1); if (map.containsKey(lastLabel)) { - map[lastLabel].add(rule); + map[lastLabel]!.add(rule); } else { var list = [rule]; map[lastLabel] = list; @@ -102,7 +102,7 @@ class Rule { /// If the rule is an ICANN/IANA rule. final bool isIcann; - List _parts; + late List _parts; Rule(String rule, {this.isIcann = true}) : isException = rule.startsWith('!'), @@ -137,7 +137,7 @@ class Rule { int get hashCode { var result = 1; - result = 31 * result + (labels != null ? labels.hashCode : 0); + result = 31 * result + labels.hashCode; result = 31 * result + (isException ? 1231 : 1237); result = 31 * result + (isIcann ? 1231 : 1237); @@ -152,7 +152,7 @@ class Rule { return false; } - Rule otherRule = other; + var otherRule = other; if (labels != otherRule.labels) { return false; } else if (isException != otherRule.isException) { diff --git a/lib/src/utilities.dart b/lib/src/utilities.dart index 0ba90cd..7f255eb 100644 --- a/lib/src/utilities.dart +++ b/lib/src/utilities.dart @@ -34,9 +34,9 @@ class DomainUtils { /// Checks if a URL is a subdomain or a root domain. /// /// [potentialSub] is parsed to a [PublicSuffix] object. It is a subdomain if - /// the [subdomain] property of the object is [null]. + /// the [PublicSuffix.subdomain] property of the object is `null`. /// - /// If [icann] is [true], [icannSubdomain] is checked instead. + /// If [icann] is `true`, [PublicSuffix.icannSubdomain] is checked instead. /// /// Throws a [StateError] if [SuffixRules] has not been initialised. static bool isSubdomain(Uri potentialSub, {bool icann = false}) { @@ -56,11 +56,11 @@ class DomainUtils { /// /// Throws a [StateError] if [suffixRules] is null and /// [DefaultSuffixRules] has not been initialised. - static bool isKnownSuffix(String suffix, {SuffixRules suffixRules}) { + static bool isKnownSuffix(String suffix, {SuffixRules? suffixRules}) { suffixRules ??= DefaultSuffixRules.rulesOrThrow(); var split = suffix.split('.'); - var rules = suffixRules.ruleMap[split.last] ?? []; + var rules = suffixRules.ruleMap[split.last] ?? []; var isKnown = false; for (var rule in rules) { @@ -76,8 +76,8 @@ class DomainUtils { /// Checks if the URL contains a registrable domain part. /// - /// If [icann] is [true] the check will be based on only the ICANN/IANA rules. - /// If [acceptDefaultRule] is [false] URLs with suffixes only matching the + /// If [icann] is `true` the check will be based on only the ICANN/IANA rules. + /// If [acceptDefaultRule] is `false` URLs with suffixes only matching the /// default rule (`*`) will be seen as invalid. /// /// Throws a [StateError] if [SuffixRules] has not been initialised. diff --git a/pubspec.yaml b/pubspec.yaml index 5a843c9..aef0e4b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,17 +1,17 @@ name: public_suffix description: A domain parser based on the Public Suffix List, for identifying the root and suffix/TLD of URLs. -version: 2.0.1 +version: 3.0.0 homepage: https://www.github.com/komposten/ repository: https://www.github.com/komposten/public_suffix issue_tracker: https://www.github.com/komposten/public_suffix/issues environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: - punycode: ^0.1.0 + punycode: ^1.0.0 dev_dependencies: - pedantic: ^1.7.0 - test: ^1.6.10 - http_multi_server: ^2.2.0 # Here because test uses an earlier version that doesn't compile + pedantic: ^1.11.0 + test: ^1.16.8 + coverage: ^1.0.2 diff --git a/test/browser_helper_test.dart b/test/browser_helper_test.dart index 80b4751..db699d6 100644 --- a/test/browser_helper_test.dart +++ b/test/browser_helper_test.dart @@ -11,7 +11,7 @@ void main() { await SuffixRulesHelper.initDefaultListFromUri(Uri.parse( 'https://raw.githubusercontent.com/Komposten/public_suffix/master/test/res/public_suffix_list.dat')); expect(DefaultSuffixRules.hasInitialised(), isTrue); - expect(DefaultSuffixRules.rules.rules, isNotEmpty); + expect(DefaultSuffixRules.rules!.rules, isNotEmpty); }); test('resourceDoesNotExist_fail', () async { diff --git a/test/default_suffix_rules_test.dart b/test/default_suffix_rules_test.dart index f0078ae..7556dc8 100644 --- a/test/default_suffix_rules_test.dart +++ b/test/default_suffix_rules_test.dart @@ -24,8 +24,8 @@ void main() { test('afterInitialising_hasSuffixList', () { DefaultSuffixRules.initFromList(['br', 'nom.br']); expect(DefaultSuffixRules.rules, isNotNull); - expect(DefaultSuffixRules.rules.rules, hasLength(2)); - expect(DefaultSuffixRules.rules.rules, + expect(DefaultSuffixRules.rules!.rules, hasLength(2)); + expect(DefaultSuffixRules.rules!.rules, containsAllInOrder([Rule('br'), Rule('nom.br')])); }); diff --git a/test/io_helper_test.dart b/test/io_helper_test.dart index 8408e46..6290c32 100644 --- a/test/io_helper_test.dart +++ b/test/io_helper_test.dart @@ -13,7 +13,7 @@ void main() { await SuffixRulesHelper.initDefaultListFromUri(Uri.parse( 'https://raw.githubusercontent.com/Komposten/public_suffix/master/test/res/public_suffix_list.dat')); expect(DefaultSuffixRules.hasInitialised(), isTrue); - expect(DefaultSuffixRules.rules.rules, isNotEmpty); + expect(DefaultSuffixRules.rules!.rules, isNotEmpty); }); test('resourceDoesNotExist_fail', () async { @@ -32,7 +32,7 @@ void main() { test('validFileUri_initList', () async { await SuffixRulesHelper.initDefaultListFromUri(getSuffixListFileUri()); expect(DefaultSuffixRules.hasInitialised(), isTrue); - expect(DefaultSuffixRules.rules.rules, isNotEmpty); + expect(DefaultSuffixRules.rules!.rules, isNotEmpty); }); }); diff --git a/test/public_suffix_base_test.dart b/test/public_suffix_base_test.dart index a2b3ee4..f18d20e 100644 --- a/test/public_suffix_base_test.dart +++ b/test/public_suffix_base_test.dart @@ -252,11 +252,11 @@ void main() { }); test('normalUrls_parseCorrectly', () { - var suffix = PublicSuffix.fromString('http://www.pub.dev'); + var suffix = PublicSuffix.fromString('http://www.pub.dev')!; expect(suffix.suffix, equals('dev')); expect(suffix.root, equals('pub')); - suffix = PublicSuffix.fromString('http://www.komposten.github.io'); + suffix = PublicSuffix.fromString('http://www.komposten.github.io')!; expect(suffix.suffix, equals('github.io')); expect(suffix.root, equals('komposten')); }); @@ -313,7 +313,7 @@ void main() { test('normalUrls_parseCorrectly', () { var suffix = - PublicSuffix.fromUrl(Uri.parse('http://www.komposten.github.io')); + PublicSuffix.fromUrl(Uri.parse('http://www.komposten.github.io'))!; expect(suffix.suffix, equals('github.io')); expect(suffix.root, equals('komposten')); }); diff --git a/test/rule_test.dart b/test/rule_test.dart index 0d97a73..17f1a49 100644 --- a/test/rule_test.dart +++ b/test/rule_test.dart @@ -66,11 +66,6 @@ void main() { expect(rule == rule, equals(true)); }); - test('compareWithNull_false', () { - var rule = Rule('ab.cd'); - expect(rule == null, equals(false)); - }); - test('otherClass_false', () { // ignore: unrelated_type_equality_checks expect(Rule('ab.cd') == 'ab.cd', equals(false)); diff --git a/test/suffix_rules_parser_test.dart b/test/suffix_rules_parser_test.dart index e9a3826..b33243b 100644 --- a/test/suffix_rules_parser_test.dart +++ b/test/suffix_rules_parser_test.dart @@ -2,7 +2,7 @@ import 'package:public_suffix/public_suffix.dart'; import 'package:test/test.dart'; void main() { - var parser; + late var parser; setUp(() { parser = SuffixRulesParser();