all2md.utils.text
Text processing utilities for AST transforms.
This module provides text manipulation functions commonly used by transforms, including slugification for heading IDs and table of contents generation.
Functions
slugify : Convert text to URL-safe slug make_unique_slug : Generate unique slug with duplicate handling
Examples
Basic slugification:
>>> from all2md.utils.text import slugify
>>> slugify("My Heading Title")
'my-heading-title'
Custom separator:
>>> slugify("My Heading Title", separator="_")
'my_heading_title'
Unique slug generation with counter:
>>> seen = {}
>>> slug1 = make_unique_slug("my-heading", seen) # 'my-heading'
>>> slug2 = make_unique_slug("my-heading", seen) # 'my-heading-2'
>>> slug3 = make_unique_slug("my-heading", seen) # 'my-heading-3'
- all2md.utils.text.slugify(text: str, *, seen_slugs: Set[str] | None = None, max_length: int = 100, separator: str = '-') str
Create a URL-safe slug from text with collision avoidance.
This function generates GitHub-flavored Markdown compatible slugs by: - Normalizing Unicode characters (NFD decomposition) - Converting to lowercase - Replacing spaces and underscores with hyphens - Removing non-alphanumeric characters (except hyphens) - Collapsing multiple consecutive hyphens - Stripping leading/trailing hyphens - Handling collisions by appending -2, -3, etc. - Limiting length to max_length characters
- Parameters:
text (str) – Text to slugify (e.g., heading text, filename)
seen_slugs (Set[str] or None, default = None) – Set of previously generated slugs for collision detection. If provided and the generated slug already exists, a numeric suffix will be appended (-2, -3, etc.). The function will automatically add the new slug to this set.
max_length (int, default = 100) – Maximum length of the slug. Slugs longer than this will be truncated before adding collision suffixes.
separator (str, default = "-") – The separator between words in the slug
- Returns:
URL-safe slug, unique if seen_slugs is provided
- Return type:
str
Examples
- Basic slugification:
>>> slugify("Hello World!") 'hello-world'
- Handle special characters:
>>> slugify("API Reference (v2.0)") 'api-reference-v20'
- Collision detection:
>>> seen = set() >>> slug1 = slugify("Introduction", seen_slugs=seen) >>> slug1 'introduction' >>> slug2 = slugify("Introduction", seen_slugs=seen) >>> slug2 'introduction-2'
- Length limiting:
>>> slugify("A" * 150, max_length=50) 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
- Unicode normalization:
>>> slugify("Café résumé") 'cafe-resume'
- all2md.utils.text.make_unique_slug(slug: str, seen_slugs: dict[str, int], separator: str = '-') str
Generate unique slug with duplicate handling.
This function ensures slug uniqueness by appending a numeric suffix when duplicates are encountered. The seen_slugs dictionary tracks occurrence counts and is mutated in-place.
- Parameters:
slug (str) – Base slug to make unique
seen_slugs (dict[str, int]) – Dictionary tracking occurrence counts (mutated in-place). Maps base slug to count of occurrences.
separator (str, default = "-") – Separator to use before numeric suffix
- Returns:
Unique slug (with numeric suffix if needed)
- Return type:
str
Examples
Basic usage:
>>> seen = {} >>> make_unique_slug("my-heading", seen) 'my-heading' >>> make_unique_slug("my-heading", seen) 'my-heading-2' >>> make_unique_slug("my-heading", seen) 'my-heading-3'
Custom separator:
>>> seen = {} >>> make_unique_slug("heading", seen, separator="_") 'heading' >>> make_unique_slug("heading", seen, separator="_") 'heading_2'
Notes
The seen_slugs dictionary is modified in-place to track counts. This allows callers to maintain state across multiple calls.
The first occurrence of a slug does not get a numeric suffix. Subsequent occurrences get suffixes starting at 2.