Changelog¶
Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
[1.0.3] - 2026-08-20¶
Fixed¶
__version__now reads from package metadata so it stays in sync withpyproject.toml.- Release workflow now correctly extracts the CHANGELOG section for GitHub releases.
[1.0.2] - 2026-08-20¶
Fixed¶
- Apply
ruff formattoslugany/_steps.pyso the CI format check passes.
[1.0.1] - 2026-08-20¶
Fixed¶
- CLI stdio UTF-8 reconfiguration now uses
getattrto satisfy mypy andcontextlib.suppressto keep ruff happy. - Wrapped the long test list in
test_mixed_case_idempotency_all_stylesto respect the 100-character line length.
[1.0.0] - 2026-08-20¶
Added¶
- Emoji
textmode: replaces emojis with textual descriptions via_EMOJI_TEXTmapping table (100+ emojis) - Emoji
keepmode: preserves emojis in output withallow_unicode=Truevalidation - Greek-to-Latin confusable mappings in
_CONFUSABLES(α→a, β→b, γ→g, etc.) deconfuse()public function for standalone Unicode homoglyph replacementdeconfuseexported fromsluganypackage (__all__)Slugifierclass: stateless slugifier bound to a fixed configuration withSlugifier.style()factorySlugifier.__call__withTypeErroron non-string inputSlugifier.__repr__for debuggingSlugifier.configread-only property exposing the frozenSlugConfig- CSS-safe slug prefixing for camel, pascal, and train styles
_apply_css_safepipeline step (before_apply_case_style)py.typedmarker (PEP 561) for type checker discovery"Typing :: Typed"classifier inpyproject.toml- CI coverage enforcement at 100% (
--cov-fail-under=100) - Trusted publishing via
pypa/gh-action-pypi-publish@release/v1with attestations - Mkdocstrings API documentation with Google-style docstrings (Args, Returns, Raises, Examples)
- Comprehensive guide documentation: migration, performance, contracts
- README with badges (PyPI, CI, coverage, Python versions, License), 3-way comparison table (python-slugify vs unicode-slugify vs slugany)
- FastAPI/Pydantic integration examples in README
- Slugifier builder pattern examples in README
- CLI examples in README
- 478 tests with 100% coverage
Changed¶
_handle_emojinow supports three modes:strip(remove),text(replace with description),keep(preserve withallow_unicode=True)_EMOJI_REregex expanded with additional ranges (U+2300-23FF, U+2B00-2BFF, U+1F000-1F0FF, etc.)- Pipeline expanded to 18 steps (added
_apply_css_safeand second_truncate/_trim_separatorspass) _CONFUSABLESexpanded with Greek uppercase and lowercase mappings- All public function docstrings completed with Google-style Args, Returns, Raises, Examples sections
- README test count badge updated to 478
- Performance documentation updated with pipeline diagram, short-circuit optimization, and Slugifier reuse section
- Migration documentation expanded with full parameter mapping table and intentional differences section
- Contracts documentation expanded with case-insensitive stopwords, CSS-safe output, and multi-character separator contracts
Fixed¶
_handle_emojimulti-character emoji matching: iterates over each character in match group for_EMOJI_TEXTlookupemoji_mode='keep'now raisesValueErrorwhenallow_unicode=Falseinstead of silently preserving emojis- Greek letters αβγ now deconfused to
abgbefore NFKD fallback (previously produced empty string) - Emoji
textmode correctly replaces emojis with descriptions before transliteration step
[0.2.0] - 2026-08-20¶
Added¶
- Language auto-detection:
lang='auto'detects dominant language from Unicode code-point ranges (es, pt, de, fr, it) and selects the appropriate transliteration table - Optional Pydantic
Slugtype:Annotated[str, BeforeValidator]that auto-slugifies string values in Pydantic models; falls back tostrwhen pydantic is not installed _LANG_DETECT_RANGEStable in_tables.pyfor language detection
Fixed¶
- Pipeline order:
_trim_separatorsnow runs before_truncateto avoid trailing separators after truncation word_boundarytruncation at exact separator position: returns full truncated text instead of losing a word when the boundary falls exactly at a separatorSlugConfig.from_kwargsnow rejectsboolformax_length(Pythonboolis a subclass ofint)is_slugwith empty separator: avoids catastrophic backtracking (ReDoS) by using a simple character-class match- CLI now catches
ValueErrorandTypeErrorfrom slugify and prints to stderr with exit code 1 instead of an unhandled traceback
[0.1.0] - 2026-08-19¶
Added¶
slugify()function with keyword-only API andTypeErroron non-string inputslugify_batch()for batch processing of multiple textsis_slug()validator withallow_unicodesupportSlugConfigfrozen dataclass withfrom_kwargs()factory and style presets- Transliteration tables for es, pt, de, fr, it
- Smart punctuation normalization (curly quotes, em-dash, NBSP, zero-width, bullets)
- HTML entity decoding (
&→&) - Emoji stripping via regex
- Confusable character detection (Cyrillic → Latin)
- Case styles: kebab, snake, camel, pascal, dot, train, filename, url
- Stopwords removal
- Pre/post replacements (dict or iterable of tuples)
max_lengthwith optionalword_boundarytruncationallow_unicodemode to preserve non-ASCII charactersfallbackparameter for empty slug resultscss_safemode to prefix digit-leading slugsemoji_mode(strip, text, keep)html_entitiesandsmart_punctuationtoggleslru_cachebuilt-in (maxsize=512) withcache_info()andcache_clear()- Pipeline architecture with 16 pure-function steps
- CLI with argparse, auto-stdin detection, and batch mode
py.typedmarker (PEP 561)- CI/CD: lint (ruff), typecheck (mypy), test (3.11/3.12/3.13), release, docs
- MkDocs Material documentation with mkdocstrings API reference
- Idempotency, determinism, ASCII output, and no-double-separator contracts
SlugConfigAPI reference page in documentationCONTRIBUTING.mdwith development setup, PR process, and code style guidelinesSECURITY.mdwith vulnerability reporting policyCODE_OF_CONDUCT.mdbased on Contributor Covenant 2.1- GitHub issue templates (bug report, feature request)
- GitHub pull request template with checklist
- Dependabot configuration for pip and GitHub Actions
- Documentation URL in
pyproject.tomlproject URLs __version__attribute exported from package
Changed¶
slugify()andslugify_batch()parameters are now properly typed (no moreAnysentinel pattern) — IDE autocompletion and type checking now work correctly for all 14 keyword argumentsslugify_batch()now accepts explicit keyword arguments instead of**kwargs: AnySlugConfig.from_kwargs()no longer usestype: ignorecomments — validation constants extracted to module-levelfrozensets_STYLE_PRESETSand validation constants moved beforeSlugConfigclass definitionis_slug()now raisesTypeErrorfor non-stringseparatorinput- CLI
_build_kwargsreturn type changed fromdict[str, object]todict[str, Any]to eliminatetype: ignoreonslugifycalls pyproject.tomldescription translated to English; license changed to SPDX expression withlicense-files- README.md and docs/index.md translated from Spanish to English
mkdocs.ymlsite description translated to English- Development status classifier updated from Alpha to Beta
- Removed redundant
re.UNICODEflag from_UNICODE_ALNUM_RE(default in Python 3) _CONFIG_DEFAULTSnow computed from dataclass fields instead of hardcoded values (DRY)- Fixed pipeline step count in documentation (16, not 17)
- Fixed benchmark numbers in performance documentation
- Fixed incorrect emoji_mode examples in README
- README expanded with advanced examples, documentation links, and contributing section
docs/index.mdrewritten as a proper landing page with feature list and navigationCONTRIBUTING.mdupdated with full dev setup (dev+docs) and Code of Conduct reference- CI/CD workflows now use pip dependency caching
Fixed¶
- Non-ASCII stopwords not transliterated before matching
- css_safe + max_length idempotency (pipeline reorder)
- train + max_length idempotency (double truncate)
- Unicode case boundary splitting for camel/pascal/train styles
- Case boundary splitting: digit-to-lowercase should not split
- Camel/pascal/train idempotency with consecutive uppercase letters
- Missing Cyrillic homoglyphs in _CONFUSABLES (в, к, м, н, т)
- Missing emoji ranges in _EMOJI_RE (U+2300-23FF, U+2B00-2BFF, etc.)
- Replacements double-application (pre/post split by ASCII/non-ASCII keys)
- CSS safe idempotency with camel/pascal/train styles
- Type validation for bool/int/str fields in from_kwargs
- Stopwords matching: non-alphanumeric chars stripped consistently
- Deconfuse skipped when allow_unicode=True
- Emoji mode text/keep preserving emojis through transliteration
- HTML entities, smart punctuation, transliteration interactions
Removed¶
_verify.py— redundant sanity-check script duplicated by the test suitedocs/changelog.md— duplicate of rootCHANGELOG.md; mkdocs now references the original