# Why paratext

> paratext against ansi-escapes, terminal-link and term-img, one capability per row, every cell linked to the test, grade or source that proves it.

Source: https://paratext.interlace.tools/docs/why-paratext

ansi-escapes, terminal-link and term-img each write the bytes a terminal needs, and paratext
writes the same bytes — its three drop-in paths are graded by each one's own test suite. What
none of them has is the other half: a text form for **every** capability, used whenever the
terminal cannot be shown to understand the sequence, so a pipe, a log and an agent read text
instead of escape bytes. terminal-link comes closest, for links alone.

The table below is the whole comparison. Every mark links to its evidence: a test in this
repository for ours, and for theirs the source file of the exact version compat-oracle grades,
or that package's own test suite. `scripts/capabilities-lock.test.ts` fails the build when a
cited test no longer contains the title it is cited for, when a source no longer contains the
line it is quoted for, or when a source we say lacks something has gained it.

✓ yes · ◐ partial (what is missing is said) · ✗ no · — does not apply. Every cell links to its evidence: our test or grade, or the incumbent’s source at the version compat-oracle grades.

### Off a terminal

| Capability | **paratext** | ansi-escapes | terminal-link | term-img |
| :-- | :-- | :-- | :-- | :-- |
| **A hyperlink on a pipe is its text and its URL** — Where OSC 8 is not understood, a link is written as `Docs (https://x.dev)`, so a log, an agent or a redirected file reads the address instead of escape bytes. | [✓](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/link.test.ts) | [✗ writes the OSC 8 bytes on every stream; it never checks](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/base.js) | [✓ the text, a space and the URL](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/index.js) | [— draws images, not links](https://cdn.jsdelivr.net/npm/term-img@7.1.0/index.js) |
| **Every OSC capability has a text form** — An image becomes its caption, a notification a printed line and a link its text and URL whenever support is absent or unknown, so no OSC byte reaches a pipe. | [✓](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/paratext.test.ts) | [✗ every OSC helper returns its bytes, whatever the stream](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/base.js) | [◐ a text form for links only; it has no other capability](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/index.js) | [◐ an unsupported terminal throws UnsupportedTerminalError unless the caller passes a fallback function](https://cdn.jsdelivr.net/npm/term-img@7.1.0/index.js) |

### Knowing the terminal

| Capability | **paratext** | ansi-escapes | terminal-link | term-img |
| :-- | :-- | :-- | :-- | :-- |
| **Hyperlink support detected as supports-hyperlinks detects it** — `paratext/terminal-link` links on exactly the terminals supports-hyperlinks 4.5.0 says understand OSC 8, and asks about stderr when the link is bound for stderr. | [✓](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/hyperlinks.test.ts) | [✗ detects nothing; the caller decides](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/base.js) | [✓](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/index.js) | [— draws images, not links](https://cdn.jsdelivr.net/npm/term-img@7.1.0/index.js) |
| **Inline-image support detected by terminal** — `paratext/term-img` draws on iTerm2, WezTerm, Konsole, Rio and VS Code at the versions term-img names, read from the environment alone. | [✓](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/term-img.test.ts) | [✗ encodes the image for any terminal it is given](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/base.js) | [— links only](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/index.js) | [✓ the same table](https://cdn.jsdelivr.net/npm/term-img@7.1.0/index.js) |

### Capabilities as data

| Capability | **paratext** | ansi-escapes | terminal-link | term-img |
| :-- | :-- | :-- | :-- | :-- |
| **A registry of capabilities, extensible by plain objects** — A capability the package never heard of — a Kitty image, a WezTerm user variable — is registered as an object with an encoding and a fallback, survives a round trip through JSON, and emits through the same call as the built-ins. | [✓](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/paratext.test.ts) | [✗ a fixed set of functions](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/base.js) | [✗ one function](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/index.js) | [✗ one function](https://cdn.jsdelivr.net/npm/term-img@7.1.0/index.js) |
| **A capability without a text form is refused** — A capability with no static projection is refused at registration, with the family's code and a fix, so nothing registered can put raw bytes into a pipe. | [✓](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/plugin.test.ts) | [✗ no helper has a text form to require](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/base.js) | [◐ its one link has a text form, and a caller can switch it off](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/index.js) | [✗ the fallback is optional, and the default is to throw](https://cdn.jsdelivr.net/npm/term-img@7.1.0/index.js) |
| **A checker for capability plugins before they ship** — `npx paratext check ./kitty.mjs` validates a plugin against the family schema without running its author's code, and exits 1 with a code and a fix when it is refused. | [✓](https://github.com/ofri-peretz/burgee/blob/main/scripts/plugin-check-lock.test.ts) | [— takes no plugins, so has nothing to check](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/package.json) | [— takes no plugins, so has nothing to check](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/package.json) | [— takes no plugins, so has nothing to check](https://cdn.jsdelivr.net/npm/term-img@7.1.0/package.json) |

### Weight

| Capability | **paratext** | ansi-escapes | terminal-link | term-img |
| :-- | :-- | :-- | :-- | :-- |
| **No runtime dependencies** — The escape sequences, the hyperlink detection, the image table and the registry install as one package that depends on nothing. | [✓](https://github.com/ofri-peretz/burgee/blob/main/scripts/package-shape-lock.test.ts) | [✗ environment](https://cdn.jsdelivr.net/npm/ansi-escapes@7.3.0/package.json) | [✗ ansi-escapes and supports-hyperlinks](https://cdn.jsdelivr.net/npm/terminal-link@5.0.0/package.json) | [✗ ansi-escapes and iterm2-version](https://cdn.jsdelivr.net/npm/term-img@7.1.0/package.json) |

### Compatibility

| Capability | **paratext** | ansi-escapes | terminal-link | term-img |
| :-- | :-- | :-- | :-- | :-- |
| **Passes ansi-escapes' own test suite** — paratext's root is graded by ansi-escapes 7.3.0's own tests, unedited, and its CSI half is byte-exact with it. | [✓ 4 / 4 of its own tests](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/baseline/ansi-escapes.json) | [✓ its own suite, the control run](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/ansi-escapes/test.js) | [— a different API](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/terminal-link/test.js) | [— a different API](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/term-img/test.js) |
| **Passes terminal-link's own test suite** — `paratext/terminal-link` is graded by terminal-link 5.0.0's own tests, unedited. | [✓ 8 / 8 of its own tests](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/baseline/terminal-link.json) | [— a different API](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/ansi-escapes/test.js) | [✓ its own suite, the control run](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/terminal-link/test.js) | [— a different API](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/term-img/test.js) |
| **Passes term-img's own test suite** — `paratext/term-img` is graded by term-img 7.1.0's own tests, unedited, and passes every case that hands it image bytes. | [◐ 12 / 18 of its own tests](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/baseline/term-img.json) | [— a different API](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/ansi-escapes/test.js) | [— a different API](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/terminal-link/test.js) | [✓ its own suite, the control run](https://github.com/ofri-peretz/burgee/blob/main/packages/compat-oracle/vendor/term-img/test.js) |

## Reading it

- **terminal-link already projects a link**, and its row says so. paratext's `text (url)` and
  terminal-link's `text url` are two spellings of the same idea; `paratext/terminal-link` keeps
  terminal-link's.
- **term-img's cells link to term-img 7.1.0 on jsDelivr**: term-img is not installed in this
  repository, so there is no local copy for the lock to read. Each URL cell was checked against
  that file by hand; the compatibility row, whose source is term-img's vendored suite, is
  checked on every run.
- **term-img is partial on purpose.** Six of its eighteen cases hand `paratext/term-img` a file
  path, and paratext takes bytes so that it never touches the filesystem (D-030). The fix for a
  caller is one `readFile` ([Coming from term-img](/docs/coming-from/term-img)).

## What is not in the table

A row goes in only when every cell of it can be proved. These were left out:

- **Clipboard, notifications, the window title and the working directory.** paratext ships
  them; ansi-escapes 7.3.0 has `setCwd` and none of the other three, and terminal-link and
  term-img have none. They are in the text-form row rather than a row each.
- **Detection as a pure function of a runtime.** `supports()` and `emit()` read only the
  runtime they are handed; each incumbent reads `process` itself. It is how every example
  on this site runs, but no single test states the comparison.
- **Weight in bytes.** The per-subpath figures are asserted by
  [`weight.test.ts`](https://github.com/ofri-peretz/burgee/blob/main/packages/paratext/src/weight.test.ts)
  and published on [Benchmarks](https://burgee.interlace.tools/docs/benchmarks).
