FIGlet fonts in Text.js
@textjs/font parses FIGlet .flf fonts and lays them out like the figlet program. Its tests replay 273 outputs recorded from figlet 2.2.5, and all of them match.
Text.js 0.3 added @textjs/font, a parser and renderer for FIGlet fonts. It ships the 17 fonts from the FIGlet 2.2.5 distribution, one ES module each, and its output matches the figlet 2.2.5 binary exactly.
import { FigletText } from "@textjs/font/react";import { slant } from "@textjs/font/slant";export default function Page() { return <FigletText font={slant} color="accent">Text.js</FigletText>;} ______ __ _ /_ __/__ _ __/ /_ (_)____ / / / _ \| |/_/ __/ / / ___/ / / / __/> </ /__ / (__ )/_/ \___/_/|_|\__(_)_/ /____/ /___/Why FIGlet
<AsciiFont> has had two built-in letterings, block and compact, since 0.1. FIGlet has been the standard for this kind of lettering since 1991, and hundreds of .flf fonts exist. Supporting the format means any of them can be dropped into a console app.
A FIGlet font is a plain-text file. A header line sets the height, the hardblank character and the layout rules, then each character is drawn as a block of rows with an endmark at the end of each row. In its default layouts, FIGlet moves each character left until it touches the previous one, then uses the font's smushing rules to decide whether the two touching sub-characters merge into one.
Layout modes
figlet has five horizontal layouts, and renderFiglet takes the same five through layout:
layout | figlet | Effect |
|---|---|---|
"default" | -s | The font's own layout, usually smushed |
"full" | -W | Full width; characters never touch |
"fitted" | -k | Characters move together until they touch |
"smushed" | -S | Smushing with the font's rules |
"universal" | -o | Later characters overlap earlier ones |
A number from -1 to 63 is a raw -m layout mode: -1 is full width, 0 is fitted, and 1 to 63 select smushing rules. All six horizontal smushing rules are implemented: equal character, underscore, hierarchy, opposite pair, big X and hardblank. The parser handles the rest of the format too: comment lines, code-tagged characters in decimal, octal and hex, the missing-character glyph and right-to-left fonts such as ivrit.
Wrapping follows FIGlet as well. width breaks at word boundaries, and inside a word when a word is wider than the line, where figlet -w would. figlet -w 80 prints at most 79 columns, so -w N corresponds to width: N - 1.
Matching the binary
packages/font/test/fixtures/references.json holds 273 outputs generated by running the real figlet 2.2.5 over every bundled font in every layout mode, with wrapping, justification, right-to-left text, paragraph mode and FIGlet's own regression input with the flags from its run-tests.sh. Each case stores the arguments, the input and the exact output, and the test turns the command line back into options:
for (const f of flags) { if (f === "W") opts.layout = "full"; else if (f === "k") opts.layout = "fitted"; else if (f === "S") opts.layout = "smushed"; else if (f === "o") opts.layout = "universal"; else if (f === "s") opts.layout = "default"; else if (f === "c") opts.align = "center"; else if (f === "r") opts.align = "right"; else if (f === "l") opts.align = "left"; else if (f === "R") opts.direction = "rtl"; else if (f === "L") opts.direction = "ltr"; else if (f === "p") opts.paragraph = true; else throw new Error(`unsupported flag -${f}`);}All 273 match. To regenerate the fixtures, put figlet 2.2.5 on your PATH and run bun run --cwd packages/font references.
Fonts on the cell grid
Every bundled font draws with printable ASCII or Latin-1, so each sub-character is exactly one cell in Menlo and lines up on the grid. <FigletText> measures its rows in cells, so lettering sits in a flexbox layout like any other <Text>, and columns and align wrap and justify it inside its box.
Each font is its own module, so an app only ships the fonts it imports, and a font is parsed on first render rather than on import. @textjs/font/all exports every font for galleries.
Any other FIGfont can be fetched and parsed at runtime:
import { parseFont } from "@textjs/font";const doom = parseFont(await (await fetch("/fonts/doom.flf")).text(), "Doom");Licensing
The bundled fonts are byte-identical to the ones in figlet-2.2.5.tar.gz and are distributed under FIGlet's BSD 3-Clause license. Each keeps its credits in its comment lines, available as font.comment. Popular fonts without a redistribution grant, such as Doom, Larry 3D, ANSI Shadow and Calvin S, are not bundled.
The full reference is in Fonts.