UNPKG

1.66 kBPlain TextView Raw
1export function dedent(
2 templ: TemplateStringsArray | string,
3 ...values: unknown[]
4): string {
5 let strings = Array.from(typeof templ === 'string' ? [templ] : templ);
6
7 // 1. Remove trailing whitespace.
8 strings[strings.length - 1] = strings[strings.length - 1].replace(
9 /\r?\n([\t ]*)$/,
10 '',
11 );
12
13 // 2. Find all line breaks to determine the highest common indentation level.
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 // 3. Remove the common indentation from all strings.
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 // 4. Remove leading whitespace.
32 strings[0] = strings[0].replace(/^\r?\n/, '');
33
34 // 5. Perform interpolation.
35 let string = strings[0];
36
37 values.forEach((value, i) => {
38 // 5.1 Read current indentation level
39 const endentations = string.match(/(?:^|\n)( *)$/)
40 const endentation = endentations ? endentations[1] : ''
41 let indentedValue = value
42 // 5.2 Add indentation to values with multiline strings
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
58export default dedent;