-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathembedder.ts
More file actions
113 lines (99 loc) · 3.21 KB
/
embedder.ts
File metadata and controls
113 lines (99 loc) · 3.21 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import type { Options } from "prettier";
import { builders, utils } from "prettier/doc.js";
import type { Embedder } from "../../types.js";
import { preparePlaceholder, printTemplateExpressions } from "../utils.js";
import { language } from "./language.js";
const { line, group, indent, softline } = builders;
const { mapDoc } = utils;
export const embedder: Embedder<Options> = async (
textToDoc,
print,
path,
options,
{ commentOrTag, embeddedOverrideOptions },
) => {
const resolvedOptions = {
...options,
...embeddedOverrideOptions,
};
const { node } = path;
const { createPlaceholder, placeholderRegex } = preparePlaceholder();
const text = node.quasis
.map((quasi, index, { length }) =>
index === length - 1
? quasi.value.cooked
: quasi.value.cooked + createPlaceholder(index),
)
.join("");
const leadingWhitespaces = text.match(/^\s+/)?.[0] ?? "";
const trailingWhitespaces = text.match(/\s+$/)?.[0] ?? "";
const trimmedText = text.slice(
leadingWhitespaces.length,
-trailingWhitespaces.length || undefined,
);
const expressionDocs = printTemplateExpressions(path, print);
const doc = await textToDoc(trimmedText, {
...resolvedOptions,
parser: resolvedOptions.embeddedHtmlParser ?? "html",
});
const contentDoc = mapDoc(doc, (doc) => {
if (typeof doc !== "string") {
return doc;
}
const parts = [];
const components = doc.split(placeholderRegex);
for (let i = 0; i < components.length; i++) {
let component = components[i]!;
if (i % 2 === 0) {
if (!component) {
continue;
}
component = component.replaceAll(/([\\`]|\${)/g, "\\$1");
if (resolvedOptions.__embeddedInHtml) {
component = component.replaceAll(/<\/(?=script\b)/gi, "<\\/");
}
parts.push(component);
} else {
const placeholderIndex = Number(component);
parts.push(expressionDocs[placeholderIndex]!);
}
}
return parts;
});
if (
resolvedOptions.htmlWhitespaceSensitivity === "strict" ||
// TODO: is css mode should be included here?
resolvedOptions.htmlWhitespaceSensitivity === "css" ||
resolvedOptions.preserveEmbeddedExteriorWhitespaces?.includes(commentOrTag)
) {
// TODO: should we label the doc with { hug: false } ?
// https://github.com/prettier/prettier/blob/5cfb76ee50cf286cab267cf3cb7a26e749c995f7/src/language-js/embed/html.js#L88
return group([
"`",
leadingWhitespaces,
resolvedOptions.noEmbeddedMultiLineIndentation?.includes(commentOrTag)
? [group(contentDoc)]
: indent([group(contentDoc)]),
trailingWhitespaces,
"`",
]);
}
const leadingLineBreak = leadingWhitespaces.length ? line : softline;
const trailingLineBreak = trailingWhitespaces.length ? line : softline;
return group([
"`",
resolvedOptions.noEmbeddedMultiLineIndentation?.includes(commentOrTag)
? [leadingLineBreak, group(contentDoc)]
: indent([leadingLineBreak, group(contentDoc)]),
trailingLineBreak,
"`",
]);
};
/**
* Register the embedder to the EmbeddedEmbedders
*/
declare module "../types.js" {
interface EmbeddedEmbedders {
[language]: typeof embedder;
}
}