Agent-First Slug v0.1.0
The first release of Agent-First Slug — a Rust slug library where every policy is set explicitly by the caller, with no hidden defaults that differ by surface.
Every slug library has a default mode. That default is someone’s guess about your target surface: which characters are allowed, how dots are handled, what to do when the result is empty. For simple cases the guess is right. The moment you’re writing into a local path, a URL segment, and a legacy system in the same codebase, you hit three sets of rules and need to force each one at the call site.
Agent-First Slug v0.1.0 makes the caller state the policy.
One config, all policies
There is a single SlugConfig struct. You fill it in — or use SlugConfig::default() for Unicode slugs with sensible trimming. The call site is the documentation:
use agent_first_slug::{slugify, AllowedCharacterSet, DotHandlingPolicy,
EmptyOutputPolicy, SlugConfig, SlugValidationPolicy,
TransliterationPolicy};
// URL path segment: dots preserved in version numbers, empty falls through
let url_config = SlugConfig {
replacement_delimiter: '-',
lowercase_enabled: true,
max_slug_chars: None,
allowed_character_set: AllowedCharacterSet::UnicodeLettersAndDecimalDigits,
dot_handling_policy: DotHandlingPolicy::PreserveDotsBetweenDecimalDigits,
transliteration_policy: TransliterationPolicy::None,
validation_policy: SlugValidationPolicy::UrlPathSegment,
empty_output_policy: EmptyOutputPolicy::KeepEmptySlug,
};
assert_eq!(slugify("Ubuntu 16.04", &url_config)?.slug, "ubuntu-16.04");
The same input through a local-path config replaces the dot:
let path_config = SlugConfig {
dot_handling_policy: DotHandlingPolicy::ReplaceAllDots,
validation_policy: SlugValidationPolicy::LocalPathSegment,
empty_output_policy: EmptyOutputPolicy::UseFallbackSlug("fallback".to_string()),
..SlugConfig::default()
};
assert_eq!(slugify("Ubuntu 16.04", &path_config)?.slug, "ubuntu-16-04");
What’s in v0.1.0
- Three character sets: ASCII alphanumeric, Unicode alphanumeric, Unicode letters + decimal digits
- Three dot policies: replace all, preserve all, preserve only between decimal digits
- Two validation targets:
LocalPathSegment(rejects/,\,.,.., control chars) andUrlPathSegment(additionally rejects?,#,%,\) - Two empty-output policies: keep empty or insert a caller-provided fallback verbatim
- Optional transliteration: pass a static replacement map; the library applies it before slugification so legacy romanization tables compose cleanly
- Truncation:
max_slug_charscounts Unicode scalar values, strips trailing delimiters after the cut, then applies the empty-output policy validate_slug: check a slug you already have against a target policy without slugifying
Unicode is preserved by default, including CJK, kana, and mixed-script inputs:
let config = SlugConfig::default();
assert_eq!(
slugify("現在的Nobody,未來的Somebody!", &config)?.slug,
"現在的nobody-未來的somebody"
);
Install
cargo add agent-first-slug