]> git.wincent.com - dented.git/blob - src/dedent.js
41319b0b9ba9f1995d71846fef51344e95979d82
[dented.git] / src / dedent.js
1 /**
2  * @flow strict
3  */
4
5 /**
6  * Tagged template literal function that trims leading and trailing whitespace
7  * and reduces the indent level back to column 0.
8  */
9 function dedent(
10   strings /*: Array<string> */,
11   ...interpolations /*: Array<mixed> */
12 ) {
13   // Insert interpolations in template.
14   const output = strings.reduce((acc, string, i) => {
15     if (i < interpolations.length) {
16       return acc + string + String(interpolations[i]);
17     } else {
18       return acc + string;
19     }
20   }, '');
21
22   // Collapse totally blank lines to empty strings.
23   const lines = output.split('\n').map(line => {
24     if (line.match(/^\s+$/)) {
25       return '';
26     } else {
27       return line;
28     }
29   });
30
31   // Find minimum indent (ignoring empty lines).
32   const minimum = lines.reduce((acc, line) => {
33     const indent = line.match(/^\s+/);
34     if (indent) {
35       const length = indent[0].length;
36       return Math.min(acc, length);
37     }
38     return acc;
39   }, Infinity);
40
41   // Strip out minimum indent from every line.
42   const dedented = isFinite(minimum) ? lines.map(line =>
43     line.replace(new RegExp(`^${' '.repeat(minimum)}`, 'g'), ''),
44   ) : lines;
45
46   // Trim first and last line if empty.
47   if (dedented[0] === '') {
48     dedented.shift();
49   }
50   if (dedented[dedented.length - 1] === '') {
51     dedented.pop();
52   }
53   return dedented.join('\n');
54 }
55
56 module.exports = dedent;