1
+ /**
2
+ * This may be wrong, but we assume a `\t` is equivalent to 2 spaces.
3
+ */
4
+ const TAB_LENGTH = 2 ;
5
+
6
+ const INDENT_REGEXP = new RegExp ( `(\t| {${ TAB_LENGTH } })` ) ;
7
+
1
8
/**
2
9
* @param {TemplateStringsArray|string } templateStrings
3
10
* @param {any[] } values
11
+ * @returns {string }
4
12
*/
5
13
export function dedent ( templateStrings , ...values ) {
6
14
let matches = [ ] ;
@@ -9,40 +17,56 @@ export function dedent(templateStrings, ...values) {
9
17
? [ templateStrings ]
10
18
: templateStrings . slice ( ) ;
11
19
12
- // 1. Remove trailing whitespace.
13
- strings [ strings . length - 1 ] = strings [ strings . length - 1 ] . replace (
14
- / \r ? \n ( [ \t ] * ) $ / ,
15
- "" ,
16
- ) ;
20
+ let string = "" ;
21
+
22
+ function interpolate ( ) {
23
+ string = strings [ 0 ] ;
24
+
25
+ for ( let i = 0 ; i < values . length ; i ++ ) {
26
+ string += values [ i ] + strings [ i + 1 ] ;
27
+ }
28
+
29
+ string = string . trim ( ) ;
30
+ }
31
+
32
+ // 1. check if its dedentable.
33
+ let isDedentable = true ;
17
34
18
35
// 2. Find all line breaks to determine the highest common indentation level.
19
36
for ( let i = 0 ; i < strings . length ; i ++ ) {
20
37
let match ;
21
38
22
- if ( ( match = strings [ i ] . match ( / \n [ \t ] + / g) ) ) {
39
+ // If any new line starts without any indentation and not an empty string, mark it as not dedentable, and then break the loop.
40
+ if ( strings [ i ] . trim ( ) && strings [ i ] . match ( / \n [ ^ \t ] / ) ) {
41
+ isDedentable = false ;
42
+ break ;
43
+ }
44
+
45
+ if (
46
+ ( match = strings [ i ] . match ( new RegExp ( `\n${ INDENT_REGEXP . source } +` , "g" ) ) )
47
+ ) {
23
48
matches . push ( ...match ) ;
24
49
}
25
50
}
26
51
52
+ if ( ! isDedentable ) {
53
+ interpolate ( ) ;
54
+ return string ;
55
+ }
56
+
27
57
// 3. Remove the common indentation from all strings.
28
58
if ( matches . length ) {
29
59
let size = Math . min ( ...matches . map ( ( value ) => value . length - 1 ) ) ;
30
- let pattern = new RegExp ( `\n[\t ] {${ size } }` , "g" ) ;
60
+ let pattern = new RegExp ( `\n(\t| ) {${ size } }` , "g" ) ;
31
61
32
62
for ( let i = 0 ; i < strings . length ; i ++ ) {
33
- strings [ i ] = strings [ i ] . replace ( pattern , "\n" ) ;
63
+ strings [ i ] = strings [ i ] . replaceAll ( pattern , "\n" ) ;
34
64
}
35
65
}
36
66
37
- // 4. Remove leading whitespace.
38
- strings [ 0 ] = strings [ 0 ] . replace ( / ^ \r ? \n / , "" ) ;
39
-
40
67
// 5. Perform interpolation.
41
- let string = strings [ 0 ] ;
42
-
43
- for ( let i = 0 ; i < values . length ; i ++ ) {
44
- string += values [ i ] + strings [ i + 1 ] ;
45
- }
68
+ interpolate ( ) ;
46
69
47
70
return string ;
48
71
}
72
+
0 commit comments