Skip to content
myakuraPublic

About

Dynamic unicode-range WOFF2 slicer and @font-face CSS generator for Japanese, Korean, and Chinese web fonts

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Cleome

Cleome is a Python CLI tool and library that slices Japanese, Korean, and Chinese (JP / KR / SC / TC / HK) variable and static fonts (.ttf / .otf) into unicode-range .woff2 files and @font-face CSS.

Cleome inspects a font's cmap once and writes deterministic static assets instead of scanning page HTML on every site deploy. You can host the generated .woff2 chunks and @font-face stylesheet directly from Next.js, Astro, Fontsource, or any static CDN. Compared to Google Fonts' static slicing templates, Cleome produces smaller stylesheets and transfers fewer .woff2 bytes while keeping OpenType layout features, UVS/IVS variation sequences, and variable font axes intact.


Installation

Requires Python >= 3.15 and uv.

# Install as a standalone CLI tool from PyPI
uv tool install cleome

# Or run directly without installing
uvx cleome plan SourceHanSansJP-VF.otf

# Or add to a Python project
uv add cleome

# Install the unreleased development version from GitHub
uv tool install git+https://github.com/myakura/cleome

CLI usage

# Preview the dynamic 4-tier slice plan without writing files (read-only)
cleome plan SourceHanSansJP-VF.otf
cleome plan SourceHanSansJP-VF.otf --json

# Slice a Variable Font (auto-detects CJK profile; outputs <out-dir>/<slug>.css and <out-dir>/slices/<slug>-*-<hash8>.woff2)
# Subsequent builds with unchanged inputs/config skip WOFF2 subsetting automatically; pass --force to rebuild
# Pass --dry-run to validate inputs and output paths without creating directories or writing files
# Pass --css-out to write the stylesheet to src/styles/ while keeping .woff2 slices in public/fonts/
# Pass --no-filename-hash when placing slices in a bundler-managed directory that adds its own asset hash
cleome build SourceHanSansJP-VF.otf -o dist/web
cleome build SourceHanSansJP-VF.otf -o dist/web --dry-run
cleome build SourceHanSansJP-VF.otf -o dist/web --force
cleome build SourceHanSansJP-VF.otf -o public/fonts --url-prefix "/fonts/slices" --css-out src/styles/fonts.css
cleome build SourceHanSansJP-VF.otf -o src/assets/fonts --no-filename-hash

# Explicitly select a CJK slicing profile (auto, jp, kr, sc, tc, hk)
cleome build SourceHanSansJP-VF.otf --locale jp -o dist/web-jp
cleome build NotoSansKR-VF.ttf --locale kr -o dist/web-kr

# Slice multiple Static Font weights into a single unified @font-face CSS and slices/ directory
cleome build MyFontJP-Regular.ttf MyFontJP-Bold.ttf -o dist/web-static

# Customize CSS font-family, URL prefix, chunk sizes, or retained OpenType layout features
# Note: --layout-features replaces the entire feature list (default is '*' for all features),
# so include vertical writing (vert,vrt2,vpal,vhal,vkrn) and composition (ccmp,locl) tags if needed.
cleome build MyFont-VF.otf -o dist/web \
  --locale jp \
  --family "My Font JP" \
  --slug "my-font-jp" \
  --url-prefix "/assets/fonts/slices" \
  --rare-chunk-size 250 \
  --layout-features "ccmp,locl,kern,mark,mkmk,liga,palt,halt,vpal,vhal,vkrn,vert,vrt2,ruby"

Python API usage

Call slice_font or slice_fonts from a build script with either file paths or in-memory fontTools.ttLib.TTFont objects. Cleome does not mutate caller-supplied TTFont instances.

When workers > 1 (the default), Cleome runs subsetting in a ProcessPoolExecutor. On platforms that use spawn or forkserver (macOS, Windows, and Linux on Python 3.14+), guard top-level scripts with if __name__ == "__main__": or pass workers=1.

from pathlib import Path
from cleome import SliceConfig, slice_font, slice_fonts

if __name__ == "__main__":
    # 1. Slice a Variable Font (path or in-memory TTFont; locale="auto" by default)
    result = slice_font(
        "SourceHanSansJP-VF.otf",
        out_dir=Path("dist/web"),
        config=SliceConfig(
            locale="auto",  # "auto", "jp", "kr", "sc", "tc", or "hk"
            slices_subdir="slices",
            rare_chunk_size=250,
        ),
    )
    print(f"Generated {result.css_path} and {len(result.built_files)} WOFF2 slices")

    # 2. Slice multiple Static Font weights into a unified stylesheet
    static_result = slice_fonts(
        [
            "MyFontJP-Regular.ttf",
            "MyFontJP-Bold.ttf",
        ],
        out_dir=Path("dist/web-static"),
        family_name="My Font JP",
    )

Development and testing

uv sync
uv run python -m unittest discover -s tests -v -f

Documentation

  • Hosting and usage guide explains how to deploy generated <slug>.css and .woff2 slices on static hosts, bundlers, and CDNs, configure --url-prefix and --slices-dir, and set preload, CORS, and Cache-Control headers.
  • Architecture and rationale explains the 4-tier cascade shadowing design, inverted-pyramid Kanji granularity simulations, OpenType subsetting details, and the issues found in Google Fonts' Japanese delivery.
  • Chinese and Korean (KR / SC / TC / HK) slicing analysis covers Google Fonts' Korean and Chinese (SC, TC, HK) slice templates, ghost unicode-range rules, punctuation, Jamo, and Bopomofo splits, and 4-tier simulation results.

Acknowledgments

  • Google Fonts published the production stylesheets, slice definitions (gfsubsets / nam-files), and corpus frequency data analyzed during this project.
  • Noto Sans Japanese (Noto Sans JP) and Source Han Sans (源ノ角ゴシック) were the primary Japanese typefaces used to test and verify Cleome.
  • fontTools handles OpenType table inspection, cmap, GSUB, and GPOS subsetting (fontTools.subset), and WOFF2 packing.
  • Brotli compresses and decompresses the WOFF2 streams.
  • HarfBuzz and uharfbuzz verify OpenType glyph shaping, cmap Format 14 variation sequences, and combining mark composition (ccmp) in the test suite.
  • Stixis validates and serializes the generated @font-face CSS rules and unicode-range descriptors.

License

MIT License

About

Dynamic unicode-range WOFF2 slicer and @font-face CSS generator for Japanese, Korean, and Chinese web fonts

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages