No description
  • Go 99.3%
  • Just 0.7%
Find a file
ryan 144e34cf4a feat: relax parser to handle real-world font quirks
Pad variable-width glyph rows with spaces instead of rejecting them,
clamp out-of-spec baseline values, and fall back to OldLayout when
FullLayout is out of range. Adds compat test against 376 external
fonts (xero/figlet-fonts), all now parse and render successfully.
2026-04-05 17:35:23 +01:00
.github fix: pin golangci-lint to v2 in CI workflow 2026-04-05 17:05:33 +01:00
benchmarks feat: add on-disk binary font cache - closes #38 2026-04-05 16:12:22 +01:00
cmd fix: resolve all lint issues and reduce complexity 2026-04-05 17:03:12 +01:00
docs test: replace shell script with go-based golden generator 2025-08-15 00:29:20 +01:00
fonts test: implement comprehensive golden test suite 2025-08-14 21:21:43 +01:00
internal feat: relax parser to handle real-world font quirks 2026-04-05 17:35:23 +01:00
testdata/goldens fix: correct space glyph and hierarchy smushing 2025-12-16 14:14:04 +00:00
.editorconfig feat: implement project setup and structure 2025-08-08 22:30:06 +01:00
.gitignore feat: relax parser to handle real-world font quirks 2026-04-05 17:35:23 +01:00
.golangci.yml chore: rewrite golangci-lint config for v2 2026-04-05 16:41:24 +01:00
CLAUDE.md feat: add comprehensive debug mode for renderer 2025-08-23 16:19:29 +01:00
compat_test.go feat: relax parser to handle real-world font quirks 2026-04-05 17:35:23 +01:00
debug_implementation_plan.md feat: implement comprehensive debug mode for renderer 2025-08-23 15:21:20 +01:00
disk_cache.go fix: resolve lint issues and migrate golangci-lint to v2 2026-04-05 16:33:16 +01:00
disk_cache_test.go feat: add on-disk binary font cache - closes #38 2026-04-05 16:12:22 +01:00
docs_test.go test: add docs validation tests - closes #37 2026-03-31 12:08:59 +00:00
figgo.go chore: rewrite golangci-lint config for v2 2026-04-05 16:41:24 +01:00
figgo_compressed_test.go chore: rewrite golangci-lint config for v2 2026-04-05 16:41:24 +01:00
figgo_test.go chore: rewrite golangci-lint config for v2 2026-04-05 16:41:24 +01:00
font_cache.go feat: add on-disk binary font cache - closes #38 2026-04-05 16:12:22 +01:00
font_cache_bench_test.go fix: resolve lint issues and migrate golangci-lint to v2 2026-04-05 16:33:16 +01:00
font_loaders_test.go fix: resolve lint issues 2025-08-09 20:20:28 +02:00
go.mod feat: add on-disk binary font cache - closes #38 2026-04-05 16:12:22 +01:00
go.sum fix: add errcheck compliance for linter 2026-01-05 00:01:30 +00:00
golden_test.go fix: resolve all lint issues and reduce complexity 2026-04-05 17:03:12 +01:00
Justfile chore: add release/versioning hygiene - closes #36 2026-03-31 12:02:29 +00:00
layout.go feat: relax parser to handle real-world font quirks 2026-04-05 17:35:23 +01:00
layout_normalization_test.go feat: relax parser to handle real-world font quirks 2026-04-05 17:35:23 +01:00
layout_test.go fix: align with figfont v2 spec and improve kerning 2025-08-10 01:49:17 +02:00
performance_bench_test.go fix: resolve all lint issues and reduce complexity 2026-04-05 17:03:12 +01:00
README.md feat: add on-disk binary font cache - closes #38 2026-04-05 16:12:22 +01:00
RELEASING.md chore: add release/versioning hygiene - closes #36 2026-03-31 12:02:29 +00:00
render_test.go chore: rewrite golangci-lint config for v2 2026-04-05 16:41:24 +01:00
types.go test: add concurrent race condition tests - closes #35 2025-12-16 18:18:08 +00:00
types_test.go feat: implement font loaders with comprehensive security and testing (closes #8) 2025-08-09 20:20:28 +02:00
unknown_rune_test.go chore: update tests and apply formatting 2025-08-12 17:45:00 +01:00

Figgo

Coverage Status

A high-performance Go library and CLI for rendering FIGlet-compatible ASCII art.

Features

  • FIGfont v2 specification compliant
  • Correct layout handling (full-width, kerning, smushing)
  • All 6 horizontal controlled smushing rules + universal smushing
  • Thread-safe, immutable font API — safe for concurrent use
  • LRU font cache (in-memory) with optional on-disk binary cache
  • LTR and RTL print direction support
  • Compressed font support (ZIP)

Installation

Library

go get github.com/ryanlewis/figgo

Requires Go 1.24 or later.

CLI

go install github.com/ryanlewis/figgo/cmd/figgo@latest

Usage

As a Library

package main

import (
    "fmt"
    "log"

    "github.com/ryanlewis/figgo"
)

func main() {
    font, err := figgo.LoadFont("fonts/standard.flf")
    if err != nil {
        log.Fatal(err)
    }

    output, err := figgo.Render("Hello, World!", font)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(output)
}

Render Options

// Force a specific layout mode
output, _ := figgo.Render("Hello", font, figgo.WithLayout(figgo.FitSmushing))

// Set output width (default 80)
output, _ := figgo.Render("Hello", font, figgo.WithWidth(120))

// Right-to-left rendering
output, _ := figgo.Render("Hello", font, figgo.WithPrintDirection(1))

// Replace unsupported characters instead of erroring
output, _ := figgo.Render("Hello 🎉", font, figgo.WithUnknownRune('?'))

// Trim trailing whitespace from each line
output, _ := figgo.Render("Hello", font, figgo.WithTrimWhitespace(true))

Font Loading

// Load from file path
font, err := figgo.LoadFont("fonts/standard.flf")

// Parse from io.Reader
font, err := figgo.ParseFont(reader)

// Parse from byte slice
font, err := figgo.ParseFontBytes(data)

// Load from a directory by name
font, err := figgo.LoadFontDir("/usr/share/figlet", "standard")

// Load from an fs.FS (e.g., embedded fonts)
font, err := figgo.LoadFontFS(myFS, "fonts/standard.flf")

Font Caching

Figgo includes a two-tier font cache for long-running applications:

// In-memory LRU cache (global convenience functions)
font, err := figgo.LoadFontCached("fonts/standard.flf")
font, err := figgo.ParseFontCached(data)

// Custom cache instance
cache := figgo.NewFontCache(50) // up to 50 fonts in memory
font, err := cache.LoadFont("fonts/standard.flf")

// Enable on-disk binary cache for faster restarts
cache := figgo.NewFontCache(50, figgo.WithDiskCache(figgo.DiskCacheConfig{
    MaxEntries: 20, // max fonts on disk
}))

// Or enable disk caching on the global default cache
figgo.EnableDefaultDiskCache(figgo.DiskCacheConfig{})

// Cache stats
stats := figgo.DefaultCacheStats()
fmt.Printf("Hit rate: %.1f%%\n", stats.HitRate())

The disk cache serializes parsed fonts to os.UserCacheDir()/figgo/fonts/ by default. It uses LRU eviction, atomic writes, and silently falls back to parsing on any error.

As a CLI Tool

# Basic usage
figgo "Hello, World!"

# Specify a font
figgo -f fonts/slant.flf "Hello"

# Set output width
figgo -w 120 "Hello, World!"

# Force smushing layout
figgo -s "Hello"

# Debug mode (JSON trace output)
figgo --debug "Hello"

Project Structure

figgo.go              Main public API (LoadFont, Render, options)
types.go              Core types (Font, Layout, Option)
layout.go             Layout bitmask definitions and fitting modes
font_cache.go         In-memory LRU font cache
disk_cache.go         On-disk binary font cache (opt-in)
internal/parser/      FIGfont file parsing with lazy trim computation
internal/renderer/    Rendering engine with smushing rules
internal/debug/       Structured debug tracing (JSON Lines)
cmd/figgo/            CLI application
cmd/generate-goldens/ Golden test file generator

Development

# Run tests with race detection
just test

# Run linting
just lint

# Format code
just fmt

# Build the binary
just build

# Run CI checks locally (lint + test + build)
just ci

# Run benchmarks
just bench

# Generate golden test files (requires system figlet)
just generate-goldens

License

MIT