Please see our community docs on contributing.
This document is for developers contributing to source code.
All logic lives in Rust (src/). UniFFI generates language bindings from the compiled library — the bindings are derived, not hand-written. Contributing means writing Rust.
Install Mise for tool version management, then:
mise installThis installs Rust (with WASM target), Bun, and Python.
mise run build # Build Rust cdylib (.so/.dylib/.dll)
mise run build:wasm # Build WASM binary
mise run test # Run Rust tests
mise run fmt # Check formatting
mise run lint # Run clippy
mise run check # All of the abovemise run generate:all # Build + generate everythingOr per-language:
mise run generate:ruby
mise run generate:kotlin
mise run generate:swift
mise run generate:python
mise run generate:javascript # WASMJavaScript bindings go through post-processing: scripts/flatten-wasm-namespace.ts flattens the WASM module namespace.
- Write the function in the appropriate
src/*.rsmodule - Annotate with
#[uniffi::export] - Add tests in
tests/ - Run
mise run generate:allto regenerate all bindings
That's it — all 5 language bindings are updated automatically.
src/
lib.rs # Crate root
ascii.rs # to_ascii
unicode.rs # to_unicode, UnicodeStandard enum
unicode/normalize.rs # normalize_unicode
transcribe.rs # transcribe, Script enum
transcribe/schemes/ # Per-script implementations (devanagari, latin, latin_scholar)
transcribe/constants.rs # Shared character class patterns
feature.rs # detect, remove, Feature enum, grouping helpers
helpers.rs # Internal macros (pipe!, translation_map!, regex!)
bindings/
javascript/ # npm package (WASM)
python/ # PyPI package
ruby/ # RubyGems gem
kotlin/ # Gradle / JNA
swift/ # Swift Package Manager
tests/ # Integration tests
scripts/ # JS post-generation transforms
mise.toml # Build tasks and tool versions
This project uses Conventional Commits and release-please for automated versioning.
Write commits like feat: add new function or fix: handle edge case. The prefix determines the version bump:
feat:→ minor (1.0.0 → 1.1.0)fix:→ patch (1.0.0 → 1.0.1)feat!:orBREAKING CHANGE:footer → major (1.0.0 → 2.0.0)chore:,ci:,docs:,refactor:,style:,test:→ no release
When commits land on main, release-please opens a Release PR with version bumps and a changelog. Merging that PR publishes to package registries.
Your contributions to open source, large or small, make great projects like this possible. Thank you for taking the time to participate in this project.