terminal-model

Terminal emulation for streaming ANSI output with proper whitespace preservation

MIT 4 个版本
安装
npm install terminal-model
yarn add terminal-model
pnpm add terminal-model
bun add terminal-model
README

terminal-model

A Node.js library for terminal emulation that handles streaming ANSI output with proper whitespace preservation. Designed to parse and process ANSI escape sequences from subprocess output, making it suitable for building terminal-based user interfaces and streaming command output with correct formatting.

Features

  • ANSI Sequence Parsing: Full support for CSI commands including SGR (colors/styles), cursor positioning, and line erasure
  • Cell-based Rendering: Each character stored with its styling for precise overwriting and correct whitespace handling
  • Streaming Transform: Node.js transform stream wrapper for easy integration
  • Flexible Line Emission: Three emission strategies:
    • ImmediateStrategy: Emit lines immediately on newline
    • TimeoutStrategy: Emit on newline or after a fixed timeout
    • StatefulTimeoutStrategy: Adaptive timeout based on line volatility
  • Color Support: Standard (0-7), bright (8-15), 256-color, and RGB colors
  • Chunk Boundary Handling: Buffers incomplete ANSI sequences across chunk boundaries
  • Node.js Compatibility: Supports Node.js 0.8+ with a compatibility layer

Installation

npm install terminal-model

Quick Start

import { TerminalTransform, StatefulTimeoutStrategy } from 'terminal-model'

const terminal = new TerminalTransform({
  strategy: new StatefulTimeoutStrategy()
})

terminal.onLine((line) => {
  console.log('Received line:', line)
})

terminal.write('Hello, World!\n')
terminal.write('\x1b[31mRed text\x1b[0m\n')

API

StreamingTerminal

The core terminal emulator class that parses ANSI sequences and maintains terminal state.

import { StreamingTerminal } from 'terminal-model'

const terminal = new StreamingTerminal()

// Write data to process
const state = terminal.write('some content\n')

// Check for unflushed content
if (terminal.hasContent()) {
  // Render current line to ANSI string
  const line = terminal.renderLine()
  console.log(line)
}

// Reset line state (preserves SGR attributes)
terminal.reset()

// Set callback for newline events
terminal.setLineReadyCallback((line) => {
  console.log('Line ready:', line)
})

// Cleanup
terminal.dispose()

TerminalTransform

A transform stream wrapper around StreamingTerminal with configurable emission strategies.

import { TerminalTransform, TimeoutStrategy } from 'terminal-model'

// Using callback API
const terminal = new TerminalTransform({
  strategy: new TimeoutStrategy({ timeout: 50 })
})

terminal.onLine((line) => {
  console.log('Emitted line:', line)
})

// Using event API
terminal.on('line', (line: string) => {
  console.log('Line event:', line)
})

// Using polling API
terminal.write('some content\n')
const pending = terminal.getPendingLines()
const consumed = terminal.consumePendingLines()
terminal.clearPendingLines()

SgrComposer

Static utility class for parsing SGR parameters, composing attributes, and generating ANSI sequences.

import { SgrComposer } from 'terminal-model'

// Parse SGR parameters
const attrs = SgrComposer.parse([31, 1]) // red + bold

// Compose/merge attributes
const base = SgrComposer.parse([31])
const overlay = SgrComposer.parse([1])
const combined = SgrComposer.compose(base, overlay)

// Generate ANSI sequence
const sequence = SgrComposer.toSequence(attrs) // '\x1b[31;1m'

// Compare attributes
SgrComposer.equals(attrs1, attrs2)

// Check if empty
SgrComposer.isEmpty(attrs) // false

// Reset to defaults
const reset = SgrComposer.reset()

AnsiParser

Static class for detecting and extracting ANSI sequences from strings.

import { AnsiParser } from 'terminal-model'

// Parse next sequence at position
const result = AnsiParser.parseNext('\x1b[31mHello', 0)
// { type: 'csi', length: 4, data: {...} }

// Check for incomplete sequences at end
const incomplete = AnsiParser.getIncompleteSequence('\x1b[31')
// '\x1b[31'

Line Emission Strategies

import {
  ImmediateStrategy,
  TimeoutStrategy,
  StatefulTimeoutStrategy
} from 'terminal-model'

// Emit only on newline
const immediate = new ImmediateStrategy()

// Emit on newline or after 100ms (default)
const timeout = new TimeoutStrategy({ timeout: 100 })

// Adaptive timeout:
// - Short (20ms) for volatile content (CR, cursor moves, erasure)
// - Long (100ms) for stable output
const stateful = new StatefulTimeoutStrategy()

Supported ANSI Features

CSI Commands

Command Description Support
m SGR (colors, bold, dim, italic, underline, blink, inverse, hidden, strikethrough) Full
G / ` Horizontal absolute positioning Full
C / D Cursor forward/backward Full
K Erase in line Full
X Erase characters Full
P / @ Delete/Insert characters Full
s / u Save/Restore cursor position Full
7 / 8 Save/Restore cursor position (DEC) Full

Ignored Commands

Multi-line or incompatible with streaming:

  • CUP (H), HVP (f), CUU/A, CUD/B (vertical movement)
  • ED (J), SU (S), SD (T), IL (L), DL (M)

Color Support

Type Range Code Examples
Standard colors 0-7 30-37 (fg), 40-47 (bg)
Bright colors 8-15 90-97 (fg), 100-107 (bg)
256-color 0-255 38;5;N (fg), 48;5;N (bg)
RGB 16,777,216 38;2;R;G;B (fg), 48;2;R;G;B (bg)

Control Characters

  • \n (newline)
  • \r (carriage return)
  • \t (tab)
  • \x08 (backspace)

Architecture

┌─────────────────────────────────────────────────┐
│                 terminal-model                   │
├─────────────────────────────────────────────────┤
│  Entry Point (src/index.ts)                     │
│  Exports: StreamingTerminal, TerminalTransform,  │
│           SgrComposer, Strategies, Types         │
└───────────────┬─────────────────────────────────┘
                │
    ┌-----------+-----------+-----------+
    ▼           ▼           ▼           ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│  ANSI  │ │Terminal│ │ SGR    │ │Strategy│
│ Parser │ │ State  │ │Composer│ │ Pattern│
└────────┘ └────────┘ └────────┘ └────────┘
                │
                ▼
      ┌─────────────────────┐
      │  TerminalTransform  │
      │  (Transform Stream) │
      └─────────────────────┘

License

MIT

版本列表
0.1.3 2026-05-26
0.1.2 2026-05-26
0.1.1 2025-12-27
0.1.0 2025-12-27