-
Notifications
You must be signed in to change notification settings - Fork 6
/
prettier-plugin-void-html.js
88 lines (74 loc) · 2.45 KB
/
prettier-plugin-void-html.js
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
import {
parsers as prettierHtmlParsers,
printers as prettierHtmlPrinters,
} from "prettier/plugins/html";
/** @typedef {import("prettier/plugins/html").HtmlNode} HtmlNode*/
/** @type{import('prettier').SupportLanguage[]} */
export const languages = [
{
name: "HTML5",
extensions: [".html"],
parsers: ["html"],
vscodeLanguageIds: ["html"],
},
];
/** @type{import('prettier').Parser<HtmlNode>} */
const htmlParser = {
...prettierHtmlParsers.html,
astFormat: "html",
};
/** @type {import('prettier').Plugin['parsers']} */
export const parsers = {
html: htmlParser,
};
/**
*
* @param {import('prettier/doc.js').builders.Doc} doc
* @returns {doc is import('prettier/doc.js').builders.Group}
*/
function isGroup(doc) {
return typeof doc === "object" && "type" in doc && doc.type === "group";
}
/** @type {import('prettier').Printer<HtmlNode>} */
const htmlPrinter = {
...prettierHtmlPrinters.html,
print(path, options, print) {
const node = path.node;
// Self-closing syntax is allowed in SVG and MathML.
if (!["svg", "math"].includes(node.namespace)) {
node.isSelfClosing = false;
}
// Prevent forward slash in void tag borrowed end marker
if (path.previous?.tagDefinition?.isVoid) {
path.previous.isSelfClosing = false;
}
// Element is not void - use default printer
if (!node.tagDefinition?.isVoid) {
return prettierHtmlPrinters.html.print(path, options, print);
}
// Pass element along to the default printer. Since it is no
// longer marked as self-closing, the printer will give it a
// closing tag. For example, `<input>` will become `<input></input>`.
const printed = prettierHtmlPrinters.html.print(path, options, print);
// The last item in the contents is the new closing tag.
// Remove it.
if (isGroup(printed) && Array.isArray(printed.contents)) {
printed.contents.pop();
// If the next element has borrowed the end marker from the new (removed) closing tag
// Remove the opening tag end marker
if (
path.next?.isLeadingSpaceSensitive &&
!path.next.hasLeadingSpaces &&
isGroup(printed.contents[0]) &&
Array.isArray(printed.contents[0].contents)
) {
printed.contents[0].contents.pop();
}
}
// Prevent unwanted linebreaks
node.isSelfClosing = true;
return printed;
},
};
/** @type {import('prettier').Plugin['printers']} */
export const printers = { html: htmlPrinter };