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_th")

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.InvalidInput(reason)) -> "Invalid input: " <> reason
  Error(errors.TooLong(current, max)) -> "Text too long"
  Error(errors.TransliterationFailed(char)) -> "Cannot transliterate: " <> char
  Error(errors.ConfigurationError(msg)) -> "Config error: " <> msg
}

Performance

Glugify is designed for high performance with comprehensive benchmarks covering various input types:

Benchmark Results

Erlang Target

Test CaseOperations/secAvg Time per Operation
Simple text (“Hello World”)4 ops/sec202ms
Unicode text with emojis12 ops/sec83ms
Long text (200+ chars)1 ops/sec619ms
Complex text (mixed case, symbols)2 ops/sec336ms
Configured simple text21 ops/sec47ms
Configured unicode text11 ops/sec84ms
Configured long text1 ops/sec629ms
Configured complex text2 ops/sec350ms

Erlang Summary: 800 total operations executed with an average of 6 operations per second.

JavaScript Target

Test CaseOperations/secAvg Time per Operation
Simple text (“Hello World”)2,702 ops/sec0.38ms
Unicode text with emojis3,030 ops/sec0.33ms
Long text (200+ chars)347 ops/sec2.88ms
Complex text (mixed case, symbols)613 ops/sec1.64ms
Configured simple text4,761 ops/sec0.21ms
Configured unicode text3,846 ops/sec0.27ms
Configured long text342 ops/sec2.92ms
Configured complex text602 ops/sec1.66ms

JavaScript Summary: 800 total operations executed with an average of 2,030 operations per second.

Performance Characteristics

Key Observations:

The benchmarks were run with 100 iterations per test case on both Erlang and JavaScript targets. Performance 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