# CHANGELOG

== 8.0.0 - 2026-11-12

- the UTF-8 helpers now only accept and produce valid Unicode characters. Before, surrogates and values above U+10FFFF were decoded or encoded into invalid UTF-8, and U+FFFE and U+FFFF crashed the encoder. A list given as UTF-8 must now contain bytes: other values such as -1 or code points above 255 used to pass through or decode to the wrong name.
- the Punycode decoder now rejects malformed input that it used to accept, such as non-ASCII characters before the delimiter, a leading delimiter, values that are not Unicode characters, or input cut off in the middle of a character, which crashed with function_clause. Valid input decodes exactly as before.
- the documentation now says that IDNA 2003 compatibility comes from UTS #46 transitional processing.
- update to Unicode 18.0.0.
- normalization and lowercasing now use Unicode data shipped with idna instead of the data of the OTP release. Before, results depended on the OTP version: OTP 28 and 29 normalized some characters added in recent Unicode versions incorrectly, so the same name could be accepted or encoded differently depending on where it ran.
- fix slow rejection of over-long labels: a label longer than 63 characters was fully Punycode-converted before being rejected, so a single long hostname label could keep the CPU busy for seconds or minutes. It is now rejected right away.
- Punycode encoding and decoding are much faster on long inputs.
- fix names with a zero width non-joiner (common in Persian and other Arabic-script languages): valid names were always rejected.
- fix slow validation of long labels with many joiners, middle dots or digits. The cost of checking a label now grows linearly with its length.
- empty labels such as in "a..b" are now rejected. Before, they were accepted, and the strict option silently dropped them. A trailing dot (the root label) is still accepted.
- invalid A-labels are now rejected: labels like "xn--abc-" that decode to plain ASCII, labels that are not the canonical encoding of what they decode to, and "xn--", which used to crash.
- new verify_dns_length option, on by default: encoding rejects domains longer than 253 characters, the DNS limit. Pass {verify_dns_length, false} to allow longer names.
- the Bidi rule now applies to every label of a domain that contains a right-to-left label, as RFC 5893 requires. Some mixed-direction domains that were accepted are now rejected.
- the uts46 option now validates with the UTS #46 rules instead of the stricter IDNA2008 tables. Characters such as ¡ or ≠ are accepted in this mode. std3_rules works again: without it, names such as "_dmarc.example" are accepted, and with it they are rejected.
- the full UTS #46 conformance test file now runs in both directions, checking that valid names are accepted and invalid ones rejected.

== 7.1.0 - 2026-01-21

- update to Unicode 17.0.0
- fix recursive processing of UTS #46 character mappings

== 7.0.0 - unreleased

- remove unicode_compat. only support Erlang >= 20

== 6.1.1 - 2020-12-06

- fix license information

== 6.1.0 - 2020-12-05

- update to Unicode 13.0.0
- bump unicode_util_compat to 0.7.0
- remove support of Erlang < 19.3
- remove support of rebar 2

== 6.0.1 - 2020-05-14

- bump to unicode_compat 0.5.0

== 6.0.0 - 2018-08-30

- IDNA 2008 support [RFC5981](https://tools.ietf.org/html/rfc5891)
- International Domain Name validation
- fix [Punycode](https://tools.ietf.org/html/rfc3492) algorithm

Breaking changes:
- `idna:to_ascii/1` in 5.1.x did not encode or enforce rules if the input is already all ascii

== 5.1.2 - 2018-06-09

- support build with rebar 2
