256 lines
6.2 KiB
JavaScript
256 lines
6.2 KiB
JavaScript
const escSeq = {
|
|
"7": null,
|
|
"8": null,
|
|
"[20h": null,
|
|
"[?1h": null,
|
|
"[?3h": null,
|
|
"[?4h": null,
|
|
"[?5h": null,
|
|
"[?6h": null,
|
|
"[?7h": null,
|
|
"[?8h": null,
|
|
"[?9h": null,
|
|
"[20l": null,
|
|
"[?1l": null,
|
|
"[?2l": null,
|
|
"[?3l": null,
|
|
"[?4l": null,
|
|
"[?5l": null,
|
|
"[?6l": null,
|
|
"[?7l": null,
|
|
"[?8l": null,
|
|
"[?9l": null,
|
|
"=": null,
|
|
">": null,
|
|
"(A": null,
|
|
")A": null,
|
|
"(B": null,
|
|
")B": null,
|
|
"(0": null,
|
|
")0": null,
|
|
"(1": null,
|
|
")1": null,
|
|
"(2": null,
|
|
")2": null,
|
|
"N": null,
|
|
"O": null,
|
|
// "[m": function (state) { if (state.spanCount > 0) {state.output +=
|
|
// '</span>'; state.spanCount--;} }, "[0m": function (state) { if
|
|
// (state.spanCount > 0) {state.output += '</span>'; state.spanCount--;} },
|
|
// "[1m": { 'class': 'bold' }, "[2m": { 'class': 'light' }, "[4m": {
|
|
// 'class': 'underline' }, "[5m": { 'class': 'blink' }, "[7m": { 'class':
|
|
// 'reverse' }, "[8m": { 'class': 'invisible' },
|
|
"[;r": null,
|
|
"[A": null,
|
|
"[B": null,
|
|
"[C": null,
|
|
"[D": null,
|
|
"[H": null,
|
|
"[;H": null,
|
|
"[f": null,
|
|
"[;f": null,
|
|
"D": null,
|
|
"M": null,
|
|
"E": null,
|
|
"H": null,
|
|
"[g": null,
|
|
"[0g": null,
|
|
"[3g": null,
|
|
"#3": null,
|
|
"#4": null,
|
|
"#5": null,
|
|
"#6": null,
|
|
"[K": null,
|
|
"[0K": null,
|
|
"[1K": null,
|
|
"[2K": null,
|
|
"[J": null,
|
|
"[0J": null,
|
|
"[1J": null,
|
|
"[2J": null,
|
|
"5n": null,
|
|
"0n": null,
|
|
"3n": null,
|
|
"6n": null,
|
|
";R": null,
|
|
"[c": null,
|
|
"[0c": null,
|
|
"[?1;0c": null,
|
|
"c": null,
|
|
"#8": null,
|
|
"[2;1y": null,
|
|
"[2;2y": null,
|
|
"[2;9y": null,
|
|
"[2;10y": null,
|
|
"[0q": null,
|
|
"[1q": null,
|
|
"[2q": null,
|
|
"[3q": null,
|
|
"[4q": null
|
|
}
|
|
|
|
const modeClasses = {
|
|
'1': 'bold',
|
|
'2': 'light',
|
|
'3': 'underline',
|
|
'4': 'blink',
|
|
'5': 'reverse',
|
|
'6': 'invisible'
|
|
}
|
|
|
|
const modeStyles = {
|
|
|
|
'30': 'color: black',
|
|
'31': 'color: red',
|
|
'32': 'color: green',
|
|
'33': 'color: yellow',
|
|
'34': 'color: blue',
|
|
'35': 'color: magenta',
|
|
'36': 'color: cyan',
|
|
'37': 'color: white',
|
|
|
|
'40': 'background-color: black',
|
|
'41': 'background-color: red',
|
|
'42': 'background-color: green',
|
|
'43': 'background-color: yellow',
|
|
'44': 'background-color: blue',
|
|
'45': 'background-color: magenta',
|
|
'46': 'background-color: cyan',
|
|
'47': 'background-color: white'
|
|
}
|
|
|
|
function processModes(escapeTxt, state) {
|
|
var modes = escapeTxt.substring(1, escapeTxt.length - 1);
|
|
|
|
if (modes.length > 0) {
|
|
modes = modes.split(';');
|
|
for (let i = 0; i < modes.length; i++) {
|
|
if (modeClasses[modes[i]]) {
|
|
state
|
|
.classes
|
|
.push(modeClasses[modes[i]]);
|
|
} else if (modeStyles[modes[i]]) {
|
|
state
|
|
.styles
|
|
.push(modeStyles[modes[i]]);
|
|
} else if (modes[i] === '0') {
|
|
if (state.spanCount > 0) {
|
|
state.output += '</span>';
|
|
state.spanCount--;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (state.spanCount > 0) {
|
|
state.output += '</span>';
|
|
state.spanCount--;
|
|
}
|
|
}
|
|
}
|
|
|
|
function isLetter(str) {
|
|
return str.length === 1 && str.match(/[a-z]/i);
|
|
}
|
|
|
|
function isDigit(str) {
|
|
return str.length === 1 && str.match(/[0-9]/i);
|
|
}
|
|
|
|
function processEscape(escapeTxt, state) {
|
|
if (escapeTxt.startsWith('[') && escapeTxt.endsWith('m')) {
|
|
processModes(escapeTxt, state);
|
|
} else {
|
|
const entry = escSeq[escapeTxt];
|
|
if (entry && entry !== null) {
|
|
if (typeof entry === 'object') {
|
|
if (entry.class) {
|
|
state
|
|
.classes
|
|
.push(entry.class);
|
|
}
|
|
if (entry.style) {
|
|
state
|
|
.styles
|
|
.push(entry.stye);
|
|
}
|
|
} else if (typeof entry === 'function') {
|
|
entry(state);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export default function parseTerminal(text) {
|
|
|
|
var escapeTxt = '';
|
|
|
|
var state = {
|
|
output: '',
|
|
spanCount: 0,
|
|
classes: [],
|
|
styles: []
|
|
}
|
|
|
|
for (let i = 0; i < text.length; i++) {
|
|
let character = text.charAt(i);
|
|
|
|
if (character === '\u001b') {
|
|
escapeTxt = text.charAt(++i);
|
|
if (escapeTxt === '[') {
|
|
// process until character
|
|
do {
|
|
character = text.charAt(++i)
|
|
escapeTxt += character;
|
|
} while (!isLetter(character) && i < text.length);
|
|
} else if (escapeTxt === '#') {
|
|
// process until digit
|
|
do {
|
|
character = text.charAt(++i)
|
|
escapeTxt += character;
|
|
} while (!isDigit(character) && i < text.length);
|
|
} else if (escapeTxt === '(' || escapeTxt === ')') {
|
|
// process another char
|
|
escapeTxt += text.charAt(++i);
|
|
} else {
|
|
// that's the escape
|
|
}
|
|
|
|
processEscape(escapeTxt, state);
|
|
|
|
} else {
|
|
if (state.classes.length > 0 || state.styles.length > 0) {
|
|
state.output += `<span
|
|
class="${state.classes.join(' ')}"
|
|
style="${state.styles.join(';')}
|
|
">`;
|
|
state.classes = [];
|
|
state.styles = [];
|
|
state.spanCount++;
|
|
}
|
|
|
|
if (character === ' ') {
|
|
state.output += ' ';
|
|
} else {
|
|
state.output += character;
|
|
}
|
|
}
|
|
}
|
|
|
|
// replace single enclosed with non characters with spaces
|
|
state.output = state
|
|
.output
|
|
.replace(/ ([^&]+) /g, ' $1 ');
|
|
|
|
// return first space to
|
|
if (state.output.startsWith(' ')) {
|
|
state.output = ' ' + state.output.substring(1);
|
|
}
|
|
|
|
|
|
for (let i = 0; i < state.spanCount; i++) {
|
|
state.output += '</span>';
|
|
}
|
|
|
|
return state.output;
|
|
}
|