str/extra
ASCII transliteration and slug generation utilities.
This module provides pragmatic tools for converting Unicode text to ASCII and generating URL-friendly slugs. Uses curated replacement tables optimized for Latin-based scripts and common ligatures. OTP-free core with optional normalizer injection for production use.
Values
pub fn ascii_fold(s: String) -> String
Converts Unicode text to ASCII equivalents. Applies replacement tables, decomposes Latin chars and removes combining marks.
ascii_fold(“café”) -> “cafe” ascii_fold(“straße”) -> “strasse” ascii_fold(“Crème Brûlée”) -> “Creme Brulee”
pub fn ascii_fold_no_decompose(s: String) -> String
ASCII folding without decomposition step. Applies only the replacement table, preserving combining marks.
ascii_fold_no_decompose(“café”) -> “cafe”
pub fn ascii_fold_no_decompose_with_normalizer(
s: String,
normalizer: fn(String) -> String,
) -> String
ASCII folding without decomposition, with custom normalizer. The replacement table is applied twice: before and after normalization. This handles cases where the normalizer (e.g., NFC) may compose characters into precomposed forms that the table can then convert.
Pipeline:
- Apply replacement table (precomposed chars)
- Apply custom normalizer (may produce new precomposed chars)
- Apply replacement table again (catch newly composed chars)
pub fn ascii_fold_with_normalizer(
s: String,
normalizer: fn(String) -> String,
) -> String
ASCII folding with custom normalizer for production Unicode handling. The normalizer (typically OTP’s :unicode module) is applied between decomposition and combining mark removal.
Pipeline:
- Apply replacement table (precomposed chars)
- Decompose Latin chars
- Apply custom normalizer (e.g., NFC/NFD from OTP)
- Remove combining marks
- Apply replacement table again (catch chars with attached combining marks)
ascii_fold_with_normalizer(“café”, my_nfd) -> “cafe”
pub fn slugify(s: String) -> String
Creates a URL-friendly slug from text. Uses default settings: hyphen separator, no token limit, ASCII output.
slugify(“Hello, World!”) -> “hello-world” slugify(“Café & Bar”) -> “cafe-bar”
pub fn slugify_opts(
s: String,
max_len: Int,
sep: String,
preserve_unicode: Bool,
) -> String
Creates a slug with configurable options. max_len limits tokens (-1 for unlimited), sep is the separator, preserve_unicode keeps Unicode chars if True.
slugify_opts(“one two three”, 2, “-”, False) -> “one-two” slugify_opts(“Hello World”, -1, “_”, False) -> “hello_world”
pub fn slugify_opts_with_normalizer(
s: String,
max_len: Int,
sep: String,
preserve_unicode: Bool,
normalizer: fn(String) -> String,
) -> String
Creates a slug with full options and custom normalizer.
slugify_opts_with_normalizer(“Crème Brûlée”, 2, “-”, False, my_nfd) -> “creme-brulee”
pub fn slugify_with_normalizer(
s: String,
normalizer: fn(String) -> String,
) -> String
Creates a slug using a custom normalizer function.
slugify_with_normalizer(“Café”, my_nfd) -> “cafe”
pub fn to_camel_case(s: String) -> String
Converts text to camelCase. First word is lowercase, subsequent words are capitalized.
to_camel_case(“hello world”) -> “helloWorld” to_camel_case(“get user by id”) -> “getUserById”
pub fn to_kebab_case(s: String) -> String
Converts text to kebab-case (lowercase with hyphens).
to_kebab_case(“Hello World”) -> “hello-world”
pub fn to_pascal_case(s: String) -> String
Converts text to PascalCase. All words are capitalized and joined without separator.
to_pascal_case(“hello world”) -> “HelloWorld” to_pascal_case(“get user by id”) -> “GetUserById”
pub fn to_snake_case(s: String) -> String
Converts text to snake_case (lowercase with underscores).
to_snake_case(“Hello World”) -> “hello_world”
pub fn to_title_case(s: String) -> String
Converts text to Title Case. Each word is capitalized with spaces between them.
to_title_case(“hello world”) -> “Hello World” to_title_case(“get user by id”) -> “Get User By Id” to_title_case(“café brûlée”) -> “Cafe Brulee”