- Pipe mode:
check-unicode -reads stdin line-by-line and writes to stdout, enabling use as a streaming Unix filter for log monitoring, CI pipelines, and editor buffer filtering --strip [dangerous|all]flag to remove non-ASCII characters;dangerousstrips only invisible/bidi chars,all(default) strips any remaining non-ASCII after allow-list processing--halt [dangerous|all]flag to stop immediately on first matching character;dangerous(default) halts on invisible/bidi chars,allhalts on any non-ASCII--fix,--strip, and--haltare fully composable and work identically across file and pipe modes
- En dash and em dash now replace to
-instead of-- - Expanded
--fixreplacement table with: hyphen variants (U+2010-2012, U+2015, U+FE58), soft hyphen (removed), bullets, dot leaders, arrows (->,<-,^,v), and math operators (x,/) - Add
pytest-sugarfor improved test output - Replace mypy with ty for type checking
- Move dev dependencies from
optional-dependenciestodependency-groups - Switch CI from pip to uv for faster, reproducible installs; check in
uv.lock - Extract codepoint/range parsing into
check_unicode.parsingmodule for reuse - Codepoint parser now validates the Unicode range (0..U+10FFFF) and rejects empty/invalid input with clear error messages
- Range parser now rejects inverted ranges (lo > hi) and tolerates whitespace around the dash separator
- Validate
severityvalues from config files and overrides (invalid values like"warn"now exit 2 instead of silently behaving as warning) - Catch config file errors (missing file, invalid TOML) and exit 2 with a friendly message instead of a raw traceback
- Validate
--allow-categoryand--allow-scriptvalues; unknown names now exit 2 with a hint to use--list-categoriesor--list-scripts - Warn on unrecognised top-level config keys (e.g. typo
alow-codepoints) - Remove dead
U+FFFDentry fromREPLACEMENT_TABLE(unreachable because U+FFFD is inDANGEROUS_INVISIBLE, which is checked first) - Exclude
tests/fixtures/from mypy (intentionally malformed Trojan Source files)
- Grouped output: findings are now grouped per file with a compact line range
header (e.g.
file.txt:1,4-80,90:), context lines shown once with multi-caret markers (^normal,!dangerous,?confusable), deduplicated identical context lines, and collapsed codepoint listing with(xN)counts
- Refactor
_apply_replacementsto usestr.translate()for cleaner code and better performance on large files - Read each file once when
--check-confusablesis enabled (previouslycheck_fileandcheck_confusableseach read the file independently) - Simplify
_parse_codepointto use prefix-stripping instead of fragile double-replace chain - Add
slots=TruetoOverridedataclass for consistency withFindingandAllowConfig
- Document per-file
[[tool.check-unicode.overrides]]in README and man page - Update man page version to 0.4.0 and fix stale pre-commit
rev - Add man page to
bump-my-versionfiles list
[[tool.check-unicode.overrides]]per-file config: apply different allow-lists, severity, and confusable settings per file pattern- Per-file severity: override
severityto"warning"for specific file patterns so findings don't affect exit code - Per-file confusable toggle: enable or disable
check-confusablesper file pattern uv.lockadded to.gitignore
--fixmode now fixes all files, not just the first (any()short-circuited after the first fixable file, skipping the rest)
CONTRIBUTING.mdguideSECURITY.mdwith private vulnerability reporting instructions- Issue templates for bug reports and feature requests
- Make
bump-my-versionhandle README.md version
- PR template with changelog and testing checklist
- Coverage threshold (80%) enforced in CI
markdownlintconfig: allow duplicate headings across sibling sections
- Grouped CLI help with
--helpshowing organized option sections - Usage examples in
--helpoutput - Man page (
docs/check-unicode.1) - Release workflow for automatic GitHub Releases on tag push
bump-my-versionconfig for version management
--allow-printableflag: allow allstr.isprintable()characters, only flagging invisible/control characters. Opt-in, not default.--allow-script SCRIPTflag: allow entire Unicode scripts (e.g. Latin, Cyrillic, Han). Repeatable. Dangerous invisible characters are never overridden by script allow-lists.--check-confusablesflag: detect mixed-script homoglyph/confusable characters (e.g. Cyrillicain a Latin identifier). Uses a curated set of ~45 security-critical mappings from Unicode confusables.txt.scripts.pymodule: zero-dependency Unicode script detection usingunicodedata.name()heuristic.confusables.pymodule: curated confusable character mappings (Cyrillic, Greek, Armenian to Latin).- New test fixtures: Trojan Source examples, mixed Cyrillic, pure Cyrillic, printable i18n text.
- TOML config keys:
allow-printable,allow-scripts,check-confusables.
Initial release.
- ASCII-only detection with configurable allow-lists (codepoints, ranges, Unicode categories)
- Dangerous invisible character detection (bidi control, zero-width) -- always flagged regardless of allow-lists
- Auto-fix mode for smart quotes, dashes, fancy spaces, ellipsis
- TOML config support (
.check-unicode.tomlorpyproject.toml) - Pre-commit hooks:
check-unicode(detect) andfix-unicode(auto-fix)