1 | export function dedent(
|
2 | templ: TemplateStringsArray | string,
|
3 | ...values: unknown[]
|
4 | ): string {
|
5 | let strings = Array.from(typeof templ === 'string' ? [templ] : templ);
|
6 |
|
7 |
|
8 | strings[strings.length - 1] = strings[strings.length - 1].replace(
|
9 | /\r?\n([\t ]*)$/,
|
10 | '',
|
11 | );
|
12 |
|
13 |
|
14 | const indentLengths = strings.reduce((arr, str) => {
|
15 | const matches = str.match(/\n([\t ]+|(?!\s).)/g);
|
16 | if (matches) {
|
17 | return arr.concat(
|
18 | matches.map((match) => match.match(/[\t ]/g)?.length ?? 0),
|
19 | );
|
20 | }
|
21 | return arr;
|
22 | }, <number[]>[]);
|
23 |
|
24 |
|
25 | if (indentLengths.length) {
|
26 | const pattern = new RegExp(`\n[\t ]{${Math.min(...indentLengths)}}`, 'g');
|
27 |
|
28 | strings = strings.map((str) => str.replace(pattern, '\n'));
|
29 | }
|
30 |
|
31 |
|
32 | strings[0] = strings[0].replace(/^\r?\n/, '');
|
33 |
|
34 |
|
35 | let string = strings[0];
|
36 |
|
37 | values.forEach((value, i) => {
|
38 |
|
39 | const endentations = string.match(/(?:^|\n)( *)$/)
|
40 | const endentation = endentations ? endentations[1] : ''
|
41 | let indentedValue = value
|
42 |
|
43 | if (typeof value === 'string' && value.includes('\n')) {
|
44 | indentedValue = String(value)
|
45 | .split('\n')
|
46 | .map((str, i) => {
|
47 | return i === 0 ? str : `${endentation}${str}`
|
48 | })
|
49 | .join('\n');
|
50 | }
|
51 |
|
52 | string += indentedValue + strings[i + 1];
|
53 | });
|
54 |
|
55 | return string;
|
56 | }
|
57 |
|
58 | export default dedent;
|