12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- 'use strict';
- const isFullwidthCodePoint = require('is-fullwidth-code-point');
- const astralRegex = require('astral-regex');
- const ansiStyles = require('ansi-styles');
- const ESCAPES = [
- '\u001B',
- '\u009B'
- ];
- const wrapAnsi = code => `${ESCAPES[0]}[${code}m`;
- const checkAnsi = (ansiCodes, isEscapes, endAnsiCode) => {
- let output = [];
- ansiCodes = [...ansiCodes];
- for (let ansiCode of ansiCodes) {
- const ansiCodeOrigin = ansiCode;
- if (ansiCode.match(';')) {
- ansiCode = ansiCode.split(';')[0][0] + '0';
- }
- const item = ansiStyles.codes.get(parseInt(ansiCode, 10));
- if (item) {
- const indexEscape = ansiCodes.indexOf(item.toString());
- if (indexEscape >= 0) {
- ansiCodes.splice(indexEscape, 1);
- } else {
- output.push(wrapAnsi(isEscapes ? item : ansiCodeOrigin));
- }
- } else if (isEscapes) {
- output.push(wrapAnsi(0));
- break;
- } else {
- output.push(wrapAnsi(ansiCodeOrigin));
- }
- }
- if (isEscapes) {
- output = output.filter((element, index) => output.indexOf(element) === index);
- if (endAnsiCode !== undefined) {
- const fistEscapeCode = wrapAnsi(ansiStyles.codes.get(parseInt(endAnsiCode, 10)));
- output = output.reduce((current, next) => next === fistEscapeCode ? [next, ...current] : [...current, next], []);
- }
- }
- return output.join('');
- };
- module.exports = (string, begin, end) => {
- const characters = [...string.normalize()];
- const ansiCodes = [];
- end = typeof end === 'number' ? end : characters.length;
- let isInsideEscape = false;
- let ansiCode;
- let visible = 0;
- let output = '';
- for (const [index, character] of characters.entries()) {
- let leftEscape = false;
- if (ESCAPES.includes(character)) {
- const code = /\d[^m]*/.exec(string.slice(index, index + 18));
- ansiCode = code && code.length > 0 ? code[0] : undefined;
- if (visible < end) {
- isInsideEscape = true;
- if (ansiCode !== undefined) {
- ansiCodes.push(ansiCode);
- }
- }
- } else if (isInsideEscape && character === 'm') {
- isInsideEscape = false;
- leftEscape = true;
- }
- if (!isInsideEscape && !leftEscape) {
- ++visible;
- }
- if (!astralRegex({exact: true}).test(character) && isFullwidthCodePoint(character.codePointAt())) {
- ++visible;
- }
- if (visible > begin && visible <= end) {
- output += character;
- } else if (visible === begin && !isInsideEscape && ansiCode !== undefined) {
- output = checkAnsi(ansiCodes);
- } else if (visible >= end) {
- output += checkAnsi(ansiCodes, true, ansiCode);
- break;
- }
- }
- return output;
- };
|