Skip to content

Commit c706678

Browse files
fiskersosukesuzuki
andauthored
Keep non-html doctype unchanged (prettier#16765)
Co-authored-by: SUZUKI Sosuke <[email protected]>
1 parent 11520b7 commit c706678

5 files changed

Lines changed: 81 additions & 5 deletions

File tree

changelog_unreleased/html/16765.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#### Keep doctype in non-html files unchanged (#16765 by @fisker)
2+
3+
In Prettier v3, [we print HTML5 doctype in lowercase](https://prettier.io/blog/2023/07/05/3.0.0#print-html5-doctype-in-lowercase-7391httpsgithubcomprettierprettierpull7391-by-fiskerhttpsgithubcomfisker), it's safe for HTML files, however users may use the `html` parser to format other files eg: XHTML files, lowercase the `doctype` will break XHTML documents.
4+
5+
Since Prettier main, we'll only lowercase [HTML5 doctype (`<!doctype html>`)](https://developer.mozilla.org/en-US/docs/MDN/Writing_guidelines/Writing_style_guide/Code_style_guide/HTML#doctype) when the file extension is `.html` or `.htm`, otherwise they will be untouched.
6+
7+
<!-- prettier-ignore -->
8+
```html
9+
<!-- Input -->
10+
<!-- foo.xhtml -->
11+
<!DOCTYPE html>
12+
13+
<!-- Prettier stable -->
14+
<!doctype html>
15+
16+
<!-- Prettier main -->
17+
<!DOCTYPE html>
18+
```

src/language-html/print/tag.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ function printClosingTagSuffix(node, options) {
6262
return needsToBorrowParentClosingTagStartMarker(node)
6363
? printClosingTagStartMarker(node.parent, options)
6464
: needsToBorrowNextOpeningTagStartMarker(node)
65-
? printOpeningTagStartMarker(node.next)
65+
? printOpeningTagStartMarker(node.next, options)
6666
: "";
6767
}
6868

@@ -325,7 +325,10 @@ function printOpeningTag(path, options, print) {
325325
function printOpeningTagStart(node, options) {
326326
return node.prev && needsToBorrowNextOpeningTagStartMarker(node.prev)
327327
? ""
328-
: [printOpeningTagPrefix(node, options), printOpeningTagStartMarker(node)];
328+
: [
329+
printOpeningTagPrefix(node, options),
330+
printOpeningTagStartMarker(node, options),
331+
];
329332
}
330333

331334
function printOpeningTagPrefix(node, options) {
@@ -336,7 +339,8 @@ function printOpeningTagPrefix(node, options) {
336339
: "";
337340
}
338341

339-
function printOpeningTagStartMarker(node) {
342+
const HTML5_DOCTYPE_START_MARKER = "<!doctype";
343+
function printOpeningTagStartMarker(node, options) {
340344
switch (node.type) {
341345
case "ieConditionalComment":
342346
case "ieConditionalStartComment":
@@ -345,8 +349,20 @@ function printOpeningTagStartMarker(node) {
345349
return "<!--<!";
346350
case "interpolation":
347351
return "{{";
348-
case "docType":
349-
return node.value === "html" ? "<!doctype" : "<!DOCTYPE";
352+
case "docType": {
353+
// Only lowercase HTML5 doctype in `.html` and `.htm` files
354+
if (node.value === "html") {
355+
const filepath = options.filepath ?? "";
356+
if (/\.html?$/u.test(filepath)) {
357+
return HTML5_DOCTYPE_START_MARKER;
358+
}
359+
}
360+
361+
const original = options.originalText.slice(locStart(node), locEnd(node));
362+
363+
return original.slice(0, HTML5_DOCTYPE_START_MARKER.length);
364+
}
365+
350366
case "angularIcuExpression":
351367
return "{";
352368
case "element":
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`snippet: #0 format 1`] = `
4+
====================================options=====================================
5+
parsers: ["html"]
6+
printWidth: 80
7+
| printWidth
8+
=====================================input======================================
9+
<!DoCtYpE html>
10+
=====================================output=====================================
11+
<!DoCtYpE html>
12+
13+
================================================================================
14+
`;
15+
16+
exports[`xhtml-doctype.xhtml format 1`] = `
17+
====================================options=====================================
18+
parsers: ["html"]
19+
printWidth: 80
20+
| printWidth
21+
=====================================input======================================
22+
<!DOCTYPE html>
23+
<script xmlns="http://www.w3.org/1999/xhtml" src="[...]"/>
24+
25+
=====================================output=====================================
26+
<!DOCTYPE html>
27+
<script xmlns="http://www.w3.org/1999/xhtml" src="[...]" />
28+
29+
================================================================================
30+
`;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
runFormatTest(
2+
{
3+
snippets: [
4+
// Unknown filename
5+
"<!DoCtYpE html>",
6+
],
7+
importMeta: import.meta,
8+
},
9+
["html"],
10+
);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!DOCTYPE html>
2+
<script xmlns="http://www.w3.org/1999/xhtml" src="[...]"/>

0 commit comments

Comments
 (0)