Skip to content

Commit

Permalink
🔀 Merge pull request #5 from Komposten/release-2.0.0
Browse files Browse the repository at this point in the history
Release 2.0.0
  • Loading branch information
Komposten authored Nov 28, 2020
2 parents 30e42b7 + 09807c2 commit 7e5d426
Show file tree
Hide file tree
Showing 27 changed files with 1,435 additions and 650 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ dart:
dart_task:
- test: --platform vm
- test: --platform chrome
- dartanalyzer: true
- dartanalyzer: example lib test
- dartfmt: true
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
## 2.0.0
### API changes
- `SuffixRules` is no longer static.
- Multiple instances can be created with different rule lists.
- `DefaultSuffixRules` has been added to provide a statically accessible rules list with a similar API to the old `SuffixRules`.
- `PublicSuffix` now takes an optional argument when created to specify the `SuffixRules` to use. If unspecified, `DefaultSuffixRules` is used (similar to previous version).
- Move `SuffixRules.process` and `SuffixRules.validate` to a new class, `SuffixRulesParser`.
- The default constructor in `PublicSuffix` now takes either a String or a URL.
- Add factory methods `PublicSuffix.fromString` and fromUrl with adjustable leniency for invalid URLs ([fixes #4](https://github.com/Komposten/public_suffix/issues/4)).
- These allow creation of `PublicSuffix` instances without getting exceptions thrown if the URL is null/empty/invalid. See the documentation for full details.
- Rename `PublicSuffix.sourceUri` to `PublicSuffix.sourceUrl`.
- Remove export of `public_suffix.dart` from the helper files.
- Rename `public_suffix_io.dart` and `public_suffix_browser.dart` to `io_helper.dart` and `browser_helper.dart`.

### Additions
- `END PRIVATE` is now respected when loading a suffix list. This means that a list can contain the private section anywhere in the list or even have multiple private sections.
- `SuffixRules.hasRules` - checks if at least one rule exists.
- `SuffixRules.fromRules` - creates a `SuffixRules` instance from an existing list of `Rule` objects.

### Fixes
- Fix rule matching not working for rules with wildcards not in the first position (e.g. `a.*.c`).
- Allow null lists when creating `SuffixRules` objects (treated as empty lists).

## 1.2.1
- Improved the suffix list format documentation in `SuffixRules` and the `SuffixRulesHelper`s.
- Improved documentation of `DomainUtils`.
Expand Down
81 changes: 67 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,30 @@ public_suffix is a dart library for identifying the public suffixes (or TLDs), r
- Check if URLs are subdomains, have valid domain parts, or end with known suffixes.

## Usage
### Option 1 - Using a statically accessible list
1) Import `public_suffix.dart`.
2) [Initialise `SuffixRules`](#initialising-suffixrules) from a suffix rule list.
2) [Initialise `DefaultSuffixRules`](#initialising-defaultsuffixrules) from a suffix rule list.
3) Create instances of `PublicSuffix` to parse URLs.
4) Access the different URL components through the `PublicSuffix` objects.

### Short example
### Option 2 - Using a non-static list
1) Import `public_suffix.dart`.
2) [Create a `SuffixRules` instance](#creating-suffixrules-instances) from a suffix rule list.
3) Create instances of `PublicSuffix` to parse URLs, passing in the `SuffixRules` instance from step 2.
4) Access the different URL components through the `PublicSuffix` objects.

### Short example using the static list
```dart
import 'package:public_suffix/public_suffix.dart';
main() {
// Load a list of suffix rules from publicsuffix.org.
String suffixListString = 'load the list into this string';
SuffixRules.initFromString(suffixListString);
var suffixListString = 'load the list into this string';
DefaultSuffixRules.initFromString(suffixListString);
// Parse a URL.
PublicSuffix parsedUrl =
PublicSuffix.fromString('https://www.komposten.github.io');
var parsedUrl =
PublicSuffix.fromString('https://www.komposten.github.io');
// Obtain information using the many getters, for example:
print(parsedUrl.suffix); // github.io
Expand All @@ -46,28 +53,62 @@ main() {
}
```

### Initialising SuffixRules
## Obtaining a suffix list
public_suffix requires a list of suffix rules to work. There is no list bundled by default as these lists are updated frequently.
Instead you'll have to load a list on your own and pass that list to `SuffixRules`. There are two ways of doing this:
1) Load the list using your own code and pass it to `SuffixRules.initFromString()`:

To use public_suffix you need to first load a list of rules, and then either initialise `DefaultSuffixRules` (for static access) or create
your own instance of `SuffixRules`.

### Initialising DefaultSuffixRules
The easiest way to use public_suffix is to get a list of rules and pass that list to `DefaultSuffixRules`. The `PublicSuffix` class will use this
list by default.

There are two ways of initialising it:
1) Load the list using your own code and pass it to `DefaultSuffixRules.initFromString()`:
```dart
//Example using Flutter
import 'package:flutter/services.dart';
import 'package:public_suffix/public_suffix.dart';
main() {
var suffixList = rootBundle.loadString('assets/public_suffix_list.dat');
DefaultSuffixRules.initFromString(suffixList);
}
```
2) Import either the `dart:io` or the `dart:html`-based helper and load the list from a URI:
```dart
//Example using dart:io; for dart:html use browser_helper.dart instead.
import 'package:public_suffix/io_helper.dart';
main() async {
var uri = Uri.parse('https://publicsuffix.org/list/public_suffix_list.dat');
await SuffixRulesHelper.initDefaultListFromUri(listUri);
}
```

### Creating SuffixRules instances
An alternative way to use public_suffix is to manually create an instance of `SuffixRules` and then pass that in when creating `PublicSuffix` objects.

Just like before, there are two ways of doing this:
1) Load the list using your own code and pass it to one of `SuffixRules` constructors:
```dart
//Example using Flutter
import 'package:flutter/services.dart';
import 'package:public_suffix/public_suffix.dart';
main() {
var suffixList = rootBundle.loadString('assets/public_suffix_list.dat');
SuffixRules.initFromString(suffixList);
var suffixRules = SuffixRules.fromString(suffixList);
}
```
2) Import either the `dart:io` or the `dart:html`-based helper and load the list from a URI:
```dart
//Example using dart:io; for dart:html use public_suffix_browser.dart instead.
import 'package:public_suffix/public_suffix_io.dart';
//Example using dart:io; for dart:html use browser_helper.dart instead.
import 'package:public_suffix/io_helper.dart';
main() async {
Uri uri = Uri.parse('https://publicsuffix.org/list/public_suffix_list.dat');
await SuffixRulesHelper.initFromUri(listUri);
var uri = Uri.parse('https://publicsuffix.org/list/public_suffix_list.dat');
var suffixRules = await SuffixRulesHelper.createListFromUri(listUri);
}
```

Expand All @@ -82,5 +123,17 @@ Several utility functions can be found in the `DomainUtils` class (imported from

Most of these create PublicSuffix objects internally. If you are already working with PublicSuffix objects, there are similar methods you can call directly on those to avoid creating new ones.

## Contributing
### Git message conventions
public_suffix uses [gitmoji](https://gitmoji.carloscuesta.me) to indicate commit types (bug fix, new feature, re-factor, etc.)

Commit messages should generally follow this format:
```
:emoji: Write a short summary on line one
Put additional information two lines down.
Use imperative forms of verbs. For example "Add", "Fix" and "Move" instead of "Added", "Fixed" and "Moved".
```

## License
public_suffix is licensed under the MIT license. See [LICENSE](https://github.com/Komposten/public_suffix/blob/master/LICENSE) for the full license text.
31 changes: 31 additions & 0 deletions example/instance_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:public_suffix/io_helper.dart';
import 'package:public_suffix/public_suffix.dart';

// This is an example that creates an instance of SuffixRules
// directly and uses that instead of DefaultSuffixRules.
Future<void> main() async {
// Create a SuffixRules instance from a list of suffix rules from
// publicsuffix.org.
var suffixRules = await SuffixRulesHelper.createListFromUri(
Uri.parse('https://publicsuffix.org/list/public_suffix_list.dat'));

// Parse a URL.
// Specify a rule list to use that instead of DefaultSuffixRules.
var parsedUrl = PublicSuffix.fromString('https://www.komposten.github.io',
suffixRules: suffixRules);

// Results when matching against both ICANN/IANA and private suffixes.
print(parsedUrl.suffix); // github.io
print(parsedUrl.root); // komposten
print(parsedUrl.domain); // komposten.github.io

// Results when matching against only ICANN/IANA suffixes.
print(parsedUrl.icannSuffix); // io
print(parsedUrl.icannRoot); // github
print(parsedUrl.icannDomain); // github.io

// Punycode decoded results.
parsedUrl = PublicSuffix.fromString('https://www.xn--6qq79v.cn');
print(parsedUrl.domain); // xn--6qq79v.cn
print(parsedUrl.punyDecoded.domain); // 你好.cn
}
16 changes: 10 additions & 6 deletions example/main.dart → example/static_list.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import 'package:public_suffix/public_suffix_io.dart';
import 'package:public_suffix/io_helper.dart';
import 'package:public_suffix/public_suffix.dart';

// This is an example that initialises DefaultSuffixRules
// with a statically accessible list of suffix rules.
Future<void> main() async {
// Load a list of suffix rules from publicsuffix.org.
await SuffixRulesHelper.initFromUri(
// Initialise DefaultSuffixRules with a list of suffix rules from
// publicsuffix.org.
await SuffixRulesHelper.initDefaultListFromUri(
Uri.parse('https://publicsuffix.org/list/public_suffix_list.dat'));

// Parse a URL.
PublicSuffix parsedUrl =
PublicSuffix.fromString('https://www.komposten.github.io');
// If we don't specify a rule list, PublicSuffix uses DefaultSuffixRules.
var parsedUrl = PublicSuffix.fromString('https://www.komposten.github.io');

// Results when matching against both ICANN/IANA and private suffixes.
print(parsedUrl.suffix); // github.io
Expand All @@ -26,5 +30,5 @@ Future<void> main() async {

// Dispose the list to unload it from memory if you wish.
// This is probably not needed since the list is relatively small.
SuffixRules.dispose();
DefaultSuffixRules.dispose();
}
1 change: 0 additions & 1 deletion lib/public_suffix_browser.dart → lib/browser_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@
* of this project.
*/

export 'public_suffix.dart';
export 'src/browser/suffix_rules_helper.dart';
1 change: 0 additions & 1 deletion lib/public_suffix_io.dart → lib/io_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@
* of this project.
*/

export 'public_suffix.dart';
export 'src/io/suffix_rules_helper.dart';
2 changes: 2 additions & 0 deletions lib/public_suffix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@

export 'src/public_suffix_base.dart';
export 'src/suffix_rules.dart';
export 'src/suffix_rules_parser.dart';
export 'src/default_suffix_rules.dart';
export 'src/utilities.dart';
58 changes: 45 additions & 13 deletions lib/src/browser/suffix_rules_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,60 @@
*/
import 'dart:html';

import 'package:public_suffix/public_suffix.dart';

import '../suffix_rules.dart';

/// A static helper class for initialising [SuffixRules].
///
/// This class provides simple functions for initialising [SuffixRules]
/// from resources obtained using http requests.
///
/// To initialise directly from strings instead, use [SuffixRules.initFromString].
/// A static helper class for initialising [DefaultSuffixRules] or
/// creating [SuffixRules] instances from resources over http.
class SuffixRulesHelper {
SuffixRulesHelper._();

/// Initialises [SuffixRules] using a suffix list resource obtained from a URI.
/// Initialises [DefaultSuffixRules] using a suffix list resource obtained from a URI.
///
/// See [SuffixRules.fromString] for the expected format of the suffix list.
///
/// [HttpRequest.request] is used to retrieve the resource, and the optional
/// parameters can be used to tweak this request. If more fine-grained control
/// over the request is needed, consider obtaining the suffix list using custom
/// code first and then passing it to [DefaultSuffixRules.initFromString].
///
/// An [Exception] is thrown if the request fails.
static Future<void> initDefaultListFromUri(Uri uri,
{bool withCredentials,
Map<String, String> requestHeaders,
dynamic sendData,
void Function(ProgressEvent) onProgress}) async {
DefaultSuffixRules.initFromString(await _getUri(uri,
withCredentials: withCredentials,
requestHeaders: requestHeaders,
sendData: sendData,
onProgress: onProgress));
}

/// Creates a [SuffixRules] object using a suffix list resource obtained from a URI.
///
/// See [SuffixRules.initFromString] for the expected format of the suffix list.
/// See [SuffixRules.fromString] for the expected format of the suffix list.
///
/// [HttpRequest.request] is used to retrieve the resource, and the optional
/// parameters can be used to tweak this request. If more fine-grained control
/// over the request is needed, consider obtaining the suffix list using custom
/// code first and then passing it to [SuffixRules.initFromString].
/// code first and then passing it to [SuffixRules.fromString].
///
/// An [Exception] is thrown if the request fails.
static Future<void> initFromUri(Uri uri,
static Future<SuffixRules> createListFromUri(Uri uri,
{bool withCredentials,
Map<String, String> requestHeaders,
dynamic sendData,
void Function(ProgressEvent) onProgress}) async {
return SuffixRules.fromString(await _getUri(uri,
withCredentials: withCredentials,
requestHeaders: requestHeaders,
sendData: sendData,
onProgress: onProgress));
}

static Future<String> _getUri(Uri uri,
{bool withCredentials,
Map<String, String> requestHeaders,
dynamic sendData,
Expand All @@ -44,7 +76,7 @@ class SuffixRulesHelper {

switch (request.status) {
case 200:
SuffixRules.initFromString(request.responseText);
return request.responseText;
break;
default:
throw request;
Expand All @@ -58,9 +90,9 @@ class SuffixRulesHelper {

if (object is HttpRequest) {
throw Exception(
"Request for public suffix list failed: [${object.status}] ${object.statusText}");
'Request for public suffix list failed: [${object.status}] ${object.statusText}');
} else {
throw Exception("Request for public suffix list failed: $object");
throw Exception('Request for public suffix list failed: $object');
}
}
}
Expand Down
Loading

0 comments on commit 7e5d426

Please sign in to comment.