ANSI Escape Sequence Support
May 28, 2026 · View on GitHub
BinktermPHP includes full support for ANSI escape sequences (also called ANSI codes or escape codes) used for text formatting, colors, and cursor control in messages.
What are ANSI Escape Sequences?
ANSI escape sequences are special character sequences that control text formatting and cursor positioning in terminals. They begin with the ESC character (ASCII 27, \x1b) followed by control codes.
ANSI codes were standardized by ANSI X3.64 and are widely used in:
- Unix/Linux terminals
- BBS systems
- FidoNet message systems
- ASCII/ANSI art
Format
ESC[<parameters>m
Where:
ESCis the escape character (ASCII 27,\x1b)[begins a Control Sequence Introducer (CSI)<parameters>are semicolon-separated numeric codesmindicates SGR (Select Graphic Rendition)
Example: \x1b[1;31m = Bold + Red text
Color Codes
Standard Foreground Colors (30-37)
30- Black31- Red32- Green33- Yellow34- Blue35- Magenta36- Cyan37- White
Bright Foreground Colors (90-97)
90- Bright Black (Gray)91- Bright Red92- Bright Green93- Bright Yellow94- Bright Blue95- Bright Magenta96- Bright Cyan97- Bright White
Standard Background Colors (40-47)
40- Black background41- Red background42- Green background43- Yellow background44- Blue background45- Magenta background46- Cyan background47- White background
Bright Background Colors (100-107)
100- Bright Black background101- Bright Red background102- Bright Green background103- Bright Yellow background104- Bright Blue background105- Bright Magenta background106- Bright Cyan background107- Bright White background
Reset Colors
39- Default foreground color49- Default background color
Text Formatting Codes
Styles
0- Reset all attributes (default)1- Bold / Increased intensity2- Dim / Faint3- Italic4- Underline5- Slow blink6- Fast blink7- Reverse video (swap foreground/background)8- Hidden / Concealed9- Strikethrough / Crossed out
Reset Specific Attributes
22- Normal intensity (not bold, not dim)23- Not italic24- Not underlined25- Not blinking27- Not reversed28- Not hidden29- Not strikethrough
Cursor Control Sequences
BinktermPHP supports cursor positioning for ASCII/ANSI art:
Cursor Movement
ESC[<n>A- Cursor up n linesESC[<n>B- Cursor down n linesESC[<n>C- Cursor forward n columnsESC[<n>D- Cursor back n columnsESC[<n>E- Cursor next line (beginning of line, n lines down)ESC[<n>F- Cursor previous line (beginning of line, n lines up)ESC[<n>G- Cursor horizontal absolute (column n)ESC[<row>;<col>H- Cursor position (row, col)ESC[<row>;<col>f- Cursor position (alternative)
Screen Control
ESC[<n>J- Clear screen0- Clear from cursor to end of screen1- Clear from cursor to beginning of screen2- Clear entire screen3- Clear entire screen and scrollback buffer
ESC[<n>K- Clear line0- Clear from cursor to end of line1- Clear from cursor to beginning of line2- Clear entire line
ESC[<n>S- Scroll up n linesESC[<n>T- Scroll down n lines
Cursor Position Save/Restore
ESC[s- Save cursor positionESC[u- Restore cursor position
Implementation
Terminal Emulation
BinktermPHP includes a full ANSI terminal emulator that:
- Maintains a virtual screen buffer (80 columns × variable rows)
- Processes cursor positioning sequences
- Handles screen clearing and scrolling
- Renders to HTML with CSS classes
Automatic Detection
The system automatically detects message content type:
ASCII/ANSI Art (uses terminal emulation):
- Contains cursor positioning codes
- Dense ANSI formatting (4+ lines, 30+ chars/line)
- Leading space patterns (ASCII art detection)
Regular Text (line-by-line parsing):
- Simple color codes without positioning
- Normal message formatting
- Better performance for non-art content
Rendering Pipeline
- Detection - Check for ANSI codes and cursor positioning
- Processing
- ASCII/ANSI art → Terminal emulator → HTML
- Regular text → Line-by-line parser → HTML
- Output - HTML with CSS classes for styling
JavaScript Functions
Main Functions
renderAnsiTerminal(text, cols=80, rows=500)
Main rendering function that:
- Auto-detects ANSI art vs regular text
- Uses terminal emulation for cursor positioning
- Falls back to simple parsing for better performance
- Returns HTML with CSS classes
parseAnsi(text)
Fast line-by-line ANSI parser for regular messages:
- Processes SGR color/style codes
- Strips cursor control sequences
- Returns HTML with CSS classes
hasAnsiCodes(text)
Detects if text contains ANSI escape sequences.
Terminal Emulator Class
AnsiTerminal(cols, rows)
Full terminal emulator with:
- Virtual screen buffer
- Cursor positioning
- Attribute tracking (colors, bold, etc.)
- Screen clearing and scrolling
- HTML rendering with proper formatting
CSS Classes
ANSI codes are rendered as HTML spans with CSS classes:
Colors
ansi-black,ansi-red,ansi-green,ansi-yellow,ansi-blue,ansi-magenta,ansi-cyan,ansi-whiteansi-bright-black,ansi-bright-red, etc.ansi-bg-black,ansi-bg-red, etc. (backgrounds)
Styles
ansi-bold- Bold textansi-dim- Dim/faint textansi-italic- Italic textansi-underline- Underlined textansi-blink- Blinking textansi-reverse- Reversed colorsansi-hidden- Hidden textansi-strike- Strikethrough text
Usage Examples
Simple Color Change
\x1b[31mThis is red\x1b[0m and this is normal
Output: This is red and this is normal
Bold + Color
\x1b[1;34mBold Blue Text\x1b[0m
Output: Bold Blue Text
Background Color
\x1b[41;37mWhite text on red background\x1b[0m
Output: White text on red background
ASCII Art with Positioning
\x1b[2J\x1b[H\x1b[1;32m
╔════════════╗
║ MENU ║
╚════════════╝
\x1b[5;5H\x1b[37m1) Option One
\x1b[6;5H2) Option Two
Uses cursor positioning to place text precisely on screen.
Multiple Attributes
\x1b[1;4;31mBold, Underlined, Red\x1b[0m
User Settings
ANSI parsing can be controlled via user settings:
window.userSettings.ansi_parsing = false; // Disable ANSI parsing
When disabled, ANSI codes are stripped and messages display as plain text.
Renderer Mode
The HTML renderer can operate in two modes, controlled by the ANSI_RENDERER_MODE environment variable in .env:
| Value | Behaviour | Default |
|---|---|---|
grouped | Consecutive characters with identical styling are merged into a single <span>. Produces compact HTML and enables URL hyperlinking inside ANSI art. | ✅ Yes |
perchar | Every character gets its own <span>. Maximally precise — each cell is independently addressable — but URLs cannot be auto-hyperlinked because they are fragmented across individual spans. | No |
# .env
ANSI_RENDERER_MODE=grouped # default
ANSI_RENDERER_MODE=perchar # one span per character
Pipe-code recognition has a separate environment control:
PIPE_CODE_PARSER_MODE=decimal_relaxed
strictkeeps the conservative uppercase-only boundary checks.decimal_relaxedis the default mode and greedily accepts two-digit decimal codes such as|01even when followed by uppercase text.looserestores the older permissive behavior for testing.
Use perchar if you observe rendering differences with specific art files and want to compare. grouped is recommended for normal operation.
Compatibility
Fully Supported
- ✅ SGR color and style codes (CSI m)
- ✅ Cursor positioning (CSI H, f, A-G)
- ✅ Screen clearing (CSI J, K)
- ✅ Scrolling (CSI S, T)
- ✅ Save/restore cursor (CSI s, u)
- ✅ 256-color palette (CSI 38;5;n / 48;5;n)
Partially Supported
- ⚠️ Blink - Mapped to CSS but may not render in all browsers
Not Supported (Stripped)
- ❌ Other escape sequences (OSC, etc.)
- ❌ Non-CSI escape codes
Works With
- Traditional BBS ANSI art
- FidoNet message formatting
- ASCII art with cursor positioning
- Terminal-style colored output
- Mixed ANSI and pipe codes
Performance Optimization
BinktermPHP uses intelligent detection to optimize performance:
- Simple messages → Fast line-by-line parser
- ASCII art → Full terminal emulation
- No codes → Plain text rendering
This ensures fast rendering for most messages while still supporting complex ANSI art when needed.
Amiga ANSI
Amiga ANSI art uses the same ANSI X3.64 escape sequence syntax as standard PC ANSI but was authored for the Amiga's Topaz terminal font and colour palette rather than IBM's CP437 character set.
BinktermPHP renders Amiga ANSI through a separate ArtAmigaAnsiDecoder that
extends the standard decoder with two differences:
-
Font — the
art-format-amiga-ansiCSS class selects the Topaz Unicode KS13 font (with Topaz Plus as a fallback), which reproduces the authentic Amiga screen appearance. Place the font files atpublic_html/fonts/TopazPlus.ttfandpublic_html/fonts/topaz_unicode_ks13_regular.ttfto activate them. -
Default colours — the container uses a dark blue-tinted background (
#06090f) with light blue default text (#cfd8ff) instead of the standard black/white ANSI defaults, matching the Amiga Workbench palette. -
Character translation — non-breaking space (
U+00A0) is mapped to a regular space to prevent layout issues;÷and×pass through unchanged.
Selecting Amiga ANSI rendering
Set a message's Art Format field to amiga_ansi, or use the render mode
cycle button in the message viewer to switch to Amiga ANSI manually.
The escape sequence parser itself is identical to the standard ANSI renderer — only the font and default colour scheme differ.
Related
- Pipe Code Support - BBS pipe codes (|XX format)
- CSS styling in
public_html/css/ansisys.css - JavaScript implementation in
public_html/js/ansisys.js
References
- ANSI X3.64 (ECMA-48) standard
- VT100/VT220 terminal sequences
- FidoNet Technical Standards (FTS-0001)