/
textUtils.mts
72 lines (65 loc) · 2.28 KB
/
textUtils.mts
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
export function splitIntoLines(text: string, width: number): string[] {
const lines: string[] = [];
const words = splitLinesKeepNewLine(text.replace(/\t/g, ' ')).flatMap((line) => line.split(/ /));
let w = 0;
let line = '';
let space = '';
for (const word of words) {
if (word === '\n' || word === '\r') {
lines.push(line);
line = '';
space = '';
w = 0;
continue;
}
if (line && w + space.length + word.length > width) {
lines.push(line);
line = '';
space = '';
w = 0;
}
line += space + word;
w += space.length + word.length;
space = ' ';
}
lines.push(line);
return lines.map((line) => line.trimEnd());
}
function _unindent(s: string) {
const lines = s.split('\n');
const indents = lines
.map((line) => line.replace(/^\s+$/, ''))
.map((line) => line.replace(/^(\s*).*/, '$1').length)
.filter((n) => n > 0);
const minIndent = Math.min(...indents);
return lines.map((line) => line.slice(minIndent)).join('\n');
}
/**
* Moves all lines to the left by the minimum amount of leading whitespace found in any line.
*
* @param str - string to unindent
* @returns unindented string
*/
export function unindent(str: string): string;
/**
* Template function that unindents a string by the minimum amount of leading whitespace found in any line.
*
* Example:
* ```ts
* const usage = unindent`\
* Usage: foo [options]
* `;
* ```
* See: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates MDN: Tagged Templates}
* @param strings - TemplateStringsArray
* @param values - values to interpolate
*/
export function unindent(strings: TemplateStringsArray, ...values: unknown[]): string;
export function unindent(strings: TemplateStringsArray | string, ...values: unknown[]): string {
return typeof strings === 'string' ? _unindent(strings) : _unindent(String.raw({ raw: strings }, ...values));
}
function splitLinesKeepNewLine(text: string): string[] {
text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
const lines = text.split('\n');
return lines.flatMap((line) => [line, '\n']).slice(0, -1);
}