Skip to content

nuintun/ansi

Repository files navigation

ansi

A pure JavaScript ANSI style parser library.

NPM Version Download Status Languages Status Tree Shakeable Side Effect License

interface

export type AnsiColor = [
  // Red
  R: number,
  // Green
  G: number,
  // Blue
  B: number
];

export interface AnsiStyle {
  dim: boolean;
  bold: boolean;
  blink: boolean;
  hidden: boolean;
  italic: boolean;
  inverse: boolean;
  overline: boolean;
  underline: boolean;
  strikethrough: boolean;
  color: AnsiColor | null;
  background: AnsiColor | null;
}

export interface AnsiBlock {
  url?: string;
  value: string;
  style: AnsiStyle;
}

export interface Theme {
  red?: AnsiColor;
  blue?: AnsiColor;
  cyan?: AnsiColor;
  black?: AnsiColor;
  green?: AnsiColor;
  white?: AnsiColor;
  yellow?: AnsiColor;
  magenta?: AnsiColor;
  brightRed?: AnsiColor;
  brightBlue?: AnsiColor;
  brightCyan?: AnsiColor;
  brightBlack?: AnsiColor;
  brightGreen?: AnsiColor;
  brightWhite?: AnsiColor;
  brightYellow?: AnsiColor;
  brightMagenta?: AnsiColor;
}

export class Ansi {
  /**
   * @public
   * @constructor
   * @description Constructor for the Ansi class.
   * @param theme The theme object containing color values.
   */
  public constructor(theme?: Theme);

  /**
   * @public
   * @description Writes the given text to the buffer and processes it.
   * @param text The text to be written.
   * @param callback The callback function to be called for each processed AnsiBlock.
   */
  public write(text: string, callback: (block: AnsiBlock) => void): void;

  /**
   * @public
   * @description Flushes the buffer and invokes the callback with the flushed block.
   * @param callback - The callback function to invoke with the flushed block.
   */
  public flush(callback: (block: AnsiBlock) => void): void;
}

Usage

import Ansi, { AnsiBlock, Theme } from '@nuintun/ansi';

function escapeHTML(text: string): string {
  return text.replace(/[&<>"']/gm, match => {
    switch (match) {
      case '&':
        return '&amp;';
      case '<':
        return '&lt;';
      case '>':
        return '&gt;';
      case '"':
        return '&quot;';
      case "'":
        return '&#x27;';
      default:
        return match;
    }
  });
}

function blockToHTML({ style, value, url }: AnsiBlock): string {
  const styles: string[] = [];
  const textDecorations: string[] = [];

  if (style.dim) {
    styles.push(`opacity: 0.5`);
  }

  if (style.bold) {
    styles.push(`font-weight: bold`);
  }

  if (style.italic) {
    styles.push(`font-style: italic`);
  }

  if (style.inverse) {
    styles.push(`filter: invert(1)`);
  }

  if (style.hidden) {
    styles.push(`visibility: hidden`);
  }

  if (style.blink) {
    textDecorations.push('blink');
  }

  if (style.overline) {
    textDecorations.push('overline');
  }

  if (style.underline) {
    textDecorations.push('underline');
  }

  if (style.strikethrough) {
    textDecorations.push('line-through');
  }

  const { color, background } = style;

  if (color) {
    styles.push(`color: rgb(${color})`);
  }

  if (background) {
    styles.push(`background-color: rgb(${background})`);
  }

  if (textDecorations.length > 0) {
    styles.push(`text-decoration: ${textDecorations.join(' ')}`);
  }

  const escapedValue = escapeHTML(value);
  const href = url ? JSON.stringify(new URL(url).toString()) : null;

  if (styles.length <= 0) {
    if (!href) {
      return escapedValue;
    }

    return `<a href=${href} target="_blank">${escapedValue}</a>`;
  }

  const inlineStyle = JSON.stringify(`${styles.join('; ')};`);

  if (!href) {
    return `<span style=${inlineStyle}>${escapedValue}</span>`;
  }

  return `<a style=${inlineStyle} href=${href} target="_blank">${escapedValue}</a>`;
}

export function ansiToHTML(text: string, theme?: Theme): string {
  let html = '';

  const ansi = new Ansi(theme);

  ansi.write(text, block => {
    html += blockToHTML(block);
  });

  ansi.flush(block => {
    html += blockToHTML(block);
  });

  return html;
}

References

Optimized and modified by drudru/ansi_up

About

A pure JavaScript ANSI style parser library.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published