-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathembedder.ts
More file actions
111 lines (96 loc) · 3.38 KB
/
embedder.ts
File metadata and controls
111 lines (96 loc) · 3.38 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
import dedent from "dedent";
import type { Options } from "prettier";
import { builders } from "prettier/doc.js";
import type { Embedder } from "../../types.js";
import {
preparePlaceholder,
printTemplateExpressions,
simpleRehydrateDoc,
} from "../utils.js";
import { language } from "./language.js";
const { line, group, indent, softline, dedentToRoot, literalline } = builders;
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(
// use `dedent` to fix unstable embedded markdown indentation with the `useTabs` option
// https://github.com/Sec-ant/prettier-plugin-embed/pull/91#issuecomment-1963760555
// https://github.com/prettier/prettier/blob/1079517b32e5bb145afa7acba448af51f8a7b6e6/src/language-js/embed/markdown.js#L15-L19
dedent(trimmedText),
{
...resolvedOptions,
parser: resolvedOptions.embeddedMarkdownParser ?? "markdown",
// this will change the code fence delimiter from ``` to ~~~
// https://github.com/prettier/prettier/blob/1079517b32e5bb145afa7acba448af51f8a7b6e6/src/language-markdown/embed.js#L15
__inJsTemplate: true,
},
);
const contentDoc = simpleRehydrateDoc(
doc,
placeholderRegex,
expressionDocs,
"hardline",
);
if (
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)
? dedentToRoot(group(contentDoc))
: indent([group(contentDoc)]),
trailingWhitespaces,
"`",
]);
}
const leadingLineBreak = leadingWhitespaces.length ? line : softline;
const trailingLineBreak = trailingWhitespaces.length ? line : softline;
// When noEmbeddedMultiLineIndentation is set, use dedentToRoot to prevent
// any indentation from being added to the markdown content.
// This matches Prettier's native behavior for markdown in template literals.
// https://github.com/prettier/prettier/blob/main/src/language-js/embed/markdown.js
if (resolvedOptions.noEmbeddedMultiLineIndentation?.includes(commentOrTag)) {
return ["`", literalline, dedentToRoot(contentDoc), softline, "`"];
}
return group([
"`",
indent([leadingLineBreak, group(contentDoc)]),
trailingLineBreak,
"`",
]);
};
/**
* Register the embedder to the EmbeddedEmbedders
*/
declare module "../types.js" {
interface EmbeddedEmbedders {
[language]: typeof embedder;
}
}