cargo build # Build project
cargo build --release # Release build
cargo build --features ffi # Build with C FFI bindings
cargo build --features wasm --target wasm32-unknown-unknown # Build for WebAssembly
cargo test # Run all tests
cargo test --test en_tests # Run a single integration test file
cargo test en_tn_tests::test_name # Run a single test by name
cargo fmt # Format code
cargo clippy --all-targets # Lint- src/itn/: ITN taggers (spoken → written, Inverse Text Normalization) per language (en, de, es, fr, hi, ja, zh)
- src/tn/: TN taggers (written → spoken, Text Normalization)
- src/custom_rules.rs: User-defined custom normalization rules (highest priority)
- src/ffi.rs: C FFI bindings for Swift/Python integration (gated by
ffifeature) - src/wasm.rs: JavaScript-callable wasm bindings (gated by
wasmfeature) - src/lib.rs: Public API entry point —
normalize()dispatches to taggers in specificity order - tests/: Integration tests (per-language ITN/TN suites +
extensive_tests.rsedge cases) - swift/, swift-test/: Swift consumer package and tests for the FFI surface
- wasm-tests/: Browser/Node tests against the wasm build
- scripts/: Build helpers (e.g.
set-wasm-package-name.mjs) - build-xcframework.sh: Builds an
.xcframeworkfor Apple platform consumers
input → custom_rules → whitelist → punctuation → word → time → telephone → ... → output
Taggers are tried in order of specificity (most specific first). If no tagger matches, the original text is returned.
- NEVER run
git pushunless explicitly requested by the user - NEVER add
Co-Authored-Bylines for Claude, Copilot, or any AI assistant in commit messages - NEVER create simplified or stub versions — implement full solutions or consult first
- NEVER introduce mock data or fabricated test cases — use realistic spoken/written forms
- Add unit/integration tests when adding new taggers or rules
- Keep all changes local to the appropriate language module under
src/itn/<lang>/orsrc/tn/<lang>/ - Maintain feature-flag isolation: code behind
ffiandwasmmust not leak into the default build
- Use
cargo fmtbefore committing — defaults to standard rustfmt rules - Use
snake_casefor functions/variables,UpperCamelCasefor types,SCREAMING_SNAKE_CASEfor consts - Public APIs: document with
///doc comments and include runnable examples where practical - Error handling: prefer
Option/Result; avoidunwrap()/expect()in library code - Control flow: prefer early returns and flat structure over nested conditionals
- Imports: group
std, external crates, and local modules separately - Keep tagger functions small and focused — one tagger per spoken-form pattern
- Maintain API consistency across language taggers (each tagger exposes
parse(&str) -> Option<String>) - Single responsibility per file: one tagger category per module (e.g.
cardinal.rs,date.rs,money.rs) - New languages should mirror the existing
itn::enmodule layout - When extending the public API, update
lib.rs, FFI bindings (ffi.rs), and wasm bindings (wasm.rs) together so all consumers stay in sync
- C FFI lives in
src/ffi.rsbehind theffifeature; consumed by the Swift package inswift/ - Wasm bindings live in
src/wasm.rsbehind thewasmfeature; consumed bywasm-tests/ - Run
cargo build --features ffiand the Swift tests underswift-test/after touching FFI signatures - Run the wasm test suite after touching
wasm.rsor anything affecting the wasm-exposed surface
Consult PLANS.md (when present) for complex tasks; plan changes first. Store plans in a local .mobius/ folder without committing to GitHub.