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. Rust port of cmatsuoka's figlet(6) v2.2.5 & Sam Hocevar's toilet(1) v0.3-1.
Ships 12 bundled .flf fonts + 3 .tlf fonts via include_bytes!. Six horizontal smush rules. Terminal-width-aware layout. 16-color, 256-color, & 24-bit truecolor output. The 10 toilet filters (crop, gay, metal, flip, flop, 180, left, right, border, nothing) composable into pipelines. HTML, IRC mIRC, & SVG export. Byte-equal strict-compat modes for both figlet 2.2.5 & toilet 0.3-1.
Every capability sits behind a Cargo feature. default-features = false strips the entire CLI surface back to the in-house FIGfont parser; pulls only thiserror.
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
# 24-bit truecolor / 256-color output (auto-detect via COLORTERM, or force)
# Background color (named ANSI or #RRGGBB hex)
# Toilet filter pipeline (-F filter1:filter2:... left-to-right)
# Multi-format export (-E html | irc | svg), safe-to-embed XSS-defended
# Toilet-strict-compat (byte-equal upstream toilet 0.3-1 stdout)
# Suppress downgrade warning when truecolor is requested but unsupported
# Paragraph mode (preserve newlines vs collapse)
# Control files (Default: accepted-but-ignored with one-time warning)
# Figlet-strict mode rejects color flags + control files + completions subcommand
Library API
Plain figlet rendering (v0.1.x surface, unchanged)
use ;
let figlet = new
.font
.width
.build
.unwrap;
let banner = figlet.render.unwrap;
print!;
TLF font loading (v0.3.0, tlf-parser leaf)
#
#
Programmatic filter chain (v0.3.0, filter-* leaves)
#
#
Multi-format export (v0.3.0, output-* leaves)
#
#
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.
To strip it down use default-features = false or --no-default-features and then add the features you want.
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 a figlet-color alias should switch to figlet-color (unchanged). HTML, IRC, & SVG export, truecolor, & toilet-strict-compat are opt-in separately. They aren't bundled here so users pick which output paths to ship. |
Safe-to-embed HTML/SVG output
The output-html & output-svg backends apply a hand-rolled 4-character escape to every text-content byte & every double-quoted attribute value: < → <, > → >, & → &, " → ". The SVG backend never emits <script>, <foreignObject>, href, xlink:href, or <image href=...>. A user-controlled byte cannot reach a script-execution context.
The --background CLI flag accepts only the 16 named ANSI colors or #RRGGBB hex. Newlines, ANSI escape bytes, shell metacharacters, & partial hex are rejected at parse time before any export emission.
Implementations: src/export/html.rs, src/export/svg.rs. XSS-payload, UTF-8, & bidirectional-script test coverage: tests/export_integration.rs.
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, & terminal_size. The resulting build pulls only thiserror & the in-house FIGfont parser. The CI test-no-default job runs cargo tree --no-default-features on every PR & fails the build if any CLI-only dep leaks back in.
Convention authority
This layout follows the portfolio-wide Cargo Features Convention. The "why" lives in ADR-0006 (option analysis & rationale); the "what" lives in project-instructions.md §Cargo Feature Surface (canonical rules per port). Every Rusty port from v0.2 onward exposes the same umbrella set (default/full/cli/<port>-classic), per-port leaves named in kebab-case, & 2 to 4 preset bundles.
Compatibility
rusty-figlet has two modes:
- Default mode. 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 emits shell tab-completion scripts. - Strict mode (activated by
--strict, theRUSTY_FIGLET_STRICT=1env var, or invoking the binary asfiglet/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.
What's not shipped
- Vertical smushing. Rarely exercised. Deferred.
- Control files (
.flc).-C/-Nare accepted-but-ignored in Default mode with a one-time warning. Strict mode rejects them. - 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 their own via-d <dir>. - Toilet TLF fonts beyond the 3 bundled placeholders (
mono9.tlf,future.tlf,pagga.tlf). The TLF parser ships in v0.3.0 via thetlf-parserleaf; the bundled fonts are placeholder glyphs pending a Linux-host capture pass for real upstream toilet bytes.
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 the cap is hit. -C/-NDefault behavior. Default mode accepts the flags & emits a one-timecontrol files not yet implemented; ignoring -C/-Nstderr warning, then renders 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) & falls back to the font's missing-character glyph + a 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.