glugify

A slugification library for Gleam that converts text into URL-friendly slugs.

Package Version Hex Docs

gleam add glugify

Quick Start

import glugify

// Simple usage - always returns a string
glugify.slugify("Hello, World!")
// -> "hello-world"

// Error-aware usage - returns Result
glugify.try_slugify("My Blog Post Title!")
// -> Ok("my-blog-post-title")

Three-Tier API

Tier 1: Simple API

Zero-configuration slugification that always returns a string:

import glugify

glugify.slugify("My awesome blog post!")
// -> "my-awesome-blog-post"

glugify.slugify("Café & Restaurant")
// -> "cafe-and-restaurant"

Tier 2: Error-Aware API

Returns Result(String, SlugifyError) for explicit error handling:

import glugify

case glugify.try_slugify("") {
  Ok(slug) -> "Generated slug: " <> slug
  Error(error) -> "Failed to generate slug"
}

Tier 3: Configurable API

Full control with custom configuration:

import glugify
import glugify/config

let custom_config = config.default()
  |> config.with_separator("_")
  |> config.with_max_length(20)
  |> config.with_word_boundary(True)

glugify.slugify_with("A Very Long Title That Needs Truncation", custom_config)
// -> Ok("a_very_long_title")

Configuration Options

import glugify/config

config.default()
  |> config.with_separator("_")           // Default: "-"
  |> config.with_lowercase(False)         // Default: True
  |> config.with_max_length(50)           // Default: None
  |> config.with_word_boundary(True)      // Default: False
  |> config.with_transliterate(False)     // Default: True
  |> config.with_allow_unicode(True)      // Default: False
  |> config.with_custom_replacements([    // Default: []
    #("&", " and "),
    #("@", " at ")
  ])
  |> config.with_stop_words(["the", "a"]) // Default: []

Advanced Examples

Custom Replacements

let config = config.default()
  |> config.with_custom_replacements([
    #("&", " and "),
    #("@", " at "),
    #("%", " percent ")
  ])

glugify.slugify_with("Cats & Dogs @ 100%", config)
// -> Ok("cats-and-dogs-at-100-percent")

Unicode Handling

// With transliteration (default)
glugify.slugify("Café naïve résumé")
// -> "cafe-naive-resume"

// Preserving Unicode
let unicode_config = config.default()
  |> config.with_transliterate(False)
  |> config.with_allow_unicode(True)

glugify.slugify_with("Café naïve résumé", unicode_config)
// -> Ok("caf-na-ve-r-sum")

Stop Words

let config = config.default()
  |> config.with_stop_words(["the", "a", "an", "and", "or"])

glugify.slugify_with("The Quick Brown Fox and the Lazy Dog", config)
// -> Ok("quick-brown-fox-lazy-dog")

Error Handling

The library provides explicit error types for robust error handling:

import glugify/errors

case glugify.try_slugify("") {
  Ok(slug) -> slug
  Error(errors.EmptyInput) -> "Please provide some text"
  Error(errors.TransliterationFailed(char)) -> "Cannot transliterate: " <> char
  Error(errors.ConfigurationError(msg)) -> "Config error: " <> msg
}

Performance

Benchmark Results (using gleamy_bench)

Erlang Target

Test CaseFunctionIPS (ops/sec)Min Time (ms)P99 Time (ms)
Simple text (“Hello World”)slugify20,4120.0460.061
Simple text (“Hello World”)slugify_with_custom_config20,6460.0460.060
Unicode text with emojisslugify11,9030.0810.098
Unicode text with emojisslugify_with_custom_config12,0640.0810.095
Long text (200+ chars)slugify1,5450.6061.090
Long text (200+ chars)slugify_with_custom_config1,5710.6070.709
Complex text (mixed case, symbols)slugify2,8970.3270.381
Complex text (mixed case, symbols)slugify_with_custom_config2,9330.3290.373

Erlang Summary: Average of ~9,750 operations per second across all test cases.

JavaScript Target

Test CaseFunctionIPS (ops/sec)Min Time (ms)P99 Time (ms)
Simple text (“Hello World”)slugify5,9250.1290.570
Simple text (“Hello World”)slugify_with_custom_config5,6810.1330.655
Unicode text with emojisslugify3,9920.1990.700
Unicode text with emojisslugify_with_custom_config4,0210.2020.729
Long text (200+ chars)slugify3852.0833.227
Long text (200+ chars)slugify_with_custom_config3692.1853.471
Complex text (mixed case, symbols)slugify6541.1952.635
Complex text (mixed case, symbols)slugify_with_custom_config6351.2642.489

JavaScript Summary: Average of ~2,670 operations per second across all test cases.

Performance Characteristics

Stuff of note:

The benchmarks were run using gleamy_bench with 1000ms duration per test and 100ms warmup. Performance includes proper statistical analysis with IPS (iterations per second), minimum time, and 99th percentile measurements. Results may vary depending on your specific use case and runtime environment.

Installation

Add glugify to your Gleam project:

gleam add glugify

Development

gleam run   # Run the project
gleam test  # Run the tests
gleam format # Format the code

Contributing

Contributions are welcome! Please feel free to submit a Pull Request!

Documentation

Further documentation can be found at https://hexdocs.pm/glugify.

Search Document