-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathdedent.ts
60 lines (55 loc) · 1.66 KB
/
dedent.ts
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
export default function dedent(literals: string): string;
export default function dedent(
strings: TemplateStringsArray,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...values: any[]
): string;
export default function dedent(
strings: string | TemplateStringsArray,
...values: string[]
) {
const raw = typeof strings === "string" ? [strings] : strings.raw;
// first, perform interpolation
let result = "";
for (let i = 0; i < raw.length; i++) {
result += raw[i]
// handle escaped newlines, backticks, and interpolation characters
.replace(/\\`/g, "`")
.replace(/\\\n[ \t]*/g, "")
.replace(/\\\$/g, "$")
.replace(/\\{/g, "{");
if (i < values.length) {
result += values[i];
}
}
// now strip indentation
const lines = result.split("\n");
let mindent: number | null = null;
for (const l of lines) {
const m = l.match(/^(\s+)\S+/);
if (m) {
const indent = m[1].length;
if (!mindent) {
// this is the first indented line
mindent = indent;
} else {
mindent = Math.min(mindent, indent);
}
}
}
if (mindent !== null) {
const m = mindent; // appease TypeScript
result = lines
// https://github.com/typescript-eslint/typescript-eslint/issues/7140
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
.map((l) => (l[0] === " " || l[0] === "\t" ? l.slice(m) : l))
.join("\n");
}
return (
result
// dedent eats leading and trailing whitespace too
.trim()
// handle escaped newlines at the end to ensure they don't get stripped too
.replace(/\\n/g, "\n")
);
}