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