mongol-norm 0.3.0

Shape-aware normalizer for Traditional Mongolian script: the UTN #57 v4 shaping engine and FVS-pinned canonical normalizer, pure Rust with zero dependencies (optional font backend).
Documentation
# mongol-norm playground

A static, English/Chinese bilingual playground for the Hudum word APIs. Enter a word to
see its `shape` sequence and `normalize` result, with Unicode code points,
copy buttons, control-character insertion, and vertical previews rendered in
the bundled `hudum.otf`. Input stays in the browser.

**[Open the live playground](https://www.satsrag.dev/norm/)** ·
**[在线使用](https://www.satsrag.dev/norm/)**

The WebAssembly adapter calls the Rust crate at `../..` directly. It has its
own Cargo workspace and lockfile so browser build dependencies do not affect
the core crate's zero-dependency or MSRV guarantees.

## Run locally

Prerequisites: current stable Rust, Node.js 22+, npm, and Python 3. Install the
WebAssembly target and the pinned binding generator once:

```sh
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.125 --locked
```

From the repository root:

```sh
npm --prefix web run dev
```

Open <http://127.0.0.1:4173>. No npm install is needed to build or serve the app.
After editing the Rust engine, rebuild and refresh. HTML, CSS, and JavaScript
changes only need a refresh. To serve an existing build without rebuilding:

```sh
npm --prefix web run serve
```

## Build and host

```sh
npm --prefix web run build
```

Serve or deploy the contents of `web/public/`, including the generated `pkg/`
directory and `fonts/`. No application server is needed; the HTTP server must
serve `.wasm` as `application/wasm`. Relative asset paths support a subdirectory
deployment. Opening `index.html` through `file://` is not supported.

`.github/workflows/deploy-web.yml` builds and browser-tests the page for each
published GitHub Release, then deploys the tested artifact to `norm/` in
`Satsrag/satsrag.github.io` using `PAGE_DEPLOY_KEY`, just like mongol-convert's
`convert/` page. Pull requests and default manual runs test without deploying.
For an initial deploy or a redeploy, run the workflow on `main` with `deploy=true`.
The site homepage has a permanent link to `/norm/`; deployments only update that
directory. See [release setup](../docs/releasing.md#the-web-playground).

The UI uses `shape` and `normalize`, which accept a single Mongolian word.
It does not trim, split, or silently rewrite the input. Spaces, mixed-script
text, and currently unsupported ZWNJ produce the engine's actual errors.
The match indicator compares the engine's shape sequences, not rendered pixels.
Norm is a canonical encoding by shape, not an orthographic spelling correction.

## Browser tests

```sh
npm --prefix web ci
cd web
npx playwright install chromium
npm test
```

To test with an installed Google Chrome instead of Playwright's Chromium:

```sh
PLAYWRIGHT_CHANNEL=chrome npm test
```

Tests compare browser results with the native CLI, check hidden controls and
errors, clipboard contents, input-method composition, mobile overflow, font
loading, and a failed engine load. For the Rust adapter:

```sh
cargo fmt --manifest-path web/wasm/Cargo.toml --check
cargo clippy --manifest-path web/wasm/Cargo.toml --target wasm32-unknown-unknown --locked -- -D warnings
```

## Font provenance

`public/fonts/hudum.otf` is the font previously generated from
Kushim-Jiang/mongolian commit `37aa567`; it is bundled unchanged. Its Noto
outlines use SIL OFL 1.1, and mongfontbuilder's generated rules use MIT.
Provenance, checksum, and both license notices are in `public/fonts/` and ship
with the static site.