A proofing sheet for Unicode blocks. Drop a font — OTF, TTF, WOFF or WOFF2 — and see which popular Unicode blocks it covers, which assigned characters are still missing, and what the font maps at codepoints Unicode has not assigned yet (e.g. provisional currency signs).
Everything runs in the browser. The font file never leaves your machine, so unreleased fonts are safe to proof.
- 61 curated blocks (Unicode 17.0.0): the full Latin range (Basic through Extended-G, IPA, phonetic extensions), all combining-mark blocks, Greek, Cyrillic, Armenian, Hebrew, Arabic, Georgian, Devanagari, Thai, Hiragana/Katakana, punctuation, currency, arrows, math, geometric shapes, dingbats and more.
- Glyph grid per block, rendered with the uploaded font itself (via the FontFace API). Missing characters are dimmed and shown in a fallback font.
- Honest coverage: "missing" means assigned in Unicode but absent from the font. Unassigned codepoints inside a block don't count against you — but if the font maps one anyway, it is shown with an amber marker.
- Coverage barcode per block — a one-tick-per-codepoint fingerprint of what's present, missing and unofficial.
- Missing lists as text (
U+XXXX<tab>CHARACTER NAME), per block or for the whole font. - Elsewhere in the font — the rest of the file's contents, listed rather
than checked: mapped codepoints the curated blocks don't already show, in
their real Unicode block (named from the full UCD), plus unencoded
glyphs — alternates, ligature targets and mark components that no
codepoint reaches.
Those are drawn by rebuilding the font in memory with a cmap that maps one
private-use codepoint to every glyph id; glyph names come from
postor the CFF charset, and the list downloads as text. Works for WOFF2 too — the transformed outlines are reconstructed first. Grids in this section are built when you open a block, so a CJK font stays responsive.
npm install
npm run dev # local dev server
npm run build # static build in dist/ — host anywheresrc/font/parse.js— self-contained sfnt/cmap/name parser. WOFF is inflated with the browser'sDecompressionStream; WOFF2 is decompressed with the pure-JSbrotlipackage and the table directory is reconstructed per the W3C spec. cmap formats 0, 4, 6, 12 and 13 are supported; all Unicode subtables are unioned. Format 14 and legacy subtables are read too, but only to tell which glyphs a codepoint can reach.src/font/glyphnames.js— glyph names frompostformat 2.0 or the CFF charset (src/font/stdnames.jsholds the two standard name tables).src/font/woff2glyf.js— undoes the WOFF2 table transforms: rebuildsglyffrom its nine sub-streams (triplet-encoded coordinates, composite stream, bbox bitmap,overlapSimpleBitmap), writes a long-formatlocaand patcheshead.indexToLocFormatto match, and restores thehmtxside bearings from each glyph's xMin. Best-effort: a file it cannot untransform stays marked as transformed and falls back to a listing without shapes.src/font/rebuild.js— re-emits the parsed tables as a plain sfnt whose cmap maps U+F0000 + gid to every glyph, so unencoded glyphs can be drawn as a secondFontFace. GSUB/GPOS/kern are dropped so the browser's default features cannot substitute one glyph for another; DSIG is dropped because the edit invalidates it.src/coverage.js— intersects the font's codepoint set with the curated block data, and groups everything else by its real Unicode block.src/ui.js,src/styles.css— no-framework rendering.src/data/blocks.json— generated data: per-block assigned codepoints (general categories Cc/Cs/Co excluded), character names and categories, the full block name table, and the general category of every assigned codepoint, run-length encoded.src/data/names.json— the character name of every assigned codepoint (~1.4 MB, ~270 kB gzipped), imported lazily bysrc/charnames.jsthe first time a block outside the curated set is opened.
curl -O https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
curl -O https://www.unicode.org/Public/UCD/latest/ucd/Blocks.txt
python3 tools/build_data.py UnicodeData.txt Blocks.txtTo add or remove blocks, edit CURATED_GROUPS in tools/build_data.py and
regenerate.
The parser was cross-checked against fontTools: for TTF, CFF-OTF, variable
OTF, WOFF and WOFF2 inputs, the extracted codepoint sets match fontTools'
cmap output exactly, glyph names match getGlyphOrder() for both the
post and CFF paths, and the rebuilt GID font loads in fontTools with valid
checksums and a cmap that maps U+F0000 + gid to the right glyph.
The WOFF2 untransform was checked the same way: for liberation.woff2,
sample.woff2 (short loca) and fixtures with a transformed hmtx and with
OVERLAP_SIMPLE set, every reconstructed glyph matches fontTools' own
reconstruction exactly — contour counts, endpoints, coordinates, full flag
bytes, bounding boxes, instructions, components and hmtx metrics. fontTools
needs the brotli package to read WOFF2; install it in a venv to re-run the
comparison (see the scripts in the repo history).