Packages

A lightweight wrapper library around Unicode normalization

Current section

Files

Jump to
unicorn src unicorn.gleam
Raw

src/unicorn.gleam

//// A lightweight wrapper library around built-in Unicode normalization functions
//// for both Erlang and JavaScript targets.
////
//// You can use either Erlang-style (`to_nfc`, `to_nfd`, `to_nfkc`, `to_nfkd`)
//// or JavaScript-style (`normalize`) APIs, with type safety provided by Gleam.
////
//// ## Usage
////
//// ```gleam
//// import gleam/int
//// import gleam/list
//// import gleam/string
////
//// import unicorn.{NFKC}
////
//// pub fn main() {
//// // **Erlang style**
////
//// // NFC: "e" with a combining acute -> single "é"
//// let s = unicorn.to_nfc("e\u{0301}")
//// echo #(s, unicode_notations(s))
//// // #("é", ["U+00E9"])
////
//// // NFD: single "が" -> "か" with a combining dakuten
//// let s = unicorn.to_nfd("が")
//// echo #(s, unicode_notations(s))
//// // #("が", ["U+304B", "U+3099"])
////
//// // NFKC: half-width "カ" + half-width dakuten -> full-width "ガ"
//// let s = unicorn.to_nfkc("ガ")
//// echo #(s, unicode_notations(s))
//// // #("ガ", ["U+30AC"])
////
//// // NFKD: single ḕ -> "e" + macron + grave
//// let s = unicorn.to_nfkd("ḕ")
//// echo #(s, unicode_notations(s))
//// // #("ḕ", ["U+0065", "U+0304", "U+0300"])
////
//// // **JavaScript style**
//// // To use it, pass (unicorn.)`Form` to the 2nd argument
////
//// // NFKC: fraction "¼" -> separate "1" + "⁄" + "4"
//// let s = unicorn.normalize("¼", NFKC)
//// echo #(s, unicode_notations(s))
//// // #("1⁄4", ["U+0031", "U+2044", "U+0034"])
////
//// // NFKC: hangul conjoining jamo "ᄀ" + "ᅡ" + "ᆨ" -> single "각"
//// let s = unicorn.normalize("각", NFKC)
//// echo #(s, unicode_notations(s))
//// // #("각", ["U+AC01"])
//// }
////
//// fn unicode_notations(s: String) -> List(String) {
//// list.map(string.to_utf_codepoints(s), fn(cp) {
//// let cp = string.utf_codepoint_to_int(cp)
//// "U+" <> string.pad_start(int.to_base16(cp), 4, "0")
//// })
//// }
//// ```
////
//// For details on Unicode normalization, see:
//// https://unicode.org/reports/tr15/
/// Represents normalization forms accepted by the `normalize` function.
/// The possible variants are `NFC`, `NFD`, `NFKC` and `NFKD`.
pub type Form {
NFC
NFD
NFKC
NFKD
}
/// Converts a `String` into its
/// canonical composition form (NFC).
@external(erlang, "er_ffi", "to_nfc")
@external(javascript, "./js_ffi.mjs", "to_nfc")
pub fn to_nfc(s: String) -> String
/// Converts a `String` into its
/// canonical decomposition form (NFD).
@external(erlang, "er_ffi", "to_nfd")
@external(javascript, "./js_ffi.mjs", "to_nfd")
pub fn to_nfd(s: String) -> String
/// Converts a `String` into its
/// compatibility composition form (NFKC).
@external(erlang, "er_ffi", "to_nfkc")
@external(javascript, "./js_ffi.mjs", "to_nfkc")
pub fn to_nfkc(s: String) -> String
/// Converts a `String` into its
/// compatibility decomposition form (NFKD).
@external(erlang, "er_ffi", "to_nfkd")
@external(javascript, "./js_ffi.mjs", "to_nfkd")
pub fn to_nfkd(s: String) -> String
/// Normalizes a `String` to the specified Unicode normalization `form`.
pub fn normalize(s: String, form form: Form) -> String {
case form {
NFC -> to_nfc(s)
NFD -> to_nfd(s)
NFKC -> to_nfkc(s)
NFKD -> to_nfkd(s)
}
}