Pre re-factor - Refactor font formula generator to streamline URL handling and improve directory structure for font files, ensuring consistent installation across all font classes.

This commit is contained in:
Matt Troutman 2026-02-09 16:28:54 -06:00
parent 04d79dd2dd
commit 69d8156b09
No known key found for this signature in database
325 changed files with 7771 additions and 0 deletions

View file

@ -0,0 +1,136 @@
---
name: Tap refactor and font tests
overview: Refactor the tap so font_files is the single source of truth, add a test suite that validates every font (structure, formula presence, and optional install checks), fix formula generation (Ruby class names, per-formula tests), consolidate to one formula per font, and add a uv-managed add-font CLI for an easy add/update workflow.
todos: []
isProject: false
---
# Custom Font Tap Refactor and Test Plan
## Current state (summary)
- **124** font folders in `font_files/` (each `font-<name>/` with `ttf/`, `otf/`, `web/`, `other_files/`).
- **250** Formula files: ~125 named `font-<name>.rb` (from generator) and ~125 legacy `<name>.rb` (no `font-` prefix). One formula (`font-acrylichand.rb`) has no matching folder (folder is `font-acrylic-hand`).
- **Scripts:** `[.fontfoldercleanup/cleanup_font_folders.py](.fontfoldercleanup/cleanup_font_folders.py)` organizes folders; `[.fontfoldercleanup/create_homebrew_formula.py](.fontfoldercleanup/create_homebrew_formula.py)` generates formulae. Formula class names use `.capitalize()` only, producing **invalid Ruby** for names with hyphens (e.g. `FontAcrylic-hand` — hyphen is minus in Ruby). Homebrew expects kebab-case filename → PascalCase class (e.g. `font-acrylic-hand.rb``FontAcrylicHand`).
- **No test suite.** Formulae have a generic `test do` that only checks share dirs exist, not that any font files were installed for that formula.
- **Add-font workflow** is manual: move folder, run cleanup, run formula generator, commit (see [PROJECT.md](PROJECT.md) § Workflows).
---
## 1. Single source of truth and Formula cleanup
- **Canonical list of fonts:** `font_files/` — every `font-*` directory is one font. Formula set must match exactly.
- **One formula per font**, named `**font-<name>.rb**` only. Remove legacy formulae that lack the `font-` prefix (e.g. `acrylic-hand.rb`, `idgrotesk.rb`) after ensuring the `font-<name>.rb` version exists and is correct. Optionally keep a one-time migration note or script that maps old names to `font-<name>` for users.
- **Fix orphan formula:** Either remove `font-acrylichand.rb` or treat it as alias for `font-acrylic-hand` (document and point to same font folder); recommend removing if it was a typo.
---
## 2. Formula generator fixes ([create_homebrew_formula.py](.fontfoldercleanup/create_homebrew_formula.py))
- **Ruby class name:** Convert formula name (the part after `font-`) to a valid PascalCase constant:
- `acrylic-hand``AcrylicHand` (split on `-` and `_`, capitalize each segment, join).
- Class: `Font` + that (e.g. `FontAcrylicHand`). No hyphens in the class name.
- **Per-formula test block:** Generate a `test do` that asserts **at least one** of the expected install paths actually has a file for this formula (e.g. for a font that has only OTF, assert `(share/"fonts/opentype").glob("*.otf").any?` or equivalent). If a font has zero ttf/otf/web files, the test can assert the formulas `share/<formula_name>` dir exists and optionally that `other_files` content was installed. This makes “tests for every font” meaningful at the Homebrew level.
- **Optional:** Add a comment in the generated formula listing expected extensions (e.g. “TTF/OTF”) so humans and audits can see what the formula is supposed to install.
---
## 3. Tests for every font
Two layers: (A) repo-level tests that run without Homebrew install, (B) optional CI that runs Homebrew audits/installs.
### 3a. Repo-level test suite (Python, e.g. pytest)
- **Location:** e.g. `tests/` at repo root (or `.fontfoldercleanup/tests/` if you prefer to keep everything under the script dir).
- **Single source of truth:** Scan `font_files/` for all `font-*` directories.
- **For each font folder, test:**
- **Structure:** Exactly four subdirs: `ttf/`, `otf/`, `web/`, `other_files/`; no other top-level files or dirs (or treat “other” as error / move to `other_files` in cleanup).
- **At least one font file:** At least one of `ttf/*.ttf`, `otf/*.otf`, or `web/*.{woff,woff2,eot,svg}` exists (avoid “font” with only docs in `other_files` and no actual font).
- **Formula exists:** `Formula/font-<name>.rb` exists for that folder name.
- **Formula content (sanity):** Generated formula references the correct `font_files/font-<name>/` paths and correct formula name; optional: regex or simple parse to ensure class name is valid (PascalCase, no hyphen).
- **Global tests:**
- Every `Formula/font-*.rb` has a matching `font_files/font-<name>/` directory (no orphan formulae).
- No duplicate formula names (only one `font-<name>.rb` per name).
- **Implementation:** Parametrized tests (e.g. one test per font for structure, one per font for “formula exists”, etc.) so “EVERY” font is explicitly covered and failures report the font name. Use the same list of `font-*` dirs and the same naming rules as the formula generator so the suite and generator stay in sync.
### 3b. Homebrew-level checks (CI)
- `**brew audit`:** Run `brew audit --formula Formula/font-*.rb` (or equivalent) in CI to catch style and metadata issues. Fix any failures (e.g. empty `sha256`) where possible; for taps that dont publish bottles, audit may still flag missing sha256 — document or suppress as appropriate.
- **Optional “install” test:** For CI, either:
- Run `brew install --formula <formula>` for each `Formula/font-*.rb` (slow but validates install and the new per-formula test block), or
- Run install only for a small subset (e.g. 510 formulae) or on a schedule to keep CI fast. The repo-level tests above already validate structure and formula presence for every font.
Recommended: add a GitHub Actions workflow under `.github/workflows/` that (1) runs the Python test suite, (2) runs `brew audit` on `Formula/*.rb`, and (3) optionally runs a few `brew install` tests.
---
## 4. Easier add/update font workflow
- **Command-line tool `add-font`:** A CLI invocable as `add-font` (or `uv run add-font` from the repo). Use **uv** for dependency management; the tool is auto-installed when you use uv to run it (e.g. `uv run add-font` creates/uses the project venv and runs the entry point; no separate install step required). Optionally run `uv tool install .` from the repo for a global `add-font` on PATH. **Behavior:**
- **Add:** Accept a path to an unpacked font (folder or archive) or a name if the folder is already in `font_files/`. If path is given, copy/move into `font_files/font-<name>` (prompt or infer `<name>` from folder name), then run cleanup then formula generator.
- **Update:** If `font_files/font-<name>` already exists, run cleanup (to reorganize any new files) then formula generator.
- **Validation:** After changes, run the Python test suite (and optionally `brew audit` for touched formulae). Exit non-zero if tests fail.
- **Project layout:** Add `pyproject.toml` at repo root with a console script entry point, e.g. `add-font = "tap_cli.main:main"`. Python tooling (tests, add-font, existing scripts) lives under this uv-managed project.
- **Documentation:** Update [PROJECT.md](PROJECT.md) (and [.cursorrules](.cursorrules) / [.claude/skills/project-context/SKILL.md](.claude/skills/project-context/SKILL.md)) so the documented “add a font” flow is: (1) put files in `To Sort/` or pass path, (2) run `uv run add-font <path_or_name>` (or `add-font <path_or_name>` if installed via `uv tool install .`), (3) commit `font_files/font-<name>/` and `Formula/font-<name>.rb`. Document “regenerate all formulae” as running the formula generator then the test suite.
---
## 5. Implementation order (suggested)
1. **Formula generator:** Fix class name generation (PascalCase, no hyphens) and improve `test do` to assert at least one font file (or other_files) for that formula. Regenerate all formulae from current `font_files/`.
2. **Remove legacy and orphan formulae:** Delete formulae without `font-` prefix; remove or fix `font-acrylichand`. Ensure 1:1 mapping font folder ↔ `Formula/font-<name>.rb`.
3. **Repo-level test suite:** Add `tests/` (or equivalent), implement parametrized tests for every font (structure, at least one font file, formula exists, formula sanity). Run and fix any failures.
4. `**add-font` CLI (uv):** Add `pyproject.toml` with uv and a console script entry point `add-font`. Implement the CLI that runs cleanup, formula generator, and test suite; document `uv run add-font` (and optional `uv tool install .`) in PROJECT.md and related context files.
5. **CI:** Add GitHub Actions workflow for Python tests and `brew audit`; optionally add a small number of `brew install` jobs.
---
## 6. Diagram (high-level)
```mermaid
flowchart LR
subgraph sources [Single source of truth]
FontDirs["font_files/font-*"]
end
subgraph scripts [Scripts and CLI]
Cleanup["cleanup_font_folders.py"]
Generator["create_homebrew_formula.py"]
AddFont["add-font CLI"]
end
subgraph tests [Tests]
PyTests["Python tests (per font)"]
BrewAudit["brew audit"]
end
FontDirs --> Cleanup
FontDirs --> Generator
Cleanup --> FontDirs
Generator --> Formula["Formula/font-*.rb"]
AddFont --> Cleanup
AddFont --> Generator
AddFont --> PyTests
FontDirs --> PyTests
Formula --> PyTests
Formula --> BrewAudit
```
---
## 7. Files to add or change (concise)
| Area | Action |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [.fontfoldercleanup/create_homebrew_formula.py](.fontfoldercleanup/create_homebrew_formula.py) | Add `formula_name_to_class(name)` (PascalCase); generate per-formula test that asserts installed files; use in `generate_formula_content`. |
| Formula/*.rb | Regenerate all; then remove legacy non`font-` formulae and fix/remove `font-acrylichand`. |
| tests/ | New: `conftest.py` or shared helper that discovers `font_files/font-*`; test_structure.py, test_formula_exists.py, test_no_orphan_formulae.py (all parametrized over font list). |
| pyproject.toml + add-font CLI | New: uv-managed project with console script `add-font`; CLI adds/updates one font, runs cleanup + generator + tests. Run via `uv run add-font` (auto-installed by uv). |
| .github/workflows/ | New: e.g. `tests.yml` — Python test suite + `brew audit` (+ optional install). |
| PROJECT.md, .cursorrules, .claude/.../SKILL.md | Update “Adding a new font” and “Regenerating” to reference `uv run add-font` and the test suite. |
This gives you **tests for every font** (structure + formula presence + optional install) and a **single, script-driven path** to add or update a font with automatic validation.