moonucdUnicode for MoonBit

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.

Type or paste any character — even emoji and astral code points.
中
U+4E2D
Passenger
Passenger ticketInternational
Class
Lo Letter, other
From
Unicode 1.1
To
CJK Unified Ideographs
Gate
Han
Platform
L
UTF-8 · E4 B8 AD
Full specimensrc/examples/inspector
Codepoint
U+4E2D
UTF-8
E4 B8 AD
UTF-16
4E2D
East Asian W.
W
Width
2 cells
Numeric
—
Emoji
—
Name
CJK UNIFIED IDEOGRAPH-4E2D
NFC / NFD
中 / 中
Already NFC
yes
Line break
ID

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.

Grapheme clusters
Words
Sentences
Line breaks (UAX #14)

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

UCD
moonbitstack/moonucd

What a character is and how it changes case.

  • category · bidi · numeric
  • has — 50 binary properties
  • upper · lower · title · fold

age

AGE
…/moonucd/age

The Unicode version that first assigned a code point.

  • age(ch) → (major, minor)?

block

BLK
…/moonucd/block

The block a code point sits in, and a block's range by name or alias.

  • block(ch) · range(name)

name

NAM
…/moonucd/name

A code point's name, and the code point a name names.

  • name(ch) · lookup(name)

normalize

NF
…/moonucd/normalize

NFC / NFD / NFKC / NFKD, the UAX #15 way.

  • normalize(form, s)
  • is_normalized · combining · decomposition

script

SCR
…/moonucd/script

The script of a code point and its extensions.

  • script(ch) · extensions(ch) · Script::of

segment

SEG
…/moonucd/segment

Grapheme clusters, words and sentences (UAX #29).

  • grapheme_clusters(s) · words(s) · sentences(s)
  • grapheme_at · word_at — the piece under an offset

width

WDT
…/moonucd/width

Terminal-cell width and East Asian Width.

  • width(ch) · text_width(s) · east_asian_width(ch)
  • ambiguous=2 for CJK terminals

linebreak

LB
…/moonucd/linebreak

Line-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.