From a06435f08ae094eabf5cfa94108791c900bf402f Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 27 Feb 2026 07:20:34 +0000 Subject: [PATCH 1/9] chore: remove abandonded oath package inline lints directly in analysis_options.yaml Signed-off-by: mark --- analysis_options.yaml | 108 +++++++++++++++++++++++++++++++----------- pubspec.yaml | 1 - 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 340d8ea..66827d6 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,30 +1,82 @@ -# This file configures the static analysis results for your project (errors, -# warnings, and lints). -# -# This enables the 'recommended' set of lints from `package:lints`. -# This set helps identify many issues that may lead to problems when running -# or consuming Dart code, and enforces writing Dart using a single, idiomatic -# style and format. -# -# If you want a smaller set of lints you can change this to specify -# 'package:lints/core.yaml'. These are just the most critical lints -# (the recommended set includes the core lints). -# The core lints are also what is used by pub.dev for scoring packages. +include: package:lints/recommended.yaml -include: package:oath/strict.yaml +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true -# Uncomment the following section to specify additional rules. - -# linter: -# rules: -# - camel_case_types - -# analyzer: -# exclude: -# - path/to/excluded/files/** - -# For more information about the core and recommended set of lints, see -# https://dart.dev/go/core-lints - -# For additional information about configuring this file, see -# https://dart.dev/guides/language/analysis-options +linter: + rules: + - always_put_required_named_parameters_first + - annotate_redeclares + - avoid_annotating_with_dynamic + - avoid_bool_literals_in_conditional_expressions + - avoid_catches_without_on_clauses + - avoid_catching_errors + - avoid_classes_with_only_static_members + - avoid_double_and_int_checks + - avoid_dynamic_calls + - avoid_equals_and_hash_code_on_mutable_classes + - avoid_escaping_inner_quotes + - avoid_field_initializers_in_const_classes + - avoid_final_parameters + - avoid_futureor_void + - avoid_js_rounded_ints + - avoid_multiple_declarations_per_line + - avoid_positional_boolean_parameters + - avoid_print + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_returning_this + - avoid_setters_without_getters + - avoid_unused_constructor_parameters + - avoid_void_async + - combinators_ordering + - comment_references + - conditional_uri_does_not_exist + - deprecated_consistency + - directives_ordering + - discarded_futures + - do_not_use_environment + - document_ignores + - implicit_reopen + - invalid_runtime_check_with_js_interop_types + - leading_newlines_in_multiline_strings + - matching_super_parameters + - missing_code_block_language_in_doc_comment + - no_literal_bool_comparisons + - noop_primitive_operations + - omit_local_variable_types + - only_throw_errors + - prefer_asserts_in_initializer_lists + - prefer_asserts_with_message + - prefer_constructors_over_static_methods + - prefer_final_in_for_each + - prefer_final_locals + - prefer_if_elements_to_conditional_expressions + - prefer_single_quotes + - public_member_api_docs + - sort_pub_dependencies + - strict_top_level_inference + - throw_in_finally + - unawaited_futures + - unintended_html_in_doc_comment + - unnecessary_async + - unnecessary_await_in_return + - unnecessary_breaks + - unnecessary_ignore + - unnecessary_lambdas + - unnecessary_library_directive + - unnecessary_library_name + - unnecessary_parenthesis + - unnecessary_raw_strings + - unnecessary_statements + - unnecessary_underscores + - unreachable_from_main + - unsafe_variance + - use_is_even_rather_than_modulo + - use_named_constants + - use_null_aware_elements + - use_raw_strings + - use_truncating_division diff --git a/pubspec.yaml b/pubspec.yaml index f44dee6..37f8113 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,5 +20,4 @@ dependencies: dev_dependencies: lints: ^5.0.0 - oath: ^0.4.0 test: ^1.24.0 From 8ad1ff34321b933a1c67946f5c81273490f03d30 Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 27 Feb 2026 07:21:54 +0000 Subject: [PATCH 2/9] chore: upgrade dependencies Signed-off-by: mark --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 37f8113..b1b327b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,8 +16,8 @@ environment: dependencies: collection: ^1.19.1 meta: ^1.16.0 - punycoder: ^0.2.0 + punycoder: ^0.3.0 dev_dependencies: - lints: ^5.0.0 + lints: ^6.1.0 test: ^1.24.0 From 01436201cfd48fdbfa7b5592456c0a24d94be03a Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 27 Feb 2026 07:47:31 +0000 Subject: [PATCH 3/9] Complete package rewrite Signed-off-by: mark --- CHANGELOG.md | 8 + README.md | 107 +- doc/api/__404error.html | 70 +- doc/api/index.html | 130 +- doc/api/index.json | 2 +- doc/api/iri/Iri-class-sidebar.html | 104 + doc/api/iri/Iri-class.html | 448 ++ doc/api/iri/Iri/Iri.file.html | 110 + doc/api/iri/Iri/Iri.fromUri.html | 108 + doc/api/iri/Iri/Iri.html | 140 + doc/api/iri/Iri/Iri.http.html | 120 + doc/api/iri/Iri/Iri.https.html | 120 + doc/api/iri/Iri/Iri.parse.html | 112 + doc/api/iri/Iri/fragment.html | 117 + doc/api/iri/Iri/hashCode.html | 148 + doc/api/iri/Iri/host.html | 122 + doc/api/iri/Iri/operator_equals.html | 145 + doc/api/iri/Iri/path.html | 127 + doc/api/iri/Iri/pathSegments.html | 117 + doc/api/iri/Iri/port.html | 117 + doc/api/iri/Iri/query.html | 117 + doc/api/iri/Iri/queryParameters.html | 117 + doc/api/iri/Iri/replace.html | 148 + doc/api/iri/Iri/resolve.html | 116 + doc/api/iri/Iri/resolveIri.html | 114 + doc/api/iri/Iri/scheme.html | 117 + doc/api/iri/Iri/toString.html | 145 + doc/api/iri/Iri/toUri.html | 131 + doc/api/iri/Iri/toUriString.html | 111 + doc/api/iri/Iri/tryParse.html | 117 + doc/api/iri/Iri/userInfo.html | 117 + doc/api/iri/index.html | 41 +- doc/api/iri/iri-library-sidebar.html | 4 +- doc/api/iri/iri-library.html | 6 +- doc/api/search.html | 23 +- doc/api/static-assets/docs.dart.js | 4776 ++++++++--------- doc/api/static-assets/docs.dart.js.map | 12 +- doc/api/static-assets/styles.css | 2 +- example/iri_example.dart | 17 +- lib/iri.dart | 15 +- ...internationalized_resource_identifier.dart | 1249 ----- lib/src/iri_base.dart | 253 + pubspec.yaml | 4 +- test/iri_test.dart | 772 ++- 44 files changed, 6547 insertions(+), 4449 deletions(-) create mode 100644 doc/api/iri/Iri-class-sidebar.html create mode 100644 doc/api/iri/Iri-class.html create mode 100644 doc/api/iri/Iri/Iri.file.html create mode 100644 doc/api/iri/Iri/Iri.fromUri.html create mode 100644 doc/api/iri/Iri/Iri.html create mode 100644 doc/api/iri/Iri/Iri.http.html create mode 100644 doc/api/iri/Iri/Iri.https.html create mode 100644 doc/api/iri/Iri/Iri.parse.html create mode 100644 doc/api/iri/Iri/fragment.html create mode 100644 doc/api/iri/Iri/hashCode.html create mode 100644 doc/api/iri/Iri/host.html create mode 100644 doc/api/iri/Iri/operator_equals.html create mode 100644 doc/api/iri/Iri/path.html create mode 100644 doc/api/iri/Iri/pathSegments.html create mode 100644 doc/api/iri/Iri/port.html create mode 100644 doc/api/iri/Iri/query.html create mode 100644 doc/api/iri/Iri/queryParameters.html create mode 100644 doc/api/iri/Iri/replace.html create mode 100644 doc/api/iri/Iri/resolve.html create mode 100644 doc/api/iri/Iri/resolveIri.html create mode 100644 doc/api/iri/Iri/scheme.html create mode 100644 doc/api/iri/Iri/toString.html create mode 100644 doc/api/iri/Iri/toUri.html create mode 100644 doc/api/iri/Iri/toUriString.html create mode 100644 doc/api/iri/Iri/tryParse.html create mode 100644 doc/api/iri/Iri/userInfo.html delete mode 100644 lib/src/internationalized_resource_identifier.dart create mode 100644 lib/src/iri_base.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index a5cb1fa..6845b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.2.0 +- Complete package rewrite that is now implemented as a wrapper around the native `Uri` class. +- Automatic Punycode conversion for hostnames in `toUri()`. +- Unicode-aware component accessors (host, path, query, fragment, userInfo). +- Support for standard constructors: `Iri()`, `Iri.http()`, `Iri.https()`, `Iri.file()`. +- Static methods `Iri.parse()` and `Iri.tryParse()`. +- Immutable design with `@immutable` and equality support. + ## 0.1.1 - Minor fixes in documentation diff --git a/README.md b/README.md index 765f0c2..6112147 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,68 @@ -[![pub package](https://img.shields.io/pub/v/iri.svg)](https://pub.dev/packages/iri) -[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) -[![Open in Firebase Studio](https://cdn.firebasestudio.dev/btn/open_light_20.svg)](https://studio.firebase.google.com/import?url=https%3A%2F%2Fgithub.com%2Fdropbear-software%iri) -# IRI - Internationalized Resource Identifiers -A Dart library for parsing, validating, manipulating, and converting -Internationalized Resource Identifiers (IRIs) based on [RFC 3987](https://www.rfc-editor.org/rfc/rfc3987). +# IRI (Internationalized Resource Identifiers) -## Overview +A pure Dart implementation of Internationalized Resource Identifiers (IRI) as defined in [RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987). -Internationalized Resource Identifiers (IRIs) extend the syntax of Uniform -Resource Identifiers (URIs) to support a wider range of characters from the -Universal Character Set (Unicode/ISO 10646). This is essential for representing -resource identifiers in languages that use characters outside the US-ASCII range. +This package provides an `Iri` class that acts as a Unicode-aware wrapper around Dart's native `Uri` class. It handles the mapping between IRIs and URIs, including automatic Punycode conversion for hostnames and UTF-8 percent-encoding for other components. -This package provides the `IRI` class to work with IRIs in Dart applications. -It handles the necessary conversions between IRIs and standard URIs, including: +## Features -* **Punycode encoding/decoding** for internationalized domain names (IDNs) within the host component. -* **Percent encoding/decoding** for other non-ASCII characters in various IRI components, using UTF-8 as required by the standard. +- **Standard Compliant**: Implements the IRI-to-URI mapping and URI-to-IRI conversion rules from RFC 3987. +- **Punycode Support**: Automatically converts non-ASCII hostnames to Punycode. +- **Unicode-Aware**: Access components (path, query, fragment, etc.) in their original Unicode form. +- **Normalization**: Automatically applies **NFKC** (Normalization Form KC) to all inputs as recommended by RFC 3987 to prevent comparison false-negatives. +- **IDNA Separators**: Supports international domain separators (`。`, `.`, `。`) during parsing and conversion. +- **Mailto Support**: Special handling for `mailto:` IRIs, ensuring email domain parts are correctly Punycode-encoded. +- **Familiar API**: Mirrors the Dart `Uri` class API, including `resolve`, `resolveIri`, and `replace`. +- **Immutable**: The `Iri` class is immutable and supports equality checks. -## Features +## RFC 3987 Compliance & Limitations -* **Parse IRI strings:** Create `IRI` objects from strings. -* **Validate IRIs:** Check if strings conform to RFC 3987 syntax. -* **Access Components:** Easily get decoded IRI components like `scheme`, `host`, `path`, `query`, `fragment`, `userInfo`, `port`. -* **IRI-to-URI Conversion:** Convert an `IRI` object to a standard Dart `Uri` object, applying Punycode and percent-encoding according to RFC 3987 rules. -* **URI-to-IRI Conversion:** Convert a standard `Uri` back into an `IRI`, decoding percent-encoded sequences where appropriate. -* **Normalization:** Applies syntax-based normalization including: - * Case normalization (scheme, host). - * Percent-encoding normalization (uses uppercase hex, decodes unreserved characters where possible in IRI representation). - * Path segment normalization (removes `.` and `..` segments). -* **Comparison:** Compare `IRI` objects based on their code point sequence (simple string comparison). +While this package aims for high compatibility with RFC 3987, there are known areas where the current implementation deviates from the strict specification: -## Getting Started +1. **Robust URI-to-IRI Decoding (RFC 3987 Section 3.2)**: When converting from a `Uri` to an `Iri`, the package currently uses standard UTF-8 decoding. If a percent-encoded sequence is invalid UTF-8 (e.g., `%FC`), the implementation may throw a `FormatException` instead of preserving the percent-encoding as required by the RFC. +2. **Prohibited Characters (RFC 3987 Section 4.1)**: Certain Unicode characters (like bidirectional control characters `U+202E`) are prohibited from appearing directly in an IRI. Currently, these characters are decoded if present in a URI, whereas they should remain percent-encoded. +3. **Bidi Validation (RFC 3987 Section 4.2)**: The package does not currently perform structural validation of bidirectional IRIs (e.g., ensuring RTL components don't mix directions incorrectly). -Add the package to your `pubspec.yaml`: +These areas **may** be a part of future updates. For most common use cases involving standard Unicode text in paths and hosts, the package provides a robust experience. -```yaml -dependencies: - iri: ^0.1.0 -``` +## Getting started -Then, import the library in your Dart code: +Add `iri` to your `pubspec.yaml` dependencies: -```dart -import 'package:iri/iri.dart'; +```yaml +dependencies: + iri: ^0.2.0 ``` ## Usage -Here's a basic example demonstrating how to create an `IRI` and convert it to a `Uri`: + +### Basic Parsing and Conversion ```dart import 'package:iri/iri.dart'; void main() { - // 1. Create an IRI from a string containing non-ASCII characters. - // 例子 means "example" in Chinese. - // The path contains 'ȧ' (U+0227 LATIN SMALL LETTER A WITH DOT ABOVE). - final iri = IRI('https://例子.com/pȧth?q=1'); - - // 2. Print the original IRI string representation. - print('Original IRI: $iri'); - // Output: Original IRI: https://例子.com/pȧth?q=1 - - // 3. Convert the IRI to its standard URI representation. - // - The host (例子.com) is converted to Punycode (xn--fsqu00a.com). - // - The non-ASCII path character 'ȧ' (UTF-8 bytes C8 A7) is percent-encoded (%C8%A7). + // Parse an IRI with Unicode characters + final iri = Iri.parse('http://résumé.example.org/résumé'); + + print('IRI host: ${iri.host}'); // résumé.example.org + print('IRI path: ${iri.path}'); // /résumé + + // Convert to a standard URI for network operations final uri = iri.toUri(); - print('Converted URI: $uri'); - // Output: Converted URI: https://xn--fsqu00a.com/p%C8%A7th?q=1 + print('URI host: ${uri.host}'); // xn--rsum-bpad.example.org + print('URI string: $uri'); // http://xn--rsum-bpad.example.org/r%C3%A9sum%C3%A9 +} +``` - // 4. Access components (values are decoded for IRI representation). - print('Scheme: ${iri.scheme}'); // Output: Scheme: https - print('Host: ${iri.host}'); // Output: Host: 例子.com - print('Path: ${iri.path}'); // Output: Path: /pȧth - print('Query: ${iri.query}'); // Output: Query: q=1 +### Creating IRIs from Components - // 5. Compare IRIs - final iri2 = IRI('https://例子.com/pȧth?q=1'); - print('IRIs equal: ${iri == iri2}'); // Output: IRIs equal: true +```dart +final iri = Iri( + scheme: 'https', + host: 'münchen.test', + path: '/city', +); - final iri3 = IRI('https://example.com/'); - print('IRIs equal: ${iri == iri3}'); // Output: IRIs equal: false -} -``` \ No newline at end of file +print(iri.toUri()); // https://xn--mnchen-3ya.test/city +``` diff --git a/doc/api/__404error.html b/doc/api/__404error.html index 63ee65f..04d34f3 100644 --- a/doc/api/__404error.html +++ b/doc/api/__404error.html @@ -30,33 +30,41 @@ -
- -
+
-
-

404: Something's gone wrong :-(

-
-

You've tried to visit a page that doesn't exist. Luckily this site - has other pages.

-

If you were looking for something specific, try searching: +

+

404: Something's gone wrong :-(

+
+

+ You've tried to visit a page that doesn't exist. Luckily this site has + other pages. +

+
+ If you were looking for something specific, try searching: -

-
-
- +
+
+ + - + +
iri - 0.1.1 + 0.2.0
diff --git a/doc/api/index.html b/doc/api/index.html index 7794d26..61c3fce 100644 --- a/doc/api/index.html +++ b/doc/api/index.html @@ -30,98 +30,72 @@ -
- -
+
-

pub package -License: MIT -Open in Firebase Studio

-

IRI - Internationalized Resource Identifiers

-

A Dart library for parsing, validating, manipulating, and converting -Internationalized Resource Identifiers (IRIs) based on RFC 3987.

-

Overview

-

Internationalized Resource Identifiers (IRIs) extend the syntax of Uniform -Resource Identifiers (URIs) to support a wider range of characters from the -Universal Character Set (Unicode/ISO 10646). This is essential for representing -resource identifiers in languages that use characters outside the US-ASCII range.

-

This package provides the IRI class to work with IRIs in Dart applications. -It handles the necessary conversions between IRIs and standard URIs, including:

-
    -
  • Punycode encoding/decoding for internationalized domain names (IDNs) within the host component.
  • -
  • Percent encoding/decoding for other non-ASCII characters in various IRI components, using UTF-8 as required by the standard.
  • -
+

IRI (Internationalized Resource Identifiers)

+

A pure Dart implementation of Internationalized Resource Identifiers (IRI) as defined in RFC 3987.

+

This package provides an Iri class that acts as a Unicode-aware wrapper around Dart's native Uri class. It handles the mapping between IRIs and URIs, including automatic Punycode conversion for hostnames and UTF-8 percent-encoding for other components.

Features

    -
  • Parse IRI strings: Create IRI objects from strings.
  • -
  • Validate IRIs: Check if strings conform to RFC 3987 syntax.
  • -
  • Access Components: Easily get decoded IRI components like scheme, host, path, query, fragment, userInfo, port.
  • -
  • IRI-to-URI Conversion: Convert an IRI object to a standard Dart Uri object, applying Punycode and percent-encoding according to RFC 3987 rules.
  • -
  • URI-to-IRI Conversion: Convert a standard Uri back into an IRI, decoding percent-encoded sequences where appropriate.
  • -
  • Normalization: Applies syntax-based normalization including: -
      -
    • Case normalization (scheme, host).
    • -
    • Percent-encoding normalization (uses uppercase hex, decodes unreserved characters where possible in IRI representation).
    • -
    • Path segment normalization (removes . and .. segments).
    • -
    -
  • -
  • Comparison: Compare IRI objects based on their code point sequence (simple string comparison).
  • +
  • Standard Compliant: Implements the IRI-to-URI mapping and URI-to-IRI conversion rules from RFC 3987.
  • +
  • Punycode Support: Automatically converts non-ASCII hostnames to Punycode.
  • +
  • Unicode-Aware: Access components (path, query, fragment, etc.) in their original Unicode form.
  • +
  • Normalization: Automatically applies NFKC (Normalization Form KC) to all inputs as recommended by RFC 3987 to prevent comparison false-negatives.
  • +
  • IDNA Separators: Supports international domain separators (, , ) during parsing and conversion.
  • +
  • Mailto Support: Special handling for mailto: IRIs, ensuring email domain parts are correctly Punycode-encoded.
  • +
  • Familiar API: Mirrors the Dart Uri class API, including resolve, resolveIri, and replace.
  • +
  • Immutable: The Iri class is immutable and supports equality checks.
-

Getting Started

-

Add the package to your pubspec.yaml:

+

RFC 3987 Compliance & Limitations

+

While this package aims for high compatibility with RFC 3987, there are known areas where the current implementation deviates from the strict specification:

+
    +
  1. Robust URI-to-IRI Decoding (RFC 3987 Section 3.2): When converting from a Uri to an Iri, the package currently uses standard UTF-8 decoding. If a percent-encoded sequence is invalid UTF-8 (e.g., %FC), the implementation may throw a FormatException instead of preserving the percent-encoding as required by the RFC.
  2. +
  3. Prohibited Characters (RFC 3987 Section 4.1): Certain Unicode characters (like bidirectional control characters U+202E) are prohibited from appearing directly in an IRI. Currently, these characters are decoded if present in a URI, whereas they should remain percent-encoded.
  4. +
  5. Bidi Validation (RFC 3987 Section 4.2): The package does not currently perform structural validation of bidirectional IRIs (e.g., ensuring RTL components don't mix directions incorrectly).
  6. +
+

These areas may be a part of future updates. For most common use cases involving standard Unicode text in paths and hosts, the package provides a robust experience.

+

Getting started

+

Add iri to your pubspec.yaml dependencies:

dependencies:
-  iri: ^0.1.0
-
-

Then, import the library in your Dart code:

-
import 'package:iri/iri.dart';
+  iri: ^0.2.0
 

Usage

-

Here's a basic example demonstrating how to create an IRI and convert it to a Uri:

+

Basic Parsing and Conversion

import 'package:iri/iri.dart';
 
 void main() {
-  // 1. Create an IRI from a string containing non-ASCII characters.
-  //    例子 means "example" in Chinese.
-  //    The path contains 'ȧ' (U+0227 LATIN SMALL LETTER A WITH DOT ABOVE).
-  final iri = IRI('https://例子.com/pȧth?q=1');
-
-  // 2. Print the original IRI string representation.
-  print('Original IRI: $iri');
-  // Output: Original IRI: https://例子.com/pȧth?q=1
-
-  // 3. Convert the IRI to its standard URI representation.
-  //    - The host (例子.com) is converted to Punycode (xn--fsqu00a.com).
-  //    - The non-ASCII path character 'ȧ' (UTF-8 bytes C8 A7) is percent-encoded (%C8%A7).
-  final uri = iri.toUri();
-  print('Converted URI: $uri');
-  // Output: Converted URI: https://xn--fsqu00a.com/p%C8%A7th?q=1
+  // Parse an IRI with Unicode characters
+  final iri = Iri.parse('http://résumé.example.org/résumé');
 
-  // 4. Access components (values are decoded for IRI representation).
-  print('Scheme: ${iri.scheme}');       // Output: Scheme: https
-  print('Host: ${iri.host}');           // Output: Host: 例子.com
-  print('Path: ${iri.path}');           // Output: Path: /pȧth
-  print('Query: ${iri.query}');         // Output: Query: q=1
+  print('IRI host: ${iri.host}'); // résumé.example.org
+  print('IRI path: ${iri.path}'); // /résumé
 
-  // 5. Compare IRIs
-  final iri2 = IRI('https://例子.com/pȧth?q=1');
-  print('IRIs equal: ${iri == iri2}'); // Output: IRIs equal: true
-
-  final iri3 = IRI('https://example.com/');
-  print('IRIs equal: ${iri == iri3}'); // Output: IRIs equal: false
+  // Convert to a standard URI for network operations
+  final uri = iri.toUri();
+  print('URI host: ${uri.host}'); // xn--rsum-bpad.example.org
+  print('URI string: $uri');      // http://xn--rsum-bpad.example.org/r%C3%A9sum%C3%A9
 }
 
+

Creating IRIs from Components

+
final iri = Iri(
+  scheme: 'https',
+  host: 'münchen.test',
+  path: '/city',
+);
+
+print(iri.toUri()); // https://xn--mnchen-3ya.test/city
+
@@ -129,11 +103,11 @@

Usage

Libraries

- iri + iri
Provides support for Internationalized Resource Identifiers (IRIs) -based on RFC 3987. +based on RFC 3987 (https://www.rfc-editor.org/rfc/rfc3987).
@@ -153,7 +127,7 @@

Libraries

  1. Libraries
  2. -
  3. iri
  4. +
  5. iri
@@ -163,7 +137,7 @@