Add slugify_or_default for core-hub parity, bump to 0.2.0, document ecosystem position in INTENT/SCOPE/README, wire capability relations to state-hub and core-hub, and extend utils tests. Part of CUST-WP-0057 consolidation.
30 lines
811 B
Python
30 lines
811 B
Python
import re
|
|
|
|
_NON_SLUG = re.compile(r"[^a-z0-9]+")
|
|
_DASHES = re.compile(r"-+")
|
|
|
|
|
|
def slugify(value: str, *, max_length: int = 100) -> str:
|
|
slug = _NON_SLUG.sub("-", value.strip().lower())
|
|
slug = _DASHES.sub("-", slug).strip("-")
|
|
if not slug:
|
|
raise ValueError("slug cannot be empty")
|
|
if max_length < 1:
|
|
raise ValueError("max_length must be >= 1")
|
|
return slug[:max_length].strip("-")
|
|
|
|
|
|
def slugify_or_default(
|
|
value: str,
|
|
*,
|
|
default: str = "resource",
|
|
max_length: int = 100,
|
|
) -> str:
|
|
"""Like slugify but returns default when input yields no slug characters.
|
|
|
|
Matches core-hub bootstrap semantics where API consumers need a fallback slug.
|
|
"""
|
|
try:
|
|
return slugify(value, max_length=max_length)
|
|
except ValueError:
|
|
return default
|