GitHub Hot Board

GitHub Hot Board · Archive du dépôt

kubetail-org/fancy-ansi

Small JavaScript library for converting ANSI to HTML (Cette description provient du dépôt lui-même.)

Données au October 25kubetail-org

Meilleur rang

#152

Pépites sous-estimées

100

Étoiles totales

3

Forks totaux

4

Jours classés (30 j)

État du projetLicence: Apache-2.0Dernier push: October 21Issues ouvertes (PR incl.): 3

Collecté depuis 2026-10-25 ; inconnu = pas encore récolté

Mettez le badge dans votre README · kubetail-org/fancy-ansi[![Mettez le badge dans votre README](https://git.vaiox.xyz/api/badge/kubetail-org/fancy-ansi.svg)](https://git.vaiox.xyz/fr/repo/kubetail-org/fancy-ansi)
<a href="https://git.vaiox.xyz/fr/repo/kubetail-org/fancy-ansi"><img src="https://git.vaiox.xyz/api/badge/kubetail-org/fancy-ansi.svg" alt="Mettez le badge dans votre README" height="20"></a>

Documentation du projet

Fancy-ANSI

Fancy-ANSI is a small JavaScript library for converting ANSI to beautiful, browser-safe HTML

Screen Shot 2024-03-30 at 1 19 54 PM

Demo: https://www.kubetail.com/demo
Preview: https://kubetail-org.github.io/fancy-ansi/

Introduction

While adding ANSI markup support to kubetail we tested out several popular popular ANSI-to-html conversion libraries (e.g. ansi-html-community, ansi-to-html, ansi_up) and ran into a few problems:

  • Failure to parse some of our users' ANSI markup
  • Use of hard-coded styles that made customization more difficult
  • Lack of support for CSS variables

To solve these problems and make something that integrated nicely into our frontend stack (Tailwind, React) we created Fancy-ANSI. The library is designed to be small (~4 kb gzipped), performant, easy-to-use and safe from XSS attacks. It has the following features:

  • Supports easy customization using CSS variables
  • Supports almost all SGR codes
  • Supports OSC 8 hyperlinks (opt-in)
  • Includes a Tailwind plugin (v3 and v4) that enables support for easy theming
  • Includes a React component for easy use in a React environment
  • Includes useful utilities like hasAnsi() and stripAnsi() that come in handy when working with ANSI
  • Includes popular color palettes that can be swapped in easily

Try it out and let us know what you think! If you notice any bugs or have any feature requests just create a GitHub Issue.

Quickstart

Install the library using your favorite package manager:

# npm
npm install fancy-ansi

# yarn
yarn add fancy-ansi

# pnpm
pnpm add fancy-ansi

Now you can use it in your code with React:

// ExampleComponent.jsx
import { AnsiHtml } from 'fancy-ansi/react';

export const ExampleComponent = () => {
  const text = '\x1b[34mhello \x1b[33mworld\x1b[0m';
  return <AnsiHtml className="font-mono whitespace-pre text-sm" text={text} />;
};

Or with Vanilla-JS:

// example.ts
import { FancyAnsi } from 'fancy-ansi';

const fancyAnsi = new FancyAnsi();

export function addElementWithAnsi() {
  const el = document.createElement('div');
  el.innerHTML = fancyAnsi.toHtml('\x1b[34mhello \x1b[33mworld\x1b[0m');
  document.body.append(el);
}

The HTML rendered is browser-safe and ready with some sensible color choices that can be customized easily (see below).

Configuration

You can configure Fancy-ANSI using CSS variables. For example, to invert blacks in dark mode you can change the value of black when the document has a "dark" class:

:root {
  --ansi-black: #000;
}

.dark {
  --ansi-black: #FFF;
}

The full list of supported variables can be found in the SGR Parameters section below.

Hyperlinks

Terminals render OSC 8 hyperlinks as clickable links. Tools such as ls --hyperlink, gcc, systemd and cargo emit them. By default, Fancy-ANSI renders only the link text. To render links as <a> tags, enable the hyperlinks option:

import { FancyAnsi } from 'fancy-ansi';

const fancyAnsi = new FancyAnsi({ hyperlinks: true });

fancyAnsi.toHtml('see \x1b]8;;https://example.com\x1b\\link text\x1b]8;;\x1b\\ after');
// => 'see <a href="https://example.com" rel="noopener noreferrer nofollow">link text</a> after'

With React, use the hyperlinks prop:

<AnsiHtml hyperlinks text={text} />

Only http: and https: URLs become links. Other URLs, such as javascript: or data:, render as plain text. Links always get rel="noopener noreferrer nofollow". To set target or class, pass an options object instead of true:

const fancyAnsi = new FancyAnsi({
  hyperlinks: { target: '_blank', className: 'ansi-link' },
});

fancyAnsi.toHtml('\x1b]8;;https://example.com\x07link\x1b]8;;\x07');
// => '<a href="https://example.com" rel="noopener noreferrer nofollow" target="_blank" class="ansi-link">link</a>'

Links have no inline styles, so your page's CSS decides how they look. SGR codes inside a link still apply.

Enable this only if you trust the input. The URL comes from the input, so link text can show one URL while the link points to another. If you render output you don't control, such as logs, leave this option off.

Output size

toHtml() output can be many times the size of its input. Each run of text after an SGR sequence gets a new <span> with the full style, even when the style did not change. A 5-byte input such as \x1b[1mx can emit hundreds of bytes.

Conversion is fast, but inserting a large result into the DOM can freeze the page. If you render input you don't control, cap its length per call. If you render logs, convert one line at a time.

SGR Parameters

n Name Supported CSS Variables Default
0 Reset ✔️
1 Bold ✔️ --ansi-bold-font-weight 600
2 Dim ✔️ --ansi-dim-opacity 0.7
3 Italic ✔️
4 Underline ✔️
5 Slow blink
6 Fast blink
7 Invert
8 Hide ✔️
9 Strikethrough ✔️
10 Default font ✔️
11 Alternative font 1 ✔️ --ansi-font-1
12 Alternative font 2 ✔️ --ansi-font-2
13 Alternative font 3 ✔️ --ansi-font-3
14 Alternative font 4 ✔️ --ansi-font-4
15 Alternative font 5 ✔️ --ansi-font-5
16 Alternative font 6 ✔️ --ansi-font-6
17 Alternative font 7 ✔️ --ansi-font-7
18 Alternative font 8 ✔️ --ansi-font-8
19 Alternative font 9 ✔️ --ansi-font-9
20 Gothic
21 Double underline ✔️
22 Bold and dim off ✔️
23 Italic off ✔️
24 Underline off ✔️
25 Blink off
26 Proportional spacing
27 Invert off
28 Hidden off ✔️
29 Strikethrough off ✔️
30 Foreground color - black ✔️ --ansi-black #2e3436
31 Foreground color - red ✔️ --ansi-red #cc0000
32 Foreground color - green ✔️ --ansi-green #4e9a06
33 Foreground color - yellow ✔️ --ansi-yellow #c4a000
34 Foreground color - blue ✔️ --ansi-blue #3465a4
35 Foregorund color - magenta ✔️ --ansi-magenta #75507b
36 Foreground color - cyan ✔️ --ansi-cyan #06989a
37 Foreground color - white ✔️ --ansi-white #d3d7cf
38 Foreground color - extended (see below) ✔️
39 Default foreground color ✔️
40 Background color - black ✔️ --ansi-black #2e3436
41 Background color - red ✔️ --ansi-red #cc0000
42 Background color - green ✔️ --ansi-green #4e9a06
43 Background color - yellow ✔️ --ansi-yellow #c4a000
44 Background color - blue ✔️ --ansi-blue #3465a4
45 Background color - magenta ✔️ --ansi-magenta #75507b
46 Background color - cyan ✔️ --ansi-cyan #06989a
47 Background color - white ✔️ --ansi-white #d3d7cf
48 Background color - extended (see below) ✔️
49 Default background color ✔️
50 Proportional spacing off
51 Frame ✔️ --ansi-frame-outline 1px solid
52 Encircle
53 Overline ✔️
54 Frame/encircle off ✔️
55 Overline off ✔️
58 Underground color - extended (see below) ✔️
59 Default underline color ✔️
60 Right side line
61 Double line on the right side
62 Left side line
63 Double line on the left side
64 Ideogram stress marking
65 Side lines off
73 Superscript ✔️ --ansi-superscript-font-size 80%
74 Subscript ✔️ --ansi-subscript-font-size 80%
75 Superscript/subscript off ✔️
90 Foreground color - bright black ✔️ --ansi-bright-black #555753
91 Foreground color - bright red ✔️ --ansi-bright-red #ef2929
92 Foreground color - bright green ✔️ --ansi-bright-green #8ae234
93 Foreground color - bright yellow ✔️ --ansi-bright-yellow #fce94f
94 Foreground color - bright blue ✔️ --ansi-bright-blue #729fcf
95 Foreground color - bright magenta ✔️ --ansi-bright-magenta #ad7fa8
96 Foreground color - bright cyan ✔️ --ansi-bright-cyan #34e2e2
97 Foreground color - bright white ✔️ --ansi-bright-white #eeeeec
100 Background color - bright black ✔️ --ansi-bright-black #555753
101 Background color - bright red ✔️ --ansi-bright-red #ef2929
102 Background color - bright green ✔️ --ansi-bright-green #8ae234
103 Background color - bright yellow ✔️ --ansi-bright-yellow #fce94f
104 Background color - bright blue ✔️ --ansi-bright-blue #729fcf
105 Background color - bright magenta ✔️ --ansi-bright-magenta #ad7fa8
106 Background color - bright cyan ✔️ --ansi-bright-cyan #34e2e2
107 Background color - bright white ✔️ --ansi-bright-white #eeeeec

Extended colors:

Code pattern Description CSS Variables
38;2;{r};{g};{b} Set foreground color - (r,g,b)
38;5;{n} (0 ≤ n ≤ 15) Set foreground color - standard colors --ansi-{color}
38;5;{n} (16 ≤ n ≤ 231) Set foreground color - 6x6 rgb cube
38;5;{n} (232 ≤ n ≤ 232) Set foreground color - 24-step grayscale --ansi-gray-{step}
48;2;{r};{g};{b} Set background color - (r,g,b)
48;5;{n} (0 ≤ n ≤ 15) Set background color - standard colors --ansi-{color}
48;5;{n} (16 ≤ n ≤ 231) Set background color - 6x6 rgb cube
48;5;{n} (232 ≤ n ≤ 232) Set background color - 24-step grayscale --ansi-gray-{step}
58;2;{r};{g};{b} Set underline color - (r,g,b)
58;5;{n} (0 ≤ n ≤ 15) Set underline color - standard colors --ansi-{color}
58;5;{n} (16 ≤ n ≤ 231) Set underline color - 6x6 rgb cube
58;5;{n} (232 ≤ n ≤ 232) Set underline color - 24-step grayscale --ansi-gray-{step}

Integrations

Tailwind

The Fancy-ANSI Tailwind plugin adds a utility for each built-in palette. To use the plugin with Tailwind v4, import it in your css after Tailwind:

/* index.css */
@import "tailwindcss";
@import "fancy-ansi/plugin";

Each ansi-{palette} utility sets the --ansi-{color} variables to that palette. The palettes are xtermjs, vga, vscode, windows10, terminalapp, putty, xterm, ubuntu and eclipse. Utilities work with variants, so you can use one palette in light mode and another in dark mode:

<html class="ansi-vscode dark:ansi-xtermjs">

You can also apply them in your css:

:root {
  @apply ansi-vscode dark:ansi-xtermjs;
}

Individual palette colors are available as theme variables named --ansi-{palette}-{color} (e.g. var(--ansi-vscode-red)).

Tailwind v3

With Tailwind v3, add the plugin to your tailwind.config.js file:

// tailwind.config.js
module.exports = {
  plugins: [
    require('fancy-ansi/plugin')
  ]
}

The palettes are available through the theme() function as ansi.colors.{palette}.{color}:

:root {
  --ansi-red: theme(ansi.colors.vscode.red);
}

React

Fancy-ANSI has a convenient React component that you can import from the fancy-ansi/react module:

// ExampleComponent.jsx
import { AnsiHtml } from 'fancy-ansi/react';

export const ExampleComponent = () => {
  const text = '\x1b[34mhello \x1b[33mworld\x1b[0m';
  return <AnsiHtml className="font-mono whitespace-pre text-sm" text={text} />;
};

Examples

You can see some example implementations in the examples/ directory:

API

FancyAnsi - The converter class

FancyAnsi

  constructor(options)
    * @param {Object} [options]
    * @param {boolean|Object} [options.hyperlinks] - Render OSC 8 hyperlinks as <a> tags (http(s) URLs only)
    * @param {string} [options.hyperlinks.target] - Value of the `target` attribute
    * @param {string} [options.hyperlinks.className] - Value of the `class` attribute

  toHtml(input)
    * @param {string} input - The input string
    * @returns {string} Browser-safe HTML string containing stylized ANSI content
    * Output can be up to 95x the input length (see "Output size")

Example:

  import { FancyAnsi } from 'fancy-ansi';

  const fancyAnsi = new FancyAnsi();
  fancyAnsi.toHtml('\x1b[1mThis is in bold.\x1b[0m');

hasAnsi() - Check if a string has ANSI markup

hasAnsi(input)

  * @param {string} input - The input string
  * @returns {boolean} Boolean indicating whether or not input string contains ANSI markup

Example:

  import { hasAnsi } from 'fancy-ansi';

  if (hasAnsi('\x1b[1mThis is in bold.\x1b[0m')) {
    console.log('string has ansi');
  } else {
    console.log('string doesn\'t have ansi');
  }

stripAnsi() - Remove ANSI markup

stripAnsi(input)

  * @param {string} input - The input string
  * @returns {string} Content of input string with ANSI markup removed

Example:

  import { stripAnsi } from 'fancy-ansi';

  const withoutAnsi = stripAnsi('\x1b[1mThis is in bold.\x1b[0m');
  console.log(`string without ansi: ${withoutAnsi}`);

stripAnsi() is not a terminal sanitizer. It uses ansi-regex, not the toHtml() parser, so the two can disagree on what a sequence is. Its output can still contain a lone ESC, the tail of an unterminated OSC sequence, and C0 characters such as \r and \b. Don't write its output to a terminal as if it were clean.

stripAnsi('x\x1bP1$r\x1b');      // => 'x1$r\x1b'  (lone ESC left)
stripAnsi('a\x1b]8;;http://x');  // => 'attp://x'  (head of unterminated OSC stripped)
stripAnsi('\x9b31mred');         // => 'red', while toHtml() keeps '\x9b31mred' as text

colors - Built-in palettes

`fancy-ansi/colors` module

Example:

  import { xtermjs, terminalapp } from 'fancy-ansi/colors';

  console.log(`xterm.js red: ${xtermjs.red}`);
  console.log(`Terminal.app red: ${terminalapp.red}`);

Available palettes:

  * eclipse
  * putty
  * terminalapp
  * ubuntu
  * vga
  * vscode
  * windows10
  * xterm
  * xtermjs

Development

Get the code

To develop Fancy-ANSI, first clone the repository then install the dependencies:

git clone git@github.com:kubetail-org/fancy-ansi.git
cd fancy-ansi
pnpm install

Run the dev server

Fancy-ANSI uses vite for development. To run run the vite dev server, use the dev command:

pnpm dev

Now you can access the demo page and see your changes at http://localhost:5173/.

Run the unit tests

Fancy-ANSI uses jest for testing (via vitest). To run the tests, use the test command:

pnpm test

The test files are colocated with the source code in the src/ directory, with the filename format {name}.test.(ts|tsx).

To check test coverage, use the coverage command. It fails if coverage drops below 100%:

pnpm coverage

Build for production

To build Fancy-ANSI for production, run the build command:

pnpm build

The production files will be located in the dist/ directory.

Security

Report vulnerabilities privately through GitHub private vulnerability reporting. See SECURITY.md for the supported versions.

Acknowledgements

Classements actuels

  • 152

    Pépites sous-estimées

    100 stars · 3 fork · Stars totales (croissant)

    Méconnus →

Évolution sur 30 jours

Étoiles cumulées

Évolution du rang

Gain quotidien

Voisins de classement sur le même tableau · Méconnus

Projets similaires · sujets partagés

← Retour aux classements