Unicode 17.0.0 · the world's characters
Every character,
a ticket to everywhere.
moonucd is the Unicode Character Database for MoonBit — a passport office for every code point of Unicode 17.0.0, from Hangul to Devanagari, emoji to the unassigned. Type a character and this page asks the compiled library what it is: its category, script, block, age, width and line-break class. No server, no guesswork: the very tables that ship in the package run right here in your browser.
Character inspector
One character, the whole dossier
Every value below comes from the real moonucd build via its JavaScript target. The character travels on a transit ticket; the detailed fields are printed as a specimen.
From every script
Some passengers to try
Click a tile to load it into the inspector above.
Segmentation & wrapping
Break a string apart
The same library applies UAX #29 and UAX #14 in the browser. Grapheme clusters keep a flag emoji or an accented letter as one unit; line breaks show where a paragraph may wrap.
What ships
Nine small packages
The root package holds the general character facts; the rest are opt-in sub-packages you import only when you need them. Everything runs on every MoonBit backend — native, wasm, wasm-gc and js.
moonucd
UCDWhat a character is and how it changes case.
- category · bidi · numeric
- has — 50 binary properties
- upper · lower · title · fold
age
AGEThe Unicode version that first assigned a code point.
- age(ch) → (major, minor)?
block
BLKThe block a code point sits in, and a block's range by name or alias.
- block(ch) · range(name)
name
NAMA code point's name, and the code point a name names.
- name(ch) · lookup(name)
normalize
NFNFC / NFD / NFKC / NFKD, the UAX #15 way.
- normalize(form, s)
- is_normalized · combining · decomposition
script
SCRThe script of a code point and its extensions.
- script(ch) · extensions(ch) · Script::of
segment
SEGGrapheme clusters, words and sentences (UAX #29).
- grapheme_clusters(s) · words(s) · sentences(s)
- grapheme_at · word_at — the piece under an offset
width
WDTTerminal-cell width and East Asian Width.
- width(ch) · text_width(s) · east_asian_width(ch)
- ambiguous=2 for CJK terminals
linebreak
LBLine-break opportunities (UAX #14).
- linebreaks(s) · lb_property(ch)
- breaks(s) — offsets, and which breaks are mandatory
The core package
// what a character is @moonucd.category('中') // Lo @moonucd.bidi('א') // R @moonucd.numeric('٣') // Some(Decimal) @moonucd.has('é', Alphabetic) // true // changing case @moonucd.upper("straße") // "STRASSE" @moonucd.lower("ΟΔΟΣ") // "οδος"
Line breaking, validated
The linebreak package is checked against the full LineBreakTest.txt — 19,338 cases — at zero conformance errors, on all four backends.
// where a line may wrap @linebreak.linebreaks("The quick 中文 fox") // ["The ", "quick ", "中", "文 ", "fox"] @linebreak.lb_property('中') // ID
Examples
Seven runnable programs
One small program per package, and one that puts width, segmentation and line breaking to work in a terminal. Run any with moon run src/examples/07-terminal.
How it is made
Generated from the UCD
Every table is generated from the Unicode Character Database 17.0.0 by the scripts in scripts/tables. They turn UnicodeData.txt, Scripts.txt, LineBreak.txt, EastAsianWidth.txt, emoji-data.txt, NormalizationTest.txt and the break tests into the run-length tables the library searches at runtime. A new Unicode release is a regeneration — the algorithm code does not change.
version() returns "17.0.0" from every package.