diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f77d65..29ba427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## 0.3.0 + +This release is a complete, ground-up rewrite of the package. It provides a fully compliant, strictly validated, and idiomatic Dart implementation of the Punycode standard. + +### 🚨 Breaking Changes +* **Separation of IDNA and Raw Punycode:** The default `PunycodeCodec` no longer attempts to automatically parse and encode/decode full domains or email addresses. It now acts purely on raw strings. +* **Removed `PunycodeCodec.simple()`:** Because the default codec now handles raw strings exclusively, the `.simple()` constructor has been removed. A new global `punycode` instance is provided for convenience. +* **Extracted Domain & Email Handling:** Domain and email conversions are now handled by dedicated top-level functions (`domainToAscii`, `domainToUnicode`, `emailToAscii`, and `emailToUnicode`). +* **Strict (but Configurable) IDNA Validation:** IDNA processing now strictly enforces formatting rules by default. Inputs with labels exceeding 63 characters, domains exceeding 253 characters, or invalid hyphen placements will actively throw a `FormatException`. You can bypass this by passing `validate: false`. + +### ✨ New Features & Improvements +* **Full RFC 3492 Compliance:** Rigorous implementation of the complete Punycode specification. +* **Mixed-Case Support (RFC 3429 Appendix A):** Added support for Appendix A mixed-case annotations, properly preserving casing during encoding and decoding. +* **Official Errata Fixes:** Implemented technical corrections for RFC 3492 Errata IDs 265 and 3026. +* **IDNA2003 Separator Support:** `domainToAscii` now recognizes and properly splits labels using standard IDNA2003 separators (`.`, `\u3002`, `\uFF0E`, `\uFF61`). +* **Platform Parity:** Added a comprehensive suite of unit and integration tests to guarantee identical behavior across both Dart VM and Web platforms. + ## 0.2.2 - Fix code formatting and ensure README is up to date. diff --git a/README.md b/README.md index 97bb540..98f1246 100644 --- a/README.md +++ b/README.md @@ -2,42 +2,26 @@ [![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%2Fpunycoder) # Punycoder -A Dart implementation of the Punycode (RFC 3492) encoding algorithm used for -Internationalized Domain Names in Applications (IDNA). -## Overview +A pure Dart implementation of Punycode ([RFC 3492](https://tools.ietf.org/html/rfc3492)) with support for mixed-case annotation and technical errata. -This package provides a robust and efficient way to convert Unicode strings, -such as internationalized domain names or email addresses, into their ASCII-Compatible -Encoding (ACE) representation according to the Punycode specification (RFC 3492), -and back again. - -Punycode allows representing Unicode characters using only the limited ASCII -character subset (letters, digits, and hyphens) allowed in components of -domain names. This is essential for the IDNA standard, enabling the use of -international characters in domain names while maintaining compatibility with -the existing DNS infrastructure. ACE labels generated by IDNA typically start -with the prefix `xn--`. +Punycoder provides an idiomatic and high-performance way to encode and decode Punycode strings, which are essential for Internationalized Domain Names in Applications (IDNA). ## Features -* **RFC 3492 Compliant:** Implements the Punycode encoding and decoding - algorithms as specified in the standard. -* **IDNA Friendly:** Provides convenient ways of converting full domain names or - email addresses, automatically handling the `xn--` prefix and processing - only the necessary parts of the string. -* **Idiomatic Dart:** This package implements the `Converter` interface - defined in `dart:convert` to make working with Punycode feel easy and familiar. -* **Efficient and Tested:** Based on a port of the well-regarded Punycode.js - library, including tests based on official RFC examples. +- **Standard Compliant**: Faithful implementation of the Bootstring algorithm specifically for Punycode. +- **Mixed-Case Annotation**: Full support for Appendix A, preserving original character casing during the encoding process. +- **Cross-Platform**: Fully compatible with both the Dart VM and Web (transpiled via dart2js or ddc). +- **Native Performance**: Uses `StringBuffer` and Unicode-aware `Runes` for efficient processing. +- **Idiomatic API**: Implements `Codec` for seamless integration with `dart:convert`. -## Getting Started +## Getting started -Add the package to your `pubspec.yaml`: +Add `punycoder` to your `pubspec.yaml` dependencies: ```yaml dependencies: - punycoder: ^0.2.0 + punycoder: ^0.3.0 ``` Then, import the library in your Dart code: @@ -48,31 +32,60 @@ import 'package:punycoder/punycoder.dart'; ## Usage +### Basic Encoding and Decoding + ```dart -import 'package:punycoder/punycoder.dart'; +// Encode a Unicode string to Punycode +final encoded = punycode.encode('münchen'); // mnchen-3ya + +// Decode a Punycode string back to Unicode +final decoded = punycode.decode('mnchen-3ya'); // münchen +``` + +### IDNA Helpers (Domains and Emails) + +Punycoder provides high-level helpers for handling Internationalized Domain Names (IDN) and email addresses. + +```dart +// Convert a Unicode domain to ASCII (Punycode) +final domainAscii = domainToAscii('mañana.com'); // xn--maana-pta.com + +// Convert back to Unicode +final domainUnicode = domainToUnicode('xn--maana-pta.com'); // mañana.com + +// Supports IDNA2003 separators (。 . 。) +final alternative = domainToAscii('mañana\u3002com'); // xn--maana-pta.com + +// Convert an email address +final emailAscii = emailToAscii('джумла@джpумлатест.bрфa'); +// джумла@xn--p-8sbkgc5ag7bhce.xn--ba-lmcq +``` + +By default, `domainToAscii` and `emailToAscii` perform validation (label length, domain length, invalid characters). You can disable this if needed: + +```dart +final raw = domainToAscii('ab--c.com', validate: false); +``` + +### Preserving Mixed Case + +By default, Punycoder uses Appendix A annotations to preserve casing: + +```dart +final encoded = punycode.encode('MÜnchen'); // Mnchen-3yA +final decoded = punycode.decode('Mnchen-3yA'); // MÜnchen +``` + +## Additional information + +### Contributions + +Contributions are welcome! Please feel free to open issues or submit pull requests on the [GitHub repository](https://github.com/dropbear-software/punycoder). + +### Reporting Issues + +If you encounter any bugs or have feature requests, please file them through the [issue tracker](https://github.com/dropbear-software/punycoder/issues). + +### License -void main() { - // Designed to be used with domains and emails which have special rules - const domainCodec = PunycodeCodec(); - // Designed to work with simple strings - const simpleCodec = PunycodeCodec.simple(); - - final encodedString = simpleCodec.encode('münchen'); - final encodedDomain = domainCodec.encode('münchen.com'); - final encodedEmail = domainCodec.encode('münchen@münchen.com'); - - stdout.writeln(encodedString); // Output: mnchen-3ya - // Uses the correct prefix for the domain - stdout.writeln(encodedDomain); // Output: xn--mnchen-3ya.com - // Only the domain should be encoded - stdout.writeln(encodedEmail); // Output: münchen@xn--mnchen-3ya.com - - final decodedString = simpleCodec.decode('mnchen-3ya'); - final decodecDomain = domainCodec.decode('xn--mnchen-3ya.com'); - final decodedEmail = domainCodec.decode('münchen@xn--mnchen-3ya.com'); - - stdout.writeln(decodedString); // Output: münchen - stdout.writeln(decodecDomain); // Output: münchen.com - stdout.writeln(decodedEmail); // Output: münchen@münchen.com -} -``` \ No newline at end of file +This project is licensed under the MIT License - see the LICENSE file for details. 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/doc/api/__404error.html b/doc/api/__404error.html index ca7d993..bfb353e 100644 --- a/doc/api/__404error.html +++ b/doc/api/__404error.html @@ -40,20 +40,31 @@
-
-

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: -

-
-
- +
+
+ + - + +
punycoder - 0.1.0 + 0.3.0
diff --git a/doc/api/index.html b/doc/api/index.html index e30c334..57dc252 100644 --- a/doc/api/index.html +++ b/doc/api/index.html @@ -47,69 +47,62 @@ License: MIT Open in Firebase Studio

Punycoder

-

A Dart implementation of the Punycode (RFC 3492) encoding algorithm used for -Internationalized Domain Names in Applications (IDNA).

-

Overview

-

This package provides a robust and efficient way to convert Unicode strings, -such as internationalized domain names or email addresses, into their ASCII-Compatible -Encoding (ACE) representation according to the Punycode specification (RFC 3492), -and back again.

-

Punycode allows representing Unicode characters using only the limited ASCII -character subset (letters, digits, and hyphens) allowed in components of -domain names. This is essential for the IDNA standard, enabling the use of -international characters in domain names while maintaining compatibility with -the existing DNS infrastructure. ACE labels generated by IDNA typically start -with the prefix xn--.

+

A pure Dart implementation of Punycode (RFC 3492) with support for mixed-case annotation and technical errata.

+

Punycoder provides an idiomatic and high-performance way to encode and decode Punycode strings, which are essential for Internationalized Domain Names in Applications (IDNA).

Features

-

Getting Started

-

Add the package to your pubspec.yaml:

+

Getting started

+

Add punycoder to your pubspec.yaml dependencies:

dependencies:
-  punycoder: 0.1.0
+  punycoder: ^0.3.0
 

Then, import the library in your Dart code:

import 'package:punycoder/punycoder.dart';
 

Usage

-

The easiest way to handle domain names or emails is using the singleton -punycodeEncoder and punycodeDecoder instances and their helper methods.

-
import 'package:punycoder/punycoder.dart';
+

Basic Encoding and Decoding

+
// Encode a Unicode string to Punycode
+final encoded = punycode.encode('münchen'); // mnchen-3ya
+
+// Decode a Punycode string back to Unicode
+final decoded = punycode.decode('mnchen-3ya'); // münchen
+
+

IDNA Helpers (Domains and Emails)

+

Punycoder provides high-level helpers for handling Internationalized Domain Names (IDN) and email addresses.

+
// Convert a Unicode domain to ASCII (Punycode)
+final domainAscii = domainToAscii('mañana.com'); // xn--maana-pta.com
+
+// Convert back to Unicode
+final domainUnicode = domainToUnicode('xn--maana-pta.com'); // mañana.com
 
-void main() {
-  // Designed to be used with domains and emails which have special rules
-  const domainCodec = PunycodeCodec();
-  // Designed to work with simple strings
-  const simpleCodec = PunycodeCodec.simple();
-
-  final encodedString = simpleCodec.encode('münchen');
-  final encodedDomain = domainCodec.encode('münchen.com');
-  final encodedEmail = domainCodec.encode('münchen@münchen.com');
-
-  stdout.writeln(encodedString); // Output: mnchen-3ya
-  // Uses the correct prefix for the domain
-  stdout.writeln(encodedDomain); // Output: xn--mnchen-3ya.com
-  // Only the domain should be encoded
-  stdout.writeln(encodedEmail); // Output: münchen@xn--mnchen-3ya.com
-
-  final decodedString = simpleCodec.decode('mnchen-3ya');
-  final decodecDomain = domainCodec.decode('xn--mnchen-3ya.com');
-  final decodedEmail = domainCodec.decode('münchen@xn--mnchen-3ya.com');
-
-  stdout.writeln(decodedString); // Output: münchen
-  stdout.writeln(decodecDomain); // Output: münchen.com
-  stdout.writeln(decodedEmail); // Output: münchen@münchen.com
-}
+// Supports IDNA2003 separators (。 . 。)
+final alternative = domainToAscii('mañana\u3002com'); // xn--maana-pta.com
+
+// Convert an email address
+final emailAscii = emailToAscii('джумла@джpумлатест.bрфa'); 
+// джумла@xn--p-8sbkgc5ag7bhce.xn--ba-lmcq
+
+

By default, domainToAscii and emailToAscii perform validation (label length, domain length, invalid characters). You can disable this if needed:

+
final raw = domainToAscii('ab--c.com', validate: false);
+
+

Preserving Mixed Case

+

By default, Punycoder uses Appendix A annotations to preserve casing:

+
final encoded = punycode.encode('MÜnchen'); // Mnchen-3yA
+final decoded = punycode.decode('Mnchen-3yA'); // MÜnchen
 
+

Additional information

+

Contributions

+

Contributions are welcome! Please feel free to open issues or submit pull requests on the GitHub repository.

+

Reporting Issues

+

If you encounter any bugs or have feature requests, please file them through the issue tracker.

+

License

+

This project is licensed under the MIT License - see the LICENSE file for details.

@@ -120,8 +113,8 @@

Libraries

punycoder -
Provides a Dart implementation of the Punycode encoding algorithm -specified in RFC 3492. +
A pure Dart implementation of Punycode (RFC 3492) with support for +mixed-case annotation and errata.
@@ -151,7 +144,7 @@

PunycodeCodec class
-

A codec for encoding and decoding strings using the Punycode algorithm.

-

Punycode is a character encoding scheme used to represent Unicode -characters in ASCII strings. It is commonly used for Internationalized -Domain Names (IDNs).

-

This codec provides methods to convert between Unicode strings and their -Punycode representations.

-

Example:

-
import 'package:punycoder/punycoder.dart';
-
-void main() {
- // Designed to be used with domains and emails which have special rules
- const domainCodec = PunycodeCodec();
- // Designed to work with simple strings
- const simpleCodec = PunycodeCodec.simple();
-
- final encodedString = simpleCodec.encode('münchen');
- final encodedDomain = domainCodec.encode('münchen.com');
- final encodedEmail = domainCodec.encode('münchen@münchen.com');
-
- print(encodedString); // Output: mnchen-3ya
- // Uses the correct prefix for the domain
- print(encodedDomain); // Output: xn--mnchen-3ya.com
- // Only the domain should be encoded
- print(encodedEmail); // Output: münchen@xn--mnchen-3ya.com
-
- final decodedString = simpleCodec.decode('mnchen-3ya');
- final decodecDomain = domainCodec.decode('xn--mnchen-3ya.com');
- final decodedEmail = domainCodec.decode('münchen@xn--mnchen-3ya.com');
-
- print(decodedString); // Output: münchen
- print(decodecDomain); // Output: münchen.com
- print(decodedEmail); // Output: münchen@münchen.com
-}
-
+

A Codec that converts Unicode strings to Punycode ASCII strings.

+

This implementation supports the mixed-case annotation described in +RFC 3492 Appendix A.

@@ -97,8 +66,8 @@

PunycodeCodec class
Inheritance
@@ -122,17 +91,7 @@

Constructors

PunycodeCodec.new()
- Creates a new instance of the Punycode codec designed -for working with domains and email addresses where -additional rules apply about how it is converted -
const
-
-
- PunycodeCodec.simple() -
-
- Creates a new instance of the Punycode codec just designed -for working with simple strings + Creates a new PunycodeCodec.
const
@@ -145,7 +104,7 @@

Properties

decoder - Converter<String, String> + Converter<String, String>
@@ -157,7 +116,7 @@

Properties

encoder - Converter<String, String> + Converter<String, String>
@@ -168,8 +127,8 @@

Properties

- hashCode - int + hashCode + int
@@ -180,8 +139,8 @@

Properties

- inverted - Codec<String, String> + inverted + Codec<String, String>
@@ -192,8 +151,8 @@

Properties

- runtimeType - Type + runtimeType + Type
@@ -213,8 +172,8 @@

Properties

Methods

- decode(String encoded) - String + decode(String encoded) + String @@ -226,8 +185,8 @@

Methods

- encode(String input) - String + encode(String input) + String @@ -239,8 +198,8 @@

Methods

- fuse<R>(Codec<String, R> other) - Codec<String, R> + fuse<R>(Codec<String, R> other) + Codec<String, R> @@ -252,7 +211,7 @@

Methods

- noSuchMethod(Invocation invocation) + noSuchMethod(Invocation invocation) → dynamic @@ -265,8 +224,8 @@

Methods

- toString() - String + toString() + String @@ -286,8 +245,8 @@

Methods

Operators

- operator ==(Object other) - bool + operator ==(Object other) + bool @@ -327,7 +286,7 @@
punycoder library
punycoder - 0.1.0 + 0.3.0
diff --git a/doc/api/punycoder/PunycodeCodec/PunycodeCodec.html b/doc/api/punycoder/PunycodeCodec/PunycodeCodec.html index 42fd62c..6701eb0 100644 --- a/doc/api/punycoder/PunycodeCodec/PunycodeCodec.html +++ b/doc/api/punycoder/PunycodeCodec/PunycodeCodec.html @@ -58,18 +58,14 @@

PunycodeCodec constructor
-

Creates a new instance of the Punycode codec designed -for working with domains and email addresses where -additional rules apply about how it is converted

+

Creates a new PunycodeCodec.

Implementation

-
const PunycodeCodec()
-  : _encoder = const PunycodeEncoder(),
-    _decoder = const PunycodeDecoder();
+
const PunycodeCodec();
@@ -97,7 +93,7 @@

PunycodeCodec class
punycoder - 0.1.0 + 0.3.0
diff --git a/doc/api/punycoder/PunycodeCodec/decoder.html b/doc/api/punycoder/PunycodeCodec/decoder.html index 8008229..f05e513 100644 --- a/doc/api/punycoder/PunycodeCodec/decoder.html +++ b/doc/api/punycoder/PunycodeCodec/decoder.html @@ -61,10 +61,10 @@

decoder property - Converter<String, String> + Converter<String, String> get decoder
override
@@ -80,7 +80,7 @@

decoder property

Implementation

@override
-Converter<String, String> get decoder => _decoder;
+Converter<String, String> get decoder => const PunycodeDecoder();

@@ -110,7 +110,7 @@
PunycodeCodec class
punycoder - 0.1.0 + 0.3.0
diff --git a/doc/api/punycoder/PunycodeCodec/encoder.html b/doc/api/punycoder/PunycodeCodec/encoder.html index ef8bd3e..e8a483a 100644 --- a/doc/api/punycoder/PunycodeCodec/encoder.html +++ b/doc/api/punycoder/PunycodeCodec/encoder.html @@ -61,10 +61,10 @@

encoder property
    -
  1. @override
  2. +
  3. @override
- Converter<String, String> + Converter<String, String> get encoder
override
@@ -80,7 +80,7 @@

encoder property

Implementation

@override
-Converter<String, String> get encoder => _encoder;
+Converter<String, String> get encoder => const PunycodeEncoder();
@@ -110,7 +110,7 @@

PunycodeCodec class
punycoder - 0.1.0 + 0.3.0
diff --git a/doc/api/punycoder/PunycodeDecoder-class-sidebar.html b/doc/api/punycoder/PunycodeDecoder-class-sidebar.html index e905c31..8234890 100644 --- a/doc/api/punycoder/PunycodeDecoder-class-sidebar.html +++ b/doc/api/punycoder/PunycodeDecoder-class-sidebar.html @@ -1,5 +1,7 @@
    +
  1. Constructors
  2. +
  3. new
  4. @@ -8,21 +10,21 @@
  5. - hashCode + hashCode
  6. - runtimeType + runtimeType
  7. Methods
  8. - bind + bind
  9. - cast + cast
  10. @@ -30,29 +32,25 @@
  11. - fuse + fuse
  12. - noSuchMethod + noSuchMethod
  13. - startChunkedConversion + startChunkedConversion
  14. - toString -
  15. - -
  16. - toUnicode + toString
  17. Operators
  18. - operator == + operator ==
  19. diff --git a/doc/api/punycoder/PunycodeDecoder-class.html b/doc/api/punycoder/PunycodeDecoder-class.html index 0e6b0c4..e2ec429 100644 --- a/doc/api/punycoder/PunycodeDecoder-class.html +++ b/doc/api/punycoder/PunycodeDecoder-class.html @@ -54,8 +54,7 @@

    PunycodeDecoder class
    -

    Converts a Punycode string of ASCII-only symbols to a string of -Unicode symbols.

    +

    Punycode decoder as defined in RFC 3492 Section 6.2.

    @@ -65,8 +64,8 @@

    PunycodeDecoder class
    Inheritance
    @@ -83,6 +82,18 @@

    PunycodeDecoder class +
    +

    Constructors

    +
    +
    + PunycodeDecoder.new() +
    +
    + Creates a new PunycodeDecoder. +
    const
    +
    +
    +
    PunycodeDecoder class

    Properties

    - hashCode - int + hashCode + int
    @@ -102,8 +113,8 @@

    Properties

    - runtimeType - Type + runtimeType + Type
    @@ -123,8 +134,8 @@

    Properties

    Methods

    - bind(Stream<String> stream) - Stream<String> + bind(Stream<String> stream) + Stream<String> @@ -136,8 +147,8 @@

    Methods

    - cast<RS, RT>() - Converter<RS, RT> + cast<RS, RT>() + Converter<RS, RT> @@ -149,8 +160,8 @@

    Methods

    - convert(String input) - String + convert(String input) + String @@ -162,8 +173,8 @@

    Methods

    - fuse<TT>(Converter<String, TT> other) - Converter<String, TT> + fuse<TT>(Converter<String, TT> other) + Converter<String, TT> @@ -175,7 +186,7 @@

    Methods

    - noSuchMethod(Invocation invocation) + noSuchMethod(Invocation invocation) → dynamic @@ -188,8 +199,8 @@

    Methods

    - startChunkedConversion(Sink<String> sink) - Sink<String> + startChunkedConversion(Sink<String> sink) + Sink<String> @@ -201,8 +212,8 @@

    Methods

    - toString() - String + toString() + String @@ -211,22 +222,6 @@

    Methods

    A string representation of this object.
    inherited
    - - -
    - toUnicode(String input) - String - - - -
    -
    - Converts a Punycode string representing a domain name or an email address -to Unicode. Only the Punycoded parts of the input will be converted, i.e. -it doesn't matter if you call it on a string that has already been -converted to Unicode. - -
    @@ -238,8 +233,8 @@

    Methods

    Operators

    - operator ==(Object other) - bool + operator ==(Object other) + bool @@ -279,7 +274,7 @@
    punycoder library
    punycoder - 0.1.0-dev + 0.3.0
    diff --git a/doc/api/punycoder/PunycodeDecoder/PunycodeDecoder.html b/doc/api/punycoder/PunycodeDecoder/PunycodeDecoder.html new file mode 100644 index 0000000..adfbce0 --- /dev/null +++ b/doc/api/punycoder/PunycodeDecoder/PunycodeDecoder.html @@ -0,0 +1,107 @@ + + + + + + + + PunycodeDecoder.new constructor - PunycodeDecoder - punycoder library - Dart API + + + + + + + + + + + + + + +
    +
    + menu + +
    PunycodeDecoder.new
    + + + + +
    +
    +
    +
    +

    PunycodeDecoder constructor +

    + +
    + const + PunycodeDecoder() +
    + +
    +

    Creates a new PunycodeDecoder.

    +
    + + + +
    +

    Implementation

    +
    const PunycodeDecoder();
    +
    + + +
    + + +
    +
    + + punycoder + 0.3.0 + + +
    + + + + + + + + diff --git a/doc/api/punycoder/PunycodeDecoder/convert.html b/doc/api/punycoder/PunycodeDecoder/convert.html index dc7f79d..9706618 100644 --- a/doc/api/punycoder/PunycodeDecoder/convert.html +++ b/doc/api/punycoder/PunycodeDecoder/convert.html @@ -56,11 +56,11 @@

    convert method -String -convert(
    1. String input
    2. +String +convert(
      1. String input
      )
      override
      @@ -77,106 +77,85 @@

      convert method

      Implementation

      @override
       String convert(String input) {
      -  final output = <int>[];
      -  final inputLength = input.length;
      -  var i = 0;
      -  var n = bootstrapValues.initialN;
      -  var bias = bootstrapValues.initialBias;
      +  final inputLen = input.length;
      +  final inputRunes = input.runes.toList();
       
      -  // Handle the basic code points: let `basic` be the number of input code
      -  // points before the last delimiter, or `0` if there is none, then copy
      -  // the first basic code points to the output.
      +  var n = initialN;
      +  var i = 0;
      +  var bias = initialBias;
       
      -  var basic = input.lastIndexOf(bootstrapValues.delimiter);
      -  if (basic < 0) {
      -    basic = 0;
      +  // Handle the basic code points:
      +  // Find the last delimiter
      +  var b = 0;
      +  for (var j = 0; j < inputLen; j++) {
      +    if (isDelimiter(inputRunes[j])) b = j;
         }
       
      -  for (var j = 0; j < basic; ++j) {
      -    // if it's not a basic code point
      -    if (input.codeUnitAt(j) >= 0x80) {
      -      throw RangeError.value(
      -        input.codeUnitAt(j),
      -        'input',
      -        'Illegal input >= 0x80 (not a basic code point)',
      +  final output = <int>[];
      +  final caseFlags = <bool>[];
      +
      +  for (var j = 0; j < b; j++) {
      +    final cp = inputRunes[j];
      +    if (!isBasic(cp)) {
      +      throw Exception(
      +        'Invalid input: non-basic code point in literal portion',
             );
           }
      -    output.add(input.codeUnitAt(j));
      +    output.add(cp);
      +    caseFlags.add(_isUpperCaseCodePoint(cp));
         }
       
      -  // Main decoding loop: start just after the last delimiter if any basic code
      -  // points were copied; start at the beginning otherwise.
      -
      -  for (var index = basic > 0 ? basic + 1 : 0; index < inputLength;) {
      -    // `index` is the index of the next character to be consumed.
      -    // Decode a generalized variable-length integer into `delta`,
      -    // which gets added to `i`. The overflow checking is easier
      -    // if we increase `i` as we go, then subtract off its starting
      -    // value at the end to obtain `delta`.
      +  // Main decoding loop:
      +  var index = b > 0 ? b + 1 : 0;
      +  while (index < inputLen) {
           final oldi = i;
      -
      -    for (var w = 1, k = bootstrapValues.base; ; k += bootstrapValues.base) {
      -      if (index >= inputLength) {
      -        throw FormatException('Invalid input: Incomplete Punycode sequence');
      +    var w = 1;
      +    for (var k = base; ; k += base) {
      +      if (index >= inputLen) {
      +        throw Exception('Invalid input: unexpected end of input');
             }
      -
      -      final digit = basicToDigit(input.codeUnitAt(index++));
      -
      -      if (digit >= bootstrapValues.base) {
      -        throw FormatException(
      -          'Invalid input: Invalid base-36 digit: ${input[index - 1]}',
      -        );
      +      final digit = decodeDigit(inputRunes[index++]);
      +      if (digit == -1) {
      +        throw Exception('Invalid input: not a valid digit');
             }
       
      -      if (digit > ((maxInt - i) ~/ w)) {
      -        throw FormatException(
      -          'Overflow: input needs wider integers to process',
      -        );
      +      if (digit > (dartMaxInt - i) ~/ w) {
      +        throw Exception('Punycode overflow');
             }
      -
             i += digit * w;
      -      final t =
      -          k <= bias
      -              ? bootstrapValues.tMin
      -              : (k >= bias + bootstrapValues.tMax
      -                  ? bootstrapValues.tMax
      -                  : k - bias);
       
      +      final t = k <= bias ? tmin : (k >= bias + tmax ? tmax : k - bias);
             if (digit < t) {
      -        break;
      -      }
      +        final isUpper = _isUpperCaseCodePoint(inputRunes[index - 1]);
       
      -      final baseMinusT = bootstrapValues.base - t;
      +        bias = adapt(i - oldi, output.length + 1, firstTime: oldi == 0);
       
      -      if (w > (maxInt ~/ baseMinusT)) {
      -        throw FormatException(
      -          'Overflow: input needs wider integers to process',
      -        );
      -      }
      +        if (i ~/ (output.length + 1) > dartMaxInt - n) {
      +          throw Exception('Punycode overflow');
      +        }
      +        n += i ~/ (output.length + 1);
      +        i %= output.length + 1;
       
      -      w = w * baseMinusT; // Multiply within integer limits
      -    }
      -
      -    final out = output.length + 1;
      -    bias = adapt(delta: i - oldi, numPoints: out, firstTime: oldi == 0);
      +        caseFlags.insert(i, isUpper);
      +        output.insert(i, n);
      +        i++;
      +        break;
      +      }
       
      -    // `i` was supposed to wrap around from `out` to `0`,
      -    // incrementing `n` each time, so we'll fix that now:
      -    if ((i ~/ out) > (maxInt - n)) {
      -      throw FormatException(
      -        'Overflow: input needs wider integers to process',
      -      );
      +      if (w > dartMaxInt ~/ (base - t)) {
      +        throw Exception('Punycode overflow');
      +      }
      +      w *= base - t;
           }
      +  }
       
      -    n += i ~/ out;
      -    i %= out;
      -
      -    // Insert `n` at position `i` of the output.
      -    output.insert(i, n);
      -    i++;
      +  // Apply case flags for mixed-case annotation
      +  final result = StringBuffer();
      +  for (var j = 0; j < output.length; j++) {
      +    result.writeCharCode(_applyCase(output[j], caseFlags[j]));
         }
       
      -  return String.fromCharCodes(output);
      +  return result.toString();
       }

    @@ -205,7 +184,7 @@

    PunycodeDecoder class
    punycoder - 0.1.0-dev + 0.3.0
    diff --git a/doc/api/punycoder/PunycodeEncoder-class-sidebar.html b/doc/api/punycoder/PunycodeEncoder-class-sidebar.html index 81a8edc..adbbb52 100644 --- a/doc/api/punycoder/PunycodeEncoder-class-sidebar.html +++ b/doc/api/punycoder/PunycodeEncoder-class-sidebar.html @@ -1,5 +1,7 @@
      +
    1. Constructors
    2. +
    3. new
    4. @@ -8,51 +10,51 @@
    5. - hashCode + hashCode
    6. - runtimeType + runtimeType
    7. Methods
    8. - bind + bind
    9. - cast + cast
    10. convert
    11. -
    12. - fuse +
    13. + encodeBasic
    14. - noSuchMethod + fuse
    15. - startChunkedConversion + noSuchMethod
    16. -
    17. - toAscii +
    18. + startChunkedConversion
    19. - toString + toString
    20. Operators
    21. - operator == + operator ==
    22. diff --git a/doc/api/punycoder/PunycodeEncoder-class.html b/doc/api/punycoder/PunycodeEncoder-class.html index 30e9b20..32c2e98 100644 --- a/doc/api/punycoder/PunycodeEncoder-class.html +++ b/doc/api/punycoder/PunycodeEncoder-class.html @@ -54,8 +54,7 @@

      PunycodeEncoder class
      -

      Converts a string of Unicode symbols (e.g. a domain name label) to a -Punycode string of ASCII-only symbols.

      +

      Punycode encoder as defined in RFC 3492 Section 6.3.

      @@ -65,8 +64,8 @@

      PunycodeEncoder class
      Inheritance
      @@ -83,6 +82,18 @@

      PunycodeEncoder class +
      +

      Constructors

      +
      +
      + PunycodeEncoder.new() +
      +
      + Creates a new PunycodeEncoder. +
      const
      +
      +
      +
      PunycodeEncoder class

      Properties

      - hashCode - int + hashCode + int
      @@ -102,8 +113,8 @@

      Properties

      - runtimeType - Type + runtimeType + Type
      @@ -123,8 +134,8 @@

      Properties

      Methods

      - bind(Stream<String> stream) - Stream<String> + bind(Stream<String> stream) + Stream<String> @@ -136,8 +147,8 @@

      Methods

      - cast<RS, RT>() - Converter<RS, RT> + cast<RS, RT>() + Converter<RS, RT> @@ -149,8 +160,8 @@

      Methods

      - convert(String input) - String + convert(String input) + String @@ -159,11 +170,25 @@

      Methods

      Converts input and returns the result of the conversion.
      override
      + + +
      + encodeBasic(int bcp, {required bool upperCase}) + int + + + +
      +
      + Forces a basic code point to lowercase if upperCase is false, +uppercase if upperCase is true. + +
      - fuse<TT>(Converter<String, TT> other) - Converter<String, TT> + fuse<TT>(Converter<String, TT> other) + Converter<String, TT> @@ -175,7 +200,7 @@

      Methods

      - noSuchMethod(Invocation invocation) + noSuchMethod(Invocation invocation) → dynamic @@ -188,8 +213,8 @@

      Methods

      - startChunkedConversion(Sink<String> sink) - Sink<String> + startChunkedConversion(Sink<String> sink) + Sink<String> @@ -198,27 +223,11 @@

      Methods

      Starts a chunked conversion.
      inherited
      - - -
      - toAscii(String input) - String - - - -
      -
      - Converts a Unicode string representing a domain name or an email address -to Punycode. Only the non-ASCII parts of the domain name will be -converted, i.e. it doesn't matter if you call it with a domain that's -already in ASCII - -
      - toString() - String + toString() + String @@ -238,8 +247,8 @@

      Methods

      Operators

      - operator ==(Object other) - bool + operator ==(Object other) + bool @@ -279,7 +288,7 @@
      punycoder library
      punycoder - 0.1.0-dev + 0.3.0
      diff --git a/doc/api/punycoder/PunycodeEncoder/PunycodeEncoder.html b/doc/api/punycoder/PunycodeEncoder/PunycodeEncoder.html new file mode 100644 index 0000000..8cb083a --- /dev/null +++ b/doc/api/punycoder/PunycodeEncoder/PunycodeEncoder.html @@ -0,0 +1,107 @@ + + + + + + + + PunycodeEncoder.new constructor - PunycodeEncoder - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      PunycodeEncoder.new
      + + +
      +
      +
      +
      +

      PunycodeEncoder constructor +

      + +
      + const + PunycodeEncoder() +
      + +
      +

      Creates a new PunycodeEncoder.

      +
      + + + +
      +

      Implementation

      +
      const PunycodeEncoder();
      +
      + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/PunycodeEncoder/convert.html b/doc/api/punycoder/PunycodeEncoder/convert.html index 0bc3643..bb4552e 100644 --- a/doc/api/punycoder/PunycodeEncoder/convert.html +++ b/doc/api/punycoder/PunycodeEncoder/convert.html @@ -56,11 +56,11 @@

      convert method -String -convert(
      1. String input
      2. +String +convert(
        1. String input
        )
        override
        @@ -77,110 +77,82 @@

        convert method

        Implementation

        @override
         String convert(String input) {
        -  final output = <int>[];
        +  final output = StringBuffer();
         
        -  // Convert the input to an array of Unicode code points.
        -  final decodedInput = input.runes.toList();
        +  // Appendix A: Mixed-case annotation
        +  // The encoder expects case-folded input. We normalize it but keep track of the original case.
        +  final originalRunes = input.runes.toList();
        +  final inputLen = originalRunes.length;
        +  final caseFlags = originalRunes.map(_isUpperCaseCodePoint).toList();
        +  final inputRunes = input.toLowerCase().runes.toList();
         
        -  // Cache the length.
        -  final inputLength = decodedInput.length;
        -
        -  // Initialize the state.
        -  var n = bootstrapValues.initialN;
        +  var n = initialN;
           var delta = 0;
        -  var bias = bootstrapValues.initialBias;
        +  var bias = initialBias;
         
        -  // Handle the basic code points.
        -  for (final currentValue in decodedInput) {
        -    if (currentValue < 0x80) {
        -      output.add(currentValue); // Add the code point directly
        +  // Handle the basic code points:
        +  for (var i = 0; i < inputLen; i++) {
        +    if (isBasic(inputRunes[i])) {
        +      output.writeCharCode(
        +        encodeBasic(inputRunes[i], upperCase: caseFlags[i]),
        +      );
             }
           }
         
        -  final basicLength = output.length;
        -  var handledCPCount = basicLength;
        -
        -  // `handledCPCount` is the number of code points that have been handled;
        -  // `basicLength` is the number of basic code points.
        -
        -  // Finish the basic string with a delimiter unless it's empty.
        -  if (basicLength > 0) {
        -    output.add(
        -      bootstrapValues.delimiter.codeUnitAt(0),
        -    ); // Add delimiter code point
        +  final b = output.length;
        +  if (b > 0) {
        +    output.writeCharCode(delimiter);
           }
         
        -  // Main encoding loop:
        -  while (handledCPCount < inputLength) {
        -    // All non-basic code points < n have been handled already. Find the next
        -    // larger one:
        -    var m = maxInt;
        -
        -    for (final currentValue in decodedInput) {
        -      if (currentValue >= n && currentValue < m) {
        -        m = currentValue;
        +  var h = b;
        +  while (h < inputLen) {
        +    // Find the next smallest non-basic code point >= n
        +    var m = dartMaxInt;
        +    for (final cp in inputRunes) {
        +      if (cp >= n && cp < m) {
        +        m = cp;
               }
             }
         
        -    // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
        -    // but guard against overflow.
        -    final handledCPCountPlusOne = handledCPCount + 1;
        -
        -    if (m - n > ((maxInt - delta) / handledCPCountPlusOne).floor()) {
        -      throw FormatException(
        -        'Overflow: input needs wider integers to process',
        -      );
        +    // Increase delta enough to advance the decoder's <n,i> state to <m,0>
        +    if (m - n > (dartMaxInt - delta) ~/ (h + 1)) {
        +      throw Exception('Punycode overflow');
             }
        -
        -    delta = delta + ((m - n) * handledCPCountPlusOne);
        +    delta += (m - n) * (h + 1);
             n = m;
         
        -    for (final currentValue in decodedInput) {
        -      if (currentValue < n) {
        +    for (var j = 0; j < inputLen; j++) {
        +      final c = inputRunes[j];
        +      if (c < n) {
                 delta++;
        -        if (delta > maxInt) {
        -          throw FormatException(
        -            'Overflow: input needs wider integers to process',
        -          );
        +        if (delta == 0 || delta > dartMaxInt) {
        +          throw Exception('Punycode overflow');
                 }
               }
         
        -      if (currentValue == n) {
        -        // Represent delta as a generalized variable-length integer.
        +      if (c == n) {
                 var q = delta;
        +        for (var k = base; ; k += base) {
        +          final t = k <= bias ? tmin : (k >= bias + tmax ? tmax : k - bias);
        +          if (q < t) break;
         
        -        for (var k = bootstrapValues.base; ; k += bootstrapValues.base) {
        -          final t =
        -              k <= bias
        -                  ? bootstrapValues.tMin
        -                  : (k >= bias + bootstrapValues.tMax
        -                      ? bootstrapValues.tMax
        -                      : k - bias);
        -
        -          if (q < t) {
        -            break;
        -          }
        -
        -          final qMinusT = q - t;
        -          final baseMinusT = bootstrapValues.base - t;
        -          output.add(digitToBasic(t + (qMinusT % baseMinusT), 0));
        -          q = qMinusT ~/ baseMinusT;
        +          final digit = t + ((q - t) % (base - t));
        +          output.writeCharCode(encodeDigit(digit, upperCase: false));
        +          q = (q - t) ~/ (base - t);
                 }
         
        -        output.add(digitToBasic(q, 0));
        -        bias = adapt(
        -          delta: delta,
        -          numPoints: handledCPCountPlusOne,
        -          firstTime: handledCPCount == basicLength,
        -        );
        +        output.writeCharCode(encodeDigit(q, upperCase: caseFlags[j]));
        +
        +        bias = adapt(delta, h + 1, firstTime: h == b);
                 delta = 0;
        -        ++handledCPCount;
        +        h++;
               }
             }
        -    ++delta;
        -    ++n;
        +    delta++;
        +    n++;
           }
        -  return String.fromCharCodes(output);
        +
        +  return output.toString();
         }

      @@ -209,7 +181,7 @@

      PunycodeEncoder class
      punycoder - 0.1.0-dev + 0.3.0
      diff --git a/doc/api/punycoder/PunycodeEncoder/encodeBasic.html b/doc/api/punycoder/PunycodeEncoder/encodeBasic.html new file mode 100644 index 0000000..873aa77 --- /dev/null +++ b/doc/api/punycoder/PunycodeEncoder/encodeBasic.html @@ -0,0 +1,117 @@ + + + + + + + + encodeBasic method - PunycodeEncoder class - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      encodeBasic
      + + +
      +
      +
      +
      +

      encodeBasic method +

      + +
      + +int +encodeBasic(
      1. int bcp, {
      2. +
      3. required bool upperCase,
      4. +
      }) + + + +
      + +
      +

      Forces a basic code point to lowercase if upperCase is false, +uppercase if upperCase is true.

      +
      + + + +
      +

      Implementation

      +
      int encodeBasic(int bcp, {required bool upperCase}) {
      +  final s = String.fromCharCode(bcp);
      +  return (upperCase ? s.toUpperCase() : s.toLowerCase()).codeUnitAt(0);
      +}
      +
      + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/domainToAscii.html b/doc/api/punycoder/domainToAscii.html new file mode 100644 index 0000000..856b8e7 --- /dev/null +++ b/doc/api/punycoder/domainToAscii.html @@ -0,0 +1,141 @@ + + + + + + + + domainToAscii function - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      domainToAscii
      + + +
      +
      +
      +
      +

      domainToAscii function + +

      + +
      + +String +domainToAscii(
      1. String domain, {
      2. +
      3. bool validate = true,
      4. +
      }) + + + +
      + +
      +

      Converts a domain name to its Punycode-encoded ASCII representation.

      +

      If validate is true (default), the function enforces RFC 1034 and +RFC 5890 rules:

      +
        +
      • Label length between 1 and 63 characters.
      • +
      • Total domain length not exceeding 253 characters.
      • +
      • Labels must not start or end with a hyphen.
      • +
      • Labels must not have hyphens in 3rd and 4th positions unless starting with 'xn--'.
      • +
      • Labels must only contain LDH (Letter-Digit-Hyphen) characters.
      • +
      +
      + + + +
      +

      Implementation

      +
      String domainToAscii(String domain, {bool validate = true}) {
      +  final labels = _splitBySeparators(domain);
      +  final encodedLabels = <String>[];
      +
      +  for (final label in labels) {
      +    if (_isAscii(label)) {
      +      encodedLabels.add(label.toLowerCase());
      +    } else {
      +      final encoded = punycode.encode(label.toLowerCase());
      +      encodedLabels.add('xn--$encoded');
      +    }
      +  }
      +
      +  final result = encodedLabels.join('.');
      +
      +  if (validate) {
      +    _validateDomain(result, encodedLabels);
      +  }
      +
      +  return result;
      +}
      +
      + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/domainToUnicode.html b/doc/api/punycoder/domainToUnicode.html new file mode 100644 index 0000000..cf7bbe0 --- /dev/null +++ b/doc/api/punycoder/domainToUnicode.html @@ -0,0 +1,121 @@ + + + + + + + + domainToUnicode function - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      domainToUnicode
      + + +
      +
      +
      +
      +

      domainToUnicode function + +

      + +
      + +String +domainToUnicode(
      1. String domain
      2. +
      ) + + + +
      + +
      +

      Converts a domain name from Punycode-encoded ASCII to Unicode.

      +
      + + + +
      +

      Implementation

      +
      String domainToUnicode(String domain) {
      +  final labels = domain.split('.');
      +  final decodedLabels = labels.map((label) {
      +    if (label.toLowerCase().startsWith('xn--')) {
      +      return punycode.decode(label.substring(4));
      +    }
      +    return label;
      +  });
      +
      +  return decodedLabels.join('.');
      +}
      +
      + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/emailToAscii.html b/doc/api/punycoder/emailToAscii.html new file mode 100644 index 0000000..f7e79f5 --- /dev/null +++ b/doc/api/punycoder/emailToAscii.html @@ -0,0 +1,123 @@ + + + + + + + + emailToAscii function - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      emailToAscii
      + + +
      +
      +
      +
      +

      emailToAscii function + +

      + +
      + +String +emailToAscii(
      1. String email, {
      2. +
      3. bool validate = true,
      4. +
      }) + + + +
      + +
      +

      Converts the domain part of an email address to Punycode-encoded ASCII.

      +

      Only the domain part (after the '@') is transformed. The local part is +preserved as-is.

      +
      + + + +
      +

      Implementation

      +
      String emailToAscii(String email, {bool validate = true}) {
      +  final parts = email.split('@');
      +  if (parts.length != 2) {
      +    throw FormatException('Invalid email format: $email');
      +  }
      +  final localPart = parts[0];
      +  final domainPart = parts[1];
      +
      +  return '$localPart@${domainToAscii(domainPart, validate: validate)}';
      +}
      +
      + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/emailToUnicode.html b/doc/api/punycoder/emailToUnicode.html new file mode 100644 index 0000000..f7f96c3 --- /dev/null +++ b/doc/api/punycoder/emailToUnicode.html @@ -0,0 +1,120 @@ + + + + + + + + emailToUnicode function - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      emailToUnicode
      + + +
      +
      +
      +
      +

      emailToUnicode function + +

      + +
      + +String +emailToUnicode(
      1. String email
      2. +
      ) + + + +
      + +
      +

      Converts the domain part of an email address from Punycode-encoded ASCII to Unicode.

      +
      + + + +
      +

      Implementation

      +
      String emailToUnicode(String email) {
      +  final parts = email.split('@');
      +  if (parts.length != 2) {
      +    throw FormatException('Invalid email format: $email');
      +  }
      +  final localPart = parts[0];
      +  final domainPart = parts[1];
      +
      +  return '$localPart@${domainToUnicode(domainPart)}';
      +}
      +
      + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/index.html b/doc/api/punycoder/index.html index 2f31577..3b442c3 100644 --- a/doc/api/punycoder/index.html +++ b/doc/api/punycoder/index.html @@ -60,37 +60,8 @@

      -

      Provides a Dart implementation of the Punycode encoding algorithm -specified in RFC 3492.

      -

      Punycode is a simple and efficient transfer encoding syntax designed -for use with Internationalized Domain Names in Applications (IDNA). -It uniquely and reversibly transforms a Unicode string into an ASCII -string suitable for host name labels, using only letters, digits, -and hyphens. This library allows encoding Unicode strings to Punycode -ASCII strings and decoding them back to Unicode.

      -

      This library exports the main PunycodeCodec which follows the -standard codec interface from dart:convert to help ensure a -smooth and idomatic Dart experience when encoding and decoding.

      -

      Usage

      -
      import 'package:punycoder/punycoder.dart';
      -
      -void main() {
      -  final codec = PunycodeCodec();
      -
      -  // Encode a Unicode string (e.g., a domain label)
      -  final encoded = codec.encode('bücher');
      -  print(encoded); // Output: bcher-kva
      -
      -  // Decode a Punycode string
      -  final decoded = codec.decode('egbpdaj6bu4bxfgehfvwxn');
      -  print(decoded); // Output: ليهماابتكلموشعربي؟
      -}
      -
      -

      See also:

      - +

      A pure Dart implementation of Punycode (RFC 3492) with support for +mixed-case annotation and errata.

      @@ -102,7 +73,23 @@

      Classes

      - A codec for encoding and decoding strings using the Punycode algorithm. + A Codec that converts Unicode strings to Punycode ASCII strings. +
      + +
      + PunycodeDecoder + +
      +
      + Punycode decoder as defined in RFC 3492 Section 6.2. +
      + +
      + PunycodeEncoder + +
      +
      + Punycode encoder as defined in RFC 3492 Section 6.3.
      @@ -112,8 +99,82 @@

      Classes

      +
      +

      Constants

      +
      +
      + punycode + → const PunycodeCodec + + +
      +
      + The default instance of PunycodeCodec. + + +
      + +
      +
      + + +
      +

      Functions

      +
      +
      + domainToAscii(String domain, {bool validate = true}) + String + + + +
      +
      + Converts a domain name to its Punycode-encoded ASCII representation. + + +
      + +
      + domainToUnicode(String domain) + String + + + +
      +
      + Converts a domain name from Punycode-encoded ASCII to Unicode. + + +
      +
      + emailToAscii(String email, {bool validate = true}) + String + + +
      +
      + Converts the domain part of an email address to Punycode-encoded ASCII. + + +
      + +
      + emailToUnicode(String email) + String + + + +
      +
      + Converts the domain part of an email address from Punycode-encoded ASCII to Unicode. + + +
      + +
      +
      @@ -143,7 +204,7 @@
      punycoder library
      punycoder - 0.1.0 + 0.3.0
      diff --git a/doc/api/punycoder/punycode-constant.html b/doc/api/punycoder/punycode-constant.html new file mode 100644 index 0000000..90eb0a4 --- /dev/null +++ b/doc/api/punycoder/punycode-constant.html @@ -0,0 +1,109 @@ + + + + + + + + punycode constant - punycoder library - Dart API + + + + + + + + + + + + + + +
      +
      + menu + +
      punycode
      + + +
      +
      +
      +
      +

      punycode top-level constant + +

      + +
      + + PunycodeCodec + const punycode + + +
      + +
      +

      The default instance of PunycodeCodec.

      +
      + + +
      +

      Implementation

      +
      const PunycodeCodec punycode = PunycodeCodec();
      +
      + + + +
      + + +
      +
      + + punycoder + 0.3.0 + + +
      + + + + + + + + diff --git a/doc/api/punycoder/punycoder-library-sidebar.html b/doc/api/punycoder/punycoder-library-sidebar.html index 2b1a29e..853a64a 100644 --- a/doc/api/punycoder/punycoder-library-sidebar.html +++ b/doc/api/punycoder/punycoder-library-sidebar.html @@ -1,12 +1,21 @@
      1. Classes
      2. PunycodeCodec
      3. +
      4. PunycodeDecoder
      5. +
      6. PunycodeEncoder
      7. +
      8. Constants
      9. +
      10. punycode
      11. +
      12. Functions
      13. +
      14. domainToAscii
      15. +
      16. domainToUnicode
      17. +
      18. emailToAscii
      19. +
      20. emailToUnicode
      21. diff --git a/doc/api/search.html b/doc/api/search.html index 1bab340..d46358d 100644 --- a/doc/api/search.html +++ b/doc/api/search.html @@ -68,7 +68,7 @@