|
|
@@ -0,0 +1,134 @@
|
|
|
+/* eslint-disable no-plusplus, no-continue */
|
|
|
+const foregroundColors = {
|
|
|
+ '30': 'black',
|
|
|
+ '31': 'red',
|
|
|
+ '32': 'green',
|
|
|
+ '33': 'yellow',
|
|
|
+ '34': 'blue',
|
|
|
+ '35': 'magenta',
|
|
|
+ '36': 'cyan',
|
|
|
+ '37': 'white',
|
|
|
+ '90': 'grey',
|
|
|
+ } as Record<string, string>;
|
|
|
+
|
|
|
+ const backgroundColors = {
|
|
|
+ '40': 'black',
|
|
|
+ '41': 'red',
|
|
|
+ '42': 'green',
|
|
|
+ '43': 'yellow',
|
|
|
+ '44': 'blue',
|
|
|
+ '45': 'magenta',
|
|
|
+ '46': 'cyan',
|
|
|
+ '47': 'white',
|
|
|
+ } as Record<string, string>;
|
|
|
+
|
|
|
+ const styles = {
|
|
|
+ '1': 'bold',
|
|
|
+ '3': 'italic',
|
|
|
+ '4': 'underline',
|
|
|
+ } as Record<string, string>;
|
|
|
+
|
|
|
+ const eraseChar = (matchingText: any, result: any) => {
|
|
|
+ if (matchingText.length) {
|
|
|
+ return [matchingText.substr(0, matchingText.length - 1), result];
|
|
|
+ } else if (result.length) {
|
|
|
+ const index = result.length - 1;
|
|
|
+ const { text } = result[index];
|
|
|
+ const newResult =
|
|
|
+ text.length === 1
|
|
|
+ ? result.slice(0, result.length - 1)
|
|
|
+ : result.map((item: any, i: number) =>
|
|
|
+ index === i
|
|
|
+ ? { ...item, text: text.substr(0, text.length - 1) }
|
|
|
+ : item
|
|
|
+ );
|
|
|
+
|
|
|
+ return [matchingText, newResult];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [matchingText, result];
|
|
|
+ };
|
|
|
+
|
|
|
+ const ansiparse = (str: string) => {
|
|
|
+ let matchingControl = null;
|
|
|
+ let matchingData = null;
|
|
|
+ let matchingText = '';
|
|
|
+ let ansiState = [] as any[];
|
|
|
+ let result = [] as any[];
|
|
|
+ let state = {} as any;
|
|
|
+
|
|
|
+ for (let i = 0; i < str.length; i++) {
|
|
|
+ if (matchingControl !== null) {
|
|
|
+ if (matchingControl === '\x1b' && str[i] === '[') {
|
|
|
+ if (matchingText) {
|
|
|
+ state.text = matchingText;
|
|
|
+ result.push(state);
|
|
|
+ state = {};
|
|
|
+ matchingText = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ matchingControl = null;
|
|
|
+ matchingData = '';
|
|
|
+ } else {
|
|
|
+ matchingText += matchingControl + str[i];
|
|
|
+ matchingControl = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (matchingData !== null) {
|
|
|
+ if (str[i] === ';') {
|
|
|
+ ansiState.push(matchingData);
|
|
|
+ matchingData = '';
|
|
|
+ } else if (str[i] === 'm') {
|
|
|
+ ansiState.push(matchingData);
|
|
|
+ matchingData = null;
|
|
|
+ matchingText = '';
|
|
|
+
|
|
|
+ for (let a = 0; a < ansiState.length; a++) {
|
|
|
+ const ansiCode = ansiState[a];
|
|
|
+
|
|
|
+ if (foregroundColors[ansiCode]) {
|
|
|
+ state.foreground = foregroundColors[ansiCode];
|
|
|
+ } else if (backgroundColors[ansiCode]) {
|
|
|
+ state.background = backgroundColors[ansiCode];
|
|
|
+ } else if (ansiCode === 39) {
|
|
|
+ delete state.foreground;
|
|
|
+ } else if (ansiCode === 49) {
|
|
|
+ delete state.background;
|
|
|
+ } else if (styles[ansiCode]) {
|
|
|
+ state[styles[ansiCode]] = true;
|
|
|
+ } else if (ansiCode === 22) {
|
|
|
+ state.bold = false;
|
|
|
+ } else if (ansiCode === 23) {
|
|
|
+ state.italic = false;
|
|
|
+ } else if (ansiCode === 24) {
|
|
|
+ state.underline = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ansiState = [];
|
|
|
+ } else {
|
|
|
+ matchingData += str[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (str[i] === '\x1b') {
|
|
|
+ matchingControl = str[i];
|
|
|
+ } else if (str[i] === '\u0008') {
|
|
|
+ [matchingText, result] = eraseChar(matchingText, result);
|
|
|
+ } else {
|
|
|
+ matchingText += str[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (matchingText) {
|
|
|
+ state.text = matchingText + (matchingControl || '');
|
|
|
+ result.push(state);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ };
|
|
|
+
|
|
|
+ export default ansiparse;
|