Blame view

node_modules/slice-ansi/index.js 1.63 KB
ce4c83ff   wxy   初始提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  '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;
  };