12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- 'use strict';
- const isFullwidthCodePoint = require('is-fullwidth-code-point');
-
- const ESCAPES = [
- '\u001B',
- '\u009B'
- ];
-
- const END_CODE = 39;
- const ASTRAL_REGEX = /[\uD800-\uDBFF][\uDC00-\uDFFF]/;
-
- const ESCAPE_CODES = new Map([
- [0, 0],
- [1, 22],
- [2, 22],
- [3, 23],
- [4, 24],
- [7, 27],
- [8, 28],
- [9, 29],
- [30, 39],
- [31, 39],
- [32, 39],
- [33, 39],
- [34, 39],
- [35, 39],
- [36, 39],
- [37, 39],
- [90, 39],
- [40, 49],
- [41, 49],
- [42, 49],
- [43, 49],
- [44, 49],
- [45, 49],
- [46, 49],
- [47, 49]
- ]);
-
- const wrapAnsi = code => `${ESCAPES[0]}[${code}m`;
-
- module.exports = (str, begin, end) => {
- const arr = Array.from(str.normalize());
-
- end = typeof end === 'number' ? end : arr.length;
-
- let insideEscape = false;
- let escapeCode;
- let visible = 0;
- let output = '';
-
- for (const item of arr.entries()) {
- const i = item[0];
- const x = item[1];
-
- let leftEscape = false;
-
- if (ESCAPES.indexOf(x) !== -1) {
- insideEscape = true;
- const code = /\d[^m]*/.exec(str.slice(i, i + 4));
- escapeCode = code === END_CODE ? null : code;
- } else if (insideEscape && x === 'm') {
- insideEscape = false;
- leftEscape = true;
- }
-
- if (!insideEscape && !leftEscape) {
- ++visible;
- }
-
- if (!ASTRAL_REGEX.test(x) && isFullwidthCodePoint(x.codePointAt())) {
- ++visible;
- }
-
- if (visible > begin && visible <= end) {
- output += x;
- } else if (visible === begin && !insideEscape && escapeCode !== undefined && escapeCode !== END_CODE) {
- output += wrapAnsi(escapeCode);
- } else if (visible >= end) {
- if (escapeCode !== undefined) {
- output += wrapAnsi(ESCAPE_CODES.get(parseInt(escapeCode, 10)) || END_CODE);
- }
- break;
- }
- }
-
- return output;
- };
|