2 const isFullwidthCodePoint = require('is-fullwidth-code-point');
3 const astralRegex = require('astral-regex');
4 const ansiStyles = require('ansi-styles');
11 const wrapAnsi = code => `${ESCAPES[0]}[${code}m`;
13 const checkAnsi = (ansiCodes, isEscapes, endAnsiCode) => {
15 ansiCodes = [...ansiCodes];
17 for (let ansiCode of ansiCodes) {
18 const ansiCodeOrigin = ansiCode;
19 if (ansiCode.includes(';')) {
20 ansiCode = ansiCode.split(';')[0][0] + '0';
23 const item = ansiStyles.codes.get(Number.parseInt(ansiCode, 10));
25 const indexEscape = ansiCodes.indexOf(item.toString());
26 if (indexEscape === -1) {
27 output.push(wrapAnsi(isEscapes ? item : ansiCodeOrigin));
29 ansiCodes.splice(indexEscape, 1);
31 } else if (isEscapes) {
32 output.push(wrapAnsi(0));
35 output.push(wrapAnsi(ansiCodeOrigin));
40 output = output.filter((element, index) => output.indexOf(element) === index);
42 if (endAnsiCode !== undefined) {
43 const fistEscapeCode = wrapAnsi(ansiStyles.codes.get(Number.parseInt(endAnsiCode, 10)));
44 output = output.reduce((current, next) => next === fistEscapeCode ? [next, ...current] : [...current, next], []);
48 return output.join('');
51 module.exports = (string, begin, end) => {
52 const characters = [...string];
55 let stringEnd = typeof end === 'number' ? end : characters.length;
56 let isInsideEscape = false;
61 for (const [index, character] of characters.entries()) {
62 let leftEscape = false;
64 if (ESCAPES.includes(character)) {
65 const code = /\d[^m]*/.exec(string.slice(index, index + 18));
66 ansiCode = code && code.length > 0 ? code[0] : undefined;
68 if (visible < stringEnd) {
69 isInsideEscape = true;
71 if (ansiCode !== undefined) {
72 ansiCodes.push(ansiCode);
75 } else if (isInsideEscape && character === 'm') {
76 isInsideEscape = false;
80 if (!isInsideEscape && !leftEscape) {
84 if (!astralRegex({exact: true}).test(character) && isFullwidthCodePoint(character.codePointAt())) {
87 if (typeof end !== 'number') {
92 if (visible > begin && visible <= stringEnd) {
94 } else if (visible === begin && !isInsideEscape && ansiCode !== undefined) {
95 output = checkAnsi(ansiCodes);
96 } else if (visible >= stringEnd) {
97 output += checkAnsi(ansiCodes, true, ansiCode);