The Problem Developers who spend many hours in terminals and IDEs need a monospace font that combines clean round‑corner glyphs, extensive ligatures, and built‑in Nerd‑Font icons while still preserving a perfect 2:1 Chinese‑to‑English width ratio. Existing fonts either lack the required ligature set, miss the icon coverage, or force a separate Chinese‑specific build.

What This Does maple-font ships the source for Maple Mono, a variable‑weight TTF that includes:

  • round‑corner glyphs and custom italics (source/MapleMono[wght].vfc, source/MapleMono[wght]-VF.ttf)
  • a full set of OpenType feature files under source/features/ (regular.fea, italic.fea, cn.fea, etc.) that drive ligatures, contextual alternates, and stylistic sets
  • Nerd‑Font icon patches generated by the source/py/task/nerdfont.py helper

The Python tooling in source/py/ builds the font from the feature files, merges optional subsets, and publishes the final archives. The Dockerfile (Dockerfile) provides an isolated build environment, and pyproject.toml/requirements.txt list the required Python packages (e.g., fontTools, requests).

How It Is Wired

  • Entry points – The CLI starts in build.py at main (line 1677). main parses command‑line arguments, loads the configuration (source/config.yaml), and invokes the build pipeline. A secondary entry point run lives in source/py/utils.py (line 13) and is used by several task scripts.
  • Core flow – main → check_ftcli → parse_args → parse_scale_factor → __load_config. The configuration feeds source/py/feature/__init__.py which generates the OpenType feature string (generate_fea_string). This string is handed to fontTools via source/py/task/merge_font/merger.py to produce the final TTF.
  • High‑blast‑radius modules – source/py/feature/ast.py is imported by 46 other modules, making it the primary hub. Changes here ripple widely. source/py/feature/__init__.py sits in a circular import with source/py/feature/calt/__init__.py; breaking this cycle will reduce coupling.
  • Key functions – subst_map (called from 43 places) and joinPaths (26 places) perform the bulk of glyph substitution logic. gly, cls, and ign are also heavily reused.
  • External effects – The build writes font files (archive_fonts in build.py) and computes a SHA‑256 hash (hashlib.sha256). source/py/utils.py runs a subprocess (subprocess.run) for Git commands and other shell tools. No network I/O beyond optional HTTP fetches for Nerd‑Font patches.
  • Task modules – source/py/task/merge_font/__init__.py validates the merge configuration, source/py/task/nerdfont.py patches icons, and source/py/task/publish.py uploads assets via a GitHub release workflow (.github/workflows/release.yml).

How To Use It

# Clone the repo
git clone https://github.com/moses-y/maple-font
cd maple-font

# Build the container (Dockerfile pins python:3.11-slim)
docker build -t maple-font-builder .

# Run the build inside the container
docker run --rm -v "$(pwd)":/src maple-font-builder \
    python build.py --config source/config.yaml --output dist/

The repo supplies a Dockerfile that installs the Python dependencies from requirements.txt and runs build.py. No additional environment variables are required.

If you prefer a local build, install the Python deps (pip install -r requirements.txt) and invoke the same command without Docker.

Real‑World Use A CI pipeline for a custom IDE theme can invoke the container step above to regenerate MapleMono[wght].ttf whenever a new ligature set is added. The resulting font can be dropped into VS Code or iTerm2, and the Nerd‑Font icons will appear automatically in the terminal prompt.

Code Health & Issues

  • High – No LICENSE – repository root lacks a licence file. Add MIT or Apache‑2.0.
  • High – No test suite – 91 source files, zero test files. Introduce unit tests for public functions (main, run, feature generation).
  • High – No lockfile – pyproject.toml is present without a lockfile; commit poetry.lock or requirements.txt generated by pip‑freeze.
  • High – Continue‑on‑error in CI – .github/workflows/custom.yml line 108 allows failures to pass; remove or isolate advisory steps.
  • Medium – Dependabot missing – No automated dependency updates; add .github/dependabot.yml.
  • Medium – Docker base image not pinned – python:3.11-slim is mutable; replace with a digest.
  • Medium – No vulnerability scan – CI lacks a dependency‑review or OSV scan; add one.
  • Medium – Unbounded HTTP request – source/py/utils.py makes a requests call without timeout; supply timeout=.
  • Medium – Checkout persists token – .github/workflows/custom.yml should set persist-credentials: false.
  • Medium – Container runs as root – Dockerfile lacks a non‑root USER; create an unprivileged user.

The Bottom Line maple-font provides a well‑documented, feature‑rich monospace font with a reproducible Python‑based build pipeline, but the code base suffers from missing licensing, tests, and a few architectural smells (import cycle, large hub module). Adding a licence, lockfile, and test suite will make it safe for integration into production tooling or downstream font customisation projects.