paratext
Coming from…

Coming from term-img

A term-img alternative with a drop-in path for image bytes: import terminalImage from paratext/term-img, graded 12 / 18 by term-img's own test suite — all six misses pass a file path, which paratext declines to read — then zero dependencies and no node:fs.

paratext is a term-img alternative you adopt by changing one import — and, if you pass file paths, one argument. paratext/term-img is term-img 7's API for image bytes, and term-img's own test suite is the grade. It is not a complete drop-in, and this page says exactly where it stops.

Migrate from term-img: one import, and bytes instead of a path

- import terminalImage, { UnsupportedTerminalError } from 'term-img';
+ import terminalImage, { UnsupportedTerminalError } from 'paratext/term-img';
+ import { readFile } from 'node:fs/promises';

- console.log(terminalImage('unicorn.jpg', { width: '50%' }));
+ console.log(terminalImage(await readFile('unicorn.jpg'), { width: '50%' }));

If you already pass a Uint8Array or a Buffer, the import line is the whole migration. Everything else stays: width, height, preserveAspectRatio and fallback; a missing or empty image throws a TypeError; an unsupported terminal calls your fallback or throws UnsupportedTerminalError, with term-img's message and name. Support is term-img's own terminal table — iTerm2 3+, WezTerm 20220319+, Konsole 22.04+, Rio 0.1.13+, VS Code 1.80+ — read from the environment, in term-img's order: the argument is checked, then the terminal, then the bytes.

A path handed to a supported terminal throws a TypeError that says to read the file first. It throws at exactly the point term-img would have called fs.readFileSync, so a path handed to an unsupported terminal still reaches your fallback, as it does upstream.

Is paratext compatible with term-img?

Partly, and graded rather than claimed. term-img's own suite, vendored at 7.1.0 and unmodified apart from the import specifier, runs against paratext/term-img beside a control that runs it against real term-img:

passingrate
paratext/term-img12 / 1866.7%
term-img itself (control)18 / 18100.0%

From Compatibility, which npm run compat:page generates from the oracle's last run; that page is the authority. The six failing cases are the same six every run — iTerm2 support, WezTerm support, Konsole support, Rio support, VSCode support and handles options parameter correctly — and every one of them hands a file path to a terminal the suite has just declared supported. paratext takes bytes only, so that node:fs stays out of a package that otherwise touches nothing but strings. Passing them would mean reading a file, which is the dependency this package declines; so 12 / 18 is this row's ceiling, and a caller who passes paths has one edit to make.

What you gain over term-img

  • Zero dependencies. term-img 7.1.0 depends on ansi-escapes and iterm2-version.
  • No filesystem access. The caller owns the read, so the package never opens a file on your behalf.
  • iTerm2 10 and later are recognised. term-img reads iTerm2's major version from its first character, so it would read 10.2.1 as 1 and refuse the terminal; the façade parses the whole number. Nothing in the suite tells the two apart, so this is a fix that costs no compatibility.
  • A caption instead of a throw, when you want one. paratext's root image() — ansi-escapes' signature, plus caption — projects an image to its caption wherever support is absent or unknown, so a pipe or an agent reads text rather than an exception or raw escape bytes.
import { image } from 'paratext';

image(bytes, { caption: 'Build graph' });
// iTerm2, on a TTY: the inline image
// a pipe:           Build graph

When to switch from term-img

  • You already hold the image as bytes, or can read it yourself in one line.
  • Your output is also piped or read by an agent, and an image should become its caption there.

If your program hands term-img a path in many places and you cannot touch them, stay on term-img for now. The registry, the schema and the plugin host are on paratext.

On this page