← Блог

Шрифты FIGlet в Text.js

@textjs/font разбирает шрифты FIGlet .flf и размещает их как программа figlet. Его тесты воспроизводят 273 результата, записанных из figlet 2.2.5, и все они совпадают.

Adam

В Text.js 0.3 появился @textjs/font, парсер и рендерер шрифтов FIGlet. Он включает 17 шрифтов из дистрибутива FIGlet 2.2.5, каждый в отдельном ES-модуле, а его вывод в точности совпадает с выводом бинарного файла figlet 2.2.5.

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>;}
  ______          __      _ /_  __/__  _  __/ /_    (_)____  / / / _ \| |/_/ __/   / / ___/ / / /  __/>  </ /__   / (__  )/_/  \___/_/|_|\__(_)_/ /____/                   /___/

Почему FIGlet

В <AsciiFont> с версии 0.1 есть два встроенных начертания: block и compact. FIGlet служит стандартом для таких надписей с 1991 года, и существуют сотни шрифтов .flf. Поддержка формата позволяет использовать любой из них в консольном приложении.

Шрифт FIGlet — это обычный текстовый файл. Строка заголовка задаёт высоту, символ hardblank и правила макета, затем каждый символ рисуется как блок строк с маркером конца в каждой строке. В стандартных макетах FIGlet сдвигает каждый символ влево до соприкосновения с предыдущим, затем по правилам слияния шрифта определяет, сольются ли два соприкасающихся подсимвола в один.

Режимы макета

У figlet пять горизонтальных макетов, и renderFiglet принимает те же пять через layout:

layoutfigletЭффект
"default"-sСобственный макет шрифта, обычно со слиянием
"full"-WПолная ширина; символы не соприкасаются
"fitted"-kСимволы сближаются до соприкосновения
"smushed"-SСлияние по правилам шрифта
"universal"-oПоследующие символы перекрывают предыдущие

Число от -1 до 63 напрямую задаёт режим макета -m: -1 означает полную ширину, 0 — сближение до соприкосновения, а значения от 1 до 63 выбирают правила слияния. Реализованы все шесть правил горизонтального слияния: одинаковые символы, подчёркивание, иерархия, противоположная пара, большой X и hardblank. Парсер обрабатывает и остальные элементы формата: строки комментариев, символы с кодами в десятичной, восьмеричной и шестнадцатеричной записи, глиф отсутствующего символа и шрифты с направлением справа налево, такие как ivrit.

Перенос строк тоже соответствует FIGlet. width переносит текст по границам слов, а если слово шире строки, то внутри слова, в тех же местах, что и figlet -w. figlet -w 80 выводит не более 79 столбцов, поэтому -w N соответствует width: N - 1.

Совпадение с бинарным файлом

В packages/font/test/fixtures/references.json хранятся 273 результата запуска настоящего figlet 2.2.5 для каждого встроенного шрифта во всех режимах макета, с переносом строк, выравниванием, текстом справа налево, режимом абзацев и собственными входными данными регрессионных тестов FIGlet с флагами из его run-tests.sh. Каждый случай хранит аргументы, входные данные и точный вывод, а тест преобразует командную строку обратно в параметры:

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}`);}

Все 273 результата совпадают. Чтобы заново сгенерировать тестовые данные, добавьте figlet 2.2.5 в PATH и запустите bun run --cwd packages/font references.

Шрифты на сетке ячеек

Каждый встроенный шрифт рисует печатными символами ASCII или Latin-1, поэтому каждый подсимвол занимает ровно одну ячейку в Menlo и выравнивается по сетке. <FigletText> измеряет свои строки в ячейках, поэтому надпись размещается в макете flexbox, как любой другой <Text>, а columns и align задают перенос и выравнивание внутри её блока.

Каждый шрифт — отдельный модуль, поэтому в приложение попадают только импортированные шрифты, а разбор шрифта выполняется при первом рендеринге, а не при импорте. @textjs/font/all экспортирует все шрифты для галерей.

Любой другой FIGfont можно загрузить и разобрать во время выполнения:

import { parseFont } from "@textjs/font";const doom = parseFont(await (await fetch("/fonts/doom.flf")).text(), "Doom");

Лицензирование

Встроенные шрифты побайтово совпадают со шрифтами в figlet-2.2.5.tar.gz и распространяются по лицензии FIGlet BSD 3-Clause. Каждый сохраняет сведения об авторах в строках комментариев, доступных через font.comment. Популярные шрифты без разрешения на распространение, такие как Doom, Larry 3D, ANSI Shadow и Calvin S, в комплект не входят.

Полный справочник находится в разделе Шрифты.