punycoder 0.1.0
punycoder: ^0.1.0 copied to clipboard
Punycoder is a well tested Dart implementation of the RFC 3492 Punycode specification
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--
.
Features #
- RFC 3492 Compliant: Implements the Punycode encoding and decoding algorithms as specified in the standard.
- IDNA Helpers: Provides convenient methods (
toAscii
,toUnicode
) for converting full domain names or email addresses, automatically handling thexn--
prefix and processing only the necessary parts of the string. - Core Codec: Offers direct access to the raw Punycode
encode
anddecode
operations viaPunycodeCodec
for advanced use cases. - Efficient and Tested: Based on a port of the well-regarded Punycode.js library, including tests based on official RFC examples.
Getting Started #
Add the package to your pubspec.yaml
:
dependencies:
punycoder: 0.1.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';
void main() {
// Use the singleton encoder/decoder for common IDNA tasks
const encoder = punycodeEncoder;
const decoder = punycodeDecoder;
// --- Convert domains/emails TO ASCII (ACE format) ---
final domainsToEncode = ['bücher.example', 'example.com', '你好.test'];
print('Encoding to ASCII:');
for (final domain in domainsToEncode) {
final asciiVersion = encoder.toAscii(domain);
// toAscii adds 'xn--' prefix only if encoding actually happens
print('"$domain" -> "$asciiVersion"');
// Output:
// "bücher.example" -> "xn--bcher-kva.example"
// "example.com" -> "example.com"
// "你好.test" -> "xn--6qq79v.test"
}
// --- Convert domains/emails FROM ASCII (ACE format) ---
final domainsToDecode = ['xn--bcher-kva.example', 'example.com', 'xn--6qq79v.test'];
print('Decoding from ASCII:');
for (final domain in domainsToDecode) {
final unicodeVersion = decoder.toUnicode(domain);
// toUnicode decodes labels starting with 'xn--'
print('"$domain" -> "$unicodeVersion"');
// Output:
// "xn--bcher-kva.example" -> "bücher.example"
// "example.com" -> "example.com"
// "xn--6qq79v.test" -> "你好.test"
}
// --- Raw Encoding/Decoding (Advanced) ---
// For direct encoding/decoding without automatic prefix handling or domain splitting:
final codec = PunycodeCodec();
final rawEncoded = codec.encode('bücher'); // -> 'bcher-kva' (no prefix)
final rawDecoded = codec.decode('bcher-kva'); // -> 'bücher'
print('\nRaw codec example: "$rawDecoded"');
}