@taml/encoder
Version:
Convert ANSI escape sequences to TAML (Terminal ANSI Markup Language) tags
284 lines • 19.3 kB
JavaScript
import { convert256ToBackgroundColor, convert256ToStandardColor, convertBasicAnsiToBackgroundColor, convertBasicAnsiToStandardColor, convertRGBToBackgroundColor, convertRGBToStandardColor, } from "./color-converter.js";
// biome-ignore lint/suspicious/noControlCharactersInRegex: <explanation>
const ANSI_ESCAPE_REGEX = /(\u001b\[[0-9;]*m)/g;
/**
* Regular expression specifically for SGR (Select Graphic Rendition) sequences
* These control text formatting, colors, etc.
*/
// biome-ignore lint/suspicious/noControlCharactersInRegex: <explanation>
const SGR_REGEX = /^(\u001b)\[([0-9;]*)m$/;
/**
* Create an initial ANSI state with default values
*/
export function createInitialAnsiState() {
return {
foreground: null,
background: null,
bold: false,
dim: false,
italic: false,
underline: false,
strikethrough: false,
};
}
/**
* Parse ANSI text into tokens containing text and escape sequences
*/
export function tokenizeAnsiText(text) {
const tokens = [];
let lastIndex = 0;
const matches = Array.from(text.matchAll(ANSI_ESCAPE_REGEX));
for (const match of matches) {
const matchIndex = match.index;
if (matchIndex === undefined)
continue;
const matchText = match[0];
// Add text before this match as a text token
if (matchIndex > lastIndex) {
const textContent = text.slice(lastIndex, matchIndex);
if (textContent) {
tokens.push({
type: "text",
content: textContent,
});
}
}
// Parse the ANSI sequence
const sequence = parseAnsiSequence(matchText);
if (sequence) {
tokens.push({
type: "sequence",
content: matchText,
sequence,
});
}
lastIndex = matchIndex + matchText.length;
}
// Add remaining text
if (lastIndex < text.length) {
const textContent = text.slice(lastIndex);
if (textContent) {
tokens.push({
type: "text",
content: textContent,
});
}
}
return tokens;
}
/**
* Parse a single ANSI escape sequence
*/
function parseAnsiSequence(sequence) {
const sgrMatch = sequence.match(SGR_REGEX);
if (!sgrMatch) {
// Not an SGR sequence, ignore
return null;
}
const params = sgrMatch[2];
if (!params) {
// Reset sequence (ESC[m or ESC[0m)
return {
type: "reset",
value: 0,
raw: sequence,
};
}
const codes = params.split(";").map((code) => Number.parseInt(code, 10) || 0);
// Handle multiple codes in one sequence
for (let i = 0; i < codes.length; i++) {
const code = codes[i];
if (code === undefined)
continue;
// Reset
if (code === 0) {
return {
type: "reset",
value: 0,
raw: sequence,
};
}
// Styles
if (code === 1) {
return { type: "style", value: "bold", raw: sequence };
}
if (code === 2) {
return { type: "style", value: "dim", raw: sequence };
}
if (code === 3) {
return { type: "style", value: "italic", raw: sequence };
}
if (code === 4) {
return { type: "style", value: "underline", raw: sequence };
}
if (code === 9) {
return { type: "style", value: "strikethrough", raw: sequence };
}
// Basic foreground colors (30-37, 90-97)
if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {
const color = convertBasicAnsiToStandardColor(code);
return {
type: "color",
value: color,
raw: sequence,
};
}
// Foreground color reset (39)
if (code === 39) {
return {
type: "foreground-reset",
value: null,
raw: sequence,
};
}
// Basic background colors (40-47, 100-107)
if ((code >= 40 && code <= 47) || (code >= 100 && code <= 107)) {
const color = convertBasicAnsiToBackgroundColor(code);
return {
type: "background",
value: color,
raw: sequence,
};
}
// Background color reset (49)
if (code === 49) {
return {
type: "background-reset",
value: null,
raw: sequence,
};
}
// Extended foreground color (38;5;n or 38;2;r;g;b)
if (code === 38 && i + 1 < codes.length) {
const mode = codes[i + 1];
if (mode === undefined)
continue;
if (mode === 5 && i + 2 < codes.length) {
// 256-color mode: 38;5;n
const colorIndex = codes[i + 2];
if (colorIndex === undefined)
continue;
const color = convert256ToStandardColor(colorIndex);
return {
type: "color",
value: color,
raw: sequence,
};
}
if (mode === 2 && i + 4 < codes.length) {
// RGB mode: 38;2;r;g;b
const r = codes[i + 2];
const g = codes[i + 3];
const b = codes[i + 4];
if (r === undefined || g === undefined || b === undefined)
continue;
const color = convertRGBToStandardColor(r, g, b);
return {
type: "color",
value: color,
raw: sequence,
};
}
}
// Extended background color (48;5;n or 48;2;r;g;b)
if (code === 48 && i + 1 < codes.length) {
const mode = codes[i + 1];
if (mode === undefined)
continue;
if (mode === 5 && i + 2 < codes.length) {
// 256-color mode: 48;5;n
const colorIndex = codes[i + 2];
if (colorIndex === undefined)
continue;
const color = convert256ToBackgroundColor(colorIndex);
return {
type: "background",
value: color,
raw: sequence,
};
}
if (mode === 2 && i + 4 < codes.length) {
// RGB mode: 48;2;r;g;b
const r = codes[i + 2];
const g = codes[i + 3];
const b = codes[i + 4];
if (r === undefined || g === undefined || b === undefined)
continue;
const color = convertRGBToBackgroundColor(r, g, b);
return {
type: "background",
value: color,
raw: sequence,
};
}
}
}
// Unknown sequence, ignore
return null;
}
/**
* Apply a parsed ANSI sequence to the current state
*/
export function applyAnsiSequence(state, sequence) {
const newState = { ...state };
switch (sequence.type) {
case "reset":
return createInitialAnsiState();
case "foreground-reset":
newState.foreground = null;
break;
case "background-reset":
newState.background = null;
break;
case "color":
newState.foreground = sequence.value;
break;
case "background":
newState.background = sequence.value;
break;
case "style": {
const styleValue = sequence.value;
switch (styleValue) {
case "bold":
newState.bold = true;
break;
case "dim":
newState.dim = true;
break;
case "italic":
newState.italic = true;
break;
case "underline":
newState.underline = true;
break;
case "strikethrough":
newState.strikethrough = true;
break;
}
break;
}
}
return newState;
}
/**
* Get the active style tags from the current ANSI state
*/
export function getActiveStyleTags(state) {
const tags = [];
if (state.bold)
tags.push("bold");
if (state.dim)
tags.push("dim");
if (state.italic)
tags.push("italic");
if (state.underline)
tags.push("underline");
if (state.strikethrough)
tags.push("strikethrough");
if (state.background)
tags.push(state.background);
if (state.foreground)
tags.push(state.foreground);
return tags;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5zaS1wYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9hbnNpLXBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLHlCQUF5QixFQUN6QixpQ0FBaUMsRUFDakMsK0JBQStCLEVBQy9CLDJCQUEyQixFQUMzQix5QkFBeUIsR0FDMUIsTUFBTSxzQkFBc0IsQ0FBQztBQUc5Qix5RUFBeUU7QUFDekUsTUFBTSxpQkFBaUIsR0FBRyxxQkFBcUIsQ0FBQztBQUVoRDs7O0dBR0c7QUFDSCx5RUFBeUU7QUFDekUsTUFBTSxTQUFTLEdBQUcsd0JBQXdCLENBQUM7QUFFM0M7O0dBRUc7QUFDSCxNQUFNLFVBQVUsc0JBQXNCO0lBQ3BDLE9BQU87UUFDTCxVQUFVLEVBQUUsSUFBSTtRQUNoQixVQUFVLEVBQUUsSUFBSTtRQUNoQixJQUFJLEVBQUUsS0FBSztRQUNYLEdBQUcsRUFBRSxLQUFLO1FBQ1YsTUFBTSxFQUFFLEtBQUs7UUFDYixTQUFTLEVBQUUsS0FBSztRQUNoQixhQUFhLEVBQUUsS0FBSztLQUNyQixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLElBQVk7SUFDM0MsTUFBTSxNQUFNLEdBQWdCLEVBQUUsQ0FBQztJQUMvQixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFFbEIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUU3RCxLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzVCLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDL0IsSUFBSSxVQUFVLEtBQUssU0FBUztZQUFFLFNBQVM7UUFDdkMsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTNCLDZDQUE2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