rusty-figlet
BREAKING (v0.3.0): Toilet feature parity added — TLF parser, 10 filters, HTML/IRC/SVG export. See CHANGELOG for migration.
Render ASCII-art banners from text. A Rust port of cmatsuoka's figlet(6) v2.2.5 with an in-house FIGfont 2.0 parser, all six horizontal smush rules + universal fallback, 12 bundled .flf fonts via include_bytes!, terminal-width-aware layout, color/rainbow output (toilet-style per-column gradient), byte-equal Strict-mode upstream compatibility, and a typed library API.
Part of the Rusty portfolio.
Install
# or, with prebuilt binaries:
# or, download directly from GitHub Releases:
# https://github.com/jsh562/rusty-figlet/releases
Usage
# Default font (standard.flf)
# Strict-compat (byte-equal upstream figlet v2.2.5 stdout)
# Font selection (-f <name> | <path>)
# Output width
# Justification (last-wins)
# Layout overrides (last layout-class flag wins)
# Color + rainbow
# Paragraph mode (preserve newlines vs collapse)
# Control files (Default: accepted-but-ignored with one-time warning)
# Strict mode rejects color flags + control files + completions subcommand
Library API
use ;
let figlet = new
.font
.width
.build
.unwrap;
let banner = figlet.render.unwrap;
print!;
For library-only consumers without CLI deps, see the Cargo Features section below.
Cargo Features
default enables full which composes every leaf; figlet-classic reproduces v0.1.x bare-port behavior matching upstream figlet 2.2.5 1:1. Library consumers strip the entire CLI surface via default-features = false.
Feature matrix
| Feature | Description | Umbrella(s) |
|---|---|---|
color |
ANSI/SGR color writer (`--color=auto | always |
rainbow |
Per-column HSV rainbow gradient (--rainbow, toilet-style). Implies color. |
full, figlet-color, figlet-toilet-compat |
terminal-width |
-t auto-detect via terminal_size. Without this leaf only an explicit -w value (or the 80-col fallback) applies. |
full |
completions |
completions <shell> subcommand emitting bash/zsh/fish/powershell scripts. Pulls clap_complete. |
full |
strict-compat |
Hand-rolled upstream-byte-equal getopt parser + --strict dispatch path (figlet 2.2.5 target). |
full, figlet-classic |
tlf-parser |
TheLetter (.tlf) font-format parser per tlf2a magic. Adds Figlet::from_tlf + Figlet::from_tlf_bytes. |
full, figlet-toilet-compat |
filter-crop |
Filter::Crop — trim all-blank rows/cols. |
full, figlet-toilet-compat |
filter-gay |
Filter::Gay — per-column rainbow palette sweep (toilet --gay). |
full, figlet-toilet-compat |
filter-metal |
Filter::Metal — blue/gray metallic gradient. |
full, figlet-toilet-compat |
filter-flip |
Filter::Flip — horizontal mirror (reverse each row). |
full, figlet-toilet-compat |
filter-flop |
Filter::Flop — vertical mirror (reverse row order). |
full, figlet-toilet-compat |
filter-rotate |
Filter::Rotate180, RotateLeft, RotateRight — three rotations share one leaf. |
full, figlet-toilet-compat |
filter-border |
Filter::Border — Unicode box-drawing wrap. |
full, figlet-toilet-compat |
color-truecolor |
24-bit SGR emission (\x1b[38;2;R;G;Bm). Implies color. Enables --truecolor. |
full |
color-256 |
256-color SGR emission (\x1b[38;5;Nm). Implies color. Enables --ansi256. |
full |
output-html |
HTML5 export with inline-CSS spans (-E html). Safe-to-embed: 4-char XSS escape applied to all text + double-quoted attributes per spec Security Posture. |
full |
output-irc |
mIRC ^C color code export (-E irc). C0/C1 non-printables stripped per FR-015. |
full |
output-svg |
SVG 1.1 <text> export (-E svg). Safe-to-embed: same 4-char XSS escape table as output-html; no <script>/<foreignObject>/xlink:href/href emission. |
full |
toilet-strict-compat |
Byte-equal-to-toilet-0.3-1 strict-render path (--strict). 16-color floor; same XSS / IRC-strip defenses as the default path. |
full |
Preset bundles
| Bundle | Composition | Use case |
|---|---|---|
figlet-classic |
cli + strict-compat |
Drop-in upstream figlet 2.2.5 replacement. No color, no rainbow, no terminal-width auto-detect, no completions subcommand. |
figlet-minimal |
cli |
Bare-bones binary — no Strict mode, no extras. Smallest functional CLI. |
figlet-color |
cli + color + rainbow |
Modern figlet with color + per-column gradient output; no Strict mode or -t auto-detect. Retained at v0.2.x semantics per AD-010 for users who relied on the v0.2.x figlet-toilet-compat deprecated alias. |
figlet-toilet-compat (v0.3.0 BREAKING) |
cli + color + rainbow + tlf-parser + filter-crop + filter-gay + filter-metal + filter-flip + filter-flop + filter-rotate + filter-border |
v0.3.0 semantics restored — actual toilet capability parity: TLF font loading + all 10 filters + color/rainbow. v0.2.x users who relied on this name as an alias for figlet-color should migrate to figlet-color (unchanged). HTML/IRC/SVG export + truecolor + strict-compat-toilet are intentionally NOT in this bundle (opt-in only — orthogonal capabilities). |
Safe-to-embed HTML/SVG guarantee
The output-html and output-svg backends apply a hand-rolled 4-character XSS escape (< → <, > → >, & → &, " → ") to every text-content byte AND every double-quoted attribute value. SVG additionally never emits <script>, <foreignObject>, href, xlink:href, or <image href=...> slots — no path exists from a user-controlled byte into a script-execution context. The --background CLI flag accepts only the 16 named ANSI colors or #RRGGBB hex; anything else (newlines, ANSI escape bytes, shell metachars, partial hex) is rejected at parse time before any export emission. See src/export/html.rs and src/export/svg.rs for the implementations; tests/export_integration.rs for the XSS-payload + UTF-8 + bidirectional script coverage.
Keep-list workaround (Cargo features are union-only)
Cargo features cannot subtract from default. To get "everything except a specific leaf," disable defaults and enumerate the features you want:
# → CLI + color + rainbow, but NO terminal-width auto-detect, NO completions,
# NO strict-compat path.
For the common cases the named preset bundles above are usually sufficient.
Library-only consumers
[]
= { = "0.2", = false }
This strips clap, clap_complete, anstyle, termcolor, and terminal_size, leaving only thiserror and the in-house FIGfont parser. Verified by tests/library_api.rs and the CI test-no-default job's cargo tree --no-default-features audit (per SC-001 of spec 00011).
Convention authority
This layout follows the portfolio-wide Cargo Features Convention codified in ADR-0006 (the "why" — option analysis + rationale) and project-instructions.md §Cargo Feature Surface (the "what" — canonical rules per per-port crate). Every Rusty port from v0.2 onward exposes the same umbrella set (default/full/cli/<port>-classic), per-port leaves named in kebab-case, and 2–4 preset bundles.
Compatibility
rusty-figlet has two modes:
- Default — clap-styled flag parser; UTF-8 input;
--color/--rainbowenabled;-C/-Naccepted-but-ignored with a one-time stderr warning;-tauto-applied when stdout is a tty AND-wis not set;completionssubcommand for shell-tab generation. - Strict (
--strictflag,RUSTY_FIGLET_STRICT=1env, or argv[0] =figlet/figlet-alias) — byte-equal stdout against upstreamfiglet 2.2.5for documented diagnostics; Latin-1 input clamp; last-wins flag resolution; rejects-C,-N,--color,--rainbow,completionswith upstream-format getopt errors (short:invalid option -- '<char>'; long:unrecognized option '--<name>'); no-tauto-apply.
Precedence for Strict activation: --strict > RUSTY_FIGLET_STRICT env > argv[0]. --no-strict overrides every lower-precedence source; if --strict and --no-strict both appear on the command line, last-wins on the command line per upstream getopt convention.
v0.1.0 excludes
- Vertical smushing (rarely exercised; deferred to v0.2.0)
- Control files (
.flc) —-C/-Naccepted-but-ignored in Default with one-time warning; rejected under Strict - Right-to-left rendering (
-L/-R) — niche; deferred - Font-info dump (
-I <code>) — debug-only; deferred - Non-Latin bundled fonts (
ivrit,smtengwar,smscript,smshadow,smslant,mnemonic,term) — low signal for the Latin/English 99% target. Users add via-d <dir>. - Custom non-FIGfont formats (TLF / toilet TLF) — v0.1.0 targets
.flfonly.
Excluded flags in Strict mode (upstream-format diagnostics)
| Flag | Type | Strict-mode diagnostic | Exit |
|---|---|---|---|
-L, -R |
short | rusty-figlet: invalid option -- '<L|R>' |
2 |
-I |
short | rusty-figlet: invalid option -- 'I' |
2 |
-N |
short | rusty-figlet: invalid option -- 'N' |
2 |
-C |
short | rusty-figlet: invalid option -- 'C' |
2 |
--color |
long | rusty-figlet: unrecognized option '--color' |
2 |
--rainbow |
long | rusty-figlet: unrecognized option '--rainbow' |
2 |
--info-dump |
long | rusty-figlet: unrecognized option '--info-dump' |
2 |
--no-controlfile |
long | rusty-figlet: unrecognized option '--no-controlfile' |
2 |
completions <shell> |
subcommand | rejected as unknown positional (exit 2) | 2 |
The program-name token is substituted figlet: → rusty-figlet: per tests/common/mod.rs::strip_for_snapshot; the format of the diagnostic mirrors upstream figlet 2.2.5 getopt byte-for-byte.
BREAKING-CHANGE vs upstream
- stdin 1 MiB cap —
rusty-figletbuffers stdin to a 1 MiB hard ceiling; upstream buffers unbounded. One-time stderr warning per process invocation when triggered. -C/-NDefault behavior — Default mode accepts the flags but emits a one-timecontrol files not yet implemented; ignoring -C/-Nstderr warning and proceeds rendering the input as-is (no transliteration). Strict mode rejects with upstream-formatinvalid option -- 'C'/unrecognized option.- UTF-8 input in Default — Default mode accepts UTF-8 bytes (Latin-1 + multibyte codepoints) and falls back to the font's missing-character glyph + one-time stderr warning when a codepoint isn't in the font's
<hexcode>table. Strict mode clamps input to Latin-1 (ISO-8859-1) bytes-as-codepoints so the upstream byte-equal contract is preserved. -tDefault auto-apply — Default mode auto-applies-twhen stdout is a tty AND-wis not set. Strict mode does NOT auto-apply-t(preserves byte-equal output at width 80).
See docs/COMPATIBILITY.md for the full per-flag matrix.
Lockstep SemVer
rusty-figlet follows the Rusty portfolio SemVer policy:
- MAJOR: change Strict-mode byte-exact output format; change
FigletErrorvariant payload signatures; change the SemVer surface ofFigletBuilder/Figlet/Banner. - MINOR: add a new
FigletErrorvariant via#[non_exhaustive]; add a new bundled font; add a new CLI flag; add a newFigletBuildersetter. - PATCH: bug fixes; performance improvements; doc-only changes.
MSRV
Rust 1.85 (edition 2024). Re-verified against the portfolio's stable-minus-two policy at each release.
License
Dual-licensed under MIT or Apache-2.0 at your option. The 12 bundled .flf fonts under assets/fonts/ are redistributed under the Artistic License as preserved in each font's .flf comment header; per-font attribution lives in THIRD_PARTY.md and the Artistic License is compatible with MIT/Apache-2.0 redistribution.